Store pair datafrmes in dataprovider for backtesting.

This commit is contained in:
Rokas Kupstys 2021-05-02 12:20:54 +03:00
parent dc6e702fec
commit cdfa6adbe5
3 changed files with 18 additions and 9 deletions

View File

@ -173,3 +173,6 @@ class DataProvider:
return self._pairlists.whitelist.copy() return self._pairlists.whitelist.copy()
else: else:
raise OperationalException("Dataprovider was not initialized with a pairlist provider.") raise OperationalException("Dataprovider was not initialized with a pairlist provider.")
def clear_cache(self):
self.__cached_pairs = {}

View File

@ -64,8 +64,8 @@ class Backtesting:
self.exchange = ExchangeResolver.load_exchange(self.config['exchange']['name'], self.config) self.exchange = ExchangeResolver.load_exchange(self.config['exchange']['name'], self.config)
dataprovider = DataProvider(self.config, self.exchange) self.dataprovider = DataProvider(self.config, self.exchange)
IStrategy.dp = dataprovider IStrategy.dp = self.dataprovider
if self.config.get('strategy_list', None): if self.config.get('strategy_list', None):
for strat in list(self.config['strategy_list']): for strat in list(self.config['strategy_list']):
@ -96,7 +96,7 @@ class Backtesting:
"PrecisionFilter not allowed for backtesting multiple strategies." "PrecisionFilter not allowed for backtesting multiple strategies."
) )
dataprovider.add_pairlisthandler(self.pairlists) self.dataprovider.add_pairlisthandler(self.pairlists)
self.pairlists.refresh_pairlist() self.pairlists.refresh_pairlist()
if len(self.pairlists.whitelist) == 0: if len(self.pairlists.whitelist) == 0:
@ -176,6 +176,7 @@ class Backtesting:
Trade.use_db = False Trade.use_db = False
PairLocks.reset_locks() PairLocks.reset_locks()
Trade.reset_trades() Trade.reset_trades()
self.dataprovider.clear_cache()
def _get_ohlcv_as_lists(self, processed: Dict[str, DataFrame]) -> Dict[str, Tuple]: 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, pair=trade.pair, trade=trade, order_type='limit', amount=trade.amount,
rate=closerate, rate=closerate,
time_in_force=time_in_force, 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 return None
trade.close(closerate, show_msg=False) trade.close(closerate, show_msg=False)
@ -286,7 +288,7 @@ class Backtesting:
# Confirm trade entry: # Confirm trade entry:
if not strategy_safe_wrapper(self.strategy.confirm_trade_entry, default_retval=True)( 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], 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 return None
if stake_amount and (not min_stake_amount or stake_amount > min_stake_amount): if stake_amount and (not min_stake_amount or stake_amount > min_stake_amount):
@ -348,6 +350,10 @@ class Backtesting:
trades: List[LocalTrade] = [] trades: List[LocalTrade] = []
self.prepare_backtest(enable_protections) 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 # Use dict of lists with data for performance
# (looping lists is a lot faster than pandas DataFrames) # (looping lists is a lot faster than pandas DataFrames)
data: Dict = self._get_ohlcv_as_lists(processed) data: Dict = self._get_ohlcv_as_lists(processed)

View File

@ -399,27 +399,27 @@ def test_custom_sell(default_conf, fee, caplog) -> None:
) )
now = arrow.utcnow().datetime 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_flag is False
assert res.sell_type == SellType.NONE assert res.sell_type == SellType.NONE
strategy.custom_sell = MagicMock(return_value=True) 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_flag is True
assert res.sell_type == SellType.CUSTOM_SELL assert res.sell_type == SellType.CUSTOM_SELL
assert res.sell_reason == 'custom_sell' assert res.sell_reason == 'custom_sell'
strategy.custom_sell = MagicMock(return_value='hello world') 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_type == SellType.CUSTOM_SELL
assert res.sell_flag is True assert res.sell_flag is True
assert res.sell_reason == 'hello world' assert res.sell_reason == 'hello world'
caplog.clear() caplog.clear()
strategy.custom_sell = MagicMock(return_value='h' * 100) 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_type == SellType.CUSTOM_SELL
assert res.sell_flag is True assert res.sell_flag is True
assert res.sell_reason == 'h' * 64 assert res.sell_reason == 'h' * 64