diff --git a/config_examples/config_freqai.example.json b/config_examples/config_freqai.example.json index f58a4468b..dfd54b3d9 100644 --- a/config_examples/config_freqai.example.json +++ b/config_examples/config_freqai.example.json @@ -79,8 +79,7 @@ "test_size": 0.33, "random_state": 1 }, - "model_training_parameters": { - } + "model_training_parameters": {} }, "bot_name": "", "force_entry_enable": true, diff --git a/docs/freqai-configuration.md b/docs/freqai-configuration.md index 5c3bbf90c..10f5838c9 100644 --- a/docs/freqai-configuration.md +++ b/docs/freqai-configuration.md @@ -26,10 +26,7 @@ FreqAI is configured through the typical [Freqtrade config file](configuration.m }, "data_split_parameters" : { "test_size": 0.25 - }, - "model_training_parameters" : { - "n_estimators": 100 - }, + } } ``` @@ -118,7 +115,7 @@ The FreqAI strategy requires including the following lines of code in the standa ``` -Notice how the `populate_any_indicators()` is where [features](freqai-feature-engineering.md#feature-engineering) and labels/targets are added. A full example strategy is available in `templates/FreqaiExampleStrategy.py`. +Notice how the `populate_any_indicators()` is where [features](freqai-feature-engineering.md#feature-engineering) and labels/targets are added. A full example strategy is available in `templates/FreqaiExampleStrategy.py`. Notice also the location of the labels under `if set_generalized_indicators:` at the bottom of the example. This is where single features and labels/targets should be added to the feature set to avoid duplication of them from various configuration parameters that multiply the feature set, such as `include_timeframes`. @@ -182,7 +179,7 @@ The `startup_candle_count` in the FreqAI strategy needs to be set up in the same ## Creating a dynamic target threshold -Deciding when to enter or exit a trade can be done in a dynamic way to reflect current market conditions. FreqAI allows you to return additional information from the training of a model (more info [here](freqai-feature-engineering.md#returning-additional-info-from-training)). For example, the `&*_std/mean` return values describe the statistical distribution of the target/label *during the most recent training*. Comparing a given prediction to these values allows you to know the rarity of the prediction. In `templates/FreqaiExampleStrategy.py`, the `target_roi` and `sell_roi` are defined to be 1.25 z-scores away from the mean which causes predictions that are closer to the mean to be filtered out. +Deciding when to enter or exit a trade can be done in a dynamic way to reflect current market conditions. FreqAI allows you to return additional information from the training of a model (more info [here](freqai-feature-engineering.md#returning-additional-info-from-training)). For example, the `&*_std/mean` return values describe the statistical distribution of the target/label *during the most recent training*. Comparing a given prediction to these values allows you to know the rarity of the prediction. In `templates/FreqaiExampleStrategy.py`, the `target_roi` and `sell_roi` are defined to be 1.25 z-scores away from the mean which causes predictions that are closer to the mean to be filtered out. ```python dataframe["target_roi"] = dataframe["&-s_close_mean"] + dataframe["&-s_close_std"] * 1.25 @@ -230,7 +227,7 @@ If you want to predict multiple targets, you need to define multiple labels usin #### Classifiers -If you are using a classifier, you need to specify a target that has discrete values. FreqAI includes a variety of classifiers, such as the `CatboostClassifier` via the flag `--freqaimodel CatboostClassifier`. If you elects to use a classifier, the classes need to be set using strings. For example, if you want to predict if the price 100 candles into the future goes up or down you would set +If you are using a classifier, you need to specify a target that has discrete values. FreqAI includes a variety of classifiers, such as the `CatboostClassifier` via the flag `--freqaimodel CatboostClassifier`. If you elects to use a classifier, the classes need to be set using strings. For example, if you want to predict if the price 100 candles into the future goes up or down you would set ```python df['&s-up_or_down'] = np.where( df["close"].shift(-100) > df["close"], 'up', 'down') diff --git a/freqtrade/configuration/config_validation.py b/freqtrade/configuration/config_validation.py index bf0657994..606f081ef 100644 --- a/freqtrade/configuration/config_validation.py +++ b/freqtrade/configuration/config_validation.py @@ -355,6 +355,13 @@ def _validate_freqai_include_timeframes(conf: Dict[str, Any]) -> None: f"Main timeframe of {main_tf} must be smaller or equal to FreqAI " f"`include_timeframes`.Offending include-timeframes: {', '.join(offending_lines)}") + # Ensure that the base timeframe is included in the include_timeframes list + if main_tf not in freqai_include_timeframes: + feature_parameters = conf.get('freqai', {}).get('feature_parameters', {}) + include_timeframes = [main_tf] + freqai_include_timeframes + conf.get('freqai', {}).get('feature_parameters', {}) \ + .update({**feature_parameters, 'include_timeframes': include_timeframes}) + def _validate_freqai_backtest(conf: Dict[str, Any]) -> None: if conf.get('runmode', RunMode.OTHER) == RunMode.BACKTEST: diff --git a/freqtrade/constants.py b/freqtrade/constants.py index d869b89f6..ca1be1d6a 100644 --- a/freqtrade/constants.py +++ b/freqtrade/constants.py @@ -608,9 +608,8 @@ CONF_SCHEMA = { "backtest_period_days", "identifier", "feature_parameters", - "data_split_parameters", - "model_training_parameters" - ] + "data_split_parameters" + ] }, }, } diff --git a/freqtrade/freqai/prediction_models/ReinforcementLearner.py b/freqtrade/freqai/prediction_models/ReinforcementLearner.py index 47dbaf99e..e62110347 100644 --- a/freqtrade/freqai/prediction_models/ReinforcementLearner.py +++ b/freqtrade/freqai/prediction_models/ReinforcementLearner.py @@ -61,7 +61,7 @@ class ReinforcementLearner(BaseReinforcementLearningModel): model = self.MODELCLASS(self.policy_type, self.train_env, policy_kwargs=policy_kwargs, tensorboard_log=Path( dk.full_path / "tensorboard" / dk.pair.split('/')[0]), - **self.freqai_info['model_training_parameters'] + **self.freqai_info.get('model_training_parameters', {}) ) else: logger.info('Continual training activated - starting training from previously ' diff --git a/tests/test_configuration.py b/tests/test_configuration.py index 1bcff20db..cdf9f2f2e 100644 --- a/tests/test_configuration.py +++ b/tests/test_configuration.py @@ -1046,8 +1046,13 @@ def test__validate_freqai_include_timeframes(default_conf, caplog) -> None: # Validation pass conf.update({'timeframe': '1m'}) validate_config_consistency(conf) - conf.update({'analyze_per_epoch': True}) + # Ensure base timeframe is in include_timeframes + conf['freqai']['feature_parameters']['include_timeframes'] = ["5m", "15m"] + validate_config_consistency(conf) + assert conf['freqai']['feature_parameters']['include_timeframes'] == ["1m", "5m", "15m"] + + conf.update({'analyze_per_epoch': True}) with pytest.raises(OperationalException, match=r"Using analyze-per-epoch .* not supported with a FreqAI strategy."): validate_config_consistency(conf)