from models.PyCryptoBot import PyCryptoBot
from models.Trading import TechnicalAnalysis
from views.TradingGraphs import TradingGraphs

app = PyCryptoBot()
trading_data = app.getHistoricalData(app.getMarket(), app.getGranularity())

ta = TechnicalAnalysis(trading_data)
ta.addAll()

df_data = ta.getDataFrame()
df_fib = ta.getFibonacciRetracementLevels()
df_sr = ta.getSupportResistanceLevels()

print(df_data)
print(df_fib)
print(df_sr)

graphs = TradingGraphs(ta)
#graphs.renderBuySellSignalEMA1226MACD(saveOnly=False)
#graphs = TradingGraphs(ta)
#graphs.renderPercentageChangeHistogram()
#graphs.renderCumulativeReturn()
#graphs.renderPercentageChangeScatterMatrix()
graphs.renderFibonacciBollingerBands(period=24)
Example #2
0
def executeJob(sc, market, granularity, tradingData=pd.DataFrame()):
    """Trading bot job which runs at a scheduled interval"""
    global action, buy_count, buy_sum, failsafe, iterations, last_action, last_buy, last_df_index, sell_count, sell_sum, x_since_buy, x_since_sell

    # increment iterations
    iterations = iterations + 1

    if is_sim == 0:
        # retrieve the market data
        api = PublicAPI()
        tradingData = api.getHistoricalData(market, granularity)

    # analyse the market data
    tradingDataCopy = tradingData.copy()
    technicalAnalysis = TechnicalAnalysis(tradingDataCopy)
    technicalAnalysis.addAll()
    df = technicalAnalysis.getDataFrame()

    if len(df) != 300:
        # data frame should have 300 rows, if not retry
        print('error: data frame length is < 300 (' + str(len(df)) + ')')
        logging.error('error: data frame length is < 300 (' + str(len(df)) +
                      ')')
        s.enter(300, 1, executeJob, (sc, market, granularity))

    if is_sim == 1:
        # with a simulation df_last will iterate through data
        df_last = df.iloc[iterations - 1:iterations]
    else:
        # df_last contains the most recent entry
        df_last = df.tail(1)

    price = float(df_last['close'].values[0])
    ema12gtema26 = bool(df_last['ema12gtema26'].values[0])
    ema12gtema26co = bool(df_last['ema12gtema26co'].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])

    # 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])

    # criteria for a buy signal
    if ((ema12gtema26co == True and macdgtsignal == True
         and macdgtsignal > 0.1) or
        (ema12gtema26 == True and macdgtsignal == True and x_since_buy > 0
         and x_since_buy <= 2)) and last_action != 'BUY':
        action = 'BUY'
    # criteria for a sell signal
    elif ((ema12ltema26co == True and macdltsignal == True) or
          (ema12ltema26 == True and macdltsignal == True and x_since_sell > 0
           and x_since_sell <= 2)) and last_action not in ['', 'SELL']:
        action = 'SELL'
        failsafe = False
    # anything other than a buy or sell, just wait
    else:
        action = 'WAIT'

    # loss failsafe sell < -5%
    if last_buy > 0 and last_action == 'BUY':
        change_pcnt = ((price / last_buy) - 1) * 100
        if (change_pcnt < -5):
            action = 'SELL'
            x_since_buy = 0
            failsafe = True
            log_text = '! Loss Failsafe Triggered (< -5%)'
            print(log_text, "\n")
            logging.warning(log_text)

    # polling is every 5 minutes (even for hourly intervals), but only process once per interval
    if (last_df_index != df_last.index.format()):
        ts_text = str(df_last.index.format()[0])

        precision = 2
        if cryptoMarket == 'XLM':
            precision = 4

        price_text = 'Price: ' + str(
            truncate(float(df_last['close'].values[0]), precision))
        ema_text = compare(df_last['ema12'].values[0],
                           df_last['ema26'].values[0], 'EMA12/26', precision)
        macd_text = compare(df_last['macd'].values[0],
                            df_last['signal'].values[0], 'MACD', precision)
        obv_text = compare(df_last['obv_pc'].values[0], 0.1, 'OBV %',
                           precision)
        counter_text = '[I:' + str(iterations) + ',B:' + str(
            x_since_buy) + ',S:' + str(x_since_sell) + ']'

        if hammer == True:
            log_text = '* Candlestick Detected: Hammer ("Weak - Reversal - Bullish Signal - Up")'
            print(log_text, "\n")
            logging.debug(log_text)

        if shooting_star == True:
            log_text = '* Candlestick Detected: Shooting Star ("Weak - Reversal - Bearish Pattern - Down")'
            print(log_text, "\n")
            logging.debug(log_text)

        if hanging_man == True:
            log_text = '* Candlestick Detected: Hanging Man ("Weak - Continuation - Bearish Pattern - Down")'
            print(log_text, "\n")
            logging.debug(log_text)

        if inverted_hammer == True:
            log_text = '* Candlestick Detected: Inverted Hammer ("Weak - Continuation - Bullish Pattern - Up")'
            print(log_text, "\n")
            logging.debug(log_text)

        if three_white_soldiers == True:
            log_text = '*** Candlestick Detected: Three White Soldiers ("Strong - Reversal - Bullish Pattern - Up")'
            print(log_text, "\n")
            logging.debug(log_text)

        if three_black_crows == True:
            log_text = '* Candlestick Detected: Three Black Crows ("Strong - Reversal - Bearish Pattern - Down")'
            print(log_text, "\n")
            logging.debug(log_text)

        if morning_star == True:
            log_text = '*** Candlestick Detected: Morning Star ("Strong - Reversal - Bullish Pattern - Up")'
            print(log_text, "\n")
            logging.debug(log_text)

        if evening_star == True:
            log_text = '*** Candlestick Detected: Evening Star ("Strong - Reversal - Bearish Pattern - Down")'
            print(log_text, "\n")
            logging.debug(log_text)

        if three_line_strike == True:
            log_text = '** Candlestick Detected: Three Line Strike ("Reliable - Reversal - Bullish Pattern - Up")'
            print(log_text, "\n")
            logging.debug(log_text)

        if abandoned_baby == True:
            log_text = '** Candlestick Detected: Abandoned Baby ("Reliable - Reversal - Bullish Pattern - Up")'
            print(log_text, "\n")
            logging.debug(log_text)

        if morning_doji_star == True:
            log_text = '** Candlestick Detected: Morning Doji Star ("Reliable - Reversal - Bullish Pattern - Up")'
            print(log_text, "\n")
            logging.debug(log_text)

        if evening_doji_star == True:
            log_text = '** Candlestick Detected: Evening Doji Star ("Reliable - Reversal - Bearish Pattern - Down")'
            print(log_text, "\n")
            logging.debug(log_text)

        if two_black_gapping == True:
            log_text = '*** Candlestick Detected: Two Black Gapping ("Reliable - Reversal - Bearish Pattern - Down")'
            print(log_text, "\n")
            logging.debug(log_text)

        ema_co_prefix = ''
        ema_co_suffix = ''
        if ema12gtema26co == True:
            ema_co_prefix = '*^ '
            ema_co_suffix = ' ^*'
        elif ema12ltema26co == True:
            ema_co_prefix = '*v '
            ema_co_suffix = ' v*'
        elif ema12gtema26 == True:
            ema_co_prefix = '^ '
            ema_co_suffix = ' ^'
        elif ema12ltema26 == True:
            ema_co_prefix = 'v '
            ema_co_suffix = ' v'

        macd_co_prefix = ''
        macd_co_suffix = ''
        if macdgtsignalco == True:
            macd_co_prefix = '*^ '
            macd_co_suffix = ' ^*'
        elif macdltsignalco == True:
            macd_co_prefix = '*v '
            macd_co_suffix = ' v*'
        elif macdgtsignal == True:
            macd_co_prefix = '^ '
            macd_co_suffix = ' ^'
        elif macdltsignal == True:
            macd_co_prefix = 'v '
            macd_co_suffix = ' v'

        obv_prefix = ''
        obv_suffix = ''
        if (obv_pc > 0.1):
            obv_prefix = '^ '
            obv_suffix = ' ^'
        else:
            obv_prefix = 'v '
            obv_suffix = ' v'

        if is_verbose == 0:
            if last_action != '':
                output_text = ts_text + ' | ' + price_text + ' | ' + ema_co_prefix + ema_text + ema_co_suffix + ' | ' + macd_co_prefix + macd_text + macd_co_suffix + ' | ' + obv_prefix + obv_text + obv_suffix + ' | ' + action + ' ' + counter_text + ' | Last Action: ' + last_action
            else:
                output_text = ts_text + ' | ' + price_text + ' | ' + ema_co_prefix + ema_text + ema_co_suffix + ' | ' + macd_co_prefix + macd_text + macd_co_suffix + ' | ' + obv_prefix + obv_text + obv_suffix + ' | ' + action + ' ' + counter_text

            if last_action == 'BUY':
                # calculate last buy minus fees
                fee = last_buy * 0.005
                last_buy_minus_fees = last_buy + fee

                margin = str(
                    truncate((((price - last_buy_minus_fees) / price) * 100),
                             2)) + '%'
                output_text += ' | ' + margin

            logging.debug(output_text)
            print(output_text)
        else:
            logging.debug('-- Iteration: ' + str(iterations) + ' --')
            logging.debug('-- Since Last Buy: ' + str(x_since_buy) + ' --')
            logging.debug('-- Since Last Sell: ' + str(x_since_sell) + ' --')

            if last_action == 'BUY':
                margin = str(truncate(
                    (((price - last_buy) / price) * 100), 2)) + '%'
                logging.debug('-- Margin: ' + margin + '% --')

            logging.debug('price: ' +
                          str(truncate(float(df_last['close'].values[0]), 2)))
            logging.debug('ema12: ' +
                          str(truncate(float(df_last['ema12'].values[0]), 2)))
            logging.debug('ema26: ' +
                          str(truncate(float(df_last['ema26'].values[0]), 2)))
            logging.debug('ema12gtema26co: ' + str(ema12gtema26co))
            logging.debug('ema12gtema26: ' + str(ema12gtema26))
            logging.debug('ema12ltema26co: ' + str(ema12ltema26co))
            logging.debug('ema12ltema26: ' + str(ema12ltema26))
            logging.debug('macd: ' +
                          str(truncate(float(df_last['macd'].values[0]), 2)))
            logging.debug('signal: ' +
                          str(truncate(float(df_last['signal'].values[0]), 2)))
            logging.debug('macdgtsignal: ' + str(macdgtsignal))
            logging.debug('macdltsignal: ' + str(macdltsignal))
            logging.debug('obv: ' + str(obv))
            logging.debug('obv_pc: ' + str(obv_pc) + '%')
            logging.debug('action: ' + action)

            # informational output on the most recent entry
            print('')
            print(
                '================================================================================'
            )
            txt = '        Iteration : ' + str(iterations)
            print('|', txt, (' ' * (75 - len(txt))), '|')
            txt = '   Since Last Buy : ' + str(x_since_buy)
            print('|', txt, (' ' * (75 - len(txt))), '|')
            txt = '  Since Last Sell : ' + str(x_since_sell)
            print('|', txt, (' ' * (75 - len(txt))), '|')
            txt = '        Timestamp : ' + str(df_last.index.format()[0])
            print('|', txt, (' ' * (75 - len(txt))), '|')
            print(
                '--------------------------------------------------------------------------------'
            )
            txt = '            EMA12 : ' + str(
                truncate(float(df_last['ema12'].values[0]), 2))
            print('|', txt, (' ' * (75 - len(txt))), '|')
            txt = '            EMA26 : ' + str(
                truncate(float(df_last['ema26'].values[0]), 2))
            print('|', txt, (' ' * (75 - len(txt))), '|')
            txt = '   Crossing Above : ' + str(ema12gtema26co)
            print('|', txt, (' ' * (75 - len(txt))), '|')
            txt = '  Currently Above : ' + str(ema12gtema26)
            print('|', txt, (' ' * (75 - len(txt))), '|')
            txt = '   Crossing Below : ' + str(ema12ltema26co)
            print('|', txt, (' ' * (75 - len(txt))), '|')
            txt = '  Currently Below : ' + str(ema12ltema26)
            print('|', txt, (' ' * (75 - len(txt))), '|')

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

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

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

            print(
                '--------------------------------------------------------------------------------'
            )
            txt = '              OBV : ' + str(truncate(obv, 4))
            print('|', txt, (' ' * (75 - len(txt))), '|')
            txt = '       OBV Change : ' + str(obv_pc) + '%'
            print('|', txt, (' ' * (75 - len(txt))), '|')

            if (obv_pc >= 2):
                txt = '        Condition : Large positive volume changes'
            elif (obv_pc < 2 and obv_pc >= 0):
                txt = '        Condition : Positive volume changes'
            else:
                txt = '        Condition : Negative volume changes'
            print('|', txt, (' ' * (75 - len(txt))), '|')

            print(
                '--------------------------------------------------------------------------------'
            )
            txt = '           Action : ' + action
            print('|', txt, (' ' * (75 - len(txt))), '|')
            print(
                '================================================================================'
            )
            if last_action == 'BUY':
                txt = '           Margin : ' + margin + '%'
                print('|', txt, (' ' * (75 - len(txt))), '|')
                print(
                    '================================================================================'
                )

        # increment x since buy
        if (ema12gtema26 == True and failsafe == False):
            x_since_buy = x_since_buy + 1
        # increment x since sell
        elif (ema12ltema26 == True):
            x_since_sell = x_since_sell + 1

        # if a buy signal
        if action == 'BUY':
            buy_count = buy_count + 1

            # reset x since sell
            x_since_sell = 0

            last_buy = price

            # if live
            if is_live == 1:
                if is_verbose == 0:
                    logging.info(ts_text + ' | ' + market + ' ' +
                                 str(granularity) + ' | ' + price_text +
                                 ' | BUY')
                    print("\n", ts_text, '|', market, granularity, '|',
                          price_text, '| BUY', "\n")
                else:
                    print(
                        '--------------------------------------------------------------------------------'
                    )
                    print(
                        '|                      *** Executing LIVE Buy Order ***                        |'
                    )
                    print(
                        '--------------------------------------------------------------------------------'
                    )
                # connect to coinbase pro api (authenticated)
                model = AuthAPI(config['api_key'], config['api_secret'],
                                config['api_pass'], config['api_url'])
                # execute a live market buy
                resp = model.marketBuy(market,
                                       float(account.getBalance(fiatMarket)))
                logging.info(resp)
                #logging.info('attempt to buy ' + resp['specified_funds'] + ' (' + resp['funds'] + ' after fees) of ' + resp['product_id'])
            # if not live
            else:
                if is_verbose == 0:
                    logging.info(ts_text + ' | ' + market + ' ' +
                                 str(granularity) + ' | ' + price_text +
                                 ' | BUY')
                    print("\n", ts_text, '|', market, granularity, '|',
                          price_text, '| BUY', "\n")
                else:
                    print(
                        '--------------------------------------------------------------------------------'
                    )
                    print(
                        '|                      *** Executing TEST Buy Order ***                        |'
                    )
                    print(
                        '--------------------------------------------------------------------------------'
                    )
                #print(df_last[['close','ema12','ema26','ema12gtema26','ema12gtema26co','macd','signal','macdgtsignal','obv','obv_pc']])

            if save_graphs == 1:
                tradinggraphs = TradingGraphs(technicalAnalysis)
                ts = datetime.now().timestamp()
                filename = 'BTC-GBP_3600_buy_' + str(ts) + '.png'
                tradinggraphs.renderEMAandMACD(24, 'graphs/' + filename, True)

        # if a sell signal
        elif action == 'SELL':
            sell_count = sell_count + 1

            # reset x since buy
            x_since_buy = 0

            # if live
            if is_live == 1:
                if is_verbose == 0:
                    logging.info(ts_text + ' | ' + market + ' ' +
                                 str(granularity) + ' | ' + price_text +
                                 ' | SELL')
                    print("\n", ts_text, '|', market, granularity, '|',
                          price_text, '| SELL', "\n")
                else:
                    print(
                        '--------------------------------------------------------------------------------'
                    )
                    print(
                        '|                      *** Executing LIVE Sell Order ***                        |'
                    )
                    print(
                        '--------------------------------------------------------------------------------'
                    )
                # connect to Coinbase Pro API live
                model = AuthAPI(config['api_key'], config['api_secret'],
                                config['api_pass'], config['api_url'])
                # execute a live market sell
                resp = model.marketSell(
                    market, float(account.getBalance(cryptoMarket)))
                logging.info(resp)
                #logging.info('attempt to sell ' + resp['size'] + ' of ' + resp['product_id'])
            # if not live
            else:
                if is_verbose == 0:
                    sell_price = float(
                        str(
                            truncate(float(df_last['close'].values[0]),
                                     precision)))
                    last_buy_price = float(
                        str(truncate(float(last_buy), precision)))
                    buy_sell_diff = round(
                        np.subtract(sell_price, last_buy_price), precision)
                    buy_sell_margin_no_fees = str(
                        truncate(
                            (((sell_price - last_buy_price) / sell_price) *
                             100), 2)) + '%'

                    # calculate last buy minus fees
                    buy_fee = last_buy_price * 0.005
                    last_buy_price_minus_fees = last_buy_price + buy_fee

                    buy_sell_margin_fees = str(
                        truncate((((sell_price - last_buy_price_minus_fees) /
                                   sell_price) * 100), 2)) + '%'

                    logging.info(ts_text + ' | ' + market + ' ' +
                                 str(granularity) + ' | SELL | ' +
                                 str(sell_price) + ' | BUY | ' +
                                 str(last_buy_price) + ' | DIFF | ' +
                                 str(buy_sell_diff) + ' | MARGIN NO FEES | ' +
                                 str(buy_sell_margin_no_fees) +
                                 ' | MARGIN FEES | ' +
                                 str(buy_sell_margin_fees))
                    print("\n", ts_text, '|', market, granularity, '| SELL |',
                          str(sell_price), '| BUY |', str(last_buy_price),
                          '| DIFF |', str(buy_sell_diff), '| MARGIN NO FEES |',
                          str(buy_sell_margin_no_fees), '| MARGIN FEES |',
                          str(buy_sell_margin_fees), "\n")

                    buy_sum = buy_sum + last_buy_price_minus_fees
                    sell_sum = sell_sum + sell_price
                else:
                    print(
                        '--------------------------------------------------------------------------------'
                    )
                    print(
                        '|                      *** Executing TEST Sell Order ***                        |'
                    )
                    print(
                        '--------------------------------------------------------------------------------'
                    )
            #print(df_last[['close','ema12','ema26','ema12ltema26','ema12ltema26co','macd','signal','macdltsignal','obv','obv_pc']])

            if save_graphs == 1:
                tradinggraphs = TradingGraphs(technicalAnalysis)
                ts = datetime.now().timestamp()
                filename = 'BTC-GBP_3600_buy_' + str(ts) + '.png'
                tradinggraphs.renderEMAandMACD(24, 'graphs/' + filename, True)

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

        last_df_index = df_last.index.format()

        if iterations == 300:
            print("\nSimulation Summary\n")

            if buy_count > sell_count:
                # calculate last buy minus fees
                fee = last_buy * 0.005
                last_buy_minus_fees = last_buy + fee

                buy_sum = buy_sum + (float(
                    truncate(float(df_last['close'].values[0]), precision)) -
                                     last_buy_minus_fees)

            print('   Buy Count :', buy_count)
            print('  Sell Count :', sell_count, "\n")
            print('   Buy Total :', buy_sum)
            print('  Sell Total :', sell_sum)
            print(
                '      Margin :',
                str(truncate(
                    (((sell_sum - buy_sum) / sell_sum) * 100), 2)) + '%', "\n")
    else:
        # decrement ignored iteration
        iterations = iterations - 1

    # if live
    if is_live == 1:
        # save csv with orders for market that are 'done'
        orders = account.getOrders(market, '', 'done')
        orders.to_csv('orders.csv', index=False)

    if is_sim == 1:
        if iterations < 300:
            if sim_speed == 'fast':
                # fast processing
                executeJob(sc, market, granularity, tradingData)
            else:
                # slow processing
                s.enter(1, 1, executeJob,
                        (sc, market, granularity, tradingData))

    else:
        # poll every 5 minutes
        s.enter(300, 1, executeJob, (sc, market, granularity))
Example #3
0
from models.PyCryptoBot import PyCryptoBot
from models.Trading import TechnicalAnalysis
from models.Binance import AuthAPI as BAuthAPI, PublicAPI as BPublicAPI
from models.CoinbasePro import AuthAPI as CBAuthAPI, PublicAPI as CBPublicAPI
from views.TradingGraphs import TradingGraphs

#app = PyCryptoBot()
app = PyCryptoBot('binance')
tradingData = app.getHistoricalData(app.getMarket(), app.getGranularity())

technicalAnalysis = TechnicalAnalysis(tradingData)
technicalAnalysis.addAll()

tradinggraphs = TradingGraphs(technicalAnalysis)
tradinggraphs.renderFibonacciRetracement(True)
tradinggraphs.renderSupportResistance(True)
tradinggraphs.renderCandlesticks(30, True)
tradinggraphs.renderSeasonalARIMAModelPrediction(1, True)
Example #4
0
# if the last transation was a buy retrieve open amount
addBalance = 0
df_orders = account.getOrders()
if len(df_orders) > 0 and df_orders.iloc[[-1]]['action'].values[0] == 'buy':
    # last trade is still open, add to closing balance
    addBalance = df_orders.iloc[[-1]]['value'].values[0]

# displays the transactions from the simulation
print('')
print(df_orders)


def truncate(f, n):
    return math.floor(f * 10**n) / 10**n


# if the last transaction was a buy add the open amount to the closing balance
result = truncate(
    round((account.getBalance(cryptoMarket) + addBalance) - openingBalance, 2),
    2)

print('')
print("Opening balance:", truncate(openingBalance, 2))
print("Closing balance:",
      truncate(round(account.getBalance(cryptoMarket) + addBalance, 2), 2))
print("         Result:", result)
print('')

# renders the DataFrame for analysis
tradinggraphs = TradingGraphs(coinbasepro)
tradinggraphs.renderBuySellSignalEMA1226MACD()
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
from models.Trading import TechnicalAnalysis
from models.CoinbasePro import PublicAPI
from views.TradingGraphs import TradingGraphs

market = 'BTC-GBP'
granularity = 3600

api = PublicAPI()
tradingData = api.getHistoricalData(market, granularity)
technicalAnalysis = TechnicalAnalysis(tradingData)
technicalAnalysis.addEMA(12)
technicalAnalysis.addEMA(26)
technicalAnalysis.addCandleHammer()
technicalAnalysis.addCandleInvertedHammer()
technicalAnalysis.addCandleShootingStar()
technicalAnalysis.addCandleHangingMan()
technicalAnalysis.addCandleThreeWhiteSoldiers()
technicalAnalysis.addCandleThreeBlackCrows()
technicalAnalysis.addCandleDoji()
technicalAnalysis.addCandleThreeLineStrike()
technicalAnalysis.addCandleTwoBlackGapping()
technicalAnalysis.addCandleEveningStar()
technicalAnalysis.addCandleAbandonedBaby()
df = technicalAnalysis.getDataFrame()

tradinggraphs = TradingGraphs(technicalAnalysis)
tradinggraphs.renderEMA12EMA26CloseCandles()
#tradinggraphs.renderEMA12EMA26CloseCandles(30, 'candles.png')
Example #6
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))
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
from models.Trading import TechnicalAnalysis
from models.CoinbasePro import PublicAPI
from views.TradingGraphs import TradingGraphs

market = 'BTC-GBP'
granularity = 3600

api = PublicAPI()
tradingData = api.getHistoricalData(market, granularity)
technicalAnalysis = TechnicalAnalysis(tradingData)
technicalAnalysis.addEMA(12)
technicalAnalysis.addEMA(26)
technicalAnalysis.addCandleHammer()
technicalAnalysis.addCandleInvertedHammer()
technicalAnalysis.addCandleShootingStar()
technicalAnalysis.addCandleHangingMan()
technicalAnalysis.addCandleThreeWhiteSoldiers()
technicalAnalysis.addCandleThreeBlackCrows()
technicalAnalysis.addCandleDojo()
technicalAnalysis.addCandleThreeLineStrike()
technicalAnalysis.addCandleTwoBlackGapping()
technicalAnalysis.addCandleEveningStar()
technicalAnalysis.addCandleAbandonedBaby()
df = technicalAnalysis.getDataFrame()

tradinggraphs = TradingGraphs(technicalAnalysis)
tradinggraphs.renderEMA12EMA26CloseCandles(market, granularity)
#tradinggraphs.renderEMA12EMA26CloseCandles(market, granularity, 30, 'candles.png')
Example #8
0
from models.CoinbasePro import CoinbasePro
from views.TradingGraphs import TradingGraphs

coinbasepro = CoinbasePro()
print(coinbasepro.getDataFrame())
coinbasepro.addMovingAverages()
print(coinbasepro.getDataFrame())
coinbasepro.addMomentumIndicators()
print(coinbasepro.getDataFrame())
print(coinbasepro.getSupportResistanceLevels())
coinbasepro.saveCSV()

tradinggraphs = TradingGraphs(coinbasepro)
tradinggraphs.renderEMAandMACD()
#tradinggraphs.renderSMAandMACD()
#tradinggraphs.renderPriceSupportResistance()
Example #9
0
def executeJob(sc, app=PyCryptoBot(), trading_data=pd.DataFrame()):
    """Trading bot job which runs at a scheduled interval"""
    global action, buy_count, buy_sum, iterations, last_action, last_buy, eri_text, last_df_index, sell_count, sell_sum, buy_state, fib_high, fib_low

    # increment iterations
    iterations = iterations + 1

    if app.isSimulation() == 0:
        # 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
    trading_dataCopy = trading_data.copy()
    ta = TechnicalAnalysis(trading_dataCopy)
    ta.addAll()
    df = ta.getDataFrame()

    if app.isSimulation() == 1:
        # with a simulation df_last will iterate through data
        df_last = df.iloc[iterations-1:iterations]
    else:
        # df_last contains the most recent entry
        df_last = df.tail(1)
    
    if len(df_last.index.format()) > 0:
        current_df_index = str(df_last.index.format()[0])
    else:
        current_df_index = last_df_index

    if app.getSmartSwitch() == 1 and app.getExchange() == 'binance' and app.getGranularity() == '1h' and app.is1hEMA1226Bull() == True and app.is6hEMA1226Bull() == True:
        print ("*** smart switch from granularity '1h' (1 hour) to '15m' (15 min) ***")

        # telegram
        if app.isTelegramEnabled():
            telegram = Telegram(app.getTelegramToken(), app.getTelegramClientId())
            telegram.send(app.getMarket() + " smart switch from granularity '1h' (1 hour) to '15m' (15 min)")

        app.setGranularity('15m')
        list(map(s.cancel, s.queue))
        s.enter(5, 1, executeJob, (sc, app))

    elif app.getSmartSwitch() == 1 and app.getExchange() == 'coinbasepro' and app.getGranularity() == 3600 and app.is1hEMA1226Bull() == True and app.is6hEMA1226Bull() == True:
        print ('*** smart switch from granularity 3600 (1 hour) to 900 (15 min) ***')

        # telegram
        if app.isTelegramEnabled():
            telegram = Telegram(app.getTelegramToken(), app.getTelegramClientId())
            telegram.send(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))

    if app.getSmartSwitch() == 1 and app.getExchange() == 'binance' and app.getGranularity() == '15m' and app.is1hEMA1226Bull() == False and app.is6hEMA1226Bull() == False:
        print ("*** smart switch from granularity '15m' (15 min) to '1h' (1 hour) ***")

        # telegram
        if app.isTelegramEnabled():
            telegram = Telegram(app.getTelegramToken(), app.getTelegramClientId())
            telegram.send(app.getMarket() + " smart switch from granularity '15m' (15 min) to '1h' (1 hour)")

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

    elif app.getSmartSwitch() == 1 and app.getExchange() == 'coinbasepro' and app.getGranularity() == 900 and app.is1hEMA1226Bull() == False and app.is6hEMA1226Bull() == False:
        print ("*** smart switch from granularity 900 (15 min) to 3600 (1 hour) ***")

        # telegram
        if app.isTelegramEnabled():
            telegram = Telegram(app.getTelegramToken(), app.getTelegramClientId())
            telegram.send(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))

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

    if len(df_last) > 0:
        if app.isSimulation() == 0:
            price = app.getTicker(app.getMarket())
            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])
        #deathcross = bool(df_last['deathcross'].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])

        # 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])

        # criteria for a buy signal
        if ema12gtema26co == True and macdgtsignal == True and goldencross == True and obv_pc > -5 and elder_ray_buy == True and last_action != 'BUY':
            action = 'BUY'
        # criteria for a sell signal
        elif ema12ltema26co == True and macdltsignal == True and last_action not in ['','SELL']:
            action = 'SELL'
        # anything other than a buy or sell, just wait
        else:
            action = 'WAIT'

        last_buy_minus_fees = 0
        if last_buy > 0 and last_action == 'BUY':
            change_pcnt = ((price / last_buy) - 1) * 100

            # calculate last buy minus fees
            fee = last_buy * 0.005
            last_buy_minus_fees = last_buy + fee
            margin = ((price - last_buy_minus_fees) / price) * 100

            # loss failsafe sell at fibonacci band
            if app.allowSellAtLoss() and app.sellLowerPcnt() == None and fib_low > 0 and fib_low >= float(price):
                action = 'SELL'
                last_action = 'BUY'
                log_text = '! Loss Failsafe Triggered (Fibonacci Band: ' + str(fib_low) + ')'
                print (log_text, "\n")
                logging.warning(log_text)

                # telegram
                if app.isTelegramEnabled():
                    telegram = Telegram(app.getTelegramToken(), app.getTelegramClientId())
                    telegram.send(app.getMarket() + ' (' + str(app.getGranularity()) + ') ' + log_text)

            # loss failsafe sell at sell_lower_pcnt
            if app.allowSellAtLoss() and app.sellLowerPcnt() != None and change_pcnt < app.sellLowerPcnt():
                action = 'SELL'
                last_action = 'BUY'
                log_text = '! Loss Failsafe Triggered (< ' + str(app.sellLowerPcnt()) + '%)'
                print (log_text, "\n")
                logging.warning(log_text)

                # telegram
                if app.isTelegramEnabled():
                    telegram = Telegram(app.getTelegramToken(), app.getTelegramClientId())
                    telegram.send(app.getMarket() + ' (' + str(app.getGranularity()) + ') ' + log_text)

            if app.getSmartSwitch() == 1 and app.getExchange() == 'binance' and app.getGranularity() == '15m' and change_pcnt >= 2:
                # profit bank at 2% in smart switched mode
                action = 'SELL'
                last_action = 'BUY'
                log_text = '! Profit Bank Triggered (Smart Switch 2%)'
                print (log_text, "\n")
                logging.warning(log_text)

                # telegram
                if app.isTelegramEnabled():
                    telegram = Telegram(app.getTelegramToken(), app.getTelegramClientId())
                    telegram.send(app.getMarket() + ' (' + str(app.getGranularity()) + ') ' + log_text)

            if app.getSmartSwitch() == 1 and app.getExchange() == 'coinbasepro' and app.getGranularity() == 900 and change_pcnt >= 2:
                # profit bank at 2% in smart switched mode
                action = 'SELL'
                last_action = 'BUY'
                log_text = '! Profit Bank Triggered (Smart Switch 2%)'
                print (log_text, "\n")
                logging.warning(log_text)

                # telegram
                if app.isTelegramEnabled():
                    telegram = Telegram(app.getTelegramToken(), app.getTelegramClientId())
                    telegram.send(app.getMarket() + ' (' + str(app.getGranularity()) + ') ' + log_text)

            # profit bank at sell_upper_pcnt
            if app.sellUpperPcnt() != None and change_pcnt > app.sellUpperPcnt():
                action = 'SELL'
                last_action = 'BUY'
                log_text = '! Profit Bank Triggered (> ' + str(app.sellUpperPcnt()) + '%)'
                print (log_text, "\n")
                logging.warning(log_text)

                # telegram
                if app.isTelegramEnabled():
                    telegram = Telegram(app.getTelegramToken(), app.getTelegramClientId())
                    telegram.send(app.getMarket() + ' (' + str(app.getGranularity()) + ') ' + log_text)

            # profit bank at sell at fibonacci band
            if margin > 3 and app.sellUpperPcnt() != None and fib_high > fib_low and fib_high <= float(price):
                action = 'SELL'
                last_action = 'BUY'
                log_text = '! Profit Bank Triggered (Fibonacci Band: ' + str(fib_high) + ')'
                print (log_text, "\n")
                logging.warning(log_text)

                # telegram
                if app.isTelegramEnabled():
                    telegram = Telegram(app.getTelegramToken(), app.getTelegramClientId())
                    telegram.send(app.getMarket() + ' (' + str(app.getGranularity()) + ') ' + log_text)

            # profit bank when strong reversal detected
            if margin > 3 and obv_pc < 0 and macdltsignal == True:
                action = 'SELL'
                last_action = 'BUY'
                log_text = '! Profit Bank Triggered (Strong Reversal Detected)'
                print (log_text, "\n")
                logging.warning(log_text)

                # telegram
                if app.isTelegramEnabled():
                    telegram = Telegram(app.getTelegramToken(), app.getTelegramClientId())
                    telegram.send(app.getMarket() + ' (' + str(app.getGranularity()) + ') ' + log_text)

            # configuration specifies to not sell at a loss
            if not app.allowSellAtLoss() and margin <= 0:
                action = 'WAIT'
                last_action = 'BUY'
                log_text = '! Ignore Sell Signal (No Sell At Loss)'
                print (log_text, "\n")
                logging.warning(log_text)

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

        # polling is every 5 minutes (even for hourly intervals), but only process once per interval
        if (last_df_index != current_df_index):
            precision = 2

            if (price < 0.01):
                precision = 8

            price_text = 'Close: ' + str(app.truncate(price, precision))
            ema_text = app.compare(df_last['ema12'].values[0], df_last['ema26'].values[0], 'EMA12/26', precision)
            macd_text = app.compare(df_last['macd'].values[0], df_last['signal'].values[0], 'MACD', precision)
            obv_text = 'OBV: ' + str(app.truncate(df_last['obv'].values[0], 4)) + ' (' + str(app.truncate(df_last['obv_pc'].values[0], 2)) + '%)'

            if elder_ray_buy == True:
                eri_text = 'ERI: buy'
            elif elder_ray_sell == True:
                eri_text = 'ERI: sell'
            else:
                eri_text = 'ERI:'

            if hammer == True:
                log_text = '* Candlestick Detected: Hammer ("Weak - Reversal - Bullish Signal - Up")'
                print (log_text, "\n")
                logging.debug(log_text)

            if shooting_star == True:
                log_text = '* Candlestick Detected: Shooting Star ("Weak - Reversal - Bearish Pattern - Down")'
                print (log_text, "\n")
                logging.debug(log_text)

            if hanging_man == True:
                log_text = '* Candlestick Detected: Hanging Man ("Weak - Continuation - Bearish Pattern - Down")'
                print (log_text, "\n")
                logging.debug(log_text)

            if inverted_hammer == True:
                log_text = '* Candlestick Detected: Inverted Hammer ("Weak - Continuation - Bullish Pattern - Up")'
                print (log_text, "\n")
                logging.debug(log_text)
   
            if three_white_soldiers == True:
                log_text = '*** Candlestick Detected: Three White Soldiers ("Strong - Reversal - Bullish Pattern - Up")'
                print (log_text, "\n")
                logging.debug(log_text)

                # telegram
                if app.isTelegramEnabled():
                    telegram = Telegram(app.getTelegramToken(), app.getTelegramClientId())
                    telegram.send(app.getMarket() + ' (' + str(app.getGranularity()) + ') ' + log_text)

            if three_black_crows == True:
                log_text = '* Candlestick Detected: Three Black Crows ("Strong - Reversal - Bearish Pattern - Down")'
                print (log_text, "\n")
                logging.debug(log_text)

                # telegram
                if app.isTelegramEnabled():
                    telegram = Telegram(app.getTelegramToken(), app.getTelegramClientId())
                    telegram.send(app.getMarket() + ' (' + str(app.getGranularity()) + ') ' + log_text)

            if morning_star == True:
                log_text = '*** Candlestick Detected: Morning Star ("Strong - Reversal - Bullish Pattern - Up")'
                print (log_text, "\n")
                logging.debug(log_text)

                # telegram
                if app.isTelegramEnabled():
                    telegram = Telegram(app.getTelegramToken(), app.getTelegramClientId())
                    telegram.send(app.getMarket() + ' (' + str(app.getGranularity()) + ') ' + log_text)

            if evening_star == True:
                log_text = '*** Candlestick Detected: Evening Star ("Strong - Reversal - Bearish Pattern - Down")'
                print (log_text, "\n")
                logging.debug(log_text)

                # telegram
                if app.isTelegramEnabled():
                    telegram = Telegram(app.getTelegramToken(), app.getTelegramClientId())
                    telegram.send(app.getMarket() + ' (' + str(app.getGranularity()) + ') ' + log_text)

            if three_line_strike == True:
                log_text = '** Candlestick Detected: Three Line Strike ("Reliable - Reversal - Bullish Pattern - Up")'
                print (log_text, "\n")
                logging.debug(log_text)

                # telegram
                if app.isTelegramEnabled():
                    telegram = Telegram(app.getTelegramToken(), app.getTelegramClientId())
                    telegram.send(app.getMarket() + ' (' + str(app.getGranularity()) + ') ' + log_text)

            if abandoned_baby == True:
                log_text = '** Candlestick Detected: Abandoned Baby ("Reliable - Reversal - Bullish Pattern - Up")'
                print (log_text, "\n")
                logging.debug(log_text)

                # telegram
                if app.isTelegramEnabled():
                    telegram = Telegram(app.getTelegramToken(), app.getTelegramClientId())
                    telegram.send(app.getMarket() + ' (' + str(app.getGranularity()) + ') ' + log_text)

            if morning_doji_star == True:
                log_text = '** Candlestick Detected: Morning Doji Star ("Reliable - Reversal - Bullish Pattern - Up")'
                print (log_text, "\n")
                logging.debug(log_text)

                # telegram
                if app.isTelegramEnabled():
                    telegram = Telegram(app.getTelegramToken(), app.getTelegramClientId())
                    telegram.send(app.getMarket() + ' (' + str(app.getGranularity()) + ') ' + log_text)

            if evening_doji_star == True:
                log_text = '** Candlestick Detected: Evening Doji Star ("Reliable - Reversal - Bearish Pattern - Down")'
                print (log_text, "\n")
                logging.debug(log_text)

                # telegram
                if app.isTelegramEnabled():
                    telegram = Telegram(app.getTelegramToken(), app.getTelegramClientId())
                    telegram.send(app.getMarket() + ' (' + str(app.getGranularity()) + ') ' + log_text)

            if two_black_gapping == True:
                log_text = '*** Candlestick Detected: Two Black Gapping ("Reliable - Reversal - Bearish Pattern - Down")'
                print (log_text, "\n")
                logging.debug(log_text)

                # telegram
                if app.isTelegramEnabled():
                    telegram = Telegram(app.getTelegramToken(), app.getTelegramClientId())
                    telegram.send(app.getMarket() + ' (' + str(app.getGranularity()) + ') ' + log_text)

            ema_co_prefix = ''
            ema_co_suffix = ''
            if ema12gtema26co == True:
                ema_co_prefix = '*^ '
                ema_co_suffix = ' ^*'
            elif ema12ltema26co == True:
                ema_co_prefix = '*v '
                ema_co_suffix = ' v*'   
            elif ema12gtema26 == True:
                ema_co_prefix = '^ '
                ema_co_suffix = ' ^'
            elif ema12ltema26 == True:
                ema_co_prefix = 'v '
                ema_co_suffix = ' v'

            macd_co_prefix = ''
            macd_co_suffix = ''
            if macdgtsignalco == True:
                macd_co_prefix = '*^ '
                macd_co_suffix = ' ^*'
            elif macdltsignalco == True:
                macd_co_prefix = '*v '
                macd_co_suffix = ' v*'
            elif macdgtsignal == True:
                macd_co_prefix = '^ '
                macd_co_suffix = ' ^'
            elif macdltsignal == True:
                macd_co_prefix = 'v '
                macd_co_suffix = ' v'

            obv_prefix = ''
            obv_suffix = ''
            if float(obv_pc) > 0:
                obv_prefix = '^ '
                obv_suffix = ' ^'
            elif float(obv_pc) < 0:
                obv_prefix = 'v '
                obv_suffix = ' v'

            if app.isVerbose() == 0:
                if last_action != '':
                    output_text = current_df_index + ' | ' + app.getMarket() + bullbeartext + ' | ' + str(app.getGranularity()) + ' | ' + price_text + ' | ' + ema_co_prefix + ema_text + ema_co_suffix + ' | ' + macd_co_prefix + macd_text + macd_co_suffix + ' | ' + obv_prefix + obv_text + obv_suffix + ' | ' + eri_text + ' | ' + action + ' | Last Action: ' + last_action
                else:
                    output_text = current_df_index + ' | ' + app.getMarket() + bullbeartext + ' | ' + str(app.getGranularity()) + ' | ' + price_text + ' | ' + ema_co_prefix + ema_text + ema_co_suffix + ' | ' + macd_co_prefix + macd_text + macd_co_suffix + ' | ' + obv_prefix + obv_text + obv_suffix + ' | ' + eri_text + ' | ' + action + ' '

                if last_action == 'BUY':
                    if last_buy_minus_fees > 0:
                        margin = str(app.truncate((((price - last_buy_minus_fees) / price) * 100), 2)) + '%'
                    else:
                        margin = '0%'

                    output_text += ' | ' +  margin

                logging.debug(output_text)
                print (output_text)
            else:
                logging.debug('-- Iteration: ' + str(iterations) + ' --' + bullbeartext)

                if last_action == 'BUY':
                    margin = str(app.truncate((((price - last_buy) / price) * 100), 2)) + '%'
                    logging.debug('-- Margin: ' + margin + '% --')            
                
                logging.debug('price: ' + str(app.truncate(price, precision)))
                logging.debug('ema12: ' + str(app.truncate(float(df_last['ema12'].values[0]), precision)))
                logging.debug('ema26: ' + str(app.truncate(float(df_last['ema26'].values[0]), precision)))
                logging.debug('ema12gtema26co: ' + str(ema12gtema26co))
                logging.debug('ema12gtema26: ' + str(ema12gtema26))
                logging.debug('ema12ltema26co: ' + str(ema12ltema26co))
                logging.debug('ema12ltema26: ' + str(ema12ltema26))
                logging.debug('sma50: ' + str(app.truncate(float(df_last['sma50'].values[0]), precision)))
                logging.debug('sma200: ' + str(app.truncate(float(df_last['sma200'].values[0]), precision)))
                logging.debug('macd: ' + str(app.truncate(float(df_last['macd'].values[0]), precision)))
                logging.debug('signal: ' + str(app.truncate(float(df_last['signal'].values[0]), precision)))
                logging.debug('macdgtsignal: ' + str(macdgtsignal))
                logging.debug('macdltsignal: ' + str(macdltsignal))
                logging.debug('obv: ' + str(obv))
                logging.debug('obv_pc: ' + str(obv_pc))
                logging.debug('action: ' + action)

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

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

                txt = '            SMA20 : ' + str(app.truncate(float(df_last['sma20'].values[0]), precision))
                print('|', txt, (' ' * (75 - len(txt))), '|')
                txt = '           SMA200 : ' + str(app.truncate(float(df_last['sma200'].values[0]), precision))
                print('|', txt, (' ' * (75 - len(txt))), '|')

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

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

                print('--------------------------------------------------------------------------------')
                txt = '           Action : ' + action
                print('|', txt, (' ' * (75 - len(txt))), '|')
                print('================================================================================')
                if last_action == 'BUY':
                    txt = '           Margin : ' + margin + '%'
                    print('|', txt, (' ' * (75 - len(txt))), '|')
                    print('================================================================================')

            # if a buy signal
            if action == 'BUY':
                last_buy = price
                buy_count = buy_count + 1
                fee = float(price) * 0.005
                price_incl_fees = float(price) + fee
                buy_sum = buy_sum + price_incl_fees

                # if live
                if app.isLive() == 1:
                    # telegram
                    if app.isTelegramEnabled():
                        telegram = Telegram(app.getTelegramToken(), app.getTelegramClientId())
                        telegram.send(app.getMarket() + ' (' + str(app.getGranularity()) + ') BUY at ' + price_text)

                    if app.isVerbose() == 0:
                        logging.info(current_df_index + ' | ' + app.getMarket() + ' ' + str(app.getGranularity()) + ' | ' + price_text + ' | BUY')
                        print ("\n", current_df_index, '|', app.getMarket(), str(app.getGranularity()), '|', price_text, '| BUY', "\n")                    
                    else:
                        print('--------------------------------------------------------------------------------')
                        print('|                      *** Executing LIVE Buy Order ***                        |')
                        print('--------------------------------------------------------------------------------')
                    
                    # display balances
                    print (app.getBaseCurrency(), 'balance before order:', account.getBalance(app.getBaseCurrency()))
                    print (app.getQuoteCurrency(), 'balance before order:', account.getBalance(app.getQuoteCurrency()))

                    # execute a live market buy
                    resp = app.marketBuy(app.getMarket(), float(account.getBalance(app.getQuoteCurrency())))
                    logging.info(resp)

                    # display balances
                    print (app.getBaseCurrency(), 'balance after order:', account.getBalance(app.getBaseCurrency()))
                    print (app.getQuoteCurrency(), 'balance after order:', account.getBalance(app.getQuoteCurrency()))

                # if not live
                else:
                    if app.isVerbose() == 0:
                        logging.info(current_df_index + ' | ' + app.getMarket() + ' ' + str(app.getGranularity()) + ' | ' + price_text + ' | BUY')
                        print ("\n", current_df_index, '|', app.getMarket(), str(app.getGranularity()), '|', price_text, '| BUY')

                        bands = ta.getFibonacciRetracementLevels(float(price))                      
                        print (' Fibonacci Retracement Levels:', str(bands))
                        ta.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':
                                    fib_low = 0
                                    fib_high = bands[first_key]
                                if first_key == 'ratio1_618':
                                    fib_low = bands[first_key]
                                    fib_high = bands[first_key] * 2
                                else:
                                    fib_low = bands[first_key]

                            elif len(bands) == 2:
                                first_key = list(bands.keys())[0]
                                second_key = list(bands.keys())[1]
                                fib_low = bands[first_key] 
                                fib_high = bands[second_key]
                            
                    else:
                        print('--------------------------------------------------------------------------------')
                        print('|                      *** Executing TEST Buy Order ***                        |')
                        print('--------------------------------------------------------------------------------')

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

            # if a sell signal
            elif action == 'SELL':
                sell_count = sell_count + 1
                fee = float(price) * 0.005
                price_incl_fees = float(price) - fee
                sell_sum = sell_sum + price_incl_fees

                # if live
                if app.isLive() == 1:
                    # telegram
                    if app.isTelegramEnabled():
                        telegram = Telegram(app.getTelegramToken(), app.getTelegramClientId())
                        telegram.send(app.getMarket() + ' (' + str(app.getGranularity()) + ') SELL at ' + price_text)

                    if app.isVerbose() == 0:
                        logging.info(current_df_index + ' | ' + app.getMarket() + ' ' + str(app.getGranularity()) + ' | ' + price_text + ' | SELL')
                        print ("\n", current_df_index, '|', app.getMarket(), str(app.getGranularity()), '|', price_text, '| SELL')

                        bands = ta.getFibonacciRetracementLevels(float(price))                      
                        print (' Fibonacci Retracement Levels:', str(bands), "\n")                    

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

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

                    else:
                        print('--------------------------------------------------------------------------------')
                        print('|                      *** Executing LIVE Sell Order ***                        |')
                        print('--------------------------------------------------------------------------------')

                    # display balances
                    print (app.getBaseCurrency(), 'balance before order:', account.getBalance(app.getBaseCurrency()))
                    print (app.getQuoteCurrency(), 'balance before order:', account.getBalance(app.getQuoteCurrency()))

                    # execute a live market sell
                    resp = app.marketSell(app.getMarket(), float(account.getBalance(app.getBaseCurrency())))
                    logging.info(resp)

                    # display balances
                    print (app.getBaseCurrency(), 'balance after order:', account.getBalance(app.getBaseCurrency()))
                    print (app.getQuoteCurrency(), 'balance after order:', account.getBalance(app.getQuoteCurrency()))

                # if not live
                else:
                    if app.isVerbose() == 0:
                        sell_price = float(str(app.truncate(price, precision)))
                        last_buy_price = float(str(app.truncate(float(last_buy), precision)))
                        buy_sell_diff = round(np.subtract(sell_price, last_buy_price), precision)

                        if (sell_price != 0):
                            buy_sell_margin_no_fees = str(app.truncate((((sell_price - last_buy_price) / sell_price) * 100), 2)) + '%'
                        else:
                            buy_sell_margin_no_fees = '0%'

                        # calculate last buy minus fees
                        buy_fee = last_buy_price * 0.005
                        last_buy_price_minus_fees = last_buy_price + buy_fee

                        if (sell_price != 0):
                            buy_sell_margin_fees = str(app.truncate((((sell_price - last_buy_price_minus_fees) / sell_price) * 100), 2)) + '%'
                        else:
                            buy_sell_margin_fees = '0%'

                        logging.info(current_df_index + ' | ' + app.getMarket() + ' ' + str(app.getGranularity()) + ' | SELL | ' + str(sell_price) + ' | BUY | ' + str(last_buy_price) + ' | DIFF | ' + str(buy_sell_diff) + ' | MARGIN NO FEES | ' + str(buy_sell_margin_no_fees) + ' | MARGIN FEES | ' + str(buy_sell_margin_fees))
                        print ("\n", current_df_index, '|', app.getMarket(), str(app.getGranularity()), '| SELL |', str(sell_price), '| BUY |', str(last_buy_price), '| DIFF |', str(buy_sell_diff) , '| MARGIN NO FEES |', str(buy_sell_margin_no_fees), '| MARGIN FEES |', str(buy_sell_margin_fees), "\n")                    
                    else:
                        print('--------------------------------------------------------------------------------')
                        print('|                      *** Executing TEST Sell Order ***                        |')
                        print('--------------------------------------------------------------------------------')

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

            # last significant action
            if action in [ 'BUY', 'SELL' ]:
                last_action = action
            
            last_df_index = str(df_last.index.format()[0])

            if iterations == len(df):
                print ("\nSimulation Summary\n")

                if buy_count > sell_count:
                    fee = price * 0.005
                    last_price_minus_fees = price - fee
                    sell_sum = sell_sum + last_price_minus_fees
                    sell_count = sell_count + 1

                print ('   Buy Count :', buy_count)
                print ('  Sell Count :', sell_count, "\n")

                if sell_count > 0:
                    print ('      Margin :', str(app.truncate((((sell_sum - buy_sum) / sell_sum) * 100), 2)) + '%', "\n")

                    print ('  ** non-live simulation, assuming highest fees', "\n")

        else:
            print (str(app.getTime()), '|', app.getMarket() + bullbeartext, '|', str(app.getGranularity()), '| Current Price:', price)

            # decrement ignored iteration
            iterations = iterations - 1

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

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

        else:
            # poll every 5 minute
            list(map(s.cancel, s.queue))
            s.enter(300, 1, executeJob, (sc, app))
"""Trading Graphs object model examples"""

import pandas as pd
from models.Trading import TechnicalAnalysis
from models.CoinbasePro import PublicAPI
from views.TradingGraphs import TradingGraphs

api = PublicAPI()
tradingData = api.getHistoricalData('BTC-GBP', 3600)

technicalAnalysis = TechnicalAnalysis(tradingData)
technicalAnalysis.addAll()

tradinggraphs = TradingGraphs(technicalAnalysis)
"""Uncomment the diagram to display"""

tradinggraphs.renderPriceEMA12EMA26()

#tradinggraphs.renderEMAandMACD()
#tradinggraphs.renderSMAandMACD()

#tradinggraphs.renderBuySellSignalEMA1226()
#tradinggraphs.renderBuySellSignalEMA1226MACD()

#tradinggraphs.renderPriceSupportResistance()

#tradinggraphs.renderSeasonalARIMAModel()
#tradinggraphs.renderSeasonalARIMAModelPredictionDays(5)
Example #11
0
"""Trading Graphs object model examples"""

import pandas as pd
from datetime import datetime
from models.Trading import TechnicalAnalysis
from models.CoinbasePro import PublicAPI
from views.TradingGraphs import TradingGraphs

api = PublicAPI()
tradingData = api.getHistoricalData('BTC-GBP', 3600)

technicalAnalysis = TechnicalAnalysis(tradingData)
technicalAnalysis.addAll()

tradinggraphs = TradingGraphs(technicalAnalysis)
"""Uncomment the diagram to display"""

#tradinggraphs.renderEMAandMACD()
#tradinggraphs.renderEMAandMACD(24)
ts = datetime.now().timestamp()
filename = 'BTC-GBP_3600_' + str(ts) + '.png'
tradinggraphs.renderEMAandMACD(24, 'graphs/' + filename, True)

#tradinggraphs.renderPriceEMA12EMA26()

#tradinggraphs.renderEMAandMACD()
#tradinggraphs.renderSMAandMACD()

#tradinggraphs.renderBuySellSignalEMA1226()
#tradinggraphs.renderBuySellSignalEMA1226MACD()
Example #12
0
def runExperiment(id, market='BTC-GBP', granularity=3600, mostRecent=True):
    """Run an experiment

    Parameters
    ----------
    market : str
        A valid market/product from the Coinbase Pro exchange. (Default: 'BTC-GBP')
    granularity : int
        A valid market interval {60, 300, 900, 3600, 21600, 86400} (Default: 86400 - 1 day)
    """

    if not isinstance(id, int):
        raise TypeError('ID not numeric.')

    if id < 0:
        raise TypeError('ID is invalid.')

    p = re.compile(r"^[A-Z]{3,4}\-[A-Z]{3,4}$")
    if not p.match(market):
        raise TypeError('Coinbase Pro market required.')

    cryptoMarket, fiatMarket = market.split('-', 2)

    if not isinstance(granularity, int):
        raise TypeError('Granularity integer required.')

    if not granularity in [60, 300, 900, 3600, 21600, 86400]:
        raise TypeError(
            'Granularity options: 60, 300, 900, 3600, 21600, 86400.')

    if not isinstance(mostRecent, bool):
        raise TypeError('Most recent is a boolean.')

    print('Experiment #' + str(id) + "\n")

    endDate = datetime.now() - timedelta(hours=random.randint(
        0, 8760 * 3))  # 3 years in hours
    startDate = endDate - timedelta(hours=300)

    if mostRecent == True:
        startDate = ''
        endDate = ''
        print('Start date:',
              (datetime.now() - timedelta(hours=300)).isoformat())
        print('  End date:', datetime.now().isoformat())
        print('')
    else:
        startDate = str(startDate.isoformat())
        endDate = str(endDate.isoformat())
        print('Start date:', startDate)
        print('  End date:', endDate)
        print('')

    # instantiate a non-live trade account
    account = TradingAccount()

    # instantiate a CoinbassePro object with desired criteria
    coinbasepro = CoinbasePro(market, granularity, startDate, endDate)

    # adds buy and sell signals to Pandas DataFrame
    coinbasepro.addEMABuySignals()
    coinbasepro.addMACDBuySignals()

    # stores the Pandas Dataframe in df
    df = coinbasepro.getDataFrame()

    # defines the buy and sell signals and consolidates into df_signals
    buysignals = ((df.ema12gtema26co == True) & (df.macdgtsignal == True) &
                  (df.obv_pc > 0)) | ((df.ema12gtema26 == True) &
                                      (df.ema12gtema26 == True) &
                                      (df.macdgtsignal == True) &
                                      (df.obv_pc >= 2))
    sellsignals = (((df.ema12ltema26co == True) & (df.macdltsignal == True)) |
                   ((df.ema12gtema26 == True) & ((df.macdltsignal == True) &
                                                 (df.obv_pc < 0))))
    df_signals = df[(buysignals) | (sellsignals)]

    diff = 0
    action = ''
    last_action = ''
    last_close = 0
    total_diff = 0
    events = []
    # iterate through the DataFrame buy and sell signals
    for index, row in df_signals.iterrows():
        df_orders = account.getOrders()

        # determine if the df_signal is a buy or sell, just a high level check
        if row['ema12gtema26'] == True and row['macdgtsignal'] == True:
            action = 'buy'
        elif row['ema12ltema26co'] == True and row['macdltsignal'] == True:
            # ignore sell if close is lower than previous buy
            if len(df_orders) > 0 and df_orders.iloc[[
                    -1
            ]]['action'].values[0] == 'buy' and row['close'] > df_orders.iloc[[
                    -1
            ]]['price'].values[0]:
                action = 'sell'

        if action != '' and action != last_action and not (
                last_action == '' and action == 'sell'):
            if last_action != '':
                if action == 'sell':
                    diff = row['close'] - last_close
                else:
                    diff = 0.00

            if action == 'buy':
                account.buy(cryptoMarket, fiatMarket, 100, row['close'])
            elif action == 'sell':
                account.sell(cryptoMarket, fiatMarket,
                             df_orders.iloc[[-1]]['size'].values[0],
                             row['close'])

            data_dict = {
                'market': market,
                'granularity': granularity,
                'start': startDate,
                'end': endDate,
                'action': action,
                'index': str(index),
                'close': row['close'],
                'sma200': row['sma200'],
                'ema12': row['ema12'],
                'ema26': row['ema26'],
                'macd': row['macd'],
                'signal': row['signal'],
                'ema12gtema26co': row['ema12gtema26co'],
                'macdgtsignal': row['macdgtsignal'],
                'ema12ltema26co': row['ema12ltema26co'],
                'macdltsignal': row['macdltsignal'],
                'obv_pc': row['obv_pc'],
                'diff': diff
            }

            events.append(data_dict)

            last_action = action
            last_close = row['close']
            total_diff = total_diff + diff

    # displays the events from the simulation
    events_df = pd.DataFrame(events)
    print(events_df)

    # if the last transation was a buy retrieve open amount
    addBalance = 0
    df_orders = account.getOrders()
    if len(df_orders) > 0 and df_orders.iloc[[-1
                                              ]]['action'].values[0] == 'buy':
        # last trade is still open, add to closing balance
        addBalance = df_orders.iloc[[-1]]['value'].values[0]

    # displays the orders from the simulation
    print('')
    print(df_orders)

    def truncate(f, n):
        return math.floor(f * 10**n) / 10**n

    # if the last transaction was a buy add the open amount to the closing balance
    result = truncate(
        round((account.getBalance(fiatMarket) + addBalance) - 1000, 2), 2)

    print('')
    print("Opening balance:", 1000)
    print("Closing balance:",
          truncate(round(account.getBalance(fiatMarket) + addBalance, 2), 2))
    print("         Result:", result)
    print('')

    # saves the rendered diagram for the DataFrame (without displaying)
    tradinggraphs = TradingGraphs(coinbasepro)
    tradinggraphs.renderBuySellSignalEMA1226MACD(
        'experiments/experiment' + str(id) + '_' + str(result) + '.png', True)

    result_dict = {
        'market':
        market,
        'granularity':
        granularity,
        'start':
        startDate,
        'end':
        endDate,
        'open':
        1000,
        'close':
        '{:.2f}'.format(round(account.getBalance(fiatMarket) + addBalance, 2)),
        'result':
        result
    }

    return result_dict