From 8d8c782bd039780f8563e8edf7f735501c9013ab Mon Sep 17 00:00:00 2001 From: Rokas Kupstys Date: Sat, 8 May 2021 16:06:19 +0300 Subject: [PATCH] Slice dataframe in backtesting, preventing access to rows past current time. --- freqtrade/data/dataprovider.py | 21 ++++++++++++++++++--- freqtrade/optimize/backtesting.py | 8 ++++++-- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/freqtrade/data/dataprovider.py b/freqtrade/data/dataprovider.py index 727768ebb..a5d059e4a 100644 --- a/freqtrade/data/dataprovider.py +++ b/freqtrade/data/dataprovider.py @@ -20,6 +20,7 @@ from freqtrade.state import RunMode logger = logging.getLogger(__name__) NO_EXCHANGE_EXCEPTION = 'Exchange is not available to DataProvider.' +MAX_DATAFRAME_CANDLES = 1000 class DataProvider: @@ -29,6 +30,14 @@ class DataProvider: self._exchange = exchange self._pairlists = pairlists self.__cached_pairs: Dict[PairWithTimeframe, Tuple[DataFrame, datetime]] = {} + self.__slice_index = None + + def _set_dataframe_max_index(self, limit_index: int): + """ + Limit analyzed dataframe to max specified index. + :param limit_index: dataframe index. + """ + self.__slice_index = limit_index def _set_cached_df(self, pair: str, timeframe: str, dataframe: DataFrame) -> None: """ @@ -85,10 +94,16 @@ class DataProvider: combination. Returns empty dataframe and Epoch 0 (1970-01-01) if no dataframe was cached. """ - if (pair, timeframe) in self.__cached_pairs: - return self.__cached_pairs[(pair, timeframe)] + pair_key = (pair, timeframe) + if pair_key in self.__cached_pairs: + if self.runmode in (RunMode.DRY_RUN, RunMode.LIVE): + df, date = self.__cached_pairs[pair_key] + else: + max_index = self.__slice_index + df, date = self.__cached_pairs[pair_key] + df = df.iloc[max(0, max_index - MAX_DATAFRAME_CANDLES):max_index] + return df, date else: - return (DataFrame(), datetime.fromtimestamp(0, tz=timezone.utc)) @property diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 80eb34c30..f7c984047 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -373,8 +373,9 @@ class Backtesting: open_trade_count_start = open_trade_count for i, pair in enumerate(data): + row_index = indexes[pair] try: - row = data[pair][indexes[pair]] + row = data[pair][row_index] except IndexError: # missing Data for one pair at the end. # Warnings for this are shown during data loading @@ -383,7 +384,10 @@ class Backtesting: # Waits until the time-counter reaches the start of the data for this pair. if row[DATE_IDX] > tmp: continue - indexes[pair] += 1 + + row_index += 1 + self.dataprovider._set_dataframe_max_index(row_index) # noqa + indexes[pair] = row_index # without positionstacking, we can only have one open trade per pair. # max_open_trades must be respected