From: Jérôme Benoit Date: Sat, 1 Aug 2026 20:53:46 +0000 (+0200) Subject: fix(quickadapter): support CatBoost continual learning (#196) X-Git-Url: https://git.piment-noir.org/?a=commitdiff_plain;h=42a0a933f930ee82964b70e537b155458da4668f;p=freqai-strategies.git fix(quickadapter): support CatBoost continual learning (#196) * fix(quickadapter): support CatBoost continual learning * fix(quickadapter): drop CatBoost init_model on GPU task_type CatBoost init_model training continuation is CPU-only and raises "Training continuation for GPU is not yet supported" on GPU. Passing it unconditionally crashed GPU CatBoost retrains under continual_learning. Drop init_model on the GPU path so it cold-starts instead. * style(quickadapter): realign README table cells after continual-learning doc edits --- diff --git a/README.md b/README.md index 3120346..a50a172 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ docker compose up -d --build | reversal_confirmation.max_natr_multiplier_fraction | 0.0125 | float [0,1] | Upper bound fraction (> lower bound) for volatility adjusted reversal threshold. | | _Regressor model_ | | | | | freqai.regressor | `xgboost` | enum {`xgboost`,`lightgbm`,`histgradientboostingregressor`,`ngboost`,`catboost`} | Machine learning regressor algorithm. | -| freqai.continual_learning | false | bool | Continue XGBoost or LightGBM training from the previously deployed model, so its booster grows at every retrain; delete trained models to reset. Under `test_size` two-stage selection, HPO and the pre-refit selection model cold-start and only the final refit continues, growing by the selection model's round count (see `test_size`). Other regressors ignore any prior model. | +| freqai.continual_learning | false | bool | Continue XGBoost, LightGBM, or CPU CatBoost training from the previously deployed model, so its booster grows at every retrain; delete trained models to reset. Under `test_size` two-stage selection, HPO and the pre-refit selection model cold-start and only the final refit continues, growing by the selection model's round count (see `test_size`). Other regressors ignore any prior model. | | _Model training parameters_ | | | | | freqai.model_training_parameters.gpu_vram_gb | 80 | int > 0 | Available GPU VRAM (GB) for CatBoost, not total. Any positive value is floored to the nearest supported tier `<= value` (tiers 8, 10, 12, 16, 24, 32, 40, 48, 64, 80; values below 8 use tier 8). Constrains `depth`, `border_count`, and `max_ctr_complexity` ranges. | | _Data split parameters_ | | | | @@ -69,11 +69,11 @@ docker compose up -d --build | freqai.data_split_parameters.gap | 0 | int >= 0 | Samples to exclude between train/test for `timeseries_split`. `0` auto-derives the gap (source and lower-bound rule depend on `causal_mode`; see `causal_mode`). Not used by `train_test_split`. | | freqai.data_split_parameters.max_train_size | None | int >= 1 \| None | Maximum training set size for `timeseries_split`. When set, creates a sliding window instead of expanding train set. None = no limit. | | _Label smoothing_ | | | | -| freqai.label_smoothing.method | `gaussian` | enum {`none`,`gaussian`,`kaiser`,`kaiser_bessel_derived`,`triang`,`smm`,`sma`,`savgol`,`gaussian_filter1d`} | Label smoothing method (`kaiser_bessel_derived` uses an even-length Kaiser-Bessel-derived zero-phase kernel; `smm`=median, `sma`=mean, `savgol`=Savitzky–Golay). | +| freqai.label_smoothing.method | `gaussian` | enum {`none`,`gaussian`,`kaiser`,`kaiser_bessel_derived`,`triang`,`smm`,`sma`,`savgol`,`gaussian_filter1d`} | Label smoothing method (`smm`=median, `sma`=mean, `savgol`=Savitzky–Golay). | | freqai.label_smoothing.window_candles | 5 | int >= 1 | Smoothing window length (candles). Values below 3 are raised to 3 at runtime. | | freqai.label_smoothing.beta | 8.0 | float > 0 | Shape parameter for `kaiser` and `kaiser_bessel_derived` kernels. | | freqai.label_smoothing.polyorder | 3 | int >= 0 | Polynomial order for `savgol` smoothing. | -| freqai.label_smoothing.mode | `mirror` | `savgol`: enum {`mirror`,`constant`,`nearest`,`wrap`,`interp`}; `gaussian_filter1d`: enum {`mirror`,`constant`,`nearest`,`wrap`}; ignored otherwise | Boundary mode for `savgol` and `gaussian_filter1d`. | +| freqai.label_smoothing.mode | `mirror` | `savgol`: enum {`mirror`,`constant`,`nearest`,`wrap`,`interp`}; `gaussian_filter1d`: enum {`mirror`,`constant`,`nearest`,`wrap`} | Boundary mode for `savgol` and `gaussian_filter1d`; ignored otherwise. | | freqai.label_smoothing.sigma | 1.0 | float > 0 | Gaussian `sigma` for `gaussian_filter1d` smoothing. | | _Label weighting_ | | | | | freqai.label_weighting.strategy | `none` | enum {`none`,`uniform`,`amplitude`,`amplitude_threshold_ratio`,`volume_rate`,`speed`,`efficiency_ratio`,`volume_weighted_efficiency_ratio`,`combined`} | Label weighting metric: none (`none`), uniform unit weight on every detected pivot (`uniform`), 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 combined metrics aggregation (`combined`). Switching between `none` and any other strategy requires deleting trained models to realign training emphasis. | @@ -139,7 +139,7 @@ docker compose up -d --build | freqai.optuna_hyperopt.warm_start | true | bool | Warm start HPO with previous best value(s). Persisted values are loaded and saved only in live and dry-run modes; non-live runs reuse only values produced earlier in the same run. | | freqai.optuna_hyperopt.n_startup_trials | 15 | int >= 0 | HPO startup trials. | | freqai.optuna_hyperopt.n_trials | 50 | int >= 1 | Maximum HPO trials. | -| freqai.optuna_hyperopt.n_jobs | 1 | int >= 1 | Parallel HPO workers. | +| freqai.optuna_hyperopt.n_jobs | 1 | int >= 1 | Parallel HPO workers. | | freqai.optuna_hyperopt.timeout | 7200 | int >= 0 | HPO wall-clock timeout in seconds. | | freqai.optuna_hyperopt.label_candles_step | 1 | int >= 1 | Step for Zigzag NATR period `label` search space. | | freqai.optuna_hyperopt.space_reduction | false | bool | Enable/disable `hp` search space reduction based on previous best parameters. | diff --git a/quickadapter/user_data/strategies/Utils.py b/quickadapter/user_data/strategies/Utils.py index 19b9710..a58b7b0 100644 --- a/quickadapter/user_data/strategies/Utils.py +++ b/quickadapter/user_data/strategies/Utils.py @@ -5193,6 +5193,9 @@ def fit_regressor( model_training_parameters.setdefault("max_ctr_complexity", 4) if loss_function not in _CATBOOST_GPU_RSM_LOSS_FUNCTIONS: model_training_parameters.pop("rsm", None) + # CatBoost init_model is CPU-only and raises on GPU; drop it so + # continual_learning cold-starts there instead. + init_model = None else: n_jobs = model_training_parameters.pop("n_jobs", None) if n_jobs is not None: @@ -5230,6 +5233,7 @@ def fit_regressor( if early_stopping_rounds is not None and has_eval_set else False, callbacks=fit_callbacks if fit_callbacks else None, + init_model=init_model, ) if pruning_callback is not None: