Esempio n. 1
0
    def marketSell(self, market: str='', base_quantity: float=0) -> list:
        """Executes a market sell providing a crypto amount"""

        # validates the market is syntactically correct
        if not self._isMarketValid(market):
            raise ValueError('Binance market is invalid.')

        if not isinstance(base_quantity, int) and not isinstance(base_quantity, float):
            raise TypeError('The crypto amount is not numeric.')

        try:
            df_filters = self.getMarketInfoFilters(market)
            step_size = float(df_filters.loc[df_filters['filterType'] == 'LOT_SIZE']['stepSize'])
            precision = int(round(-math.log(step_size, 10), 0))

            # remove fees
            base_quantity = base_quantity - (base_quantity * self.getTradeFee(market))

            # execute market sell
            stepper = 10.0 ** precision
            truncated = math.trunc(stepper * base_quantity) / stepper
            Logger.info('Order quantity after rounding and fees: ' + str(truncated))
            return self.client.order_market_sell(symbol=market, quantity=truncated)
        except Exception as err:
            ts = datetime.now().strftime("%d-%m-%Y %H:%M:%S")
            Logger.error(ts + ' Binance ' + ' marketSell ' + str(err))
            return []
Esempio n. 2
0
 def line(self, left_text, right_text):
     left_slice = left_text[slice(self.max_left)]
     right_slice = right_text[slice(self.max_right)]
     left_space = (' ' * (self.max_left - len(left_slice)))
     right_space = (' ' * (self.max_right - len(right_slice)))
     Logger.info(
         f'| {left_space}{left_slice} : {right_slice}{right_space} |')
    def renderPercentageChangeHistogram(self, show_desc=True):
        """Render Percentage Change Histogram

        Parameters
        ----------
        saveOnly : bool
            Save the figure without displaying it
        """

        # get dataframe from technical analysis object
        df = self.technical_analysis.getDataFrame()

        # extract market and granularity from trading dataframe
        market = df.iloc[0].market
        granularity = df.iloc[0].granularity

        fig, ax = plt.subplots(ncols=1, figsize=(12, 6))  # pylint: disable=unused-variable
        fig.autofmt_xdate()

        ax = plt.subplot(111)
        df.close_pc.hist(bins=50)
        ax.set_title("Close Percent Change")

        plt.xlabel(market + " - " + str(granularity))
        plt.xticks(rotation=90)
        plt.tight_layout()
        plt.legend()

        plt.show()

        if show_desc is True:
            Logger.info(df["close_pc"].describe())
Esempio n. 4
0
 def handle_api_error(self, err: str, reason: str) -> dict:
     if self.debug:
         if self.die_on_api_error:
             raise SystemExit(err)
         else:
             Logger.debug(err)
             return {}
     else:
         if self.die_on_api_error:
             raise SystemExit(f"{reason}: {self._api_url}")
         else:
             Logger.info(f"{reason}: {self._api_url}")
             return {}
Esempio n. 5
0
    def handle_api_error(self, err: str, reason: str) -> pd.DataFrame:
        """Handle API errors"""

        if self.debug:
            if self.die_on_api_error:
                raise SystemExit(err)
            else:
                Logger.error(err)
                return pd.DataFrame()
        else:
            if self.die_on_api_error:
                raise SystemExit(f"{reason}: {self._api_url}")
            else:
                Logger.info(f"{reason}: {self._api_url}")
                return pd.DataFrame()
Esempio n. 6
0
    def checkTrailingBuy(self, app, state, price: float = 0.0):
        # If buy signal, save the price and check if it decreases before buying.
        trailing_buy_logtext = ""
        waitpcnttext = ""
        immediate_action = False
        if state.trailing_buy == 0:
            state.waiting_buy_price = price
            pricechange = 0
        elif state.trailing_buy == 1 and state.waiting_buy_price > 0:
            pricechange = ((price - state.waiting_buy_price) /
                           state.waiting_buy_price * 100)
            if price < state.waiting_buy_price:
                state.waiting_buy_price = price
                waitpcnttext += f"Price decreased - resetting wait price. "

        waitpcnttext += f"** {app.getMarket()} - "
        if pricechange < app.getTrailingBuyPcnt(
        ):  # get pcnt from config, if not, use 0%
            state.action = "WAIT"
            state.trailing_buy = 1
            if app.getTrailingBuyPcnt() > 0:
                trailing_buy_logtext = f" - Wait Chg: {_truncate(pricechange,2)}%/{app.getTrailingBuyPcnt()}%"
                waitpcnttext += f"Waiting to buy until {state.waiting_buy_price} increases {app.getTrailingBuyPcnt()}% - change {_truncate(pricechange,2)}%"
            else:
                trailing_buy_logtext = f" - Wait Chg: {_truncate(pricechange,2)}%"
                waitpcnttext += f"Waiting to buy until {state.waiting_buy_price} stops decreasing - change {_truncate(pricechange,2)}%"
        else:
            state.action = "BUY"
            state.trailing_buy = 1
            if app.trailingImmediateBuy():
                immediate_action = True
            trailing_buy_logtext = f" - Ready Chg: {_truncate(pricechange,2)}%/{app.getTrailingBuyPcnt()}%"
            waitpcnttext += f"Ready to buy. {state.waiting_buy_price} change of {_truncate(pricechange,2)}% is above setting of {app.getTrailingBuyPcnt()}%"

        if app.isVerbose() and (not app.isSimulation() or
                                (app.isSimulation()
                                 and not app.simResultOnly())):
            Logger.info(waitpcnttext)

        return state.action, state.trailing_buy, trailing_buy_logtext, immediate_action
Esempio n. 7
0
    def printSupportResistanceLevel(self, price: float=0) -> None:
        if isinstance(price, int) or isinstance(price, float):
            df = self.getSupportResistanceLevels()

            if len(df) > 0:
                df_last = df.tail(1)
                if float(df_last[0]) < price:
                    Logger.info(' Support level of ' + str(df_last[0]) + ' formed at ' + str(df_last.index[0]))
                elif float(df_last[0]) > price:
                    Logger.info(' Resistance level of ' + str(df_last[0]) + ' formed at ' + str(df_last.index[0]))
                else:
                    Logger.info(' Support/Resistance level of ' + str(df_last[0]) + ' formed at ' + str(df_last.index[0]))
Esempio n. 8
0
 def center(self, text):
     text_slice = text[slice(self.width - 4)]
     left_space = ' ' * int((self.width - len(text_slice) - 2) / 2)
     right_space = ' ' * (self.width - len(text_slice) - len(left_space) -
                          2)
     Logger.info(f'|{left_space}{text_slice}{right_space}|')
Esempio n. 9
0
 def doubleLine(self):
     Logger.info('=' * self.width)
Esempio n. 10
0
 def singleLine(self):
     Logger.info('-' * self.width)
Esempio n. 11
0
    def getHistoricalData(self, market: str=DEFAULT_MARKET, granularity: str=DEFAULT_GRANULARITY, iso8601start: str='', iso8601end: str='') -> pd.DataFrame:
        # validates the market is syntactically correct
        if not self._isMarketValid(market):
            raise TypeError('Binance market required.')

        # validates granularity is a string
        if not isinstance(granularity, str):
            raise TypeError('Granularity string required.')

        # validates the granularity is supported by Binance
        if not granularity in SUPPORTED_GRANULARITY:
            raise TypeError('Granularity options: ' + ", ".join(map(str, SUPPORTED_GRANULARITY)))

        # validates the ISO 8601 start date is a string (if provided)
        if not isinstance(iso8601start, str):
            raise TypeError('ISO8601 start integer as string required.')

        # validates the ISO 8601 end date is a string (if provided)
        if not isinstance(iso8601end, str):
            raise TypeError('ISO8601 end integer as string required.')

        # if only a start date is provided
        if iso8601start != '' and iso8601end == '':
            try:
                multiplier = MULTIPLIER_EQUIVALENTS[SUPPORTED_GRANULARITY.index(granularity)] 
            except:
                multiplier = 1
    
            # calculate the end date using the granularity
            iso8601end = str((datetime.strptime(iso8601start, '%Y-%m-%dT%H:%M:%S.%f') + timedelta(minutes=granularity * multiplier)).isoformat())

        if iso8601start != '' and iso8601end != '':
            Logger.info('Attempting to retrieve data from ' + iso8601start)
            resp = self.client.get_historical_klines(market, granularity, iso8601start, iso8601end)

            if len(resp) > 300:
                resp = resp[:300]
        else: # TODO: replace with a KLINE_MESSAGE_FOO equivalent
            if granularity == '1m':
                resp = self.client.get_historical_klines(market, granularity, '12 hours ago UTC')
                resp = resp[-300:]
            elif granularity == '5m':
                resp = self.client.get_historical_klines(market, granularity, '2 days ago UTC')
                resp = resp[-300:]
            elif granularity == '15m':
                resp = self.client.get_historical_klines(market, granularity, '4 days ago UTC')
                resp = resp[-300:]
            elif granularity == '1h':
                resp = self.client.get_historical_klines(market, granularity, '13 days ago UTC')
                resp = resp[-300:]
            elif granularity == '6h':
                resp = self.client.get_historical_klines(market, granularity, '75 days ago UTC')
                resp = resp[-300:]
            elif granularity == '1d':
                resp = self.client.get_historical_klines(market, granularity, '251 days ago UTC')
            else:
                raise Exception('Something went wrong!')
                   
        # convert the API response into a Pandas DataFrame
        df = pd.DataFrame(resp, columns=[ 'open_time', 'open', 'high', 'low', 'close', 'volume', 'close_time', 'quote_asset_volume', 'number_of_trades', 'taker_buy_base_asset_volume', 'traker_buy_quote_asset_volume', 'ignore' ])
        df['market'] = market
        df['granularity'] = granularity

        # binance epoch is too long
        df['open_time'] = df['open_time'] + 1
        df['open_time'] = df['open_time'].astype(str)
        df['open_time'] = df['open_time'].str.replace(r'\d{3}$', '', regex=True)   

        try:
            freq = FREQUENCY_EQUIVALENTS[SUPPORTED_GRANULARITY.index(granularity)]
        except:
            freq = "D"

        # convert the DataFrame into a time series with the date as the index/key
        try:
            tsidx = pd.DatetimeIndex(pd.to_datetime(df['open_time'], unit='s'), dtype='datetime64[ns]', freq=freq)
            df.set_index(tsidx, inplace=True)
            df = df.drop(columns=['open_time'])
            df.index.names = ['ts']
            df['date'] = tsidx
        except ValueError:
            tsidx = pd.DatetimeIndex(pd.to_datetime(df['open_time'], unit='s'), dtype='datetime64[ns]')
            df.set_index(tsidx, inplace=True)
            df = df.drop(columns=['open_time'])
            df.index.names = ['ts']           
            df['date'] = tsidx

        # re-order columns
        df = df[[ 'date', 'market', 'granularity', 'low', 'high', 'open', 'close', 'volume' ]]

        # correct column types
        df['low'] = df['low'].astype(float)
        df['high'] = df['high'].astype(float)   
        df['open'] = df['open'].astype(float)   
        df['close'] = df['close'].astype(float)   
        df['volume'] = df['volume'].astype(float)      

        # reset pandas dataframe index
        df.reset_index()

        return df
Esempio n. 12
0
    def renderSupportResistance(self, saveOnly=False):
        """Render Support and Resistance Levels

        Parameters
        ----------
        saveOnly : bool
            Save the figure without displaying it
        """

        # get dataframe from technical analysis object
        df = self.technical_analysis.getDataFrame()

        # extract market and granularity from trading dataframe
        market = df.iloc[0].market
        granularity = df.iloc[0].granularity

        fig, ax = plt.subplots(ncols=1, figsize=(12, 6))  # pylint: disable=unused-variable
        fig.autofmt_xdate()

        ax = plt.subplot(111)
        ax.plot(df.close, label="price", color="black")
        ax.set_title("Support and Resistance Levels")

        rotation = 1
        last_level = 0
        for level in self.levels:
            # plt.axhline(y=level, color='grey')
            if last_level != 0:
                if rotation == 1:
                    ax.axhspan(
                        last_level,
                        level,
                        alpha=0.4,
                        color="lightsalmon",
                        label=str(level),
                    )
                elif rotation == 2:
                    ax.axhspan(
                        last_level,
                        level,
                        alpha=0.5,
                        color="palegreen",
                        label=str(level),
                    )
                elif rotation == 3:
                    ax.axhspan(
                        last_level,
                        level,
                        alpha=0.5,
                        color="palegoldenrod",
                        label=str(level),
                    )
                elif rotation == 4:
                    ax.axhspan(
                        last_level,
                        level,
                        alpha=0.5,
                        color="powderblue",
                        label=str(level),
                    )
                else:
                    ax.axhspan(last_level, level, alpha=0.4)
            last_level = level
            if rotation < 4:
                rotation += 1
            else:
                rotation = 1

        plt.xlabel(market + " - " + str(granularity))
        plt.ylabel("Price")
        plt.xticks(rotation=90)
        plt.tight_layout()
        plt.legend()

        try:
            Logger.info(
                f"creating: graphs/SRL_{market}_{str(granularity)}.png")
            plt.savefig(f"graphs/SRL_{market}_{str(granularity)}.png", dpi=300)
        except OSError:
            raise SystemExit(
                f"Unable to save: graphs/SRL_{market}_{str(granularity)}.png")

        if saveOnly is False:
            plt.show()
Esempio n. 13
0
    def renderCandlesticks(self, period=30, saveOnly=False):
        # get dataframe from technical analysis object
        df = self.technical_analysis.getDataFrame()

        if not isinstance(period, int):
            raise TypeError("Period parameter is not perioderic.")

        if period < 1 or period > len(df):
            raise ValueError("Period is out of range")

        # extract market and granularity from trading dataframe
        market = df.iloc[0].market
        granularity = df.iloc[0].granularity

        df_subset = df.iloc[-period::]

        fig, axes = plt.subplots(ncols=1, figsize=(12, 6))  # pylint: disable=unused-variable
        fig.autofmt_xdate()
        ax1 = plt.subplot(111)
        ax1.set_title("Candlestick Patterns")
        plt.plot(df_subset["close"], label="price", color="black")
        plt.plot(df_subset["ema12"], label="ema12", color="orange")
        plt.plot(df_subset["ema26"], label="ema26", color="purple")
        plt.tick_params(axis="x",
                        which="both",
                        bottom=False,
                        top=False,
                        labelbottom=False)

        df_candlestick = self.df[self.df["three_white_soldiers"] is True]
        df_candlestick_in_range = df_candlestick[
            df_candlestick.index >= np.min(df_subset.index)]
        for idx in df_candlestick_in_range.index.tolist():
            plt.plot(
                idx,
                df_candlestick_in_range.loc[idx]["close"],
                "g*",
                markersize=10,
                label="Three White Soldiers",
            )

        df_candlestick = self.df[self.df["three_black_crows"] is True]
        df_candlestick_in_range = df_candlestick[
            df_candlestick.index >= np.min(df_subset.index)]
        for idx in df_candlestick_in_range.index.tolist():
            plt.plot(
                idx,
                df_candlestick_in_range.loc[idx]["close"],
                "r*",
                markersize=10,
                label="Three Black Crows",
            )

        df_candlestick = self.df[self.df["inverted_hammer"] is True]
        df_candlestick_in_range = df_candlestick[
            df_candlestick.index >= np.min(df_subset.index)]
        for idx in df_candlestick_in_range.index.tolist():
            plt.plot(
                idx,
                df_candlestick_in_range.loc[idx]["close"],
                "g*",
                markersize=10,
                label="Inverted Hammer",
            )

        df_candlestick = self.df[self.df["hammer"] is True]
        df_candlestick_in_range = df_candlestick[
            df_candlestick.index >= np.min(df_subset.index)]
        for idx in df_candlestick_in_range.index.tolist():
            plt.plot(
                idx,
                df_candlestick_in_range.loc[idx]["close"],
                "g*",
                markersize=10,
                label="Hammer",
            )

        df_candlestick = self.df[self.df["hanging_man"] is True]
        df_candlestick_in_range = df_candlestick[
            df_candlestick.index >= np.min(df_subset.index)]
        for idx in df_candlestick_in_range.index.tolist():
            plt.plot(
                idx,
                df_candlestick_in_range.loc[idx]["close"],
                "r*",
                markersize=10,
                label="Hanging Man",
            )

        df_candlestick = self.df[self.df["shooting_star"] is True]
        df_candlestick_in_range = df_candlestick[
            df_candlestick.index >= np.min(df_subset.index)]
        for idx in df_candlestick_in_range.index.tolist():
            plt.plot(
                idx,
                df_candlestick_in_range.loc[idx]["close"],
                "r*",
                markersize=10,
                label="Shooting Star",
            )

        df_candlestick = self.df[self.df["doji"] is True]
        df_candlestick_in_range = df_candlestick[
            df_candlestick.index >= np.min(df_subset.index)]
        for idx in df_candlestick_in_range.index.tolist():
            plt.plot(
                idx,
                df_candlestick_in_range.loc[idx]["close"],
                "b*",
                markersize=10,
                label="Doji",
            )

        df_candlestick = self.df[self.df["three_line_strike"] is True]
        df_candlestick_in_range = df_candlestick[
            df_candlestick.index >= np.min(df_subset.index)]
        for idx in df_candlestick_in_range.index.tolist():
            plt.plot(
                idx,
                df_candlestick_in_range.loc[idx]["close"],
                "g*",
                markersize=10,
                label="Three Line Strike",
            )

        df_candlestick = self.df[self.df["two_black_gapping"] is True]
        df_candlestick_in_range = df_candlestick[
            df_candlestick.index >= np.min(df_subset.index)]
        for idx in df_candlestick_in_range.index.tolist():
            plt.plot(
                idx,
                df_candlestick_in_range.loc[idx]["close"],
                "r*",
                markersize=10,
                label="Two Black Gapping",
            )

        df_candlestick = self.df[self.df["morning_star"] is True]
        df_candlestick_in_range = df_candlestick[
            df_candlestick.index >= np.min(df_subset.index)]
        for idx in df_candlestick_in_range.index.tolist():
            plt.plot(
                idx,
                df_candlestick_in_range.loc[idx]["close"],
                "g*",
                markersize=10,
                label="Morning Star",
            )

        df_candlestick = self.df[self.df["evening_star"] is True]
        df_candlestick_in_range = df_candlestick[
            df_candlestick.index >= np.min(df_subset.index)]
        for idx in df_candlestick_in_range.index.tolist():
            plt.plot(
                idx,
                df_candlestick_in_range.loc[idx]["close"],
                "r*",
                markersize=10,
                label="Evening Star",
            )

        df_candlestick = self.df[self.df["morning_doji_star"] is True]
        df_candlestick_in_range = df_candlestick[
            df_candlestick.index >= np.min(df_subset.index)]
        for idx in df_candlestick_in_range.index.tolist():
            plt.plot(
                idx,
                df_candlestick_in_range.loc[idx]["close"],
                "g*",
                markersize=10,
                label="Morning Doji Star",
            )

        df_candlestick = self.df[self.df["evening_doji_star"] is True]
        df_candlestick_in_range = df_candlestick[
            df_candlestick.index >= np.min(df_subset.index)]
        for idx in df_candlestick_in_range.index.tolist():
            plt.plot(
                idx,
                df_candlestick_in_range.loc[idx]["close"],
                "r*",
                markersize=10,
                label="Evening Doji Star",
            )

        df_candlestick = self.df[self.df["abandoned_baby"] is True]
        df_candlestick_in_range = df_candlestick[
            df_candlestick.index >= np.min(df_subset.index)]
        for idx in df_candlestick_in_range.index.tolist():
            plt.plot(
                idx,
                df_candlestick_in_range.loc[idx]["close"],
                "g*",
                markersize=10,
                label="Abandoned Baby",
            )

        plt.xlabel(market + " - " + str(granularity))
        plt.ylabel("Price")
        plt.xticks(rotation=90)
        plt.tight_layout()
        plt.legend()

        try:
            Logger.info(
                f"creating: graphs/CSP_{market}_{str(granularity)}.png")
            plt.savefig(f"graphs/CSP_{market}_{str(granularity)}.png", dpi=300)
        except OSError:
            raise SystemExit(
                f"Unable to save: graphs/CSP_{market}_{str(granularity)}.png")

        if saveOnly is False:
            plt.show()
Esempio n. 14
0
 def on_message(self, msg):
     Logger.info(msg)
Esempio n. 15
0
 def on_close(self):
     Logger.info("-- Websocket Closed --")
Esempio n. 16
0
 def on_open(self):
     Logger.info("-- Websocket Subscribed! --")
Esempio n. 17
0
    def startApp(self, account, last_action='', banner=True):
        if banner:
            Logger.info(
                '--------------------------------------------------------------------------------'
            )
            Logger.info(
                '|                             Python Crypto Bot                                |'
            )
            Logger.info(
                '--------------------------------------------------------------------------------'
            )
            txt = '              Release : ' + self.getVersionFromREADME()
            Logger.info('|  ' + txt + (' ' * (75 - len(txt))) + ' | ')

            Logger.info(
                '-----------------------------------------------------------------------------'
            )

            if self.isVerbose():
                txt = '               Market : ' + self.getMarket()
                Logger.info('|  ' + txt + (' ' * (75 - len(txt))) + ' | ')
                txt = '          Granularity : ' + str(
                    self.getGranularity()) + ' seconds'
                Logger.info('|  ' + txt + (' ' * (75 - len(txt))) + ' | ')
                Logger.info(
                    '-----------------------------------------------------------------------------'
                )

            if self.isLive():
                txt = '             Bot Mode : LIVE - live trades using your funds!'
            else:
                txt = '             Bot Mode : TEST - test trades using dummy funds :)'

            Logger.info('|  ' + txt + (' ' * (75 - len(txt))) + ' | ')

            txt = '          Bot Started : ' + str(datetime.now())
            Logger.info('|  ' + txt + (' ' * (75 - len(txt))) + ' | ')
            Logger.info(
                '================================================================================'
            )

            if self.sellUpperPcnt() != None:
                txt = '           Sell Upper : ' + str(
                    self.sellUpperPcnt()) + '%'
                Logger.info('|  ' + txt + (' ' * (75 - len(txt))) + ' | ')

            if self.sellLowerPcnt() != None:
                txt = '           Sell Lower : ' + str(
                    self.sellLowerPcnt()) + '%'
                Logger.info('|  ' + txt + (' ' * (75 - len(txt))) + ' | ')

            if self.trailingStopLoss() != None:
                txt = '   Trailing Stop Loss : ' + str(
                    self.trailingStopLoss()) + '%'
                Logger.info(' | ' + txt + (' ' * (75 - len(txt))) + ' | ')

            txt = '         Sell At Loss : ' + str(
                self.allowSellAtLoss()) + '  --sellatloss ' + str(
                    self.allowSellAtLoss())
            Logger.info('|  ' + txt + (' ' * (75 - len(txt))) + ' | ')

            txt = '   Sell At Resistance : ' + str(
                self.sellAtResistance()) + '  --sellatresistance'
            Logger.info('|  ' + txt + (' ' * (75 - len(txt))) + ' | ')

            txt = '      Trade Bull Only : ' + str(
                not self.disableBullOnly()) + '  --disablebullonly'
            Logger.info('|  ' + txt + (' ' * (75 - len(txt))) + ' | ')

            txt = '        Buy Near High : ' + str(
                not self.disableBuyNearHigh()) + '  --disablebuynearhigh'
            Logger.info('|  ' + txt + (' ' * (75 - len(txt))) + ' | ')

            txt = '         Use Buy MACD : ' + str(
                not self.disableBuyMACD()) + '  --disablebuymacd'
            Logger.info('|  ' + txt + (' ' * (75 - len(txt))) + ' | ')

            txt = '          Use Buy OBV : ' + str(
                not self.disableBuyOBV()) + '  --disablebuyobv'
            Logger.info('|  ' + txt + (' ' * (75 - len(txt))) + ' | ')

            txt = '    Use Buy Elder-Ray : ' + str(
                not self.disableBuyElderRay()) + '  --disablebuyelderray'
            Logger.info('|  ' + txt + (' ' * (75 - len(txt))) + ' | ')

            txt = '   Sell Fibonacci Low : ' + str(
                not self.disableFailsafeFibonacciLow()
            ) + '  --disablefailsafefibonaccilow'
            Logger.info('|  ' + txt + (' ' * (75 - len(txt))) + ' | ')

            if self.sellLowerPcnt() != None:
                txt = '      Sell Lower Pcnt : ' + str(
                    not self.disableFailsafeLowerPcnt()
                ) + '  --disablefailsafelowerpcnt'
                Logger.info('|  ' + txt + (' ' * (75 - len(txt))) + ' | ')

            if self.sellUpperPcnt() != None:
                txt = '      Sell Upper Pcnt : ' + str(
                    not self.disableFailsafeLowerPcnt()
                ) + '  --disableprofitbankupperpcnt'
                Logger.info('|  ' + txt + (' ' * (75 - len(txt))) + ' | ')

            txt = ' Candlestick Reversal : ' + str(
                not self.disableProfitbankReversal()
            ) + '  --disableprofitbankreversal'
            Logger.info('|  ' + txt + (' ' * (75 - len(txt))) + ' | ')

            txt = '             Telegram : ' + str(
                not self.disabletelegram) + '  --disabletelegram'
            Logger.info('|  ' + txt + (' ' * (75 - len(txt))) + ' | ')

            txt = '                  Log : ' + str(
                not self.disableLog()) + '  --disablelog'
            Logger.info('|  ' + txt + (' ' * (75 - len(txt))) + ' | ')

            txt = '              Tracker : ' + str(
                not self.disableTracker()) + '  --disabletracker'
            Logger.info('|  ' + txt + (' ' * (75 - len(txt))) + ' | ')

            txt = '     Auto restart Bot : ' + str(
                self.autoRestart()) + '  --autorestart'
            Logger.info('|  ' + txt + (' ' * (75 - len(txt))) + ' | ')

            if self.getBuyMaxSize():
                txt = '         Max Buy Size : ' + str(
                    self.getBuyMaxSize()) + '  --buymaxsize <size>'
                Logger.info('|  ' + txt + (' ' * (75 - len(txt))) + ' | ')

            Logger.info(
                '================================================================================'
            )

        # run the first job immediately after starting
        if self.isSimulation():
            if self.simuluationSpeed() in ['fast-sample', 'slow-sample']:
                tradingData = pd.DataFrame()

                attempts = 0

                if self.simstartdate is not None:
                    date = self.simstartdate.split('-')
                    startDate = datetime(int(date[0]), int(date[1]),
                                         int(date[2]))
                    endDate = startDate + timedelta(
                        minutes=(self.getGranularity() / 60) * 300)
                    while len(tradingData) != 300 and attempts < 10:
                        tradingData = self.getHistoricalData(
                            self.getMarket(), self.getGranularity(),
                            startDate.isoformat(timespec='milliseconds'))
                        attempts += 1
                elif self.simenddate is not None:
                    if self.simenddate == 'now':
                        endDate = datetime.now()
                    else:
                        date = self.simenddate.split('-')
                        endDate = datetime(int(date[0]), int(date[1]),
                                           int(date[2]))
                    startDate = endDate - timedelta(
                        minutes=(self.getGranularity() / 60) * 300)
                    while len(tradingData) != 300 and attempts < 10:
                        tradingData = self.getHistoricalData(
                            self.getMarket(), self.getGranularity(),
                            startDate.isoformat(timespec='milliseconds'))
                        attempts += 1
                else:
                    while len(tradingData) != 300 and attempts < 10:
                        endDate = datetime.now() - timedelta(
                            hours=random.randint(0,
                                                 8760 * 3))  # 3 years in hours
                        startDate = endDate - timedelta(
                            minutes=(self.getGranularity() / 60) * 300)
                        tradingData = self.getHistoricalData(
                            self.getMarket(), self.getGranularity(),
                            startDate.isoformat(timespec='milliseconds'))
                        attempts += 1
                    if len(tradingData) != 300:
                        raise Exception(
                            'Unable to retrieve 300 random sets of data between '
                            + str(startDate) + ' and ' + str(endDate) +
                            ' in ' + str(attempts) + ' attempts.')

                if banner:
                    startDate = str(startDate.isoformat())
                    endDate = str(endDate.isoformat())
                    txt = '   Sampling start : ' + str(startDate)
                    Logger.info(' | ' + txt + (' ' * (75 - len(txt))) + ' | ')
                    txt = '     Sampling end : ' + str(endDate)
                    Logger.info(' | ' + txt + (' ' * (75 - len(txt))) + ' | ')
                    if self.simstartdate != None:
                        txt = '    WARNING: Using less than 300 intervals'
                        Logger.info(' | ' + txt + (' ' * (75 - len(txt))) +
                                    ' | ')
                        txt = '    Interval size : ' + str(len(tradingData))
                        Logger.info(' | ' + txt + (' ' * (75 - len(txt))) +
                                    ' | ')
                    Logger.info(
                        '================================================================================'
                    )

            else:
                tradingData = self.getHistoricalData(self.getMarket(),
                                                     self.getGranularity())

            return tradingData
Esempio n. 18
0
def executeJob(sc=None,
               app: PyCryptoBot = None,
               state: AppState = None,
               trading_data=pd.DataFrame()):
    """Trading bot job which runs at a scheduled interval"""

    global technical_analysis

    # connectivity check (only when running live)
    if app.isLive() and app.getTime() is None:
        Logger.warning(
            'Your connection to the exchange has gone down, will retry in 1 minute!'
        )

        # poll every 5 minute
        list(map(s.cancel, s.queue))
        s.enter(300, 1, executeJob, (sc, app, state))
        return

    # increment state.iterations
    state.iterations = state.iterations + 1

    if not app.isSimulation():
        # retrieve the app.getMarket() data
        trading_data = app.getHistoricalData(app.getMarket(),
                                             app.getGranularity())

    else:
        if len(trading_data) == 0:
            return None

    # analyse the market data
    if app.isSimulation() and len(trading_data.columns) > 8:
        df = trading_data
        # if smartswitch the get the market data using new granularity
        if app.sim_smartswitch:
            df_last = app.getInterval(df, state.iterations)
            if len(df_last.index.format()) > 0:

                current_df_index = str(df_last.index.format()[0])
                current_sim_date = f'{current_df_index} 00:00:00' if len(
                    current_df_index) == 10 else current_df_index
                dt = current_sim_date.split(' ')
                date = dt[0].split('-')
                time = dt[1].split(':')
                startDate = datetime(int(date[0]), int(date[1]), int(date[2]),
                                     int(time[0]), int(time[1]), int(time[2]))
                trading_data = app.getHistoricalData(
                    app.getMarket(), app.getGranularity(),
                    startDate.isoformat(timespec='milliseconds'),
                    datetime.now().isoformat(timespec='milliseconds'))
                trading_dataCopy = trading_data.copy()
                technical_analysis = TechnicalAnalysis(trading_dataCopy)
                technical_analysis.addAll()
                df = technical_analysis.getDataFrame()
                state.iterations = 1
            app.sim_smartswitch = False

    else:
        trading_dataCopy = trading_data.copy()
        technical_analysis = TechnicalAnalysis(trading_dataCopy)
        technical_analysis.addAll()
        df = technical_analysis.getDataFrame()

    if app.isSimulation():
        df_last = app.getInterval(df, state.iterations)
    else:
        df_last = app.getInterval(df)

    if len(df_last.index.format()) > 0:
        current_df_index = str(df_last.index.format()[0])
    else:
        current_df_index = state.last_df_index

    formatted_current_df_index = f'{current_df_index} 00:00:00' if len(
        current_df_index) == 10 else current_df_index

    current_sim_date = formatted_current_df_index

    # use actual sim mode date to check smartchswitch
    if app.getSmartSwitch() == 1 and app.getGranularity(
    ) == 3600 and app.is1hEMA1226Bull(
            current_sim_date) is True and app.is6hEMA1226Bull(
                current_sim_date) is True:
        Logger.info(
            '*** smart switch from granularity 3600 (1 hour) to 900 (15 min) ***'
        )

        if app.isSimulation():
            app.sim_smartswitch = True

        app.notifyTelegram(
            app.getMarket() +
            " smart switch from granularity 3600 (1 hour) to 900 (15 min)")

        app.setGranularity(900)
        list(map(s.cancel, s.queue))
        s.enter(5, 1, executeJob, (sc, app, state))

    # use actual sim mode date to check smartchswitch
    if app.getSmartSwitch() == 1 and app.getGranularity(
    ) == 900 and app.is1hEMA1226Bull(
            current_sim_date) is False and app.is6hEMA1226Bull(
                current_sim_date) is False:
        Logger.info(
            "*** smart switch from granularity 900 (15 min) to 3600 (1 hour) ***"
        )

        if app.isSimulation():
            app.sim_smartswitch = True

        app.notifyTelegram(
            app.getMarket() +
            " smart switch from granularity 900 (15 min) to 3600 (1 hour)")

        app.setGranularity(3600)
        list(map(s.cancel, s.queue))
        s.enter(5, 1, executeJob, (sc, app, state))

    if app.getExchange() == 'binance' and app.getGranularity() == 86400:
        if len(df) < 250:
            # data frame should have 250 rows, if not retry
            Logger.error('error: data frame length is < 250 (' + str(len(df)) +
                         ')')
            list(map(s.cancel, s.queue))
            s.enter(300, 1, executeJob, (sc, app, state))
    else:
        if len(df) < 300:
            if not app.isSimulation():
                # data frame should have 300 rows, if not retry
                Logger.error('error: data frame length is < 300 (' +
                             str(len(df)) + ')')
                list(map(s.cancel, s.queue))
                s.enter(300, 1, executeJob, (sc, app, state))

    if len(df_last) > 0:
        now = datetime.today().strftime('%Y-%m-%d %H:%M:%S')

        # last_action polling if live
        if app.isLive():
            last_action_current = state.last_action
            state.pollLastAction()
            if last_action_current != state.last_action:
                Logger.info(
                    f'last_action change detected from {last_action_current} to {state.last_action}'
                )
                app.notifyTelegram(
                    f"{app.getMarket} last_action change detected from {last_action_current} to {state.last_action}"
                )

        if not app.isSimulation():
            ticker = app.getTicker(app.getMarket())
            now = ticker[0]
            price = ticker[1]
            if price < df_last['low'].values[0] or price == 0:
                price = float(df_last['close'].values[0])
        else:
            price = float(df_last['close'].values[0])

        if price < 0.0001:
            raise Exception(
                app.getMarket() +
                ' is unsuitable for trading, quote price is less than 0.0001!')

        # technical indicators
        ema12gtema26 = bool(df_last['ema12gtema26'].values[0])
        ema12gtema26co = bool(df_last['ema12gtema26co'].values[0])
        goldencross = bool(df_last['goldencross'].values[0])
        macdgtsignal = bool(df_last['macdgtsignal'].values[0])
        macdgtsignalco = bool(df_last['macdgtsignalco'].values[0])
        ema12ltema26 = bool(df_last['ema12ltema26'].values[0])
        ema12ltema26co = bool(df_last['ema12ltema26co'].values[0])
        macdltsignal = bool(df_last['macdltsignal'].values[0])
        macdltsignalco = bool(df_last['macdltsignalco'].values[0])
        obv = float(df_last['obv'].values[0])
        obv_pc = float(df_last['obv_pc'].values[0])
        elder_ray_buy = bool(df_last['eri_buy'].values[0])
        elder_ray_sell = bool(df_last['eri_sell'].values[0])

        # if simulation, set goldencross based on actual sim date
        if app.isSimulation():
            goldencross = app.is1hSMA50200Bull(current_sim_date)

        # if simulation interations < 200 set goldencross to true
        #if app.isSimulation() and state.iterations < 200:
        #    goldencross = True

        # candlestick detection
        hammer = bool(df_last['hammer'].values[0])
        inverted_hammer = bool(df_last['inverted_hammer'].values[0])
        hanging_man = bool(df_last['hanging_man'].values[0])
        shooting_star = bool(df_last['shooting_star'].values[0])
        three_white_soldiers = bool(df_last['three_white_soldiers'].values[0])
        three_black_crows = bool(df_last['three_black_crows'].values[0])
        morning_star = bool(df_last['morning_star'].values[0])
        evening_star = bool(df_last['evening_star'].values[0])
        three_line_strike = bool(df_last['three_line_strike'].values[0])
        abandoned_baby = bool(df_last['abandoned_baby'].values[0])
        morning_doji_star = bool(df_last['morning_doji_star'].values[0])
        evening_doji_star = bool(df_last['evening_doji_star'].values[0])
        two_black_gapping = bool(df_last['two_black_gapping'].values[0])

        strategy = Strategy(app, state, df, state.iterations)
        state.action = strategy.getAction()

        immediate_action = False
        margin, profit, sell_fee = 0, 0, 0

        if state.last_buy_size > 0 and state.last_buy_price > 0 and price > 0 and state.last_action == 'BUY':
            # update last buy high
            if price > state.last_buy_high:
                state.last_buy_high = price

            if state.last_buy_high > 0:
                change_pcnt_high = ((price / state.last_buy_high) - 1) * 100
            else:
                change_pcnt_high = 0

            # buy and sell calculations
            state.last_buy_fee = round(state.last_buy_size * app.getTakerFee(),
                                       8)
            state.last_buy_filled = round(
                ((state.last_buy_size - state.last_buy_fee) /
                 state.last_buy_price), 8)

            # if not a simulation, sync with exchange orders
            if not app.isSimulation():
                exchange_last_buy = app.getLastBuy()
                if exchange_last_buy is not None:
                    if state.last_buy_size != exchange_last_buy['size']:
                        state.last_buy_size = exchange_last_buy['size']
                    if state.last_buy_filled != exchange_last_buy['filled']:
                        state.last_buy_filled = exchange_last_buy['filled']
                    if state.last_buy_price != exchange_last_buy['price']:
                        state.last_buy_price = exchange_last_buy['price']

                    if app.getExchange() == 'coinbasepro':
                        if state.last_buy_fee != exchange_last_buy['fee']:
                            state.last_buy_fee = exchange_last_buy['fee']

            margin, profit, sell_fee = calculate_margin(
                buy_size=state.last_buy_size,
                buy_filled=state.last_buy_filled,
                buy_price=state.last_buy_price,
                buy_fee=state.last_buy_fee,
                sell_percent=app.getSellPercent(),
                sell_price=price,
                sell_taker_fee=app.getTakerFee())

            # handle immedate sell actions
            if strategy.isSellTrigger(price,
                                      technical_analysis.getTradeExit(price),
                                      margin, change_pcnt_high, obv_pc,
                                      macdltsignal):
                state.action = 'SELL'
                state.last_action = 'BUY'
                immediate_action = True

            # handle overriding wait actions (do not sell if sell at loss disabled!)
            if strategy.isWaitTrigger(margin):
                state.action = 'WAIT'
                state.last_action = 'BUY'
                immediate_action = False

        bullbeartext = ''
        if app.disableBullOnly() is True or (df_last['sma50'].values[0]
                                             == df_last['sma200'].values[0]):
            bullbeartext = ''
        elif goldencross is True:
            bullbeartext = ' (BULL)'
        elif goldencross is False:
            bullbeartext = ' (BEAR)'

        # polling is every 5 minutes (even for hourly intervals), but only process once per interval
        if (immediate_action is True
                or state.last_df_index != current_df_index):
            precision = 4

            if (price < 0.01):
                precision = 8

            # Since precision does not change after this point, it is safe to prepare a tailored `truncate()` that would
            # work with this precision. It should save a couple of `precision` uses, one for each `truncate()` call.
            truncate = functools.partial(_truncate, n=precision)

            price_text = 'Close: ' + truncate(price)
            ema_text = ''
            if app.disableBuyEMA() is False:
                ema_text = app.compare(df_last['ema12'].values[0],
                                       df_last['ema26'].values[0], 'EMA12/26',
                                       precision)

            macd_text = ''
            if app.disableBuyMACD() is False:
                macd_text = app.compare(df_last['macd'].values[0],
                                        df_last['signal'].values[0], 'MACD',
                                        precision)

            obv_text = ''
            if app.disableBuyOBV() is False:
                obv_text = 'OBV: ' + truncate(
                    df_last['obv'].values[0]) + ' (' + str(
                        truncate(df_last['obv_pc'].values[0])) + '%)'

            state.eri_text = ''
            if app.disableBuyElderRay() is False:
                if elder_ray_buy is True:
                    state.eri_text = 'ERI: buy | '
                elif elder_ray_sell is True:
                    state.eri_text = 'ERI: sell | '
                else:
                    state.eri_text = 'ERI: | '

            if hammer is True:
                log_text = '* Candlestick Detected: Hammer ("Weak - Reversal - Bullish Signal - Up")'
                Logger.info(log_text)

            if shooting_star is True:
                log_text = '* Candlestick Detected: Shooting Star ("Weak - Reversal - Bearish Pattern - Down")'
                Logger.info(log_text)

            if hanging_man is True:
                log_text = '* Candlestick Detected: Hanging Man ("Weak - Continuation - Bearish Pattern - Down")'
                Logger.info(log_text)

            if inverted_hammer is True:
                log_text = '* Candlestick Detected: Inverted Hammer ("Weak - Continuation - Bullish Pattern - Up")'
                Logger.info(log_text)

            if three_white_soldiers is True:
                log_text = '*** Candlestick Detected: Three White Soldiers ("Strong - Reversal - Bullish Pattern - Up")'
                Logger.info(log_text)

                app.notifyTelegram(app.getMarket() + ' (' +
                                   app.printGranularity() + ') ' + log_text)

            if three_black_crows is True:
                log_text = '* Candlestick Detected: Three Black Crows ("Strong - Reversal - Bearish Pattern - Down")'
                Logger.info(log_text)

                app.notifyTelegram(app.getMarket() + ' (' +
                                   app.printGranularity() + ') ' + log_text)

            if morning_star is True:
                log_text = '*** Candlestick Detected: Morning Star ("Strong - Reversal - Bullish Pattern - Up")'
                Logger.info(log_text)

                app.notifyTelegram(app.getMarket() + ' (' +
                                   app.printGranularity() + ') ' + log_text)

            if evening_star is True:
                log_text = '*** Candlestick Detected: Evening Star ("Strong - Reversal - Bearish Pattern - Down")'
                Logger.info(log_text)

                app.notifyTelegram(app.getMarket() + ' (' +
                                   app.printGranularity() + ') ' + log_text)

            if three_line_strike is True:
                log_text = '** Candlestick Detected: Three Line Strike ("Reliable - Reversal - Bullish Pattern - Up")'
                Logger.info(log_text)

                app.notifyTelegram(app.getMarket() + ' (' +
                                   app.printGranularity() + ') ' + log_text)

            if abandoned_baby is True:
                log_text = '** Candlestick Detected: Abandoned Baby ("Reliable - Reversal - Bullish Pattern - Up")'
                Logger.info(log_text)

                app.notifyTelegram(app.getMarket() + ' (' +
                                   app.printGranularity() + ') ' + log_text)

            if morning_doji_star is True:
                log_text = '** Candlestick Detected: Morning Doji Star ("Reliable - Reversal - Bullish Pattern - Up")'
                Logger.info(log_text)

                app.notifyTelegram(app.getMarket() + ' (' +
                                   app.printGranularity() + ') ' + log_text)

            if evening_doji_star is True:
                log_text = '** Candlestick Detected: Evening Doji Star ("Reliable - Reversal - Bearish Pattern - Down")'
                Logger.info(log_text)

                app.notifyTelegram(app.getMarket() + ' (' +
                                   app.printGranularity() + ') ' + log_text)

            if two_black_gapping is True:
                log_text = '*** Candlestick Detected: Two Black Gapping ("Reliable - Reversal - Bearish Pattern - Down")'
                Logger.info(log_text)

                app.notifyTelegram(app.getMarket() + ' (' +
                                   app.printGranularity() + ') ' + log_text)

            ema_co_prefix = ''
            ema_co_suffix = ''
            if app.disableBuyEMA() is False:
                if ema12gtema26co is True:
                    ema_co_prefix = '*^ '
                    ema_co_suffix = ' ^*'
                elif ema12ltema26co is True:
                    ema_co_prefix = '*v '
                    ema_co_suffix = ' v*'
                elif ema12gtema26 is True:
                    ema_co_prefix = '^ '
                    ema_co_suffix = ' ^'
                elif ema12ltema26 is True:
                    ema_co_prefix = 'v '
                    ema_co_suffix = ' v'

            macd_co_prefix = ''
            macd_co_suffix = ''
            if app.disableBuyMACD() is False:
                if macdgtsignalco is True:
                    macd_co_prefix = '*^ '
                    macd_co_suffix = ' ^*'
                elif macdltsignalco is True:
                    macd_co_prefix = '*v '
                    macd_co_suffix = ' v*'
                elif macdgtsignal is True:
                    macd_co_prefix = '^ '
                    macd_co_suffix = ' ^'
                elif macdltsignal is True:
                    macd_co_prefix = 'v '
                    macd_co_suffix = ' v'

            obv_prefix = ''
            obv_suffix = ''
            if app.disableBuyOBV() is False:
                if float(obv_pc) > 0:
                    obv_prefix = '^ '
                    obv_suffix = ' ^ | '
                elif float(obv_pc) < 0:
                    obv_prefix = 'v '
                    obv_suffix = ' v | '

            if not app.isVerbose():
                if state.last_action != '':
                    output_text = formatted_current_df_index + ' | ' + app.getMarket() + bullbeartext + ' | ' + \
                                  app.printGranularity() + ' | ' + price_text + ' | ' + ema_co_prefix + \
                                  ema_text + ema_co_suffix + ' | ' + macd_co_prefix + macd_text + macd_co_suffix + \
                                  obv_prefix + obv_text + obv_suffix + state.eri_text + ' | ' + state.action + \
                                  ' | Last Action: ' + state.last_action
                else:
                    output_text = formatted_current_df_index + ' | ' + app.getMarket() + bullbeartext + ' | ' + \
                                  app.printGranularity() + ' | ' + price_text + ' | ' + ema_co_prefix + \
                                  ema_text + ema_co_suffix + ' | ' + macd_co_prefix + macd_text + macd_co_suffix + \
                                  obv_prefix + obv_text + obv_suffix + state.eri_text + ' | ' + state.action + ' '

                if state.last_action == 'BUY':
                    if state.last_buy_size > 0:
                        margin_text = truncate(margin) + '%'
                    else:
                        margin_text = '0%'

                    output_text += ' | ' + margin_text + ' (delta: ' + str(
                        round(price - state.last_buy_price, precision)) + ')'

                Logger.info(output_text)

                # Seasonal Autoregressive Integrated Moving Average (ARIMA) model (ML prediction for 3 intervals from now)
                if not app.isSimulation():
                    try:
                        prediction = technical_analysis.seasonalARIMAModelPrediction(
                            int(app.getGranularity() / 60) *
                            3)  # 3 intervals from now
                        Logger.info(
                            f'Seasonal ARIMA model predicts the closing price will be {str(round(prediction[1], 2))} at {prediction[0]} (delta: {round(prediction[1] - price, 2)})'
                        )
                    except:
                        pass

                if state.last_action == 'BUY':
                    # display support, resistance and fibonacci levels
                    Logger.info(
                        technical_analysis.
                        printSupportResistanceFibonacciLevels(price))

            else:
                Logger.debug('-- Iteration: ' + str(state.iterations) + ' --' +
                             bullbeartext)

                if state.last_action == 'BUY':
                    if state.last_buy_size > 0:
                        margin_text = truncate(margin) + '%'
                    else:
                        margin_text = '0%'

                    Logger.debug('-- Margin: ' + margin_text + ' --')

                Logger.debug('price: ' + truncate(price))
                Logger.debug('ema12: ' +
                             truncate(float(df_last['ema12'].values[0])))
                Logger.debug('ema26: ' +
                             truncate(float(df_last['ema26'].values[0])))
                Logger.debug('ema12gtema26co: ' + str(ema12gtema26co))
                Logger.debug('ema12gtema26: ' + str(ema12gtema26))
                Logger.debug('ema12ltema26co: ' + str(ema12ltema26co))
                Logger.debug('ema12ltema26: ' + str(ema12ltema26))
                Logger.debug('sma50: ' +
                             truncate(float(df_last['sma50'].values[0])))
                Logger.debug('sma200: ' +
                             truncate(float(df_last['sma200'].values[0])))
                Logger.debug('macd: ' +
                             truncate(float(df_last['macd'].values[0])))
                Logger.debug('signal: ' +
                             truncate(float(df_last['signal'].values[0])))
                Logger.debug('macdgtsignal: ' + str(macdgtsignal))
                Logger.debug('macdltsignal: ' + str(macdltsignal))
                Logger.debug('obv: ' + str(obv))
                Logger.debug('obv_pc: ' + str(obv_pc))
                Logger.debug('action: ' + state.action)

                # informational output on the most recent entry
                Logger.info('')
                Logger.info(
                    '================================================================================'
                )
                txt = '        Iteration : ' + str(
                    state.iterations) + bullbeartext
                Logger.info(' | ' + txt + (' ' * (75 - len(txt))) + ' | ')
                txt = '        Timestamp : ' + str(df_last.index.format()[0])
                Logger.info(' | ' + txt + (' ' * (75 - len(txt))) + ' | ')
                Logger.info(
                    '--------------------------------------------------------------------------------'
                )
                txt = '            Close : ' + truncate(price)
                Logger.info(' | ' + txt + (' ' * (75 - len(txt))) + ' | ')
                txt = '            EMA12 : ' + truncate(
                    float(df_last['ema12'].values[0]))
                Logger.info(' | ' + txt + (' ' * (75 - len(txt))) + ' | ')
                txt = '            EMA26 : ' + truncate(
                    float(df_last['ema26'].values[0]))
                Logger.info(' | ' + txt + (' ' * (75 - len(txt))) + ' | ')
                txt = '   Crossing Above : ' + str(ema12gtema26co)
                Logger.info(' | ' + txt + (' ' * (75 - len(txt))) + ' | ')
                txt = '  Currently Above : ' + str(ema12gtema26)
                Logger.info(' | ' + txt + (' ' * (75 - len(txt))) + ' | ')
                txt = '   Crossing Below : ' + str(ema12ltema26co)
                Logger.info(' | ' + txt + (' ' * (75 - len(txt))) + ' | ')
                txt = '  Currently Below : ' + str(ema12ltema26)
                Logger.info(' | ' + txt + (' ' * (75 - len(txt))) + ' | ')

                if (ema12gtema26 is True and ema12gtema26co is True):
                    txt = '        Condition : EMA12 is currently crossing above EMA26'
                elif (ema12gtema26 is True and ema12gtema26co is False):
                    txt = '        Condition : EMA12 is currently above EMA26 and has crossed over'
                elif (ema12ltema26 is True and ema12ltema26co is True):
                    txt = '        Condition : EMA12 is currently crossing below EMA26'
                elif (ema12ltema26 is True and ema12ltema26co is False):
                    txt = '        Condition : EMA12 is currently below EMA26 and has crossed over'
                else:
                    txt = '        Condition : -'
                Logger.info(' | ' + txt + (' ' * (75 - len(txt))) + ' | ')

                txt = '            SMA20 : ' + truncate(
                    float(df_last['sma20'].values[0]))
                Logger.info(' | ' + txt + (' ' * (75 - len(txt))) + ' | ')
                txt = '           SMA200 : ' + truncate(
                    float(df_last['sma200'].values[0]))
                Logger.info(' | ' + txt + (' ' * (75 - len(txt))) + ' | ')

                Logger.info(
                    '--------------------------------------------------------------------------------'
                )
                txt = '             MACD : ' + truncate(
                    float(df_last['macd'].values[0]))
                Logger.info(' | ' + txt + (' ' * (75 - len(txt))) + ' | ')
                txt = '           Signal : ' + truncate(
                    float(df_last['signal'].values[0]))
                Logger.info(' | ' + txt + (' ' * (75 - len(txt))) + ' | ')
                txt = '  Currently Above : ' + str(macdgtsignal)
                Logger.info(' | ' + txt + (' ' * (75 - len(txt))) + ' | ')
                txt = '  Currently Below : ' + str(macdltsignal)
                Logger.info(' | ' + txt + (' ' * (75 - len(txt))) + ' | ')

                if (macdgtsignal is True and macdgtsignalco is True):
                    txt = '        Condition : MACD is currently crossing above Signal'
                elif (macdgtsignal is True and macdgtsignalco is False):
                    txt = '        Condition : MACD is currently above Signal and has crossed over'
                elif (macdltsignal is True and macdltsignalco is True):
                    txt = '        Condition : MACD is currently crossing below Signal'
                elif (macdltsignal is True and macdltsignalco is False):
                    txt = '        Condition : MACD is currently below Signal and has crossed over'
                else:
                    txt = '        Condition : -'
                Logger.info(' | ' + txt + (' ' * (75 - len(txt))) + ' | ')

                Logger.info(
                    '--------------------------------------------------------------------------------'
                )
                txt = '           Action : ' + state.action
                Logger.info(' | ' + txt + (' ' * (75 - len(txt))) + ' | ')
                Logger.info(
                    '================================================================================'
                )
                if state.last_action == 'BUY':
                    txt = '           Margin : ' + margin_text
                    Logger.info(' | ' + txt + (' ' * (75 - len(txt))) + ' | ')
                    Logger.info(
                        '================================================================================'
                    )

            # if a buy signal
            if state.action == 'BUY':
                state.last_buy_price = price
                state.last_buy_high = state.last_buy_price

                # if live
                if app.isLive():
                    app.notifyTelegram(app.getMarket() + ' (' +
                                       app.printGranularity() + ') BUY at ' +
                                       price_text)

                    if not app.isVerbose():
                        Logger.info(formatted_current_df_index + ' | ' +
                                    app.getMarket() + ' | ' +
                                    app.printGranularity() + ' | ' +
                                    price_text + ' | BUY')
                    else:
                        Logger.info(
                            '--------------------------------------------------------------------------------'
                        )
                        Logger.info(
                            '|                      *** Executing LIVE Buy Order ***                        |'
                        )
                        Logger.info(
                            '--------------------------------------------------------------------------------'
                        )

                    # display balances
                    Logger.info(app.getBaseCurrency() +
                                ' balance before order: ' +
                                str(account.getBalance(app.getBaseCurrency())))
                    Logger.info(
                        app.getQuoteCurrency() + ' balance before order: ' +
                        str(account.getBalance(app.getQuoteCurrency())))

                    # execute a live market buy
                    state.last_buy_size = float(
                        account.getBalance(app.getQuoteCurrency()))
                    if app.getBuyMaxSize(
                    ) and state.last_buy_size > app.getBuyMaxSize():
                        state.last_buy_size = app.getBuyMaxSize()

                    resp = app.marketBuy(app.getMarket(), state.last_buy_size,
                                         app.getBuyPercent())
                    Logger.debug(resp)

                    # display balances
                    Logger.info(app.getBaseCurrency() +
                                ' balance after order: ' +
                                str(account.getBalance(app.getBaseCurrency())))
                    Logger.info(
                        app.getQuoteCurrency() + ' balance after order: ' +
                        str(account.getBalance(app.getQuoteCurrency())))
                # if not live
                else:
                    app.notifyTelegram(app.getMarket() + ' (' +
                                       app.printGranularity() +
                                       ') TEST BUY at ' + price_text)
                    # TODO: Improve simulator calculations by including calculations for buy and sell limit configurations.
                    if state.last_buy_size == 0 and state.last_buy_filled == 0:
                        state.last_buy_size = 1000
                        state.first_buy_size = 1000

                    state.buy_count = state.buy_count + 1
                    state.buy_sum = state.buy_sum + state.last_buy_size

                    if not app.isVerbose():
                        Logger.info(formatted_current_df_index + ' | ' +
                                    app.getMarket() + ' | ' +
                                    app.printGranularity() + ' | ' +
                                    price_text + ' | BUY')

                        bands = technical_analysis.getFibonacciRetracementLevels(
                            float(price))
                        Logger.info(' Fibonacci Retracement Levels:' +
                                    str(bands))
                        technical_analysis.printSupportResistanceLevel(
                            float(price))

                        if len(bands) >= 1 and len(bands) <= 2:
                            if len(bands) == 1:
                                first_key = list(bands.keys())[0]
                                if first_key == 'ratio1':
                                    state.fib_low = 0
                                    state.fib_high = bands[first_key]
                                if first_key == 'ratio1_618':
                                    state.fib_low = bands[first_key]
                                    state.fib_high = bands[first_key] * 2
                                else:
                                    state.fib_low = bands[first_key]

                            elif len(bands) == 2:
                                first_key = list(bands.keys())[0]
                                second_key = list(bands.keys())[1]
                                state.fib_low = bands[first_key]
                                state.fib_high = bands[second_key]

                    else:
                        Logger.info(
                            '--------------------------------------------------------------------------------'
                        )
                        Logger.info(
                            '|                      *** Executing TEST Buy Order ***                        |'
                        )
                        Logger.info(
                            '--------------------------------------------------------------------------------'
                        )

                if app.shouldSaveGraphs():
                    tradinggraphs = TradingGraphs(technical_analysis)
                    ts = datetime.now().timestamp()
                    filename = app.getMarket() + '_' + app.printGranularity(
                    ) + '_buy_' + str(ts) + '.png'
                    tradinggraphs.renderEMAandMACD(len(trading_data),
                                                   'graphs/' + filename, True)

            # if a sell signal
            elif state.action == 'SELL':
                # if live
                if app.isLive():
                    app.notifyTelegram(
                        app.getMarket() + ' (' + app.printGranularity() +
                        ') SELL at ' + price_text + ' (margin: ' +
                        margin_text + ', (delta: ' +
                        str(round(price - state.last_buy_price, precision)) +
                        ')')

                    if not app.isVerbose():
                        Logger.info(formatted_current_df_index + ' | ' +
                                    app.getMarket() + ' | ' +
                                    app.printGranularity() + ' | ' +
                                    price_text + ' | SELL')

                        bands = technical_analysis.getFibonacciRetracementLevels(
                            float(price))
                        Logger.info(' Fibonacci Retracement Levels:' +
                                    str(bands))

                        if len(bands) >= 1 and len(bands) <= 2:
                            if len(bands) == 1:
                                first_key = list(bands.keys())[0]
                                if first_key == 'ratio1':
                                    state.fib_low = 0
                                    state.fib_high = bands[first_key]
                                if first_key == 'ratio1_618':
                                    state.fib_low = bands[first_key]
                                    state.fib_high = bands[first_key] * 2
                                else:
                                    state.fib_low = bands[first_key]

                            elif len(bands) == 2:
                                first_key = list(bands.keys())[0]
                                second_key = list(bands.keys())[1]
                                state.fib_low = bands[first_key]
                                state.fib_high = bands[second_key]

                    else:
                        Logger.info(
                            '--------------------------------------------------------------------------------'
                        )
                        Logger.info(
                            '|                      *** Executing LIVE Sell Order ***                        |'
                        )
                        Logger.info(
                            '--------------------------------------------------------------------------------'
                        )

                    # display balances
                    Logger.info(app.getBaseCurrency() +
                                ' balance before order: ' +
                                str(account.getBalance(app.getBaseCurrency())))
                    Logger.info(
                        app.getQuoteCurrency() + ' balance before order: ' +
                        str(account.getBalance(app.getQuoteCurrency())))

                    # execute a live market sell
                    resp = app.marketSell(
                        app.getMarket(),
                        float(account.getBalance(app.getBaseCurrency())),
                        app.getSellPercent())
                    Logger.debug(resp)

                    # display balances
                    Logger.info(app.getBaseCurrency() +
                                ' balance after order: ' +
                                str(account.getBalance(app.getBaseCurrency())))
                    Logger.info(
                        app.getQuoteCurrency() + ' balance after order: ' +
                        str(account.getBalance(app.getQuoteCurrency())))

                # if not live
                else:
                    margin, profit, sell_fee = calculate_margin(
                        buy_size=state.last_buy_size,
                        buy_filled=state.last_buy_filled,
                        buy_price=state.last_buy_price,
                        buy_fee=state.last_buy_fee,
                        sell_percent=app.getSellPercent(),
                        sell_price=price,
                        sell_taker_fee=app.getTakerFee())

                    if state.last_buy_size > 0:
                        margin_text = truncate(margin) + '%'
                    else:
                        margin_text = '0%'
                    app.notifyTelegram(
                        app.getMarket() + ' (' + app.printGranularity() +
                        ') TEST SELL at ' + price_text + ' (margin: ' +
                        margin_text + ', (delta: ' +
                        str(round(price - state.last_buy_price, precision)) +
                        ')')

                    # Preserve next buy values for simulator
                    state.sell_count = state.sell_count + 1
                    buy_size = ((app.getSellPercent() / 100) *
                                ((price / state.last_buy_price) *
                                 (state.last_buy_size - state.last_buy_fee)))
                    state.last_buy_size = buy_size - sell_fee
                    state.sell_sum = state.sell_sum + state.last_buy_size

                    if not app.isVerbose():
                        if price > 0:
                            margin_text = truncate(margin) + '%'
                        else:
                            margin_text = '0%'

                        Logger.info(formatted_current_df_index + ' | ' +
                                    app.getMarket() + ' | ' +
                                    app.printGranularity() + ' | SELL | ' +
                                    str(price) + ' | BUY | ' +
                                    str(state.last_buy_price) + ' | DIFF | ' +
                                    str(price - state.last_buy_price) +
                                    ' | DIFF | ' + str(profit) +
                                    ' | MARGIN NO FEES | ' + margin_text +
                                    ' | MARGIN FEES | ' +
                                    str(round(sell_fee, precision)))

                    else:
                        Logger.info(
                            '--------------------------------------------------------------------------------'
                        )
                        Logger.info(
                            '|                      *** Executing TEST Sell Order ***                        |'
                        )
                        Logger.info(
                            '--------------------------------------------------------------------------------'
                        )

                if app.shouldSaveGraphs():
                    tradinggraphs = TradingGraphs(technical_analysis)
                    ts = datetime.now().timestamp()
                    filename = app.getMarket() + '_' + app.printGranularity(
                    ) + '_sell_' + str(ts) + '.png'
                    tradinggraphs.renderEMAandMACD(len(trading_data),
                                                   'graphs/' + filename, True)

            # last significant action
            if state.action in ['BUY', 'SELL']:
                state.last_action = state.action

            state.last_df_index = str(df_last.index.format()[0])

            if not app.isLive() and state.iterations == len(df):
                Logger.info("\nSimulation Summary: ")

                if state.buy_count > state.sell_count and app.allowSellAtLoss(
                ):
                    # Calculate last sell size
                    state.last_buy_size = ((app.getSellPercent() / 100) * (
                        (price / state.last_buy_price) *
                        (state.last_buy_size - state.last_buy_fee)))
                    # Reduce sell fee from last sell size
                    state.last_buy_size = state.last_buy_size - state.last_buy_price * app.getTakerFee(
                    )
                    state.sell_sum = state.sell_sum + state.last_buy_size
                    state.sell_count = state.sell_count + 1

                elif state.buy_count > state.sell_count and not app.allowSellAtLoss(
                ):
                    Logger.info("\n")
                    Logger.info(
                        '        Note : "sell at loss" is disabled and you have an open trade, if the margin'
                    )
                    Logger.info(
                        '               result below is negative it will assume you sold at the end of the'
                    )
                    Logger.info(
                        '               simulation which may not be ideal. Try setting --sellatloss 1'
                    )

                Logger.info("\n")
                Logger.info('   Buy Count : ' + str(state.buy_count))
                Logger.info('  Sell Count : ' + str(state.sell_count))
                Logger.info('   First Buy : ' + str(state.first_buy_size))
                Logger.info('   Last Sell : ' + str(state.last_buy_size))

                app.notifyTelegram(
                    f"Simulation Summary\n   Buy Count: {state.buy_count}\n   Sell Count: {state.sell_count}\n   First Buy: {state.first_buy_size}\n   Last Sell: {state.last_buy_size}\n"
                )

                if state.sell_count > 0:
                    Logger.info("\n")
                    Logger.info('      Margin : ' + _truncate((
                        ((state.last_buy_size - state.first_buy_size) /
                         state.first_buy_size) * 100), 4) + '%')
                    Logger.info("\n")
                    Logger.info(
                        '  ** non-live simulation, assuming highest fees')
                    app.notifyTelegram(
                        f"      Margin: {_truncate((((state.last_buy_size - state.first_buy_size) / state.first_buy_size) * 100), 4)}%\n  ** non-live simulation, assuming highest fees\n"
                    )

        else:
            if state.last_buy_size > 0 and state.last_buy_price > 0 and price > 0 and state.last_action == 'BUY':
                # show profit and margin if already bought
                Logger.info(now + ' | ' + app.getMarket() + bullbeartext +
                            ' | ' + app.printGranularity() +
                            ' | Current Price: ' + str(price) + ' | Margin: ' +
                            str(margin) + ' | Profit: ' + str(profit))
            else:
                Logger.info(now + ' | ' + app.getMarket() + bullbeartext +
                            ' | ' + app.printGranularity() +
                            ' | Current Price: ' + str(price))

            # decrement ignored iteration
            state.iterations = state.iterations - 1

        # if live
        if not app.disableTracker() and app.isLive():
            # update order tracker csv
            if app.getExchange() == 'binance':
                account.saveTrackerCSV(app.getMarket())
            elif app.getExchange() == 'coinbasepro':
                account.saveTrackerCSV()

        if app.isSimulation():
            if state.iterations < 300:
                if app.simuluationSpeed() in ['fast', 'fast-sample']:
                    # fast processing
                    list(map(s.cancel, s.queue))
                    s.enter(0, 1, executeJob, (sc, app, state, df))
                else:
                    # slow processing
                    list(map(s.cancel, s.queue))
                    s.enter(1, 1, executeJob, (sc, app, state, df))

        else:
            # poll every 1 minute
            list(map(s.cancel, s.queue))
            s.enter(60, 1, executeJob, (sc, app, state))
Esempio n. 19
0
    def renderSeasonalARIMAModelPrediction(self, days=30, saveOnly=False):
        """Render the seasonal ARIMA model prediction

        Parameters
        ----------
        days     : int
            Number of days to predict
        saveOnly : bool
            Save the figure without displaying it
        """

        # get dataframe from technical analysis object
        df = self.technical_analysis.getDataFrame()

        if not isinstance(days, int):
            raise TypeError("Prediction days is not numeric.")

        if days < 1 or days > len(df):
            raise ValueError("Predication days is out of range")

        # extract market and granularity from trading dataframe
        market = df.iloc[0].market
        granularity = df.iloc[0].granularity

        results_ARIMA = self.technical_analysis.seasonalARIMAModel()

        df = pd.DataFrame(self.df["close"])
        start_date = df.last_valid_index()
        end_date = start_date + datetime.timedelta(days=days)
        pred = results_ARIMA.predict(start=str(start_date),
                                     end=str(end_date),
                                     dynamic=True)

        fig, axes = plt.subplots(ncols=1, figsize=(12, 6))  # pylint: disable=unused-variable
        fig.autofmt_xdate()
        ax1 = plt.subplot(111)
        ax1.set_title("Seasonal ARIMA Model Prediction")

        date = pd.to_datetime(pred.index).to_pydatetime()

        pred_length = len(pred)
        # the evenly spaced plot indices
        indices = np.arange(pred_length)  # pylint: disable=unused-variable

        def format_date(x, pos=None):  # pylint: disable=unused-argument
            thisind = np.clip(int(x + 0.5), 0, pred_length - 1)
            return date[thisind].strftime("%Y-%m-%d %H:%M:%S")

        fig, ax = plt.subplots(ncols=1, figsize=(12, 6))  # pylint: disable=unused-variable
        fig.autofmt_xdate()

        ax = plt.subplot(111)
        ax.set_title("Seasonal ARIMA Model Prediction")
        ax.plot(pred, label="prediction", color="black")
        ax.xaxis.set_major_formatter(ticker.FuncFormatter(format_date))

        plt.xticks(rotation=90)
        plt.tight_layout()

        try:
            Logger.info(
                f"creating: graphs/SAM_{market}_{str(granularity)}.png")
            plt.savefig(f"graphs/SAM_{market}_{str(granularity)}.png", dpi=300)
        except OSError:
            raise SystemExit(
                f"Unable to save: graphs/SAM_{market}_{str(granularity)}.png")

        if saveOnly is False:
            plt.show()
Esempio n. 20
0
    def show(self):
        if self.app.getStats():
            # get completed live orders
            self.app.setLive(1)
            self.orders = self.account.getOrders(self.app.getMarket(), '',
                                                 'done')

            # get buy/sell pairs (merge as necessary)
            order_pairs = []
            last_order = None
            # pylint: disable=unused-variable
            for index, row in self.orders.iterrows():
                time = row['created_at'].to_pydatetime()
                if row['action'] == 'buy':
                    if last_order in ['sell', None]:
                        last_order = 'buy'
                        order_pairs.append({
                            'buy': {
                                'time': time,
                                'size': row['size']
                            },
                            'sell': None
                        })
                    else:
                        last_order = 'buy'
                        order_pairs[-1]['buy']['size'] += row['size']
                else:
                    if last_order == None:  # first order is a sell (no pair)
                        continue
                    if last_order == 'buy':
                        last_order = 'sell'
                        order_pairs[-1]['sell'] = {
                            'time': time,
                            'size': row['size']
                        }
                    else:
                        order_pairs[-1]['sell']['size'] += row['size']

            # remove open trade
            if len(order_pairs) > 0:
                if order_pairs[-1]['sell'] == None:
                    order_pairs = order_pairs[:-1]

            # get % gains and delta
            for pair in order_pairs:
                pair['gain'] = ((pair['sell']['size'] - pair['buy']['size']) /
                                pair['buy']['size']) * 100
                pair['delta'] = pair['sell']['size'] - pair['buy']['size']

            # get day/week/month/all time totals
            totals = {'today': [], 'week': [], 'month': [], 'all_time': []}
            today = datetime.today().date()
            lastweek = today - timedelta(days=7)
            lastmonth = today - timedelta(days=30)
            for pair in order_pairs:
                totals['all_time'].append(pair)
                if pair['sell']['time'].date() == today:
                    totals['today'].append(pair)
                if pair['sell']['time'].date() > lastweek:
                    totals['week'].append(pair)
                if pair['sell']['time'].date() > lastmonth:
                    totals['month'].append(pair)

            # prepare data for output
            today_per = [x['gain'] for x in totals['today']]
            week_per = [x['gain'] for x in totals['week']]
            month_per = [x['gain'] for x in totals['month']]
            all_time_per = [x['gain'] for x in totals['all_time']]
            today_gain = [x['delta'] for x in totals['today']]
            week_gain = [x['delta'] for x in totals['week']]
            month_gain = [x['delta'] for x in totals['month']]
            all_time_gain = [x['delta'] for x in totals['all_time']]

            if len(today_per) > 0:
                today_delta = [
                    (x['sell']['time'] - x['buy']['time']).total_seconds()
                    for x in totals['today']
                ]
                today_delta = timedelta(
                    seconds=int(sum(today_delta) / len(today_delta)))
            else:
                today_delta = '0:0:0'
            if len(week_per) > 0:
                week_delta = [
                    (x['sell']['time'] - x['buy']['time']).total_seconds()
                    for x in totals['week']
                ]
                week_delta = timedelta(
                    seconds=int(sum(week_delta) / len(week_delta)))
            else:
                week_delta = '0:0:0'
            if len(month_per) > 0:
                month_delta = [
                    (x['sell']['time'] - x['buy']['time']).total_seconds()
                    for x in totals['month']
                ]
                month_delta = timedelta(
                    seconds=int(sum(month_delta) / len(month_delta)))
            else:
                month_delta = '0:0:0'
            if len(all_time_per) > 0:
                all_time_delta = [
                    (x['sell']['time'] - x['buy']['time']).total_seconds()
                    for x in totals['all_time']
                ]
                all_time_delta = timedelta(
                    seconds=int(sum(all_time_delta) / len(all_time_delta)))
            else:
                all_time_delta = '0:0:0'

            # popular currencies
            symbol = self.app.getQuoteCurrency()
            if symbol in ['USD', 'AUD', 'CAD', 'SGD', 'NZD']: symbol = '$'
            if symbol == 'EUR': symbol = '€'
            if symbol == 'GBP': symbol = '£'

            today_sum = symbol + ' {:.2f}'.format(round(sum(
                today_gain), 2)) if len(today_gain) > 0 else symbol + ' 0.00'
            week_sum = symbol + ' {:.2f}'.format(round(
                sum(week_gain), 2)) if len(week_gain) > 0 else symbol + ' 0.00'
            month_sum = symbol + ' {:.2f}'.format(round(sum(
                month_gain), 2)) if len(month_gain) > 0 else symbol + ' 0.00'
            all_time_sum = symbol + ' {:.2f}'.format(
                round(sum(all_time_gain),
                      2)) if len(all_time_gain) > 0 else symbol + ' 0.00'
            today_percent = str(round(
                sum(today_per), 4)) + '%' if len(today_per) > 0 else '0.0000%'
            week_percent = str(round(
                sum(week_per), 4)) + '%' if len(week_per) > 0 else '0.0000%'
            month_percent = str(round(
                sum(month_per), 4)) + '%' if len(month_per) > 0 else '0.0000%'
            all_time_percent = str(round(sum(all_time_per), 4)) + '%' if len(
                all_time_per) > 0 else '0.0000%'

            trades = 'Number of Completed Trades:'
            gains = 'Percentage Gains:'
            aver = 'Average Time Held (H:M:S):'
            success = 'Total Profit/Loss:'
            width = 30

            Logger.info(
                f'------------- TODAY : {self.app.getMarket()} --------------')
            Logger.info(trades + ' ' * (width - len(trades)) +
                        str(len(today_per)))
            Logger.info(gains + ' ' * (width - len(gains)) + today_percent)
            Logger.info(aver + ' ' * (width - len(aver)) + str(today_delta))
            Logger.info(success + ' ' * (width - len(success)) + today_sum)
            Logger.info(
                f'\n-------------- WEEK : {self.app.getMarket()} --------------'
            )
            Logger.info(trades + ' ' * (width - len(trades)) +
                        str(len(week_per)))
            Logger.info(gains + ' ' * (width - len(gains)) + week_percent)
            Logger.info(aver + ' ' * (width - len(aver)) + str(week_delta))
            Logger.info(success + ' ' * (width - len(success)) + week_sum)
            Logger.info(
                f'\n------------- MONTH : {self.app.getMarket()} --------------'
            )
            Logger.info(trades + ' ' * (width - len(trades)) +
                        str(len(month_per)))
            Logger.info(gains + ' ' * (width - len(gains)) + month_percent)
            Logger.info(aver + ' ' * (width - len(aver)) + str(month_delta))
            Logger.info(success + ' ' * (width - len(success)) + month_sum)
            Logger.info(
                f'\n------------ ALL TIME : {self.app.getMarket()} ------------'
            )
            Logger.info(trades + ' ' * (width - len(trades)) +
                        str(len(all_time_per)))
            Logger.info(gains + ' ' * (width - len(gains)) + all_time_percent)
            Logger.info(aver + ' ' * (width - len(aver)) + str(all_time_delta))
            Logger.info(success + ' ' * (width - len(success)) + all_time_sum)

            sys.exit()
Esempio n. 21
0
    def renderCandlestickAstralPattern(self, period=30, saveOnly=False):
        # get dataframe from technical analysis object
        df = self.technical_analysis.getDataFrame()

        if not isinstance(period, int):
            raise TypeError("Period parameter is not perioderic.")

        if period < 1 or period > len(df):
            raise ValueError("Period is out of range")

        # extract market and granularity from trading dataframe
        market = df.iloc[0].market
        granularity = df.iloc[0].granularity

        df_subset = df.iloc[-period::]

        fig, axes = plt.subplots(ncols=1, figsize=(12, 6))  # pylint: disable=unused-variable
        fig.autofmt_xdate()
        ax1 = plt.subplot(111)
        ax1.set_title("Astral Candlestick Pattern")
        plt.plot(df_subset["close"], label="price", color="black")
        plt.plot(df_subset["ema12"], label="ema12", color="orange")
        plt.plot(df_subset["ema26"], label="ema26", color="purple")
        plt.tick_params(axis="x",
                        which="both",
                        bottom=False,
                        top=False,
                        labelbottom=False)

        df_candlestick = self.df[self.df["astral_buy"] is True]
        df_candlestick_in_range = df_candlestick[
            df_candlestick.index >= np.min(df_subset.index)]
        for idx in df_candlestick_in_range.index.tolist():
            plt.plot(idx,
                     df_candlestick_in_range.loc[idx]["close"],
                     "g^",
                     markersize=8)

        df_candlestick = self.df[self.df["astral_sell"] is True]
        df_candlestick_in_range = df_candlestick[
            df_candlestick.index >= np.min(df_subset.index)]
        for idx in df_candlestick_in_range.index.tolist():
            plt.plot(idx,
                     df_candlestick_in_range.loc[idx]["close"],
                     "rv",
                     markersize=8)

        plt.xlabel(market + " - " + str(granularity))
        plt.ylabel("Price")
        plt.xticks(rotation=90)
        plt.tight_layout()
        plt.legend()

        try:
            Logger.info(
                f"creating: graphs/CAP_{market}_{str(granularity)}.png")
            plt.savefig(f"graphs/CAP_{market}_{str(granularity)}.png", dpi=300)
        except OSError:
            raise SystemExit(
                f"Unable to save: graphs/CAP_{market}_{str(granularity)}.png")

        if saveOnly is False:
            plt.show()
Esempio n. 22
0
    def renderCandlesticks(self, period=30, saveOnly=False):
        # get dataframe from technical analysis object
        df = self.technical_analysis.getDataFrame()

        if not isinstance(period, int):
            raise TypeError('Period parameter is not perioderic.')

        if period < 1 or period > len(df):
            raise ValueError('Period is out of range')

        # extract market and granularity from trading dataframe
        market = df.iloc[0].market
        granularity = df.iloc[0].granularity

        df_subset = df.iloc[-period::]

        fig, axes = plt.subplots(ncols=1, figsize=(12, 6))  #pylint: disable=unused-variable
        fig.autofmt_xdate()
        ax1 = plt.subplot(111)
        ax1.set_title('Candlestick Patterns')
        plt.plot(df_subset['close'], label='price', color='black')
        plt.plot(df_subset['ema12'], label='ema12', color='orange')
        plt.plot(df_subset['ema26'], label='ema26', color='purple')
        plt.tick_params(axis='x',
                        which='both',
                        bottom=False,
                        top=False,
                        labelbottom=False)

        df_candlestick = self.df[self.df['three_white_soldiers'] is True]
        df_candlestick_in_range = df_candlestick[
            df_candlestick.index >= np.min(df_subset.index)]
        for idx in df_candlestick_in_range.index.tolist():
            plt.plot(idx,
                     df_candlestick_in_range.loc[idx]['close'],
                     'g*',
                     markersize=10,
                     label='Three White Soldiers')

        df_candlestick = self.df[self.df['three_black_crows'] is True]
        df_candlestick_in_range = df_candlestick[
            df_candlestick.index >= np.min(df_subset.index)]
        for idx in df_candlestick_in_range.index.tolist():
            plt.plot(idx,
                     df_candlestick_in_range.loc[idx]['close'],
                     'r*',
                     markersize=10,
                     label='Three Black Crows')

        df_candlestick = self.df[self.df['inverted_hammer'] is True]
        df_candlestick_in_range = df_candlestick[
            df_candlestick.index >= np.min(df_subset.index)]
        for idx in df_candlestick_in_range.index.tolist():
            plt.plot(idx,
                     df_candlestick_in_range.loc[idx]['close'],
                     'g*',
                     markersize=10,
                     label='Inverted Hammer')

        df_candlestick = self.df[self.df['hammer'] is True]
        df_candlestick_in_range = df_candlestick[
            df_candlestick.index >= np.min(df_subset.index)]
        for idx in df_candlestick_in_range.index.tolist():
            plt.plot(idx,
                     df_candlestick_in_range.loc[idx]['close'],
                     'g*',
                     markersize=10,
                     label='Hammer')

        df_candlestick = self.df[self.df['hanging_man'] is True]
        df_candlestick_in_range = df_candlestick[
            df_candlestick.index >= np.min(df_subset.index)]
        for idx in df_candlestick_in_range.index.tolist():
            plt.plot(idx,
                     df_candlestick_in_range.loc[idx]['close'],
                     'r*',
                     markersize=10,
                     label='Hanging Man')

        df_candlestick = self.df[self.df['shooting_star'] is True]
        df_candlestick_in_range = df_candlestick[
            df_candlestick.index >= np.min(df_subset.index)]
        for idx in df_candlestick_in_range.index.tolist():
            plt.plot(idx,
                     df_candlestick_in_range.loc[idx]['close'],
                     'r*',
                     markersize=10,
                     label='Shooting Star')

        df_candlestick = self.df[self.df['doji'] is True]
        df_candlestick_in_range = df_candlestick[
            df_candlestick.index >= np.min(df_subset.index)]
        for idx in df_candlestick_in_range.index.tolist():
            plt.plot(idx,
                     df_candlestick_in_range.loc[idx]['close'],
                     'b*',
                     markersize=10,
                     label='Doji')

        df_candlestick = self.df[self.df['three_line_strike'] is True]
        df_candlestick_in_range = df_candlestick[
            df_candlestick.index >= np.min(df_subset.index)]
        for idx in df_candlestick_in_range.index.tolist():
            plt.plot(idx,
                     df_candlestick_in_range.loc[idx]['close'],
                     'g*',
                     markersize=10,
                     label='Three Line Strike')

        df_candlestick = self.df[self.df['two_black_gapping'] is True]
        df_candlestick_in_range = df_candlestick[
            df_candlestick.index >= np.min(df_subset.index)]
        for idx in df_candlestick_in_range.index.tolist():
            plt.plot(idx,
                     df_candlestick_in_range.loc[idx]['close'],
                     'r*',
                     markersize=10,
                     label='Two Black Gapping')

        df_candlestick = self.df[self.df['morning_star'] is True]
        df_candlestick_in_range = df_candlestick[
            df_candlestick.index >= np.min(df_subset.index)]
        for idx in df_candlestick_in_range.index.tolist():
            plt.plot(idx,
                     df_candlestick_in_range.loc[idx]['close'],
                     'g*',
                     markersize=10,
                     label='Morning Star')

        df_candlestick = self.df[self.df['evening_star'] is True]
        df_candlestick_in_range = df_candlestick[
            df_candlestick.index >= np.min(df_subset.index)]
        for idx in df_candlestick_in_range.index.tolist():
            plt.plot(idx,
                     df_candlestick_in_range.loc[idx]['close'],
                     'r*',
                     markersize=10,
                     label='Evening Star')

        df_candlestick = self.df[self.df['morning_doji_star'] is True]
        df_candlestick_in_range = df_candlestick[
            df_candlestick.index >= np.min(df_subset.index)]
        for idx in df_candlestick_in_range.index.tolist():
            plt.plot(idx,
                     df_candlestick_in_range.loc[idx]['close'],
                     'g*',
                     markersize=10,
                     label='Morning Doji Star')

        df_candlestick = self.df[self.df['evening_doji_star'] is True]
        df_candlestick_in_range = df_candlestick[
            df_candlestick.index >= np.min(df_subset.index)]
        for idx in df_candlestick_in_range.index.tolist():
            plt.plot(idx,
                     df_candlestick_in_range.loc[idx]['close'],
                     'r*',
                     markersize=10,
                     label='Evening Doji Star')

        df_candlestick = self.df[self.df['abandoned_baby'] is True]
        df_candlestick_in_range = df_candlestick[
            df_candlestick.index >= np.min(df_subset.index)]
        for idx in df_candlestick_in_range.index.tolist():
            plt.plot(idx,
                     df_candlestick_in_range.loc[idx]['close'],
                     'g*',
                     markersize=10,
                     label='Abandoned Baby')

        plt.xlabel(market + ' - ' + str(granularity))
        plt.ylabel('Price')
        plt.xticks(rotation=90)
        plt.tight_layout()
        plt.legend()

        try:
            Logger.info('creating: graphs/CSP_' + market + '_' +
                        str(granularity) + '.png')
            plt.savefig('graphs/CSP_' + market + '_' + str(granularity) +
                        '.png',
                        dpi=300)
        except OSError:
            raise SystemExit('Unable to save: graphs/CSP_' + market + '_' +
                             str(granularity) + '.png')

        if saveOnly is False:
            plt.show()
Esempio n. 23
0
    def renderFibonacciRetracement(self, saveOnly=False):
        """Render Fibonacci Retracement Levels

        Parameters
        ----------
        saveOnly : bool
            Save the figure without displaying it
        """

        # get dataframe from technical analysis object
        df = self.technical_analysis.getDataFrame()

        # extract market and granularity from trading dataframe
        market = df.iloc[0].market
        granularity = df.iloc[0].granularity

        # closing price min and max values
        price_min = df.close.min()
        price_max = df.close.max()

        # fibonacci retracement levels
        diff = price_max - price_min
        level1 = price_max - 0.236 * diff
        level2 = price_max - 0.382 * diff
        level3 = price_max - 0.618 * diff

        fig, ax = plt.subplots(ncols=1, figsize=(12, 6))  # pylint: disable=unused-variable
        fig.autofmt_xdate()

        ax = plt.subplot(111)
        ax.plot(df.close, label="price", color="black")
        ax.set_title("Fibonacci Retracement Levels")
        ax.axhspan(level1,
                   price_min,
                   alpha=0.4,
                   color="lightsalmon",
                   label="0.618")
        ax.axhspan(level3, level2, alpha=0.5, color="palegreen", label="0.382")
        ax.axhspan(level2,
                   level1,
                   alpha=0.5,
                   color="palegoldenrod",
                   label="0.236")
        ax.axhspan(price_max, level3, alpha=0.5, color="powderblue", label="0")

        plt.xlabel(market + " - " + str(granularity))
        plt.ylabel("Price")
        plt.xticks(rotation=90)
        plt.tight_layout()
        plt.legend()

        try:
            Logger.info(
                f"creating: graphs/FRL_{market}_{str(granularity)}.png")
            plt.savefig(f"graphs/FRL_{market}_{str(granularity)}.png", dpi=300)
        except OSError:
            raise SystemExit(
                f"Unable to save: graphs/FRL_{market}_{str(granularity)}.png")

        if saveOnly is False:
            plt.show()
Esempio n. 24
0
    def data_display(self):
        # get % gains and delta
        for pair in self.order_pairs:
            pair['delta'] = pair['sell']['size'] - pair['buy']['size']
            pair['gain'] = (pair['delta'] / pair['buy']['size']) * 100

        # get day/week/month/all time totals
        totals = {'today': [], 'week': [], 'month': [], 'all_time': []}
        today = datetime.today().date()
        lastweek = today - timedelta(days=7)
        lastmonth = today - timedelta(days=30)
        if self.app.statstartdate:
            try:
                start = datetime.strptime(self.app.statstartdate, '%Y-%m-%d').date()
            except:
                raise ValueError("format of --statstartdate must be yyyy-mm-dd")
        else:
            start = None
        
        # popular currencies
        symbol = self.app.getQuoteCurrency()
        if symbol in ['USD', 'AUD', 'CAD', 'SGD', 'NZD']: symbol = '$'
        if symbol == 'EUR': symbol = '€'
        if symbol == 'GBP': symbol = '£'

        if self.app.statdetail:
            headers = ["| Num  ", "| Market     ", "| Date of Sell ", "| Price bought ", "| Price sold  ", "| Delta     ", "| Gain/Loss  |"]
            border = "+"
            for header in headers:
                border += "-" * (len(header) - 1) + '+'
            border = border[:-2] + '+'
            Logger.info(border + "\n" + "".join([x for x in headers]) + "\n" + border)
            for i, pair in enumerate(self.order_pairs):
                if start:
                    if pair['sell']['time'].date() < start:
                        continue
                d_num = '| ' + str(i + 1)
                d_num = d_num + ' ' * (len(headers[0]) - len(d_num))
                d_date = '| ' + str(pair['sell']['time'].date())
                d_market = '| ' + pair['market']
                d_market = d_market + ' ' * (len(headers[1]) - len(d_market))
                d_date = d_date + ' ' * (len(headers[2]) - len(d_date))
                d_buy_size = '| ' + symbol + ' ' + '{:.2f}'.format(pair['buy']['size'])
                d_buy_size = d_buy_size + ' ' * (len(headers[3]) - len(d_buy_size))
                d_sell_size = '| ' + symbol + ' ' + '{:.2f}'.format(pair['sell']['size'])
                d_sell_size = d_sell_size + ' ' * (len(headers[4]) - len(d_sell_size))
                if pair['delta'] > 0:
                    d_delta = '| ' + symbol + ' {:.2f}'.format(pair['delta'])
                else:
                    d_delta = '| ' + symbol + '{:.2f}'.format(pair['delta'])
                d_delta = d_delta + ' ' * (len(headers[5]) - len(d_delta))
                if pair['gain'] > 0:
                    d_gain = '|  ' + '{:.2f}'.format(pair['gain']) + ' %'
                else:
                    d_gain = '| ' + '{:.2f}'.format(pair['gain']) + ' %'
                d_gain = d_gain + ' ' * (len(headers[6]) - len(d_gain) -1) + '|'
                Logger.info(d_num + d_market + d_date + d_buy_size + d_sell_size + d_delta + d_gain)
            Logger.info(border)
            sys.exit()

        for pair in self.order_pairs:
            if start:
                if pair['sell']['time'].date() < start:
                    continue
            totals['all_time'].append(pair)
            if pair['sell']['time'].date() == today:
                totals['today'].append(pair)
            if pair['sell']['time'].date() > lastweek:
                totals['week'].append(pair)
            if pair['sell']['time'].date() > lastmonth:
                totals['month'].append(pair)
        
        # prepare data for output
        today_per = [x['gain'] for x in totals['today']]
        week_per = [x['gain'] for x in totals['week']]
        month_per = [x['gain'] for x in totals['month']]
        all_time_per = [x['gain'] for x in totals['all_time']]
        today_gain = [x['delta'] for x in totals['today']]
        week_gain = [x['delta'] for x in totals['week']]
        month_gain = [x['delta'] for x in totals['month']]
        all_time_gain = [x['delta'] for x in totals['all_time']]

        if len(today_per) > 0:
            today_delta = [(x['sell']['time'] - x['buy']['time']).total_seconds() for x in totals['today']]
            today_delta = timedelta(seconds=int(sum(today_delta) / len(today_delta)))
        else: today_delta = '0:0:0'
        if len(week_per) > 0:
            week_delta = [(x['sell']['time'] - x['buy']['time']).total_seconds() for x in totals['week']]
            week_delta = timedelta(seconds=int(sum(week_delta) / len(week_delta)))
        else: week_delta = '0:0:0'
        if len(month_per) > 0:
            month_delta = [(x['sell']['time'] - x['buy']['time']).total_seconds() for x in totals['month']]
            month_delta = timedelta(seconds=int(sum(month_delta) / len(month_delta)))
        else: month_delta = '0:0:0'
        if len(all_time_per) > 0:
            all_time_delta = [(x['sell']['time'] - x['buy']['time']).total_seconds() for x in totals['all_time']]
            all_time_delta = timedelta(seconds=int(sum(all_time_delta) / len(all_time_delta)))
        else: all_time_delta = '0:0:0'

        today_sum = symbol + ' {:.2f}'.format(round(sum(today_gain), 2)) if len(today_gain) > 0 else symbol + ' 0.00'
        week_sum = symbol + ' {:.2f}'.format(round(sum(week_gain), 2)) if len(week_gain) > 0 else symbol + ' 0.00'
        month_sum= symbol + ' {:.2f}'.format(round(sum(month_gain), 2)) if len(month_gain) > 0 else symbol + ' 0.00'
        all_time_sum = symbol + ' {:.2f}'.format(round(sum(all_time_gain), 2)) if len(all_time_gain) > 0 else symbol + ' 0.00'
        today_percent = str(round(sum(today_per), 4)) + '%' if len(today_per) > 0 else '0.0000%'
        week_percent = str(round(sum(week_per), 4)) + '%' if len(week_per) > 0 else '0.0000%'
        month_percent = str(round(sum(month_per), 4)) + '%' if len(month_per) > 0 else '0.0000%'
        all_time_percent = str(round(sum(all_time_per), 4)) + '%' if len(all_time_per) > 0 else '0.0000%'
            
        trades = 'Number of Completed Trades:'
        gains = 'Percentage Gains:'
        aver = 'Average Time Held (H:M:S):'
        success = 'Total Profit/Loss:'
        width = 30
        if self.app.statgroup: header = 'MERGE'
        else: header = self.app.getMarket()

        Logger.info(f'------------- TODAY : {header} --------------')
        Logger.info(trades + ' ' * (width-len(trades)) + str(len(today_per)))
        Logger.info(gains + ' ' * (width-len(gains)) + today_percent)
        Logger.info(aver + ' ' * (width-len(aver)) + str(today_delta))
        Logger.info(success + ' ' * (width-len(success)) + today_sum)
        Logger.info(f'\n-------------- WEEK : {header} --------------')
        Logger.info(trades + ' ' * (width-len(trades)) + str(len(week_per)))
        Logger.info(gains + ' ' * (width-len(gains)) + week_percent)
        Logger.info(aver + ' ' * (width-len(aver)) + str(week_delta))
        Logger.info(success + ' ' * (width-len(success)) + week_sum)
        Logger.info(f'\n------------- MONTH : {header} --------------')
        Logger.info(trades + ' ' * (width-len(trades)) + str(len(month_per)))
        Logger.info(gains + ' ' * (width-len(gains)) + month_percent)
        Logger.info(aver + ' ' * (width-len(aver)) + str(month_delta))
        Logger.info(success + ' ' * (width-len(success)) + month_sum)
        Logger.info(f'\n------------ ALL TIME : {header} ------------')
        Logger.info(trades + ' ' * (width-len(trades)) + str(len(all_time_per)))
        Logger.info(gains + ' ' * (width-len(gains)) + all_time_percent)
        Logger.info(aver + ' ' * (width-len(aver)) + str(all_time_delta))
        Logger.info(success + ' ' * (width-len(success)) + all_time_sum)

        sys.exit()
Esempio n. 25
0
    def renderCandlestickAstralPattern(self, period=30, saveOnly=False):
        # get dataframe from technical analysis object
        df = self.technical_analysis.getDataFrame()

        if not isinstance(period, int):
            raise TypeError('Period parameter is not perioderic.')

        if period < 1 or period > len(df):
            raise ValueError('Period is out of range')

        # extract market and granularity from trading dataframe
        market = df.iloc[0].market
        granularity = df.iloc[0].granularity

        df_subset = df.iloc[-period::]

        fig, axes = plt.subplots(ncols=1, figsize=(12, 6))  #pylint: disable=unused-variable
        fig.autofmt_xdate()
        ax1 = plt.subplot(111)
        ax1.set_title('Astral Candlestick Pattern')
        plt.plot(df_subset['close'], label='price', color='black')
        plt.plot(df_subset['ema12'], label='ema12', color='orange')
        plt.plot(df_subset['ema26'], label='ema26', color='purple')
        plt.tick_params(axis='x',
                        which='both',
                        bottom=False,
                        top=False,
                        labelbottom=False)

        df_candlestick = self.df[self.df['astral_buy'] is True]
        df_candlestick_in_range = df_candlestick[
            df_candlestick.index >= np.min(df_subset.index)]
        for idx in df_candlestick_in_range.index.tolist():
            plt.plot(idx,
                     df_candlestick_in_range.loc[idx]['close'],
                     'g^',
                     markersize=8)

        df_candlestick = self.df[self.df['astral_sell'] is True]
        df_candlestick_in_range = df_candlestick[
            df_candlestick.index >= np.min(df_subset.index)]
        for idx in df_candlestick_in_range.index.tolist():
            plt.plot(idx,
                     df_candlestick_in_range.loc[idx]['close'],
                     'rv',
                     markersize=8)

        plt.xlabel(market + ' - ' + str(granularity))
        plt.ylabel('Price')
        plt.xticks(rotation=90)
        plt.tight_layout()
        plt.legend()

        try:
            Logger.info('creating: graphs/CAP_' + market + '_' +
                        str(granularity) + '.png')
            plt.savefig('graphs/CAP_' + market + '_' + str(granularity) +
                        '.png',
                        dpi=300)
        except OSError:
            raise SystemExit('Unable to save: graphs/CAP_' + market + '_' +
                             str(granularity) + '.png')

        if saveOnly is False:
            plt.show()
Esempio n. 26
0
    def getTradeFee(self, market: str) -> float:
        resp = self.client.get_trade_fee(symbol=market, timestamp=self.getTime())
      
        if 'tradeFee' not in resp:
            Logger.info('*** getTradeFee(' + market + ') - missing "tradeFee" ***')
            Logger.info(resp)
        else:
            if len(resp['tradeFee']) == 0:
                Logger.info('*** getTradeFee(' + market + ') - "tradeFee" empty ***') 
                Logger.info(resp)
            else:
                if 'taker' not in resp['tradeFee'][0]:
                    Logger.info('*** getTradeFee(' + market + ') - missing "trader" ***')
                    Logger.info(resp)                    

        if 'success' in resp:
            return resp['tradeFee'][0]['taker']
        else:
            return DEFAULT_TRADE_FEE_RATE