From: Jérôme Benoit Date: Thu, 25 Dec 2025 16:22:13 +0000 (+0100) Subject: refactor(quickadapter)!: rename nadaraya_watson to gaussian_filter1d X-Git-Url: https://git.piment-noir.org/?a=commitdiff_plain;h=f312eb65b9f42fbda62d2cea33cac733db7be6be;p=freqai-strategies.git refactor(quickadapter)!: rename nadaraya_watson to gaussian_filter1d Signed-off-by: Jérôme Benoit --- diff --git a/README.md b/README.md index 13e90a2..765926d 100644 --- a/README.md +++ b/README.md @@ -60,12 +60,12 @@ docker compose up -d --build | _Regressor model_ | | | | | freqai.regressor | `xgboost` | enum {`xgboost`,`lightgbm`} | Machine learning regressor algorithm. | | _Extrema smoothing_ | | | | -| freqai.extrema_smoothing.method | `gaussian` | enum {`gaussian`,`kaiser`,`triang`,`smm`,`sma`,`savgol`,`nadaraya_watson`} | Extrema smoothing method (`smm`=median, `sma`=mean, `savgol`=Savitzky–Golay, `nadaraya_watson`=Gaussian kernel regression). | +| freqai.extrema_smoothing.method | `gaussian` | enum {`gaussian`,`kaiser`,`triang`,`smm`,`sma`,`savgol`,`gaussian_filter1d`} | Extrema smoothing method (`smm`=median, `sma`=mean, `savgol`=Savitzky–Golay). | | freqai.extrema_smoothing.window | 5 | int >= 3 | Smoothing window length (candles). | | freqai.extrema_smoothing.beta | 8.0 | float > 0 | Shape parameter for `kaiser` kernel. | | freqai.extrema_smoothing.polyorder | 3 | int >= 1 | Polynomial order for `savgol` smoothing. | -| freqai.extrema_smoothing.mode | `mirror` | enum {`mirror`,`constant`,`nearest`,`wrap`,`interp`} | Boundary mode for `savgol` and `nadaraya_watson`. | -| freqai.extrema_smoothing.bandwidth | 1.0 | float > 0 | Gaussian bandwidth for `nadaraya_watson` smoothing. | +| freqai.extrema_smoothing.mode | `mirror` | enum {`mirror`,`constant`,`nearest`,`wrap`,`interp`} | Boundary mode for `savgol` and `gaussian_filter1d`. | +| freqai.extrema_smoothing.sigma | 1.0 | float > 0 | Gaussian `sigma` for `gaussian_filter1d` smoothing. | | _Extrema weighting_ | | | | | freqai.extrema_weighting.strategy | `none` | enum {`none`,`amplitude`,`amplitude_threshold_ratio`,`volume_rate`,`speed`,`efficiency_ratio`,`volume_weighted_efficiency_ratio`,`hybrid`} | Extrema weighting source: unweighted (`none`), swing amplitude (`amplitude`), swing amplitude / median volatility-threshold ratio (`amplitude_threshold_ratio`), swing volume per candle (`volume_rate`), swing speed (`speed`), swing efficiency ratio (`efficiency_ratio`), swing volume-weighted efficiency ratio (`volume_weighted_efficiency_ratio`), or `hybrid`. | | freqai.extrema_weighting.source_weights | `{}` | dict[str, float] | Weights on extrema weighting sources for `hybrid`. | diff --git a/quickadapter/user_data/strategies/QuickAdapterV3.py b/quickadapter/user_data/strategies/QuickAdapterV3.py index 7e81951..b5290c5 100644 --- a/quickadapter/user_data/strategies/QuickAdapterV3.py +++ b/quickadapter/user_data/strategies/QuickAdapterV3.py @@ -409,9 +409,7 @@ class QuickAdapterV3(IStrategy): logger.info(f" beta: {format_number(self.extrema_smoothing['beta'])}") logger.info(f" polyorder: {self.extrema_smoothing['polyorder']}") logger.info(f" mode: {self.extrema_smoothing['mode']}") - logger.info( - f" bandwidth: {format_number(self.extrema_smoothing['bandwidth'])}" - ) + logger.info(f" sigma: {format_number(self.extrema_smoothing['sigma'])}") logger.info("Reversal Confirmation:") logger.info(f" lookback_period: {self._reversal_lookback_period}") @@ -1036,18 +1034,18 @@ class QuickAdapterV3(IStrategy): ) smoothing_mode = SMOOTHING_MODES[0] - smoothing_bandwidth = extrema_smoothing.get( - "bandwidth", DEFAULTS_EXTREMA_SMOOTHING["bandwidth"] + smoothing_sigma = extrema_smoothing.get( + "sigma", DEFAULTS_EXTREMA_SMOOTHING["sigma"] ) if ( - not isinstance(smoothing_bandwidth, (int, float)) - or smoothing_bandwidth <= 0 - or not np.isfinite(smoothing_bandwidth) + not isinstance(smoothing_sigma, (int, float)) + or smoothing_sigma <= 0 + or not np.isfinite(smoothing_sigma) ): logger.warning( - f"Invalid extrema_smoothing bandwidth {smoothing_bandwidth}, must be a positive finite number, using default {DEFAULTS_EXTREMA_SMOOTHING['bandwidth']}" + f"Invalid extrema_smoothing sigma {smoothing_sigma}, must be a positive finite number, using default {DEFAULTS_EXTREMA_SMOOTHING['sigma']}" ) - smoothing_bandwidth = DEFAULTS_EXTREMA_SMOOTHING["bandwidth"] + smoothing_sigma = DEFAULTS_EXTREMA_SMOOTHING["sigma"] return { "method": smoothing_method, @@ -1055,7 +1053,7 @@ class QuickAdapterV3(IStrategy): "beta": smoothing_beta, "polyorder": int(smoothing_polyorder), "mode": smoothing_mode, - "bandwidth": float(smoothing_bandwidth), + "sigma": float(smoothing_sigma), } @staticmethod @@ -1163,7 +1161,7 @@ class QuickAdapterV3(IStrategy): self.extrema_smoothing["beta"], self.extrema_smoothing["polyorder"], self.extrema_smoothing["mode"], - self.extrema_smoothing["bandwidth"], + self.extrema_smoothing["sigma"], ) if debug: diff --git a/quickadapter/user_data/strategies/Utils.py b/quickadapter/user_data/strategies/Utils.py index d78aacb..a5e393f 100644 --- a/quickadapter/user_data/strategies/Utils.py +++ b/quickadapter/user_data/strategies/Utils.py @@ -98,7 +98,7 @@ RANK_METHODS: Final[tuple[RankMethod, ...]] = ( SmoothingKernel = Literal["gaussian", "kaiser", "triang"] SmoothingMethod = Union[ - SmoothingKernel, Literal["smm", "sma", "savgol", "nadaraya_watson"] + SmoothingKernel, Literal["smm", "sma", "savgol", "gaussian_filter1d"] ] SMOOTHING_METHODS: Final[tuple[SmoothingMethod, ...]] = ( "gaussian", @@ -107,7 +107,7 @@ SMOOTHING_METHODS: Final[tuple[SmoothingMethod, ...]] = ( "smm", "sma", "savgol", - "nadaraya_watson", + "gaussian_filter1d", ) SmoothingMode = Literal["mirror", "constant", "nearest", "wrap", "interp"] @@ -126,7 +126,7 @@ DEFAULTS_EXTREMA_SMOOTHING: Final[dict[str, Any]] = { "beta": 8.0, "polyorder": 3, "mode": SMOOTHING_MODES[0], # "mirror" - "bandwidth": 1.0, + "sigma": 1.0, } DEFAULTS_EXTREMA_WEIGHTING: Final[dict[str, Any]] = { @@ -209,19 +209,6 @@ def get_savgol_params( return window, polyorder, mode -def nadaraya_watson( - series: pd.Series, bandwidth: float, mode: SmoothingMode -) -> pd.Series: - return pd.Series( - gaussian_filter1d( - series.to_numpy(), - sigma=bandwidth, - mode=mode, # type: ignore - ), - index=series.index, - ) - - @lru_cache(maxsize=8) def _calculate_coeffs( window: int, @@ -270,7 +257,7 @@ def smooth_extrema( beta: float = DEFAULTS_EXTREMA_SMOOTHING["beta"], polyorder: int = DEFAULTS_EXTREMA_SMOOTHING["polyorder"], mode: SmoothingMode = DEFAULTS_EXTREMA_SMOOTHING["mode"], - bandwidth: float = DEFAULTS_EXTREMA_SMOOTHING["bandwidth"], + sigma: float = DEFAULTS_EXTREMA_SMOOTHING["sigma"], ) -> pd.Series: n = len(series) if n == 0: @@ -326,8 +313,15 @@ def smooth_extrema( ), index=series.index, ) - elif method == SMOOTHING_METHODS[6]: # "nadaraya_watson" - return nadaraya_watson(series, bandwidth, mode) + elif method == SMOOTHING_METHODS[6]: # "gaussian_filter1d" + return pd.Series( + gaussian_filter1d( + series.to_numpy(), + sigma=sigma, + mode=mode, # type: ignore + ), + index=series.index, + ) else: return zero_phase_filter( series=series,