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