From bfb2fea1b1b84a47f90607e0cf369e7f56a572d3 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Sat, 13 Dec 2025 22:09:33 +0100 Subject: [PATCH] chore(qav3): bump versions MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Jérôme Benoit --- README.md | 38 ++++++++++++------- .../freqaimodels/QuickAdapterRegressorV3.py | 2 +- .../user_data/strategies/QuickAdapterV3.py | 4 +- quickadapter/user_data/strategies/Utils.py | 36 +++++++++--------- 4 files changed, 44 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index d572cab..1e6e82e 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,8 @@ ### Quick start -Change the timezone according to your location in [`docker-compose.yml`](./quickadapter/docker-compose.yml). +Change the timezone according to your location in +[`docker-compose.yml`](./quickadapter/docker-compose.yml). From the repository root, configure, build and start the QuickAdapter container: @@ -25,7 +26,8 @@ cd quickadapter cp user_data/config-template.json user_data/config.json ``` -Adapt the configuration to your needs: edit `user_data/config.json` to set your exchange API keys and tune the `freqai` section. +Adapt the configuration to your needs: edit `user_data/config.json` to set your +exchange API keys and tune the `freqai` section. Then build and start the container: @@ -63,12 +65,12 @@ docker compose up -d --build | 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`. | +| freqai.extrema_smoothing.bandwidth | 1.0 | float > 0 | Gaussian bandwidth for `nadaraya_watson` smoothing. | | _Extrema weighting_ | | | | -| freqai.extrema_weighting.strategy | `none` | enum {`none`,`amplitude`,`amplitude_threshold_ratio`,`volume`,`speed`,`efficiency_ratio`,`hybrid`} | Extrema weighting source: unweighted (`none`), single-source (`amplitude`,`amplitude_threshold_ratio`,`volume`,`speed`,`efficiency_ratio`), or `hybrid` (combine multiple sources via `freqai.extrema_weighting.source_weights`). | -| freqai.extrema_weighting.source_weights | all sources = 1.0 | object with keys in {`amplitude`,`amplitude_threshold_ratio`,`volume`,`speed`,`efficiency_ratio`} and float >= 0 | Hybrid-only: per-source coefficients. If not set (or invalid/empty), defaults to equal weights. Coefficients are L1-normalized (sum to 1.0) before aggregation; zero/NaN/Inf entries are ignored. | -| freqai.extrema_weighting.aggregation | `weighted_sum` | enum {`weighted_sum`,`geometric_mean`} | Hybrid-only: how normalized per-source weights are combined into a single per-extremum weight. `geometric_mean` uses abs(values) for numerical stability. | -| freqai.extrema_weighting.aggregation_normalization | `none` | enum {`minmax`,`sigmoid`,`softmax`,`l1`,`l2`,`rank`,`none`} | Hybrid-only: optional post-aggregation normalization. Applies after aggregation without re-standardization and without a second gamma correction. | +| freqai.extrema_weighting.strategy | `none` | enum {`none`,`amplitude`,`amplitude_threshold_ratio`,`volume`,`speed`,`efficiency_ratio`,`hybrid`} | Extrema weighting source: unweighted (`none`), swing amplitude (`amplitude`), swing amplitude / median volatility-threshold ratio (`amplitude_threshold_ratio`), swing volume (`volume`), swing speed (`speed`), swing efficiency ratio (`efficiency_ratio`), or `hybrid`. | +| freqai.extrema_weighting.source_weights | `{}` | dict[str, float] | Weights on extrema extrema weighting sources for `hybrid`. | +| freqai.extrema_weighting.aggregation | `weighted_sum` | enum {`weighted_sum`,`geometric_mean`} | Aggregation method applied to weighted extrema weighting sources for `hybrid`. | +| freqai.extrema_weighting.aggregation_normalization | `none` | enum {`minmax`,`sigmoid`,`softmax`,`l1`,`l2`,`rank`,`none`} | Normalization method applied to the aggregated extrema weighting source for `hybrid`. | | freqai.extrema_weighting.standardization | `none` | enum {`none`,`zscore`,`robust`,`mmad`} | Standardization method applied before normalization. `none`=no standardization, `zscore`=(w-μ)/σ, `robust`=(w-median)/IQR, `mmad`=(w-median)/MAD. | | freqai.extrema_weighting.robust_quantiles | [0.25, 0.75] | list[float] where 0 <= Q1 < Q3 <= 1 | Quantile range for robust standardization, Q1 and Q3. | | freqai.extrema_weighting.mmad_scaling_factor | 1.4826 | float > 0 | Scaling factor for MMAD standardization. | @@ -100,7 +102,7 @@ docker compose up -d --build | _Predictions extrema_ | | | | | freqai.predictions_extrema.selection_method | `rank` | enum {`rank`,`values`,`partition`} | Extrema selection method. `rank` uses ranked extrema values, `values` uses reversal values, `partition` uses sign-based partitioning. | | freqai.predictions_extrema.thresholds_smoothing | `mean` | enum {`mean`,`isodata`,`li`,`minimum`,`otsu`,`triangle`,`yen`,`median`,`soft_extremum`} | Thresholding method for prediction thresholds smoothing. | -| freqai.predictions_extrema.thresholds_alpha | 12.0 | float > 0 | Alpha for `soft_extremum`. | +| freqai.predictions_extrema.thresholds_alpha | 12.0 | float > 0 | Alpha for `soft_extremum` for thesholds smoothing. | | freqai.predictions_extrema.threshold_outlier | 0.999 | float (0,1) | Quantile threshold for predictions outlier filtering. | | freqai.predictions_extrema.extrema_fraction | 1.0 | float (0,1] | Fraction of extrema used for thresholds. `1.0` uses all, lower values keep only most significant. Applies to `rank` and `values`; ignored for `partition`. | | _Optuna / HPO_ | | | | @@ -124,7 +126,8 @@ docker compose up -d --build ### Quick start -Change the timezone according to your location in [`docker-compose.yml`](./ReforceXY/docker-compose.yml). +Change the timezone according to your location in +[`docker-compose.yml`](./ReforceXY/docker-compose.yml). From the repository root, configure, build and start the ReforceXY container: @@ -133,7 +136,8 @@ cd ReforceXY cp user_data/config-template.json user_data/config.json ``` -Adapt the configuration to your needs: edit `user_data/config.json` to set your exchange API keys and tune the `freqai` section. +Adapt the configuration to your needs: edit `user_data/config.json` to set your +exchange API keys and tune the `freqai` section. Then build and start the container: @@ -147,9 +151,11 @@ PPO, MaskablePPO, RecurrentPPO, DQN, QRDQN ### Configuration tunables -The documented list of model tunables is at the top of the [ReforceXY.py](./ReforceXY/user_data/freqaimodels/ReforceXY.py) file. +The documented list of model tunables is at the top of the +[ReforceXY.py](./ReforceXY/user_data/freqaimodels/ReforceXY.py) file. -The rewarding logic and tunables are documented in the [reward space analysis](./ReforceXY/reward_space_analysis/README.md). +The rewarding logic and tunables are documented in the +[reward space analysis](./ReforceXY/reward_space_analysis/README.md). ## Common workflows @@ -190,7 +196,9 @@ cp ../scripts/docker-upgrade.sh . ./docker-upgrade.sh ``` -The script checks for new Freqtrade image versions on Docker Hub, rebuilds and restarts containers if updates are found, sends Telegram notifications (if configured), and cleans up unused images. +The script checks for new Freqtrade image versions on Docker Hub, rebuilds and +restarts containers if updates are found, sends Telegram notifications (if +configured), and cleans up unused images. _Configuration and environment variables:_ @@ -210,4 +218,6 @@ _Cronjob setup (daily check at 3:00 AM):_ ## Note -> Do not expect any support of any kind on the Internet. Nevertheless, PRs implementing documentation, bug fixes, cleanups or sensible features will be discussed and might get merged. +> Do not expect any support of any kind on the Internet. Nevertheless, PRs +> implementing documentation, bug fixes, cleanups or sensible features will be +> discussed and might get merged. diff --git a/quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py b/quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py index 65cb631..9c90314 100644 --- a/quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py +++ b/quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py @@ -73,7 +73,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel): https://github.com/sponsors/robcaulk """ - version = "3.7.130" + version = "3.7.131" _SQRT_2: Final[float] = np.sqrt(2.0) diff --git a/quickadapter/user_data/strategies/QuickAdapterV3.py b/quickadapter/user_data/strategies/QuickAdapterV3.py index 537243e..322b190 100644 --- a/quickadapter/user_data/strategies/QuickAdapterV3.py +++ b/quickadapter/user_data/strategies/QuickAdapterV3.py @@ -106,7 +106,7 @@ class QuickAdapterV3(IStrategy): _TRADING_MODES: Final[tuple[TradingMode, ...]] = ("spot", "margin", "futures") def version(self) -> str: - return "3.3.180" + return "3.3.181" timeframe = "5m" @@ -1000,7 +1000,7 @@ class QuickAdapterV3(IStrategy): ) weighted_extrema, _ = get_weighted_extrema( - series=dataframe[EXTREMA_COLUMN], + extrema=dataframe[EXTREMA_COLUMN], indices=pivots_indices, amplitudes=pivots_amplitudes, amplitude_threshold_ratios=pivots_amplitude_threshold_ratios, diff --git a/quickadapter/user_data/strategies/Utils.py b/quickadapter/user_data/strategies/Utils.py index 250f7e6..f0e6052 100644 --- a/quickadapter/user_data/strategies/Utils.py +++ b/quickadapter/user_data/strategies/Utils.py @@ -631,7 +631,7 @@ def _weights_array_to_series( def calculate_hybrid_extrema_weights( - series: pd.Series, + extrema: pd.Series, indices: list[int], amplitudes: list[float], amplitude_threshold_ratios: list[float], @@ -662,7 +662,7 @@ def calculate_hybrid_extrema_weights( ) -> pd.Series: n = len(indices) if n == 0: - return pd.Series(DEFAULT_EXTREMA_WEIGHT, index=series.index) + return pd.Series(DEFAULT_EXTREMA_WEIGHT, index=extrema.index) if not isinstance(source_weights, dict): source_weights = {} @@ -706,7 +706,7 @@ def calculate_hybrid_extrema_weights( ) source_weights_sum = np.nansum(np.abs(np_source_weights)) if not np.isfinite(source_weights_sum) or source_weights_sum <= 0: - return pd.Series(DEFAULT_EXTREMA_WEIGHT, index=series.index) + return pd.Series(DEFAULT_EXTREMA_WEIGHT, index=extrema.index) np_source_weights = np_source_weights / source_weights_sum normalized_source_weights: list[NDArray[np.floating]] = [] @@ -757,10 +757,10 @@ def calculate_hybrid_extrema_weights( combined_source_weights.size == 0 or not np.isfinite(combined_source_weights).all() ): - return pd.Series(DEFAULT_EXTREMA_WEIGHT, index=series.index) + return pd.Series(DEFAULT_EXTREMA_WEIGHT, index=extrema.index) return _weights_array_to_series( - index=series.index, + index=extrema.index, indices=indices, weights=combined_source_weights, default_weight=np.nanmedian(combined_source_weights), @@ -827,7 +827,7 @@ def calculate_extrema_weights( def compute_extrema_weights( - series: pd.Series, + extrema: pd.Series, indices: list[int], amplitudes: list[float], amplitude_threshold_ratios: list[float], @@ -858,7 +858,7 @@ def compute_extrema_weights( gamma: float = DEFAULTS_EXTREMA_WEIGHTING["gamma"], ) -> pd.Series: if len(indices) == 0 or strategy == WEIGHT_STRATEGIES[0]: # "none" - return pd.Series(DEFAULT_EXTREMA_WEIGHT, index=series.index) + return pd.Series(DEFAULT_EXTREMA_WEIGHT, index=extrema.index) if strategy in { WEIGHT_STRATEGIES[1], @@ -881,10 +881,10 @@ def compute_extrema_weights( weights = np.asarray([], dtype=float) if weights.size == 0: - return pd.Series(DEFAULT_EXTREMA_WEIGHT, index=series.index) + return pd.Series(DEFAULT_EXTREMA_WEIGHT, index=extrema.index) return calculate_extrema_weights( - series=series, + series=extrema, indices=indices, weights=weights, standardization=standardization, @@ -900,7 +900,7 @@ def compute_extrema_weights( if strategy == WEIGHT_STRATEGIES[6]: # "hybrid" return calculate_hybrid_extrema_weights( - series=series, + extrema=extrema, indices=indices, amplitudes=amplitudes, amplitude_threshold_ratios=amplitude_threshold_ratios, @@ -924,16 +924,16 @@ def compute_extrema_weights( raise ValueError(f"Unknown extrema weighting strategy: {strategy}") -def apply_weights(series: pd.Series, weights: pd.Series) -> pd.Series: +def _apply_weights(extrema: pd.Series, weights: pd.Series) -> pd.Series: if weights.empty: - return series + return extrema if np.allclose(weights.to_numpy(dtype=float), DEFAULT_EXTREMA_WEIGHT): - return series - return series * weights + return extrema + return extrema * weights def get_weighted_extrema( - series: pd.Series, + extrema: pd.Series, indices: list[int], amplitudes: list[float], amplitude_threshold_ratios: list[float], @@ -963,10 +963,8 @@ def get_weighted_extrema( # Phase 3: Post-processing gamma: float = DEFAULTS_EXTREMA_WEIGHTING["gamma"], ) -> tuple[pd.Series, pd.Series]: - """Apply extrema weighting and return (weighted_extrema, extrema_weights).""" - weights = compute_extrema_weights( - series=series, + extrema=extrema, indices=indices, amplitudes=amplitudes, amplitude_threshold_ratios=amplitude_threshold_ratios, @@ -988,7 +986,7 @@ def get_weighted_extrema( gamma=gamma, ) - weighted_extrema = apply_weights(series, weights) + weighted_extrema = _apply_weights(extrema, weights) return weighted_extrema, weights -- 2.43.0