From: Jérôme Benoit Date: Wed, 6 Aug 2025 20:04:01 +0000 (+0200) Subject: refactor(qav3): move extrema smoothing code to utils X-Git-Url: https://git.piment-noir.org/?a=commitdiff_plain;h=2623590d003b31585c7d67c67eca91c7ef532710;p=freqai-strategies.git refactor(qav3): move extrema smoothing code to utils Signed-off-by: Jérôme Benoit --- diff --git a/quickadapter/user_data/strategies/QuickAdapterV3.py b/quickadapter/user_data/strategies/QuickAdapterV3.py index 7a6f472..9130338 100644 --- a/quickadapter/user_data/strategies/QuickAdapterV3.py +++ b/quickadapter/user_data/strategies/QuickAdapterV3.py @@ -24,14 +24,12 @@ from Utils import ( calculate_quantile, ewo, get_distance, - get_gaussian_std, - get_odd_window, get_zl_ma_fn, non_zero_diff, price_retracement_percent, + smooth_extrema, top_change_percent, vwapb, - zero_phase, zigzag, zlema, ) @@ -479,9 +477,11 @@ class QuickAdapterV3(IStrategy): logger.info( f"{pair}: labeled {len(pivots_indices)} extrema (label_period={QuickAdapterV3.td_format(label_period)} / {label_period_candles=} / {label_natr_ratio=:.2f})" ) - dataframe[EXTREMA_COLUMN] = self.smooth_extrema( + dataframe[EXTREMA_COLUMN] = smooth_extrema( dataframe[EXTREMA_COLUMN], - self.freqai_info.get("extrema_smoothing_window", 5), + str(self.freqai_info.get("extrema_smoothing", "gaussian")), + int(self.freqai_info.get("extrema_smoothing_window", 5)), + float(self.freqai_info.get("extrema_smoothing_beta", 8.0)), ) if debug: extrema = dataframe[EXTREMA_COLUMN] @@ -1179,51 +1179,6 @@ class QuickAdapterV3(IStrategy): else: raise ValueError(f"Invalid trading_mode: {trading_mode}") - def smooth_extrema( - self, - series: Series, - window: int, - ) -> Series: - extrema_smoothing = str(self.freqai_info.get("extrema_smoothing", "gaussian")) - std = get_gaussian_std(window) - extrema_smoothing_beta = float( - self.freqai_info.get("extrema_smoothing_beta", 8.0) - ) - if debug: - logger.info( - f"{extrema_smoothing=}, {window=}, {std=}, {extrema_smoothing_beta=}" - ) - odd_window = get_odd_window(window) - smoothing_methods: dict[str, Series] = { - "gaussian": zero_phase( - series=series, - window=window, - win_type="gaussian", - std=std, - beta=extrema_smoothing_beta, - ), - "kaiser": zero_phase( - series=series, - window=window, - win_type="kaiser", - std=std, - beta=extrema_smoothing_beta, - ), - "triang": zero_phase( - series=series, - window=window, - win_type="triang", - std=std, - beta=extrema_smoothing_beta, - ), - "smm": series.rolling(window=odd_window, center=True).median(), - "sma": series.rolling(window=odd_window, center=True).mean(), - } - return smoothing_methods.get( - extrema_smoothing, - smoothing_methods["gaussian"], - ) - def optuna_load_best_params( self, pair: str, namespace: str ) -> Optional[dict[str, Any]]: diff --git a/quickadapter/user_data/strategies/Utils.py b/quickadapter/user_data/strategies/Utils.py index 6b8d5f4..88d000e 100644 --- a/quickadapter/user_data/strategies/Utils.py +++ b/quickadapter/user_data/strategies/Utils.py @@ -76,6 +76,42 @@ def zero_phase( return pd.Series(filtered_values, index=series.index) +def smooth_extrema( + series: pd.Series, method: str, window: int, beta: float +) -> pd.Series: + std = get_gaussian_std(window) + odd_window = get_odd_window(window) + smoothing_methods: dict[str, pd.Series] = { + "gaussian": zero_phase( + series=series, + window=window, + win_type="gaussian", + std=std, + beta=beta, + ), + "kaiser": zero_phase( + series=series, + window=window, + win_type="kaiser", + std=std, + beta=beta, + ), + "triang": zero_phase( + series=series, + window=window, + win_type="triang", + std=std, + beta=beta, + ), + "smm": series.rolling(window=odd_window, center=True).median(), + "sma": series.rolling(window=odd_window, center=True).mean(), + } + return smoothing_methods.get( + method, + smoothing_methods["gaussian"], + ) + + @lru_cache(maxsize=128) def calculate_min_extrema( size: int, fit_live_predictions_candles: int, min_extrema: int = 4