示例#1
0
        last_action = 'BUY'
    elif (market.startswith('BCH-')
          and account.getBalance(cryptoMarket) > 0.01):
        last_action = 'BUY'
    elif (market.startswith('ETH-')
          and account.getBalance(cryptoMarket) > 0.01):
        last_action = 'BUY'
    elif (market.startswith('LTC-')
          and account.getBalance(cryptoMarket) > 0.1):
        last_action = 'BUY'
    elif (market.startswith('XLM-') and account.getBalance(cryptoMarket) > 35):
        last_action = 'BUY'
    elif (account.getBalance(fiatMarket) > 30):
        last_action = 'SELL'

    authAPI = AuthAPI(config['api_key'], config['api_secret'],
                      config['api_pass'], config['api_url'])
    orders = authAPI.getOrders(market)
    if len(orders) > 0:
        df = orders[-1:]
        price = df[df.action == 'buy']['price']
        if len(price) > 0:
            last_buy = float(truncate(price, 2))


def executeJob(sc, market, granularity, tradingData=pd.DataFrame()):
    """Trading bot job which runs at a scheduled interval"""
    global action, iterations, last_action, last_buy, last_df_index, x_since_buy, x_since_sell

    # increment iterations
    iterations = iterations + 1
示例#2
0
def executeJob(sc, market, granularity, tradingData=pd.DataFrame()):
    """Trading bot job which runs at a scheduled interval"""
    global action, iterations, last_action, last_buy, last_df_index, 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_star_doji = bool(df_last['morning_star_doji'].values[0])
    evening_star_doji = bool(df_last['evening_star_doji'].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 obv_pc > 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'
    # anything other than a buy or sell, just wait
    else:
        action = 'WAIT'

    # 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])
        price_text = 'Price: ' + str(
            truncate(float(df_last['close'].values[0]), 2))
        ema_text = compare(df_last['ema12'].values[0],
                           df_last['ema26'].values[0], 'EMA12/26')
        macd_text = compare(df_last['macd'].values[0],
                            df_last['signal'].values[0], 'MACD')
        obv_text = compare(df_last['obv_pc'].values[0], 0.1, 'OBV %')
        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 Patern - Up")'
            print(log_text, "\n")
            logging.debug(log_text)

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

        if three_black_crows == True:
            log_text = '* Candlestick Detected: Inverted Hammer ("Weak - Continuation - Bullish Patern - Up")'
            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: Morning Star ("Strong - Reversal - Bullish Pattern - Up")'
            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_star_doji == True:
            log_text = '** Candlestick Detected: Morning Star Doji ("Reliable - Reversal - Bullish Pattern  - Up")'
            print(log_text, "\n")
            logging.debug(log_text)

        if evening_star_doji == True:
            log_text = '** Candlestick Detected: Morning Star Doji ("Reliable - Reversal - Bullish Pattern  - Up")'
            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 ema12gtema26 == True:
            ema_co_prefix = '^ '
            ema_co_suffix = ' ^'
        elif ema12ltema26 == True:
            ema_co_prefix = 'v '
            ema_co_suffix = ' v'
        elif ema12gtema26co == True:
            ema_co_prefix = '*^ '
            ema_co_suffix = ' ^*'
        elif ema12ltema26co == True:
            ema_co_prefix = '*v '
            ema_co_suffix = ' v*'

        macd_co_prefix = ''
        macd_co_suffix = ''
        if macdgtsignal == True:
            macd_co_prefix = '^ '
            macd_co_suffix = ' ^'
        elif macdltsignal == True:
            macd_co_prefix = 'v '
            macd_co_suffix = ' v'
        elif macdgtsignalco == True:
            macd_co_prefix = '*^ '
            macd_co_suffix = ' ^*'
        elif macdltsignalco == 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 (ema12gtema26co == True and macdgtsignal == True):
            x_since_buy = x_since_buy + 1
        # increment x since sell
        elif (ema12ltema26co == True and macdltsignal == True):
            x_since_sell = x_since_sell + 1

        # if a buy signal
        if action == 'BUY':
            # 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':
            # 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:
                    logging.info(ts_text + ' | ' + market + ' ' +
                                 str(granularity) + ' | ' + price_text +
                                 ' | SELL')
                    print("\n", ts_text, '|', market, granularity, '|',
                          price_text, '| SELL', "\n")
                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()
    else:
        # decrement igored 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))
def test_instantiate_authapi_without_error():
    api_key = "00000000000000000000000000000000"
    api_secret = "0000/0000000000/0000000000000000000000000000000000000000000000000000000000/00000000000=="
    api_passphrase = "00000000000"
    exchange = AuthAPI(api_key, api_secret, api_passphrase)
    assert type(exchange) is AuthAPI
示例#4
0
def executeJob(sc, market, granularity, tradingData=pd.DataFrame()):
    """Trading bot job which runs at a scheduled interval"""
    global action, iterations, x_since_buy, x_since_sell, last_action, last_df_index

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

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

    # criteria for a buy signal
    if ((ema12gtema26co == True and macdgtsignal == True and obv_pc > 0.1) or
        (ema12gtema26 == True and macdgtsignal == True and obv_pc > 0.1
         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) and last_action not in ['', 'SELL']:
        action = 'SELL'
    # anything other than a buy or sell, just wait
    else:
        action = 'WAIT'

    # 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])
        price_text = 'Price: ' + str(
            truncate(float(df_last['close'].values[0]), 2))
        ema_text = compare(df_last['ema12'].values[0],
                           df_last['ema26'].values[0], 'EMA12/26')
        macd_text = compare(df_last['macd'].values[0],
                            df_last['signal'].values[0], 'MACD')
        obv_text = compare(df_last['obv_pc'].values[0], 0, 'OBV %')
        counter_text = '[I:' + str(iterations) + ',B:' + str(
            x_since_buy) + ',S:' + str(x_since_sell) + ']'

        ema_co_prefix = ''
        ema_co_suffix = ''
        if ema12gtema26co == True or ema12ltema26co == True:
            ema_co_prefix = '* '
            ema_co_suffix = ' *'

        macd_co_prefix = ''
        macd_co_suffix = ''
        if macdgtsignalco == True or macdltsignalco == True:
            macd_co_prefix = '* '
            macd_co_suffix = ' *'

        if is_verbose == 0:
            output_text = ts_text + ' | ' + price_text + ' | ' + ema_co_prefix + ema_text + ema_co_suffix + ' | ' + macd_co_prefix + macd_text + macd_co_suffix + ' | ' + obv_text + ' | ' + action + ' ' + counter_text
            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) + ' --')

            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':
            x_since_buy = x_since_buy + 1
        elif last_action == 'SELL':
            x_since_sell = x_since_sell + 1

        # if a buy signal
        if action == 'BUY':
            # increment x since buy
            x_since_buy = x_since_buy + 1

            # reset x since sell
            x_since_sell = 0

            # if live
            if is_live == 1:
                if is_verbose == 0:
                    logging.info(ts_text + ' | ' + market + ' ' +
                                 str(granularity) + ' | ' + price_text +
                                 ' | BUY')
                    print(ts_text, '|', market, granularity, '|', price_text,
                          '| BUY')
                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(ts_text, '|', market, granularity, '|', price_text,
                          '| BUY')
                else:
                    print(
                        '--------------------------------------------------------------------------------'
                    )
                    print(
                        '|                      *** Executing TEST Buy Order ***                        |'
                    )
                    print(
                        '--------------------------------------------------------------------------------'
                    )
            #print(df_last[['close','ema12','ema26','ema12gtema26','ema12gtema26co','macd','signal','macdgtsignal','obv','obv_pc']])

        # if a sell signal
        elif action == 'SELL':
            # increment x since buy
            x_since_sell = x_since_sell + 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(ts_text, '|', market, granularity, '|', price_text,
                          '| SELL')
                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:
                    logging.info(ts_text + ' | ' + market + ' ' +
                                 str(granularity) + ' | ' + price_text +
                                 ' | SELL')
                    print(ts_text, '|', market, granularity, '|', price_text,
                          '| SELL')
                else:
                    print(
                        '--------------------------------------------------------------------------------'
                    )
                    print(
                        '|                      *** Executing TEST Sell Order ***                        |'
                    )
                    print(
                        '--------------------------------------------------------------------------------'
                    )
            #print(df_last[['close','ema12','ema26','ema12ltema26','ema12ltema26co','macd','signal','macdltsignal','obv','obv_pc']])

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

        last_df_index = df_last.index.format()

    # 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))
    def sell(self,
             cryptoMarket,
             fiatMarket,
             cryptoAmount,
             manualPrice=0.00000000):
        """Places a sell order either live or simulation

        Parameters
        ----------
        cryptoMarket: str
            Crypto market you wish to purchase
        fiatMarket, str
            FIAT market funding the purchase
        fiatAmount, float
            FIAT amount of crypto currency to purchase
        manualPrice, float
            Used for simulations specifying the live price to purchase
        """
        # crypto market should be either BCH, BTC, ETH or LTC
        if cryptoMarket not in ['BCH', 'BTC', 'ETH', 'LTC']:
            raise Exception('Invalid crypto market: BCH, BTC, ETH, LTC or ETH')

        # fiat market should be either EUR, GBP, or USD
        if fiatMarket not in ['EUR', 'GBP', 'USD']:
            raise Exception('Invalid FIAT market: EUR, GBP, USD')

        # reconstruct the exchange market using crypto and fiat inputs
        market = cryptoMarket + '-' + fiatMarket

        # crypto amount must be an integer or float
        if not isinstance(cryptoAmount, float) and not isinstance(
                cryptoAmount, int):
            raise TypeError('Crypto amount not numeric.')

        # crypto amount must be positive
        if cryptoAmount <= 0:
            raise Exception('Invalid crypto amount.')

        if self.mode == 'live':
            # connect to Coinbase Pro API live
            model = AuthAPI(self.api_key, self.api_secret, self.api_pass,
                            self.api_url)

            # execute a live market sell
            resp = model.marketSell(market,
                                    float(self.getBalance(cryptoMarket)))

            # TODO: not finished
            print(resp)
        else:
            # crypto amount should exceed balance
            if cryptoAmount > self.getBalance(cryptoMarket):
                raise Exception('Insufficient funds.')

            # manual price must be an integer or float
            if not isinstance(manualPrice, float) and not isinstance(
                    manualPrice, int):
                raise TypeError('Optional manual price not numeric.')

            # calculate purchase fees
            fee = cryptoAmount * 0.005
            cryptoAmountMinusFee = cryptoAmount - fee

            price = manualPrice
            if manualPrice <= 0:
                # if manualPrice is non-positive retrieve the current live price
                resp = requests.get(
                    'https://api-public.sandbox.pro.coinbase.com/products/' +
                    market + '/ticker')
                if resp.status_code != 200:
                    raise Exception('GET /products/' + market +
                                    '/ticker {}'.format(resp.status_code))
                resp.raise_for_status()
                json = resp.json()
                price = float(json['price'])

            total = price * cryptoAmountMinusFee

            # append dummy order into orders dataframe
            ts = pd.Timestamp.now()
            price = ((price * cryptoAmount) * 100) / (cryptoAmount * 100)
            order = pd.DataFrame([[
                market, 'sell', 'market', cryptoAmountMinusFee,
                float('{:.8f}'.format(total)), 'done', price
            ]],
                                 columns=[
                                     'market', 'action', 'type', 'size',
                                     'value', 'status', 'price'
                                 ],
                                 index=[ts])
            self.orders = pd.concat(
                [self.orders, pd.DataFrame(order)], ignore_index=False)

            # update the dummy fiat balance
            self.balance.loc[self.balance['currency'] == fiatMarket,
                             'balance'] = self.getBalance(fiatMarket) + total
            self.balance.loc[self.balance['currency'] == fiatMarket,
                             'available'] = self.getBalance(fiatMarket) + total

            # update the dummy crypto balance
            self.balance.loc[
                self.balance['currency'] == cryptoMarket,
                'balance'] = self.getBalance(cryptoMarket) - cryptoAmount
            self.balance.loc[
                self.balance['currency'] == cryptoMarket,
                'available'] = self.getBalance(cryptoMarket) - cryptoAmount
    def getBalance(self, currency=''):
        """Retrieves balance either live or simulation

        Parameters
        ----------
        currency: str, optional
            Filters orders by currency
        """

        if self.mode == 'live':
            # if config is provided and live connect to Coinbase Pro account portfolio
            model = AuthAPI(self.api_key, self.api_secret, self.api_pass,
                            self.api_url)
            if currency == '':
                # retrieve all balances
                return model.getAccounts()[[
                    'currency', 'balance', 'hold', 'available'
                ]]
            else:
                df = model.getAccounts()
                # retrieve balance of specified currency
                df_filtered = df[df['currency'] == currency]['available']
                if len(df_filtered) == 0:
                    # return nil balance if no positive balance was found
                    return 0.0
                else:
                    # return balance of specified currency (if positive)
                    if currency in ['EUR', 'GBP', 'USD']:
                        return self.truncate(
                            float(df[df['currency'] == currency]
                                  ['available'].values[0]), 2)
                    else:
                        return self.truncate(
                            float(df[df['currency'] == currency]
                                  ['available'].values[0]), 4)

        else:
            # return dummy balances

            if currency == '':
                # retrieve all balances
                return self.balance
            else:
                # replace FIAT and CRYPTO placeholders
                if currency in ['EUR', 'GBP', 'USD']:
                    self.balance = self.balance.replace('FIAT', currency)
                elif currency in ['BCH', 'BTC', 'ETH', 'LTC']:
                    self.balance = self.balance.replace('CRYPTO', currency)

                if self.balance.currency[self.balance.currency.isin(
                    [currency])].empty == True:
                    self.balance.loc[len(self.balance)] = [currency, 0, 0, 0]

                # retrieve balance of specified currency
                df = self.balance
                df_filtered = df[df['currency'] == currency]['available']

                if len(df_filtered) == 0:
                    # return nil balance if no positive balance was found
                    return 0.0
                else:
                    # return balance of specified currency (if positive)
                    if currency in ['EUR', 'GBP', 'USD']:
                        return self.truncate(
                            float(df[df['currency'] == currency]
                                  ['available'].values[0]), 2)
                    else:
                        return self.truncate(
                            float(df[df['currency'] == currency]
                                  ['available'].values[0]), 4)
示例#7
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, buy_state, x_since_buy, x_since_sell

    # increment iterations
    iterations = iterations + 1

    # coinbase pro public api
    api = PublicAPI()

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

    df = pd.DataFrame()
    if len(tradingData) != 300:
        # data frame should have 300 rows, if not retry
        print('error: data frame length is < 300 (' + str(len(tradingData)) +
              ')')
        logging.error('error: data frame length is < 300 (' +
                      str(len(tradingData)) + ')')
        s.enter(1, 1, executeJob, (sc, market, granularity))
    else:
        # analyse the market data
        tradingDataCopy = tradingData.copy()
        technicalAnalysis = TechnicalAnalysis(tradingDataCopy)
        technicalAnalysis.addAll()
        df = technicalAnalysis.getDataFrame()

    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)

    current_df_index = str(df_last.index.format()[0])

    if is_sim == 0:
        price = api.getTicker(market)
        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])

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

    # 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 obv_pc > 1) or
        (ema12gtema26 == True and macdgtsignal == True and obv_pc > 1
         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'

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

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

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

    goldendeathtext = ''
    if goldencross == True:
        goldendeathtext = ' (BULL)'
    else:
        goldendeathtext = ' (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 cryptoMarket == 'XLM':
            precision = 4

        price_text = 'Close: ' + str(truncate(price, 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 = current_df_index + ' | ' + market + goldendeathtext + ' | ' + str(
                    granularity
                ) + ' | ' + 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 = current_df_index + ' | ' + market + goldendeathtext + ' | ' + str(
                    granularity
                ) + ' | ' + 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) + ' --' +
                          goldendeathtext)
            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(price, 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) + goldendeathtext
            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 = '            Close : ' + str(truncate(price, 2))
            print('|', txt, (' ' * (75 - len(txt))), '|')
            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):
            if buy_state == '':
                buy_state = 'NO_BUY'

            if buy_state != 'NO_BUY' or buy_state == 'NORMAL':
                x_since_buy = x_since_buy + 1

        # increment x since sell
        elif (ema12ltema26 == True):
            x_since_sell = x_since_sell + 1
            buy_state = 'NORMAL'
            failsafe = False

        # 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(current_df_index + ' | ' + market + ' ' +
                                 str(granularity) + ' | ' + price_text +
                                 ' | BUY')
                    print("\n", current_df_index, '|', 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(current_df_index + ' | ' + market + ' ' +
                                 str(granularity) + ' | ' + price_text +
                                 ' | BUY')
                    print("\n", current_df_index, '|', market, granularity,
                          '|', price_text, '| BUY')
                    print(
                        ' Fibonacci Retracement Levels:',
                        str(
                            technicalAnalysis.getFibonacciRetracementLevels(
                                float(price))), "\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(current_df_index + ' | ' + market + ' ' +
                                 str(granularity) + ' | ' + price_text +
                                 ' | SELL')
                    print("\n", current_df_index, '|', market, granularity,
                          '|', price_text, '| SELL')
                    print(
                        ' Fibonacci Retracement Levels:',
                        str(
                            technicalAnalysis.getFibonacciRetracementLevels(
                                float(price))), "\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 == 1:
                    print(
                        '--------------------------------------------------------------------------------'
                    )
                    print(
                        '|                      *** Executing TEST Sell Order ***                        |'
                    )
                    print(
                        '--------------------------------------------------------------------------------'
                    )

                sell_price = float(str(truncate(price, 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(current_df_index + ' | ' + 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", current_df_index, '|', 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

            #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 = str(df_last.index.format()[0])

        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(price, precision)) -
                                     last_buy_minus_fees)

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

            margin_decimal = (sell_sum - buy_sum) / sell_sum if sell_sum else 0
            print('      Margin :',
                  str(truncate((margin_decimal * 100), 2)) + '%', "\n")
    else:
        now = datetime.today().strftime('%Y-%m-%d %H:%M:%S')
        print(now, '|', market + goldendeathtext, '|', str(granularity),
              '| Current Price:', price)

        # decrement ignored iteration
        iterations = iterations - 1

    # if live
    if is_live == 1:
        # update order tracker csv
        account.saveTrackerCSV()

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

    else:
        # poll every 5 minute
        s.enter(300, 1, executeJob, (sc, market, granularity))