From: Jérôme Benoit Date: Thu, 13 Mar 2025 11:19:45 +0000 (+0100) Subject: refactor(qav3): use builtin method to propagate label_period_candles X-Git-Url: https://git.piment-noir.org/?a=commitdiff_plain;h=b166363c2b28ba71ad5ab955b54b7126b235599b;p=freqai-strategies.git refactor(qav3): use builtin method to propagate label_period_candles Signed-off-by: Jérôme Benoit --- diff --git a/quickadapter/user_data/freqaimodels/LightGBMRegressorQuickAdapterV35.py b/quickadapter/user_data/freqaimodels/LightGBMRegressorQuickAdapterV35.py index 65d2f25..35f40b6 100644 --- a/quickadapter/user_data/freqaimodels/LightGBMRegressorQuickAdapterV35.py +++ b/quickadapter/user_data/freqaimodels/LightGBMRegressorQuickAdapterV35.py @@ -68,12 +68,6 @@ class LightGBMRegressorQuickAdapterV35(BaseRegressionModel): self.__optuna_period_params[pair] = ( self.optuna_load_best_params(pair, "period") or {} ) - self.freqai_info["feature_parameters"][pair] = {} - self.freqai_info["feature_parameters"][pair]["label_period_candles"] = ( - self.__optuna_period_params[pair].get( - "label_period_candles", self.ft_params["label_period_candles"] - ) - ) def fit(self, data_dictionary: dict, dk: FreqaiDataKitchen, **kwargs) -> Any: """ @@ -140,11 +134,6 @@ class LightGBMRegressorQuickAdapterV35(BaseRegressionModel): y_test = y_test.iloc[-test_window:] test_weights = test_weights[-test_window:] - # FIXME: find a better way to propagate optuna computed params to strategy - self.freqai_info["feature_parameters"][dk.pair][ - "label_period_candles" - ] = self.__optuna_period_params[dk.pair].get("label_period_candles") - model = LGBMRegressor(objective="regression", **model_training_parameters) eval_set, eval_weights = self.eval_set_and_weights(X_test, y_test, test_weights) diff --git a/quickadapter/user_data/freqaimodels/XGBoostRegressorQuickAdapterV35.py b/quickadapter/user_data/freqaimodels/XGBoostRegressorQuickAdapterV35.py index eeaecba..29a5efa 100644 --- a/quickadapter/user_data/freqaimodels/XGBoostRegressorQuickAdapterV35.py +++ b/quickadapter/user_data/freqaimodels/XGBoostRegressorQuickAdapterV35.py @@ -68,12 +68,6 @@ class XGBoostRegressorQuickAdapterV35(BaseRegressionModel): self.__optuna_period_params[pair] = ( self.optuna_load_best_params(pair, "period") or {} ) - self.freqai_info["feature_parameters"][pair] = {} - self.freqai_info["feature_parameters"][pair]["label_period_candles"] = ( - self.__optuna_period_params[pair].get( - "label_period_candles", self.ft_params["label_period_candles"] - ) - ) def fit(self, data_dictionary: dict, dk: FreqaiDataKitchen, **kwargs) -> Any: """ @@ -140,11 +134,6 @@ class XGBoostRegressorQuickAdapterV35(BaseRegressionModel): y_test = y_test.iloc[-test_window:] test_weights = test_weights[-test_window:] - # FIXME: find a better way to propagate optuna computed params to strategy - self.freqai_info["feature_parameters"][dk.pair][ - "label_period_candles" - ] = self.__optuna_period_params[dk.pair].get("label_period_candles") - model = XGBRegressor( objective="reg:squarederror", eval_metric="rmse", diff --git a/quickadapter/user_data/strategies/QuickAdapterV3.py b/quickadapter/user_data/strategies/QuickAdapterV3.py index 7c4cb54..07cecb1 100644 --- a/quickadapter/user_data/strategies/QuickAdapterV3.py +++ b/quickadapter/user_data/strategies/QuickAdapterV3.py @@ -1,6 +1,8 @@ +import json import logging from functools import reduce import datetime +from pathlib import Path import talib.abstract as ta from pandas import DataFrame, Series from technical import qtpylib @@ -122,6 +124,25 @@ class QuickAdapterV3(IStrategy): def startup_candle_count(self): return int(self.freqai_info.get("fit_live_predictions_candles", 100) / 2) + def __init__(self, config: dict) -> None: + super().__init__(config) + self.pairs = self.config.get("exchange", {}).get("pair_whitelist") + if not self.pairs: + raise ValueError( + "FreqAI strategy requires StaticPairList method defined in pairlists configuration and pair_whitelist defined in exchange section configuration" + ) + self.models_full_path = Path( + self.config["user_data_dir"] + / "models" + / f"{self.config.get('freqai', {}).get('identifier', 'no_id_provided')}" + ) + self.__period_params: dict[str, dict] = {} + for pair in self.pairs: + self.__period_params[pair] = self.load_period_best_params(pair) or {} + logger.info( + f"Loaded period best params for {pair}: {self.__period_params[pair]}" + ) + def feature_engineering_expand_all(self, dataframe, period, **kwargs): dataframe["%-rsi-period"] = ta.RSI(dataframe, timeperiod=period) dataframe["%-aroonosc-period"] = ta.AROONOSC(dataframe, timeperiod=period) @@ -249,13 +270,12 @@ class QuickAdapterV3(IStrategy): def set_freqai_targets(self, dataframe, metadata, **kwargs): pair = str(metadata.get("pair")) - label_period_candles = ( - self.freqai_info["feature_parameters"] - .get(pair, {}) - .get( - "label_period_candles", - self.freqai_info["feature_parameters"]["label_period_candles"], - ) + label_period_candles = self.__period_params.get(pair, {}).get( + "label_period_candles", + self.freqai_info["feature_parameters"]["label_period_candles"], + ) + logger.info( + f"label_period_candles: {label_period_candles} for {pair}" ) min_peaks = argrelmin( dataframe["low"].values, @@ -284,6 +304,17 @@ class QuickAdapterV3(IStrategy): 1, ) + # pair = str(metadata.get("pair")) + # self.__period_params[pair]["label_period_candles"] = dataframe[ + # "label_period_candles" + # ] + # logger.info( + # f"label_period_candles: {self.__period_params[pair]['label_period_candles']}" + # ) + # logger.info( + # f"label_period_candles extra returns: {dataframe['label_period_candles']}" + # ) + dataframe["minima_threshold"] = dataframe[MINIMA_THRESHOLD_COLUMN] dataframe["maxima_threshold"] = dataframe[MAXIMA_THRESHOLD_COLUMN] @@ -439,6 +470,17 @@ class QuickAdapterV3(IStrategy): ), ) + def load_period_best_params(self, pair: str) -> dict | None: + namespace = "period" + best_params_path = Path( + self.models_full_path + / f"optuna-{namespace}-best-params-{pair.split('/')[0]}.json" + ) + if best_params_path.is_file(): + with best_params_path.open("r", encoding="utf-8") as read_file: + return json.load(read_file) + return None + def top_change_percent(dataframe: DataFrame, period: int) -> Series: """