From: Jérôme Benoit Date: Thu, 20 Feb 2025 09:20:41 +0000 (+0100) Subject: refactor(qav3): readd label period optimization X-Git-Url: https://git.piment-noir.org/?a=commitdiff_plain;h=190e672d2c22abad61739c3eabae93baf0f1fef6;p=freqai-strategies.git refactor(qav3): readd label period optimization Signed-off-by: Jérôme Benoit --- diff --git a/quickadapter/user_data/config-template.json b/quickadapter/user_data/config-template.json index 64dca39..5c77e1f 100644 --- a/quickadapter/user_data/config-template.json +++ b/quickadapter/user_data/config-template.json @@ -131,7 +131,7 @@ "DI_cutoff": 2, "&s-minima_threshold": -2, "&s-maxima_threshold": 2, - // "label_period_candles": 100, + "label_period_candles": 100, "hp_rmse": -1, "period_rmse": -1 }, diff --git a/quickadapter/user_data/freqaimodels/LightGBMRegressorQuickAdapterV35.py b/quickadapter/user_data/freqaimodels/LightGBMRegressorQuickAdapterV35.py index 460e743..34a3ace 100644 --- a/quickadapter/user_data/freqaimodels/LightGBMRegressorQuickAdapterV35.py +++ b/quickadapter/user_data/freqaimodels/LightGBMRegressorQuickAdapterV35.py @@ -127,12 +127,12 @@ class LightGBMRegressorQuickAdapterV35(BaseRegressionModel): y_test = y_test.tail(test_window) test_weights = test_weights[-test_window:] - # # FIXME: find a better way to propagate optuna computed params to strategy - # if dk.pair not in self.freqai_info["feature_parameters"]: - # self.freqai_info["feature_parameters"][dk.pair] = {} - # self.freqai_info["feature_parameters"][dk.pair][ - # "label_period_candles" - # ] = self.__optuna_period_params[dk.pair].get("label_period_candles") + # FIXME: find a better way to propagate optuna computed params to strategy + if dk.pair not in self.freqai_info["feature_parameters"]: + self.freqai_info["feature_parameters"][dk.pair] = {} + self.freqai_info["feature_parameters"][dk.pair][ + "label_period_candles" + ] = self.__optuna_period_params[dk.pair].get("label_period_candles") model = LGBMRegressor( objective="regression", metric="rmse", **model_training_parameters @@ -178,13 +178,12 @@ class LightGBMRegressorQuickAdapterV35(BaseRegressionModel): dk.data["extra_returns_per_train"][MINIMA_THRESHOLD_COLUMN] = -2 dk.data["extra_returns_per_train"][MAXIMA_THRESHOLD_COLUMN] = 2 else: - # if self.__optuna_hyperopt: - # label_period_candles = self.__optuna_period_params.get(pair, {}).get( - # "label_period_candles", self.ft_params["label_period_candles"] - # ) - # else: - # label_period_candles = self.ft_params["label_period_candles"] - label_period_candles = self.ft_params["label_period_candles"] + if self.__optuna_hyperopt: + label_period_candles = self.__optuna_period_params.get(pair, {}).get( + "label_period_candles", self.ft_params["label_period_candles"] + ) + else: + label_period_candles = self.ft_params["label_period_candles"] min_pred, max_pred = self.min_max_pred( pred_df_full, num_candles, @@ -223,11 +222,11 @@ class LightGBMRegressorQuickAdapterV35(BaseRegressionModel): dk.data["extra_returns_per_train"]["DI_value_param3"] = f[2] dk.data["extra_returns_per_train"]["DI_cutoff"] = cutoff - # dk.data["extra_returns_per_train"]["label_period_candles"] = ( - # self.__optuna_period_params.get(pair, {}).get( - # "label_period_candles", self.ft_params["label_period_candles"] - # ) - # ) + dk.data["extra_returns_per_train"]["label_period_candles"] = ( + self.__optuna_period_params.get(pair, {}).get( + "label_period_candles", self.ft_params["label_period_candles"] + ) + ) dk.data["extra_returns_per_train"]["hp_rmse"] = self.__optuna_hp_rmse.get( pair, -1 ) @@ -400,6 +399,7 @@ class LightGBMRegressorQuickAdapterV35(BaseRegressionModel): y_test, test_weights, self.data_split_parameters.get("test_size", TEST_SIZE), + self.freqai_info.get("fit_live_predictions_candles", 100), self.__optuna_config.get("candles_step", 100), model_training_parameters, ), @@ -529,6 +529,7 @@ def period_objective( y_test, test_weights, test_size, + fit_live_predictions_candles, candles_step, model_training_parameters, ) -> float: @@ -571,6 +572,16 @@ def period_objective( ) y_pred = model.predict(X_test) + min_label_period_candles = int(fit_live_predictions_candles / 6) + max_label_period_candles = int(fit_live_predictions_candles / 2) + label_period_candles = trial.suggest_int( + "label_period_candles", + min_label_period_candles, + max_label_period_candles, + ) + y_test = y_test.tail(label_period_candles) + y_pred = y_pred[-label_period_candles:] + error = sklearn.metrics.root_mean_squared_error(y_test, y_pred) return error diff --git a/quickadapter/user_data/freqaimodels/XGBoostRegressorQuickAdapterV35.py b/quickadapter/user_data/freqaimodels/XGBoostRegressorQuickAdapterV35.py index 75e77d9..b22cbe1 100644 --- a/quickadapter/user_data/freqaimodels/XGBoostRegressorQuickAdapterV35.py +++ b/quickadapter/user_data/freqaimodels/XGBoostRegressorQuickAdapterV35.py @@ -127,12 +127,12 @@ class XGBoostRegressorQuickAdapterV35(BaseRegressionModel): y_test = y_test.tail(test_window) test_weights = test_weights[-test_window:] - # # FIXME: find a better way to propagate optuna computed params to strategy - # if dk.pair not in self.freqai_info["feature_parameters"]: - # self.freqai_info["feature_parameters"][dk.pair] = {} - # self.freqai_info["feature_parameters"][dk.pair][ - # "label_period_candles" - # ] = self.__optuna_period_params[dk.pair].get("label_period_candles") + # FIXME: find a better way to propagate optuna computed params to strategy + if dk.pair not in self.freqai_info["feature_parameters"]: + self.freqai_info["feature_parameters"][dk.pair] = {} + self.freqai_info["feature_parameters"][dk.pair][ + "label_period_candles" + ] = self.__optuna_period_params[dk.pair].get("label_period_candles") model = XGBRegressor( objective="reg:squarederror", @@ -179,13 +179,12 @@ class XGBoostRegressorQuickAdapterV35(BaseRegressionModel): dk.data["extra_returns_per_train"][MINIMA_THRESHOLD_COLUMN] = -2 dk.data["extra_returns_per_train"][MAXIMA_THRESHOLD_COLUMN] = 2 else: - # if self.__optuna_hyperopt: - # label_period_candles = self.__optuna_period_params.get(pair, {}).get( - # "label_period_candles", self.ft_params["label_period_candles"] - # ) - # else: - # label_period_candles = self.ft_params["label_period_candles"] - label_period_candles = self.ft_params["label_period_candles"] + if self.__optuna_hyperopt: + label_period_candles = self.__optuna_period_params.get(pair, {}).get( + "label_period_candles", self.ft_params["label_period_candles"] + ) + else: + label_period_candles = self.ft_params["label_period_candles"] min_pred, max_pred = self.min_max_pred( pred_df_full, num_candles, @@ -224,11 +223,11 @@ class XGBoostRegressorQuickAdapterV35(BaseRegressionModel): dk.data["extra_returns_per_train"]["DI_value_param3"] = f[2] dk.data["extra_returns_per_train"]["DI_cutoff"] = cutoff - # dk.data["extra_returns_per_train"]["label_period_candles"] = ( - # self.__optuna_period_params.get(pair, {}).get( - # "label_period_candles", self.ft_params["label_period_candles"] - # ) - # ) + dk.data["extra_returns_per_train"]["label_period_candles"] = ( + self.__optuna_period_params.get(pair, {}).get( + "label_period_candles", self.ft_params["label_period_candles"] + ) + ) dk.data["extra_returns_per_train"]["hp_rmse"] = self.__optuna_hp_rmse.get( pair, -1 ) @@ -401,6 +400,7 @@ class XGBoostRegressorQuickAdapterV35(BaseRegressionModel): y_test, test_weights, self.data_split_parameters.get("test_size", TEST_SIZE), + self.freqai_info.get("fit_live_predictions_candles", 100), self.__optuna_config.get("candles_step", 100), model_training_parameters, ), @@ -530,6 +530,7 @@ def period_objective( y_test, test_weights, test_size, + fit_live_predictions_candles, candles_step, model_training_parameters, ) -> float: @@ -575,6 +576,16 @@ def period_objective( ) y_pred = model.predict(X_test) + min_label_period_candles = int(fit_live_predictions_candles / 6) + max_label_period_candles = int(fit_live_predictions_candles / 2) + label_period_candles = trial.suggest_int( + "label_period_candles", + min_label_period_candles, + max_label_period_candles, + ) + y_test = y_test.tail(label_period_candles) + y_pred = y_pred[-label_period_candles:] + error = sklearn.metrics.root_mean_squared_error(y_test, y_pred) return error diff --git a/quickadapter/user_data/strategies/QuickAdapterV3.py b/quickadapter/user_data/strategies/QuickAdapterV3.py index 13cb7e6..0159c7b 100644 --- a/quickadapter/user_data/strategies/QuickAdapterV3.py +++ b/quickadapter/user_data/strategies/QuickAdapterV3.py @@ -240,16 +240,14 @@ class QuickAdapterV3(IStrategy): def set_freqai_targets(self, dataframe, metadata, **kwargs): pair = str(metadata.get("pair")) - # label_period_candles = ( - # self.freqai_info["feature_parameters"] - # .get(pair, {}) - # .get( - # "label_period_candles", - # self.freqai_info["feature_parameters"]["label_period_candles"], - # ) - # ) - label_period_candles = self.freqai_info["feature_parameters"]["label_period_candles"] - dataframe[EXTREMA_COLUMN] = 0 + label_period_candles = ( + self.freqai_info["feature_parameters"] + .get(pair, {}) + .get( + "label_period_candles", + self.freqai_info["feature_parameters"]["label_period_candles"], + ) + ) min_peaks, _ = find_peaks( -dataframe["low"].values, distance=label_period_candles, @@ -258,6 +256,7 @@ class QuickAdapterV3(IStrategy): dataframe["high"].values, distance=label_period_candles, ) + dataframe[EXTREMA_COLUMN] = 0 for mp in min_peaks: dataframe.at[mp, EXTREMA_COLUMN] = -1 for mp in max_peaks: