diff --git a/freqtrade/data/dataprovider.py b/freqtrade/data/dataprovider.py index b4dea0743..6cc32157e 100644 --- a/freqtrade/data/dataprovider.py +++ b/freqtrade/data/dataprovider.py @@ -173,3 +173,6 @@ class DataProvider: return self._pairlists.whitelist.copy() else: raise OperationalException("Dataprovider was not initialized with a pairlist provider.") + + def clear_cache(self): + self.__cached_pairs = {} diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 80d816985..73ad4e774 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -64,8 +64,8 @@ class Backtesting: self.exchange = ExchangeResolver.load_exchange(self.config['exchange']['name'], self.config) - dataprovider = DataProvider(self.config, self.exchange) - IStrategy.dp = dataprovider + self.dataprovider = DataProvider(self.config, self.exchange) + IStrategy.dp = self.dataprovider if self.config.get('strategy_list', None): for strat in list(self.config['strategy_list']): @@ -96,7 +96,7 @@ class Backtesting: "PrecisionFilter not allowed for backtesting multiple strategies." ) - dataprovider.add_pairlisthandler(self.pairlists) + self.dataprovider.add_pairlisthandler(self.pairlists) self.pairlists.refresh_pairlist() if len(self.pairlists.whitelist) == 0: @@ -176,6 +176,7 @@ class Backtesting: Trade.use_db = False PairLocks.reset_locks() Trade.reset_trades() + self.dataprovider.clear_cache() def _get_ohlcv_as_lists(self, processed: Dict[str, DataFrame]) -> Dict[str, Tuple]: """ @@ -266,7 +267,8 @@ class Backtesting: pair=trade.pair, trade=trade, order_type='limit', amount=trade.amount, rate=closerate, time_in_force=time_in_force, - sell_reason=sell.sell_reason): + sell_reason=sell.sell_reason, + current_time=sell_row[DATE_IDX].to_pydatetime()): return None trade.close(closerate, show_msg=False) @@ -286,7 +288,7 @@ class Backtesting: # Confirm trade entry: if not strategy_safe_wrapper(self.strategy.confirm_trade_entry, default_retval=True)( pair=pair, order_type=order_type, amount=stake_amount, rate=row[OPEN_IDX], - time_in_force=time_in_force): + time_in_force=time_in_force, current_time=row[DATE_IDX].to_pydatetime()): return None if stake_amount and (not min_stake_amount or stake_amount > min_stake_amount): @@ -348,6 +350,10 @@ class Backtesting: trades: List[LocalTrade] = [] self.prepare_backtest(enable_protections) + # Update dataprovider cache + for pair, dataframe in processed.items(): + self.dataprovider._set_cached_df(pair, self.timeframe, dataframe) + # Use dict of lists with data for performance # (looping lists is a lot faster than pandas DataFrames) data: Dict = self._get_ohlcv_as_lists(processed) diff --git a/tests/strategy/test_interface.py b/tests/strategy/test_interface.py index 182dde335..ded396779 100644 --- a/tests/strategy/test_interface.py +++ b/tests/strategy/test_interface.py @@ -399,27 +399,27 @@ def test_custom_sell(default_conf, fee, caplog) -> None: ) now = arrow.utcnow().datetime - res = strategy.should_sell(None, trade, 1, now, False, False, None, None, 0) + res = strategy.should_sell(trade, 1, now, False, False, None, None, 0) assert res.sell_flag is False assert res.sell_type == SellType.NONE strategy.custom_sell = MagicMock(return_value=True) - res = strategy.should_sell(None, trade, 1, now, False, False, None, None, 0) + res = strategy.should_sell(trade, 1, now, False, False, None, None, 0) assert res.sell_flag is True assert res.sell_type == SellType.CUSTOM_SELL assert res.sell_reason == 'custom_sell' strategy.custom_sell = MagicMock(return_value='hello world') - res = strategy.should_sell(None, trade, 1, now, False, False, None, None, 0) + res = strategy.should_sell(trade, 1, now, False, False, None, None, 0) assert res.sell_type == SellType.CUSTOM_SELL assert res.sell_flag is True assert res.sell_reason == 'hello world' caplog.clear() strategy.custom_sell = MagicMock(return_value='h' * 100) - res = strategy.should_sell(None, trade, 1, now, False, False, None, None, 0) + res = strategy.should_sell(trade, 1, now, False, False, None, None, 0) assert res.sell_type == SellType.CUSTOM_SELL assert res.sell_flag is True assert res.sell_reason == 'h' * 64