def start(self) -> None: """ Run backtesting end-to-end :return: None """ data: Dict[str, Any] = {} logger.info('Using stake_currency: %s ...', self.config['stake_currency']) logger.info('Using stake_amount: %s ...', self.config['stake_amount']) # Use max_open_trades in backtesting, except --disable-max-market-positions is set if self.config.get('use_max_market_positions', True): max_open_trades = self.config['max_open_trades'] else: logger.info( 'Ignoring max_open_trades (--disable-max-market-positions was used) ...' ) max_open_trades = 0 position_stacking = self.config.get('position_stacking', False) data, timerange = self.load_bt_data() all_results = {} preprocessed_data = {} for strat in self.strategylist: logger.info("Running backtesting for Strategy %s", strat.get_strategy_name()) self._set_strategy(strat) # need to reprocess data every time to populate signals preprocessed = self.strategy.ohlcvdata_to_dataframe(data) # Trim startup period from analyzed dataframe for pair, df in preprocessed.items(): preprocessed[pair] = trim_dataframe(df, timerange) min_date, max_date = history.get_timerange(preprocessed) logger.info('Backtesting with data from %s up to %s (%s days)..', min_date.isoformat(), max_date.isoformat(), (max_date - min_date).days) # Store reprocessed data for later use in export preprocessed_data[self.strategy.get_strategy_name()] = preprocessed # Execute backtest and print results all_results[self.strategy.get_strategy_name()] = self.backtest( processed=preprocessed, stake_amount=self.config['stake_amount'], start_date=min_date, end_date=max_date, max_open_trades=max_open_trades, position_stacking=position_stacking, ) if self.config.get('export', False): store_backtest_result(self.config, preprocessed_data, all_results) # Show backtest results show_backtest_results(self.config, data, all_results)
def test_backtest_record(default_conf, fee, mocker): names = [] records = [] patch_exchange(mocker) mocker.patch('freqtrade.exchange.Exchange.get_fee', fee) mocker.patch( 'freqtrade.optimize.optimize_reports.file_dump_json', new=lambda n, r: (names.append(n), records.append(r)) ) results = {'DefStrat': pd.DataFrame({"pair": ["UNITTEST/BTC", "UNITTEST/BTC", "UNITTEST/BTC", "UNITTEST/BTC"], "profit_percent": [0.003312, 0.010801, 0.013803, 0.002780], "profit_abs": [0.000003, 0.000011, 0.000014, 0.000003], "open_time": [Arrow(2017, 11, 14, 19, 32, 00).datetime, Arrow(2017, 11, 14, 21, 36, 00).datetime, Arrow(2017, 11, 14, 22, 12, 00).datetime, Arrow(2017, 11, 14, 22, 44, 00).datetime], "close_time": [Arrow(2017, 11, 14, 21, 35, 00).datetime, Arrow(2017, 11, 14, 22, 10, 00).datetime, Arrow(2017, 11, 14, 22, 43, 00).datetime, Arrow(2017, 11, 14, 22, 58, 00).datetime], "open_rate": [0.002543, 0.003003, 0.003089, 0.003214], "close_rate": [0.002546, 0.003014, 0.003103, 0.003217], "open_index": [1, 119, 153, 185], "close_index": [118, 151, 184, 199], "trade_duration": [123, 34, 31, 14], "open_at_end": [False, False, False, True], "sell_reason": [SellType.ROI, SellType.STOP_LOSS, SellType.ROI, SellType.FORCE_SELL] })} store_backtest_result(Path("backtest-result.json"), results) # Assert file_dump_json was only called once assert names == [Path('backtest-result.json')] records = records[0] # Ensure records are of correct type assert len(records) == 4 # reset test to test with strategy name names = [] records = [] results['Strat'] = results['DefStrat'] results['Strat2'] = results['DefStrat'] store_backtest_result(Path("backtest-result.json"), results) assert names == [ Path('backtest-result-DefStrat.json'), Path('backtest-result-Strat.json'), Path('backtest-result-Strat2.json'), ] records = records[0] # Ensure records are of correct type assert len(records) == 4 # ('UNITTEST/BTC', 0.00331158, '1510684320', '1510691700', 0, 117) # Below follows just a typecheck of the schema/type of trade-records oix = None for (pair, profit, date_buy, date_sell, buy_index, dur, openr, closer, open_at_end, sell_reason) in records: assert pair == 'UNITTEST/BTC' assert isinstance(profit, float) # FIX: buy/sell should be converted to ints assert isinstance(date_buy, float) assert isinstance(date_sell, float) assert isinstance(openr, float) assert isinstance(closer, float) assert isinstance(open_at_end, bool) assert isinstance(sell_reason, str) isinstance(buy_index, pd._libs.tslib.Timestamp) if oix: assert buy_index > oix oix = buy_index assert dur > 0