import pandas as pd from models.Trading import TechnicalAnalysis from models.CoinbasePro import PublicAPI api = PublicAPI() data = api.getHistoricalData('BTC-GBP', 3600) ta = TechnicalAnalysis(data) ta.addAll() #ta.addChangePct() #ta.addCMA() #ta.addSMA(20) #ta.addSMA(50) #ta.addSMA(200) #ta.addEMA(12) #ta.addEMA(26) #ta.addRSI(14) #ta.addMACD() #ta.addOBV() #ta.addEMABuySignals() #ta.addMACDBuySignals() #ta.addCandleHammer() #ta.addCandleInvertedHammer() #ta.addCandleShootingStar() #ta.addCandleHangingMan() #ta.addCandleThreeWhiteSoldiers() #ta.addCandleThreeBlackCrows() #ta.addCandleDojo() #ta.addCandleThreeLineStrike() #ta.addCandleTwoBlackGapping() #ta.addCandleEveningStar()
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))
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))
# if live if is_live == 1: # if live, ensure sufficient funds to place next buy order if (last_action == '' or last_action == 'SELL') and account.getBalance(fiatMarket) == 0: raise Exception('Insufficient ' + fiatMarket + ' funds to place next buy order!') # if live, ensure sufficient crypto to place next sell order elif last_action == 'BUY' and account.getBalance(cryptoMarket) == 0: raise Exception('Insufficient ' + cryptoMarket + ' funds to place next sell order!') s = sched.scheduler(time.time, time.sleep) # run the first job immediately after starting if is_sim == 1: api = PublicAPI() tradingData = api.getHistoricalData(market, granularity) executeJob(s, market, granularity, tradingData) else: executeJob(s, market, granularity) s.run() # catches a keyboard break of app, exits gracefully except KeyboardInterrupt: print(datetime.now(), 'closed') try: sys.exit(0) except SystemExit: os._exit(0)
s = sched.scheduler(time.time, time.sleep) # run the first job immediately after starting if is_sim == 1: api = PublicAPI() if sim_speed in ['fast-sample', 'slow-sample']: tradingData = pd.DataFrame() attempts = 0 while len(tradingData) != 300 and attempts < 10: endDate = datetime.now() - timedelta(hours=random.randint( 0, 8760 * 3)) # 3 years in hours startDate = endDate - timedelta(hours=300) tradingData = api.getHistoricalData(market, granularity, startDate.isoformat(), endDate.isoformat()) attempts += 1 if len(tradingData) != 300: raise Exception( 'Unable to retrieve 300 random sets of data between ' + str(startDate) + ' and ' + str(endDate) + ' in ' + str(attempts) + ' attempts.') startDate = str(startDate.isoformat()) endDate = str(endDate.isoformat()) txt = ' Sampling start : ' + str(startDate) print('|', txt, (' ' * (75 - len(txt))), '|') txt = ' Sampling end : ' + str(endDate) print('|', txt, (' ' * (75 - len(txt))), '|')