Merge pull request #7454 from freqtrade/fix_backtesting_dfsize_freqai
Ensure the DF has the same size in backtesting FreqAI
This commit is contained in:
commit
585342f193
@ -208,8 +208,10 @@ class DataProvider:
|
|||||||
if saved_pair not in self.__cached_pairs_backtesting:
|
if saved_pair not in self.__cached_pairs_backtesting:
|
||||||
timerange = TimeRange.parse_timerange(None if self._config.get(
|
timerange = TimeRange.parse_timerange(None if self._config.get(
|
||||||
'timerange') is None else str(self._config.get('timerange')))
|
'timerange') is None else str(self._config.get('timerange')))
|
||||||
# Move informative start time respecting startup_candle_count
|
|
||||||
startup_candles = self.get_required_startup(str(timeframe))
|
# It is not necessary to add the training candles, as they
|
||||||
|
# were already added at the beginning of the backtest.
|
||||||
|
startup_candles = self.get_required_startup(str(timeframe), False)
|
||||||
tf_seconds = timeframe_to_seconds(str(timeframe))
|
tf_seconds = timeframe_to_seconds(str(timeframe))
|
||||||
timerange.subtract_start(tf_seconds * startup_candles)
|
timerange.subtract_start(tf_seconds * startup_candles)
|
||||||
self.__cached_pairs_backtesting[saved_pair] = load_pair_history(
|
self.__cached_pairs_backtesting[saved_pair] = load_pair_history(
|
||||||
@ -223,7 +225,7 @@ class DataProvider:
|
|||||||
)
|
)
|
||||||
return self.__cached_pairs_backtesting[saved_pair].copy()
|
return self.__cached_pairs_backtesting[saved_pair].copy()
|
||||||
|
|
||||||
def get_required_startup(self, timeframe: str) -> int:
|
def get_required_startup(self, timeframe: str, add_train_candles: bool = True) -> int:
|
||||||
freqai_config = self._config.get('freqai', {})
|
freqai_config = self._config.get('freqai', {})
|
||||||
if not freqai_config.get('enabled', False):
|
if not freqai_config.get('enabled', False):
|
||||||
return self._config.get('startup_candle_count', 0)
|
return self._config.get('startup_candle_count', 0)
|
||||||
@ -233,6 +235,8 @@ class DataProvider:
|
|||||||
# make sure the startupcandles is at least the set maximum indicator periods
|
# make sure the startupcandles is at least the set maximum indicator periods
|
||||||
self._config['startup_candle_count'] = max(startup_candles, max(indicator_periods))
|
self._config['startup_candle_count'] = max(startup_candles, max(indicator_periods))
|
||||||
tf_seconds = timeframe_to_seconds(timeframe)
|
tf_seconds = timeframe_to_seconds(timeframe)
|
||||||
|
train_candles = 0
|
||||||
|
if add_train_candles:
|
||||||
train_candles = freqai_config['train_period_days'] * 86400 / tf_seconds
|
train_candles = freqai_config['train_period_days'] * 86400 / tf_seconds
|
||||||
total_candles = int(self._config['startup_candle_count'] + train_candles)
|
total_candles = int(self._config['startup_candle_count'] + train_candles)
|
||||||
logger.info(f'Increasing startup_candle_count for freqai to {total_candles}')
|
logger.info(f'Increasing startup_candle_count for freqai to {total_candles}')
|
||||||
|
@ -466,27 +466,6 @@ class FreqaiDataKitchen:
|
|||||||
|
|
||||||
return df
|
return df
|
||||||
|
|
||||||
def remove_training_from_backtesting(
|
|
||||||
self
|
|
||||||
) -> DataFrame:
|
|
||||||
"""
|
|
||||||
Function which takes the backtesting time range and
|
|
||||||
remove training data from dataframe, keeping only the
|
|
||||||
startup_candle_count candles
|
|
||||||
"""
|
|
||||||
startup_candle_count = self.config.get('startup_candle_count', 0)
|
|
||||||
tf = self.config['timeframe']
|
|
||||||
tr = self.config["timerange"]
|
|
||||||
|
|
||||||
backtesting_timerange = TimeRange.parse_timerange(tr)
|
|
||||||
if startup_candle_count > 0 and backtesting_timerange:
|
|
||||||
backtesting_timerange.subtract_start(timeframe_to_seconds(tf) * startup_candle_count)
|
|
||||||
|
|
||||||
start = datetime.fromtimestamp(backtesting_timerange.startts, tz=timezone.utc)
|
|
||||||
df = self.return_dataframe
|
|
||||||
df = df.loc[df["date"] >= start, :]
|
|
||||||
return df
|
|
||||||
|
|
||||||
def principal_component_analysis(self) -> None:
|
def principal_component_analysis(self) -> None:
|
||||||
"""
|
"""
|
||||||
Performs Principal Component Analysis on the data for dimensionality reduction
|
Performs Principal Component Analysis on the data for dimensionality reduction
|
||||||
@ -994,8 +973,6 @@ class FreqaiDataKitchen:
|
|||||||
|
|
||||||
to_keep = [col for col in dataframe.columns if not col.startswith("&")]
|
to_keep = [col for col in dataframe.columns if not col.startswith("&")]
|
||||||
self.return_dataframe = pd.concat([dataframe[to_keep], self.full_df], axis=1)
|
self.return_dataframe = pd.concat([dataframe[to_keep], self.full_df], axis=1)
|
||||||
|
|
||||||
self.return_dataframe = self.remove_training_from_backtesting()
|
|
||||||
self.full_df = DataFrame()
|
self.full_df = DataFrame()
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -139,9 +139,14 @@ class Backtesting:
|
|||||||
|
|
||||||
# Get maximum required startup period
|
# Get maximum required startup period
|
||||||
self.required_startup = max([strat.startup_candle_count for strat in self.strategylist])
|
self.required_startup = max([strat.startup_candle_count for strat in self.strategylist])
|
||||||
|
self.exchange.validate_required_startup_candles(self.required_startup, self.timeframe)
|
||||||
|
|
||||||
|
if self.config.get('freqai', {}).get('enabled', False):
|
||||||
|
# For FreqAI, increase the required_startup to includes the training data
|
||||||
|
self.required_startup = self.dataprovider.get_required_startup(self.timeframe)
|
||||||
|
|
||||||
# Add maximum startup candle count to configuration for informative pairs support
|
# Add maximum startup candle count to configuration for informative pairs support
|
||||||
self.config['startup_candle_count'] = self.required_startup
|
self.config['startup_candle_count'] = self.required_startup
|
||||||
self.exchange.validate_required_startup_candles(self.required_startup, self.timeframe)
|
|
||||||
|
|
||||||
self.trading_mode: TradingMode = config.get('trading_mode', TradingMode.SPOT)
|
self.trading_mode: TradingMode = config.get('trading_mode', TradingMode.SPOT)
|
||||||
# strategies which define "can_short=True" will fail to load in Spot mode.
|
# strategies which define "can_short=True" will fail to load in Spot mode.
|
||||||
@ -217,7 +222,7 @@ class Backtesting:
|
|||||||
pairs=self.pairlists.whitelist,
|
pairs=self.pairlists.whitelist,
|
||||||
timeframe=self.timeframe,
|
timeframe=self.timeframe,
|
||||||
timerange=self.timerange,
|
timerange=self.timerange,
|
||||||
startup_candles=self.dataprovider.get_required_startup(self.timeframe),
|
startup_candles=self.config['startup_candle_count'],
|
||||||
fail_without_data=True,
|
fail_without_data=True,
|
||||||
data_format=self.config.get('dataformat_ohlcv', 'json'),
|
data_format=self.config.get('dataformat_ohlcv', 'json'),
|
||||||
candle_type=self.config.get('candle_type_def', CandleType.SPOT)
|
candle_type=self.config.get('candle_type_def', CandleType.SPOT)
|
||||||
|
Loading…
Reference in New Issue
Block a user