in tech test
This commit is contained in:
		| @@ -73,6 +73,35 @@ class Backtesting(object): | |||||||
|  |  | ||||||
|         self.stop_loss_value = self.analyze.strategy.stoploss |         self.stop_loss_value = self.analyze.strategy.stoploss | ||||||
|  |  | ||||||
|  |         #### backslap config | ||||||
|  |         ''' | ||||||
|  |         Numpy arrays are used for 100x speed up | ||||||
|  |         We requires setting Int values for | ||||||
|  |         buy stop triggers and stop calculated on | ||||||
|  |         # buy 0 - open 1 - close 2 - sell 3 - high 4 - low 5 - stop 6 | ||||||
|  |         ''' | ||||||
|  |         self.np_buy: int = 0 | ||||||
|  |         self.np_open: int = 1 | ||||||
|  |         self.np_close: int = 2 | ||||||
|  |         self.np_sell: int = 3 | ||||||
|  |         self.np_high: int = 4 | ||||||
|  |         self.np_low: int = 5 | ||||||
|  |         self.np_stop: int = 6 | ||||||
|  |         self.np_bto: int = self.np_close  # buys_triggered_on - should be close | ||||||
|  |         self.np_bco: int = self.np_open  # buys calculated on - open of the next candle. | ||||||
|  |         # self.np_sto: int = self.np_low  # stops_triggered_on - Should be low, FT uses close | ||||||
|  |         # self.np_sco: int = self.np_stop  # stops_calculated_on - Should be stop, FT uses close | ||||||
|  |         self.np_sto: int = self.np_close  # stops_triggered_on - Should be low, FT uses close | ||||||
|  |         self.np_sco: int = self.np_close  # stops_calculated_on - Should be stop, FT uses close | ||||||
|  |  | ||||||
|  |         self.use_backslap = True                # Enable backslap | ||||||
|  |         self.debug = False                       # Main debug enable, very print heavy, enable 2 loops recommended | ||||||
|  |         self.debug_timing = False                # Stages within Backslap | ||||||
|  |         self.debug_2loops = False               # Limit each pair to two loops, useful when debugging | ||||||
|  |         self.debug_vector = False               # Debug vector calcs | ||||||
|  |         self.debug_timing_main_loop = False     # print overall timing per pair | ||||||
|  |  | ||||||
|  |  | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def get_timeframe(data: Dict[str, DataFrame]) -> Tuple[arrow.Arrow, arrow.Arrow]: |     def get_timeframe(data: Dict[str, DataFrame]) -> Tuple[arrow.Arrow, arrow.Arrow]: | ||||||
|         """ |         """ | ||||||
| @@ -215,7 +244,7 @@ class Backtesting(object): | |||||||
|             realistic: do we try to simulate realistic trades? (default: True) |             realistic: do we try to simulate realistic trades? (default: True) | ||||||
|         :return: DataFrame |         :return: DataFrame | ||||||
|         """ |         """ | ||||||
|         debug_timing = False |  | ||||||
|  |  | ||||||
|         headers = ['date', 'buy', 'open', 'close', 'sell', 'high', 'low'] |         headers = ['date', 'buy', 'open', 'close', 'sell', 'high', 'low'] | ||||||
|         processed = args['processed'] |         processed = args['processed'] | ||||||
| @@ -224,10 +253,11 @@ class Backtesting(object): | |||||||
|         trades = [] |         trades = [] | ||||||
|         trade_count_lock: Dict = {} |         trade_count_lock: Dict = {} | ||||||
|  |  | ||||||
|         ########################### Call out BSlap instead of using FT |         use_backslap = self.use_backslap | ||||||
|  |         debug_timing = self.debug_timing_main_loop | ||||||
|  |         if use_backslap: # Use Back Slap code | ||||||
|  |             ########################### Call out BSlap Loop instead of Original BT code | ||||||
|             bslap_results: list = [] |             bslap_results: list = [] | ||||||
|  |  | ||||||
|  |  | ||||||
|             for pair, pair_data in processed.items(): |             for pair, pair_data in processed.items(): | ||||||
|                 if debug_timing: # Start timer |                 if debug_timing: # Start timer | ||||||
|                     fl = self.s() |                     fl = self.s() | ||||||
| @@ -235,11 +265,10 @@ class Backtesting(object): | |||||||
|                 ticker_data = self.populate_sell_trend( |                 ticker_data = self.populate_sell_trend( | ||||||
|                         self.populate_buy_trend(pair_data))[headers].copy() |                         self.populate_buy_trend(pair_data))[headers].copy() | ||||||
|  |  | ||||||
|             ticker_data.drop(ticker_data.head(1).index, inplace=True) |  | ||||||
|                 if debug_timing: # print time taken |                 if debug_timing: # print time taken | ||||||
|                     flt = self.f(fl) |                     flt = self.f(fl) | ||||||
|                 print("populate_buy_trend:", pair, round(flt, 10)) |                     #print("populate_buy_trend:", pair, round(flt, 10)) | ||||||
|                 st = self.st() |                     st = self.s() | ||||||
|  |  | ||||||
|                 # #dump same DFs to disk for offline testing in scratch |                 # #dump same DFs to disk for offline testing in scratch | ||||||
|                 # f_pair:str = pair |                 # f_pair:str = pair | ||||||
| @@ -271,52 +300,67 @@ class Backtesting(object): | |||||||
|  |  | ||||||
|             return bslap_results_df |             return bslap_results_df | ||||||
|  |  | ||||||
|         ########################### Original BT loop |         else: # use Original Back test code | ||||||
|         # for pair, pair_data in processed.items(): |             ########################## Original BT loop | ||||||
|         #     pair_data['buy'], pair_data['sell'] = 0, 0  # cleanup from previous run |  | ||||||
|         # |             for pair, pair_data in processed.items(): | ||||||
|         #     ticker_data = self.populate_sell_trend( |                 if debug_timing: # Start timer | ||||||
|         #         self.populate_buy_trend(pair_data))[headers].copy() |                     fl = self.s() | ||||||
|         # |  | ||||||
|         #     # to avoid using data from future, we buy/sell with signal from previous candle |                 pair_data['buy'], pair_data['sell'] = 0, 0  # cleanup from previous run | ||||||
|         #     ticker_data.loc[:, 'buy'] = ticker_data['buy'].shift(1) |  | ||||||
|         #     ticker_data.loc[:, 'sell'] = ticker_data['sell'].shift(1) |                 ticker_data = self.populate_sell_trend( | ||||||
|         # |                     self.populate_buy_trend(pair_data))[headers].copy() | ||||||
|         #     ticker_data.drop(ticker_data.head(1).index, inplace=True) |  | ||||||
|         # |                 # to avoid using data from future, we buy/sell with signal from previous candle | ||||||
|         #     # Convert from Pandas to list for performance reasons |                 ticker_data.loc[:, 'buy'] = ticker_data['buy'].shift(1) | ||||||
|         #     # (Looping Pandas is slow.) |                 ticker_data.loc[:, 'sell'] = ticker_data['sell'].shift(1) | ||||||
|         #     ticker = [x for x in ticker_data.itertuples()] |  | ||||||
|         # |                 ticker_data.drop(ticker_data.head(1).index, inplace=True) | ||||||
|         #     lock_pair_until = None |  | ||||||
|         #     for index, row in enumerate(ticker): |                 if debug_timing: # print time taken | ||||||
|         #         if row.buy == 0 or row.sell == 1: |                     flt = self.f(fl) | ||||||
|         #             continue  # skip rows where no buy signal or that would immediately sell off |                     #print("populate_buy_trend:", pair, round(flt, 10)) | ||||||
|         # |                     st = self.s() | ||||||
|         #         if realistic: |  | ||||||
|         #             if lock_pair_until is not None and row.date <= lock_pair_until: |                 # Convert from Pandas to list for performance reasons | ||||||
|         #                 continue |                 # (Looping Pandas is slow.) | ||||||
|         #         if max_open_trades > 0: |                 ticker = [x for x in ticker_data.itertuples()] | ||||||
|         #             # Check if max_open_trades has already been reached for the given date |  | ||||||
|         #             if not trade_count_lock.get(row.date, 0) < max_open_trades: |                 lock_pair_until = None | ||||||
|         #                 continue |                 for index, row in enumerate(ticker): | ||||||
|         # |                     if row.buy == 0 or row.sell == 1: | ||||||
|         #             trade_count_lock[row.date] = trade_count_lock.get(row.date, 0) + 1 |                         continue  # skip rows where no buy signal or that would immediately sell off | ||||||
|         # |  | ||||||
|         #         trade_entry = self._get_sell_trade_entry(pair, row, ticker[index + 1:], |                     if realistic: | ||||||
|         #                                                  trade_count_lock, args) |                         if lock_pair_until is not None and row.date <= lock_pair_until: | ||||||
|         # |                             continue | ||||||
|         # |                     if max_open_trades > 0: | ||||||
|         #         if trade_entry: |                         # Check if max_open_trades has already been reached for the given date | ||||||
|         #             lock_pair_until = trade_entry.close_time |                         if not trade_count_lock.get(row.date, 0) < max_open_trades: | ||||||
|         #             trades.append(trade_entry) |                             continue | ||||||
|         #         else: |  | ||||||
|         #             # Set lock_pair_until to end of testing period if trade could not be closed |                         trade_count_lock[row.date] = trade_count_lock.get(row.date, 0) + 1 | ||||||
|         #             # This happens only if the buy-signal was with the last candle |  | ||||||
|         #             lock_pair_until = ticker_data.iloc[-1].date |                     trade_entry = self._get_sell_trade_entry(pair, row, ticker[index + 1:], | ||||||
|         # |                                                              trade_count_lock, args) | ||||||
|         # return DataFrame.from_records(trades, columns=BacktestResult._fields) |  | ||||||
|         ######################## Original BT loop end |  | ||||||
|  |                     if trade_entry: | ||||||
|  |                         lock_pair_until = trade_entry.close_time | ||||||
|  |                         trades.append(trade_entry) | ||||||
|  |                     else: | ||||||
|  |                         # Set lock_pair_until to end of testing period if trade could not be closed | ||||||
|  |                         # This happens only if the buy-signal was with the last candle | ||||||
|  |                         lock_pair_until = ticker_data.iloc[-1].date | ||||||
|  |  | ||||||
|  |                 if debug_timing:  # print time taken | ||||||
|  |                     tt = self.f(st) | ||||||
|  |                     print("Time to BackTest :", pair, round(tt, 10)) | ||||||
|  |                     print("-----------------------") | ||||||
|  |  | ||||||
|  |             return DataFrame.from_records(trades, columns=BacktestResult._fields) | ||||||
|  |             ####################### Original BT loop end | ||||||
|  |  | ||||||
|     def vector_fill_results_table(self, bslap_results_df: DataFrame): |     def vector_fill_results_table(self, bslap_results_df: DataFrame): | ||||||
|         """ |         """ | ||||||
| @@ -333,13 +377,18 @@ class Backtesting(object): | |||||||
|         :return: bslap_results Dataframe |         :return: bslap_results Dataframe | ||||||
|         """ |         """ | ||||||
|         import pandas as pd |         import pandas as pd | ||||||
|         debug = False |         debug = self.debug_vector | ||||||
|  |  | ||||||
|         # stake and fees |         # stake and fees | ||||||
|         stake = 0.015 |         # stake = 0.015 | ||||||
|         # 0.05% is 0.00,05 |         # 0.05% is 0.0005 | ||||||
|         open_fee = 0.0000 |         #fee = 0.001 | ||||||
|         close_fee = 0.0000 |  | ||||||
|  |         stake = self.config.get('stake_amount') | ||||||
|  |         fee = self.fee | ||||||
|  |         open_fee = fee / 2 | ||||||
|  |         close_fee = fee / 2 | ||||||
|  |  | ||||||
|         if debug: |         if debug: | ||||||
|             print("Stake is,", stake, "the sum of currency to spend per trade") |             print("Stake is,", stake, "the sum of currency to spend per trade") | ||||||
|             print("The open fee is", open_fee, "The close fee is", close_fee) |             print("The open fee is", open_fee, "The close fee is", close_fee) | ||||||
| @@ -420,9 +469,12 @@ class Backtesting(object): | |||||||
|         from datetime import datetime |         from datetime import datetime | ||||||
|  |  | ||||||
|         ### backslap debug wrap |         ### backslap debug wrap | ||||||
|         debug_2loops = False  # only loop twice, for faster debug |         # debug_2loops = False  # only loop twice, for faster debug | ||||||
|         debug_timing = False  # print timing for each step |         # debug_timing = False  # print timing for each step | ||||||
|         debug = False  # print values, to check accuracy |         # debug = False  # print values, to check accuracy | ||||||
|  |         debug_2loops = self.debug_2loops  # only loop twice, for faster debug | ||||||
|  |         debug_timing = self.debug_timing  # print timing for each step | ||||||
|  |         debug = self.debug  # print values, to check accuracy | ||||||
|  |  | ||||||
|         # Read Stop Loss Values and Stake |         # Read Stop Loss Values and Stake | ||||||
|         stop = self.stop_loss_value |         stop = self.stop_loss_value | ||||||
| @@ -451,20 +503,34 @@ class Backtesting(object): | |||||||
|         buy stop triggers and stop calculated on |         buy stop triggers and stop calculated on | ||||||
|         # buy 0 - open 1 - close 2 - sell 3 - high 4 - low 5 - stop 6 |         # buy 0 - open 1 - close 2 - sell 3 - high 4 - low 5 - stop 6 | ||||||
|         ''' |         ''' | ||||||
|         np_buy: int = 0 |         # np_buy: int = 0 | ||||||
|         np_open: int = 1 |         # np_open: int = 1 | ||||||
|         np_close: int = 2 |         # np_close: int = 2 | ||||||
|         np_sell: int = 3 |         # np_sell: int = 3 | ||||||
|         np_high: int = 4 |         # np_high: int = 4 | ||||||
|         np_low: int = 5 |         # np_low: int = 5 | ||||||
|         np_stop: int = 6 |         # np_stop: int = 6 | ||||||
|         np_bto: int = np_close  # buys_triggered_on - should be close |         # np_bto: int = np_close  # buys_triggered_on - should be close | ||||||
|         np_bco: int = np_open  # buys calculated on - open of the next candle. |         # np_bco: int = np_open  # buys calculated on - open of the next candle. | ||||||
|         #np_sto: int = np_low  # stops_triggered_on - Should be low, FT uses close |         # #np_sto: int = np_low  # stops_triggered_on - Should be low, FT uses close | ||||||
|         #np_sco: int = np_stop  # stops_calculated_on - Should be stop, FT uses close |         # #np_sco: int = np_stop  # stops_calculated_on - Should be stop, FT uses close | ||||||
|         np_sto: int = np_close  # stops_triggered_on - Should be low, FT uses close |         # np_sto: int = np_close  # stops_triggered_on - Should be low, FT uses close | ||||||
|         np_sco: int = np_close  # stops_calculated_on - Should be stop, FT uses close |         # np_sco: int = np_close  # stops_calculated_on - Should be stop, FT uses close | ||||||
|         # |  | ||||||
|  |         ####### | ||||||
|  |         #  Use vars set at top of backtest | ||||||
|  |         np_buy: int = self.np_buy | ||||||
|  |         np_open: int = self.np_open | ||||||
|  |         np_close: int = self.np_close | ||||||
|  |         np_sell: int = self.np_sell | ||||||
|  |         np_high: int = self.np_high | ||||||
|  |         np_low: int = self.np_low | ||||||
|  |         np_stop: int = self.np_stop | ||||||
|  |         np_bto: int = self.np_bto  # buys_triggered_on - should be close | ||||||
|  |         np_bco: int = self.np_bco  # buys calculated on - open of the next candle. | ||||||
|  |         np_sto: int = self.np_sto  # stops_triggered_on - Should be low, FT uses close | ||||||
|  |         np_sco: int = self.np_sco  # stops_calculated_on - Should be stop, FT uses close | ||||||
|  |  | ||||||
|         ### End Config |         ### End Config | ||||||
|  |  | ||||||
|         pair: str = pair |         pair: str = pair | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user