def tick_by_tick(market, entry_funcs, exit_funcs, interval=var.default_interval, smas=var.default_smas, emas=var.default_emas, refresh_interval=1, from_file=True, plot=False, log_level=2): ''' Simulates a working bot, in realtime or in faster speed, using pre own data from DB or file, to test an autonomous bot on a specific market. Args: markets(string): list with markets to backtest or empty to run all available markets. entry_funcs(list): list of entry functions to test. exit_funcs(list): list of entry functions to test. interval(string): time between measures. smas(list): list of SMA values to use. emas(list): list of EMA values to use. refresh_interval(int): Refresh rate. main_coins(list): ''' #log_level: # 0 - Only presents total. # 1 - Writes logs to file. # 2 - Writes logs to file and prints on screen. # Default is 2. #plt.ion() var.global_log_level = log_level signal.signal(signal.SIGINT, signal_handler) date = [0, 0] total = 0 #market = check_market_name(market) entry_points_x = [] entry_points_y = [] exit_points_x = [] exit_points_y = [] if not isinstance(entry_funcs, list): entry_funcs = [entry_funcs] if not isinstance(exit_funcs, list): exit_funcs = [exit_funcs] print(f'[Market analysis]: {market}') if from_file: try: data = get_data_from_file(market, interval=interval) except Exception as e: log(str(e), 1) log('[ERROR] Can\'t find ' + market + ' in files.', 1) return 0 data_init = data #if type(_date[0]) is str: # date[0], date[1] = time_to_index(data, _date) #if date[1] == 0: # data = data[date[0]:] #else: # data = data[date[0]:date[1]] else: try: data = get_historical_data(market, interval=interval, init_date=_date[0], end_date=_date[1]) date[0], date[1] = 0, len(data) data_init = data except Exception as e: log(str(e), 1) log('[ERROR] Can\'t find ' + market + ' in BD.', 1) return 0 #continue aux_buy = False buy_price = 0 high_price = 0 #plt.show() #Tests several functions. for i in range(len(data) - 110): start_time = time() #print(data_init.Last.iloc[i]) if not aux_buy: if is_time_to_buy(data[i:i + 110], entry_funcs, smas, emas): buy_price = data_init.Ask.iloc[i + 109 + date[0]] high_price = buy_price entry_points_x.append(i + 109) entry_points_y.append(data_init.Ask.iloc[i + 109 + date[0]]) if exit_funcs: aux_buy = True print(f'''{data_init.time.iloc[i + 109 + date[0]]} \ [BUY] @ {data_init.Ask.iloc[i + 109 + date[0]]}''') else: # Used for trailing stop loss. if data_init.Last.iloc[i + 109 + date[0]] > high_price: high_price = data_init.Last.iloc[i + 109 + date[0]] if is_time_to_exit(data[i:i + 110], exit_funcs, smas, emas, stop=0, bought_at=buy_price, max_price=high_price): exit_points_x.append(i + 109) exit_points_y.append(data_init.Bid.iloc[i + 109 + date[0]]) aux_buy = False total += round( ((data_init.Bid.iloc[i + 109 + date[0]] - buy_price) / buy_price) * 100, 2) print(f'''{data_init.time.iloc[i + 109 + date[0]]} \ [SELL]@ {data_init.Bid.iloc[i + 109 + date[0]]}''') print(f'[P&L] > {total}%.') #plt.plot(data.Last.iloc[i:i+50]) #plt.draw() #plt.clf() # In case of processing time is bigger than *refresh_interval* doesn't sleep. if refresh_interval - (time() - start_time) >= 0: sleep(refresh_interval - (time() - start_time)) return total
def backtest_market(entry_funcs, exit_funcs, interval, _date, smas, emas, from_file, to_file, plot, exchange, db_client, log_level, market): ''' Backtests strategies for a specific market. Args: entry_funcs(list): list of entry functions to test. exit_funcs(list): list of entry functions to test. interval(string): time between measures. _date(list): init and end point to backtest. smas(list): list of SMA values to use. emas(list): list of EMA values to use. to_file(bool): plot to file. from_file(bool): get data from file. plot(bool): plot data. markets(string): list with markets to backtest or empty to test all available markets. Returns: float: returns backtests profit & loss value for applied strategies. ''' date = [0, 0] total = 0 #market = check_market_name(market) #global cached is_cached = False entry_points_x = [] entry_points_y = [] exit_points_x = [] exit_points_y = [] full_log = '[Market analysis]: ' + market + '\n' if from_file: try: data = get_data_from_file(market, interval=interval) except Exception as e: log(str(e), 0, log_level) log('[ERROR] Can\'t find ' + market + ' in files.', 0, log_level) return 0 data_init = data if isinstance(_date[0], str): date[0], date[1] = time_to_index(data, _date) else: date = _date if date[1] == 0: data = data[date[0]:] else: data = data[date[0]:date[1]] else: if market in cached and \ cached[market]['interval'] == interval and \ cached[market]['init_date'] == _date[0] and \ cached[market]['end_date'] == _date[1]: # Check if cached data is the same as you want. data = cached[market]['data'] cached[market]['last'] = 2 is_cached = True else: try: data = get_historical_data(market, interval=interval, init_date=_date[0], end_date=_date[1], exchange=exchange) date[0], date[1] = 0, len(data) except Exception as e: log(str(e), 0, log_level) log('[ERROR] Can\'t find ' + market + ' in BD.', 0, log_level) return 0 #continue data_init = data aux_buy = False buy_price = 0 high_price = 0 # # Test for volume. # if data.BaseVolume.mean() < 20: # log(full_log, 1, log_level) # del data # del data_init # return 0 #Tests several functions. for i in range(len(data) - 110): if not aux_buy: if is_time_to_buy(data[i:i + 110], entry_funcs, smas, emas): buy_price = data_init.Ask.iloc[i + 109 + date[0]] high_price = buy_price entry_points_x.append(i + 109) entry_points_y.append(data_init.Ask.iloc[i + 109 + date[0]]) if exit_funcs: aux_buy = True full_log += str(data_init.time.iloc[i + 109 + date[0]]) + \ ' [BUY] @ ' + str(data_init.Ask.iloc[i + 109 + date[0]]) + '\n' else: # Used for trailing stop loss. if data_init.Last.iloc[i + 109 + date[0]] > high_price: high_price = data_init.Last.iloc[i + 109 + date[0]] if is_time_to_exit(data[i:i + 110], exit_funcs, smas, emas, stop=0, bought_at=buy_price, max_price=high_price): exit_points_x.append(i + 109) exit_points_y.append(data_init.Bid.iloc[i + 109 + date[0]]) aux_buy = False total += round( ((data_init.Bid.iloc[i + 109 + date[0]] - buy_price) / buy_price) * 100, 2) full_log += str(data_init.time.iloc[i + 109 + date[0]]) + \ ' [SELL]@ ' + str(data_init.Bid.iloc[i + 109 + date[0]]) + '\n' full_log += '[P&L] > ' + str(total) + '%.' + '\n' del data_init # Use plot_data for just a few markets. If you try to run plot_data for several markets, # computer can start run really slow. try: if plot: plot_data(data, name=market, date=[0, 0], smas=smas, emas=None, entry_points=(entry_points_x, entry_points_y), exit_points=(exit_points_x, exit_points_y), show_smas=True, show_emas=True, show_bbands=False, to_file=to_file) except Exception as e: log("[ERROR] Ploting data: " + str(e), 0, log_level) if not is_cached: cached[market] = { 'interval': interval, 'init_date': _date[0], 'end_date': _date[1], 'data': data, 'last': 2 } #if len(exit_points_x): # log(market + ' > ' + str(total), log_level) log('[' + market + '][TOTAL]> ' + str(total) + '%.', 0, log_level) log(full_log, 1, log_level) if isnan(total): log("[ERROR] Total is isnan", 0, log_level) return 0 return total
def tick_by_tick( market, entry_funcs, exit_funcs, interval=var.default_interval, smas=var.default_smas, emas=var.default_emas, refresh_interval=1, from_file=True, # plot=False ): """ Simulates a working bot, in realtime or in faster speed, using pre own data from DB or file, to test an autonomous bot on a specific market. Args: market(string): list with markets to backtest or empty to run all available markets. entry_funcs(list): list of entry functions to test. exit_funcs(list): list of entry functions to test. interval(string): time between measures. smas(list): list of SMA values to use. emas(list): list of EMA values to use. refresh_interval(int): Refresh rate. from_file(bool): Select the origin of data. # plot(bool: plots data. """ # plt.ion() signal.signal(signal.SIGINT, signal_handler) date = [0, 0] total = 0 # market = check_market_name(market) entry_points_x = [] entry_points_y = [] exit_points_x = [] exit_points_y = [] if not isinstance(entry_funcs, list): entry_funcs = [entry_funcs] if not isinstance(exit_funcs, list): exit_funcs = [exit_funcs] log.info(f"[Market analysis]: {market}") if from_file: try: data = get_data_from_file(market, interval=interval) except Exception as e: log.error(f"Unable to get data from file: {e}") log.error(f"Unable to find {market} in files.") return 0 data_init = data # if type(_date[0]) is str: # date[0], date[1] = time_to_index(data, _date) # if date[1] == 0: # data = data[date[0]:] # else: # data = data[date[0]:date[1]] else: try: data = get_historical_data(market, interval=interval) date[0], date[1] = 0, len(data) data_init = data except Exception as e: log.error(f"Unable to get data from file: {e}") log.error(f"Unable to find {market} in DB.") return 0 aux_buy = False buy_price = 0 high_price = 0 # plt.show() # Tests several functions. for i in range(len(data) - 110): start_time = time() # print(data_init.Last.iloc[i]) if not aux_buy: if is_time_to_buy(data[i:i + 110], entry_funcs, smas, emas): buy_price = data_init.Ask.iloc[i + 109 + date[0]] high_price = buy_price entry_points_x.append(i + 109) entry_points_y.append(data_init.Ask.iloc[i + 109 + date[0]]) if exit_funcs: aux_buy = True log.info(f'''{data_init.time.iloc[i + 109 + date[0]]} \ [BUY] @ {data_init.Ask.iloc[i + 109 + date[0]]}''') else: # Used for trailing stop loss. if data_init.Last.iloc[i + 109 + date[0]] > high_price: high_price = data_init.Last.iloc[i + 109 + date[0]] if is_time_to_exit(data[i:i + 110], exit_funcs, smas, emas, stop=var.stop_type, bought_at=buy_price, max_price=high_price): exit_points_x.append(i + 109) exit_points_y.append(data_init.Bid.iloc[i + 109 + date[0]]) aux_buy = False total += round( ((data_init.Bid.iloc[i + 109 + date[0]] - buy_price) / buy_price) * 100, 2) log.info(f'''{data_init.time.iloc[i + 109 + date[0]]} \ [SELL]@ {data_init.Bid.iloc[i + 109 + date[0]]}''') log.info(f'[P&L] > {total}%.') # plt.plot(data.Last.iloc[i:i+50]) # plt.draw() # plt.clf() # In case of processing time is bigger than *refresh_interval* doesn't sleep. if refresh_interval - (time() - start_time) >= 0: sleep(refresh_interval - (time() - start_time)) return total