From 69ec66641a60bb1508ff53f5aec6db136172a673 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Tue, 4 Mar 2025 09:27:54 +0100 Subject: [PATCH] refactor(qav3): cleanup smoothing tunables handling MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Jérôme Benoit --- ReforceXY/user_data/freqaimodels/ReforceXY.py | 2 +- .../LightGBMRegressorQuickAdapterV35.py | 23 +++++--------- .../XGBoostRegressorQuickAdapterV35.py | 23 +++++--------- .../user_data/strategies/QuickAdapterV3.py | 31 +++++++++++++++---- 4 files changed, 40 insertions(+), 39 deletions(-) diff --git a/ReforceXY/user_data/freqaimodels/ReforceXY.py b/ReforceXY/user_data/freqaimodels/ReforceXY.py index fa53dbf..e6559be 100644 --- a/ReforceXY/user_data/freqaimodels/ReforceXY.py +++ b/ReforceXY/user_data/freqaimodels/ReforceXY.py @@ -273,7 +273,7 @@ class ReforceXY(BaseReinforcementLearningModel): no_improvement_callback = StopTrainingOnNoModelImprovement( max_no_improvement_evals=self.max_no_improvement_evals, min_evals=self.min_evals, - verbose=1, + verbose=verbose, ) if self.activate_tensorboard: diff --git a/quickadapter/user_data/freqaimodels/LightGBMRegressorQuickAdapterV35.py b/quickadapter/user_data/freqaimodels/LightGBMRegressorQuickAdapterV35.py index cced5a2..5fcd4d1 100644 --- a/quickadapter/user_data/freqaimodels/LightGBMRegressorQuickAdapterV35.py +++ b/quickadapter/user_data/freqaimodels/LightGBMRegressorQuickAdapterV35.py @@ -274,22 +274,13 @@ class LightGBMRegressorQuickAdapterV35(BaseRegressionModel): prediction_thresholds_smoothing = self.freqai_info.get( "prediction_thresholds_smoothing", "mean" ) - if prediction_thresholds_smoothing == "quantile": - return self.quantile_min_max_pred( - pred_df, fit_live_predictions_candles, label_period_candles - ) - elif prediction_thresholds_smoothing == "mean": - return mean_min_max_pred( - pred_df, fit_live_predictions_candles, label_period_candles - ) - elif prediction_thresholds_smoothing == "median": - return median_min_max_pred( - pred_df, fit_live_predictions_candles, label_period_candles - ) - else: - raise ValueError( - f"Invalid prediction_thresholds_smoothing value: '{prediction_thresholds_smoothing}'" - ) + return { + "quantile": self.quantile_min_max_pred, + "mean": mean_min_max_pred, + "median": median_min_max_pred, + }[prediction_thresholds_smoothing]( + pred_df, fit_live_predictions_candles, label_period_candles + ) def optuna_hp_enqueue_previous_best_trial( self, diff --git a/quickadapter/user_data/freqaimodels/XGBoostRegressorQuickAdapterV35.py b/quickadapter/user_data/freqaimodels/XGBoostRegressorQuickAdapterV35.py index be7ad10..bdb9bdc 100644 --- a/quickadapter/user_data/freqaimodels/XGBoostRegressorQuickAdapterV35.py +++ b/quickadapter/user_data/freqaimodels/XGBoostRegressorQuickAdapterV35.py @@ -275,22 +275,13 @@ class XGBoostRegressorQuickAdapterV35(BaseRegressionModel): prediction_thresholds_smoothing = self.freqai_info.get( "prediction_thresholds_smoothing", "mean" ) - if prediction_thresholds_smoothing == "quantile": - return self.quantile_min_max_pred( - pred_df, fit_live_predictions_candles, label_period_candles - ) - elif prediction_thresholds_smoothing == "mean": - return mean_min_max_pred( - pred_df, fit_live_predictions_candles, label_period_candles - ) - elif prediction_thresholds_smoothing == "median": - return median_min_max_pred( - pred_df, fit_live_predictions_candles, label_period_candles - ) - else: - raise ValueError( - f"Invalid prediction_thresholds_smoothing value: '{prediction_thresholds_smoothing}'" - ) + return { + "quantile": self.quantile_min_max_pred, + "mean": mean_min_max_pred, + "median": median_min_max_pred, + }[prediction_thresholds_smoothing]( + pred_df, fit_live_predictions_candles, label_period_candles + ) def optuna_hp_enqueue_previous_best_trial( self, diff --git a/quickadapter/user_data/strategies/QuickAdapterV3.py b/quickadapter/user_data/strategies/QuickAdapterV3.py index 1c35c68..17b0328 100644 --- a/quickadapter/user_data/strategies/QuickAdapterV3.py +++ b/quickadapter/user_data/strategies/QuickAdapterV3.py @@ -263,12 +263,7 @@ class QuickAdapterV3(IStrategy): dataframe.at[mp, EXTREMA_COLUMN] = 1 dataframe["minima"] = np.where(dataframe[EXTREMA_COLUMN] == -1, -1, 0) dataframe["maxima"] = np.where(dataframe[EXTREMA_COLUMN] == 1, 1, 0) - dataframe[EXTREMA_COLUMN] = ( - dataframe[EXTREMA_COLUMN] - .rolling(window=5, win_type="gaussian", center=True) - .mean(std=0.5) - ) - return dataframe + return self.smooth_extrema(dataframe, EXTREMA_COLUMN, 5) def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: dataframe = self.freqai.start(dataframe, metadata, self) @@ -409,6 +404,30 @@ class QuickAdapterV3(IStrategy): else: raise ValueError(f"Invalid trading_mode: {trading_mode}") + def smooth_extrema( + self, + dataframe: DataFrame, + extrema_column: str, + window: int, + center: bool = True, + std: float = 0.5, + ) -> DataFrame: + extrema_smoothing = self.freqai_info.get("extrema_smoothing", "gaussian") + dataframe[extrema_column] = { + "gaussian": ( + dataframe[extrema_column] + .rolling(window=window, win_type="gaussian", center=center) + .mean(std=std) + ), + "triang": ( + dataframe[extrema_column] + .rolling(window=window, win_type="triang", center=center) + .mean() + ), + "ewma": dataframe[extrema_column].ewm(span=window).mean(), + }[extrema_smoothing] + return dataframe + def top_percent_change(dataframe: DataFrame, length: int) -> float: """ -- 2.43.0