From 0af22ace025dafec8cbfb9baf7a9d1f3f7c55e63 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Fri, 4 Apr 2025 22:58:17 +0200 Subject: [PATCH] refactor(qav3): cleanup label period candles handling MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Jérôme Benoit --- .../freqaimodels/QuickAdapterRegressorV3.py | 39 +++++++++---------- .../user_data/strategies/QuickAdapterV3.py | 23 ++++++----- 2 files changed, 30 insertions(+), 32 deletions(-) diff --git a/quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py b/quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py index fbea95e..ea9f6dd 100644 --- a/quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py +++ b/quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py @@ -44,7 +44,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel): https://github.com/sponsors/robcaulk """ - version = "3.6.4" + version = "3.6.5" @cached_property def __optuna_config(self) -> dict: @@ -498,7 +498,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel): .reset_index(drop=True) ) label_period_frequency: int = max( - 1, int(fit_live_predictions_candles / (label_period_candles * 2)) + 1, fit_live_predictions_candles // label_period_candles ) return pred_df_sorted, label_period_frequency @@ -652,10 +652,10 @@ def period_objective( ) y_pred = model.predict(X_test) - min_label_period_candles: int = max(fit_live_predictions_candles // 20, 20) + min_label_period_candles: int = max(fit_live_predictions_candles // 9, 20) max_label_period_candles: int = min( - max(fit_live_predictions_candles // 6, min_label_period_candles), - test_window // 2, + max(fit_live_predictions_candles // 3, min_label_period_candles), + max(test_window // 2, min_label_period_candles), ) label_period_candles: int = trial.suggest_int( "label_period_candles", @@ -663,28 +663,27 @@ def period_objective( max_label_period_candles, step=candles_step, ) - label_window_length: int = label_period_candles * 2 - label_windows_length: int = ( - test_window // label_window_length - ) * label_window_length - if label_windows_length == 0 or label_window_length > test_window: + label_periods_candles: int = ( + test_window // label_period_candles + ) * label_period_candles + if label_periods_candles == 0 or label_period_candles > test_window: return float("inf") - y_test_period = [ - y_test.iloc[-label_windows_length:].to_numpy()[i : i + label_window_length] - for i in range(0, label_windows_length, label_window_length) + y_test_periods = [ + y_test.iloc[-label_periods_candles:].to_numpy()[i : i + label_period_candles] + for i in range(0, label_periods_candles, label_period_candles) ] - test_weights_period = [ - test_weights[-label_windows_length:][i : i + label_window_length] - for i in range(0, label_windows_length, label_window_length) + test_weights_periods = [ + test_weights[-label_periods_candles:][i : i + label_period_candles] + for i in range(0, label_periods_candles, label_period_candles) ] - y_pred_period = [ - y_pred[-label_windows_length:][i : i + label_window_length] - for i in range(0, label_windows_length, label_window_length) + y_pred_periods = [ + y_pred[-label_periods_candles:][i : i + label_period_candles] + for i in range(0, label_periods_candles, label_period_candles) ] errors = [ sklearn.metrics.root_mean_squared_error(y_t, y_p, sample_weight=t_w) - for y_t, y_p, t_w in zip(y_test_period, y_pred_period, test_weights_period) + for y_t, y_p, t_w in zip(y_test_periods, y_pred_periods, test_weights_periods) ] return geometric_mean(errors) diff --git a/quickadapter/user_data/strategies/QuickAdapterV3.py b/quickadapter/user_data/strategies/QuickAdapterV3.py index c642cf2..c748216 100644 --- a/quickadapter/user_data/strategies/QuickAdapterV3.py +++ b/quickadapter/user_data/strategies/QuickAdapterV3.py @@ -59,7 +59,7 @@ class QuickAdapterV3(IStrategy): INTERFACE_VERSION = 3 def version(self) -> str: - return "3.2.10" + return "3.2.11" timeframe = "5m" @@ -349,12 +349,12 @@ class QuickAdapterV3(IStrategy): def set_freqai_targets(self, dataframe, metadata, **kwargs): label_period_candles = self.get_label_period_candles(str(metadata.get("pair"))) - peaks_distance = label_period_candles * 2 - peaks_width = label_period_candles // 2 + peaks_distance = label_period_candles + peaks_width = label_period_candles // 4 # To match current market condition, use the current close price and NATR to evaluate peaks prominence peaks_prominence = ( dataframe["close"].iloc[-1] - * ta.NATR(dataframe, timeperiod=peaks_distance).iloc[-1] + * ta.NATR(dataframe, timeperiod=label_period_candles).iloc[-1] * 0.0025 ) min_peaks, _ = find_peaks( @@ -397,10 +397,9 @@ class QuickAdapterV3(IStrategy): "label_period_candles" ].iloc[-1] - labeling_window = self.get_label_period_candles(pair) * 2 - - dataframe["natr_labeling_window"] = ta.NATR( - dataframe, timeperiod=labeling_window + label_period_candles = self.get_label_period_candles(pair) + dataframe["natr_label_period_candles"] = ta.NATR( + dataframe, timeperiod=label_period_candles ) dataframe["minima_threshold"] = dataframe[MINIMA_THRESHOLD_COLUMN] @@ -450,7 +449,7 @@ class QuickAdapterV3(IStrategy): if entry_candle is None: return None entry_candle = entry_candle.squeeze() - return entry_candle["natr_labeling_window"] + return entry_candle["natr_label_period_candles"] def get_trade_duration_candles(self, df: DataFrame, trade: Trade) -> Optional[int]: """ @@ -482,7 +481,7 @@ class QuickAdapterV3(IStrategy): trade_duration_candles = self.get_trade_duration_candles(df, trade) if QuickAdapterV3.is_trade_duration_valid(trade_duration_candles) is False: return None - current_natr = df["natr_labeling_window"].iloc[-1] + current_natr = df["natr_label_period_candles"].iloc[-1] if isna(current_natr): return None return ( @@ -499,7 +498,7 @@ class QuickAdapterV3(IStrategy): entry_natr = self.get_trade_entry_natr(df, trade) if isna(entry_natr): return None - current_natr = df["natr_labeling_window"].iloc[-1] + current_natr = df["natr_label_period_candles"].iloc[-1] if isna(current_natr): return None return ( @@ -622,7 +621,7 @@ class QuickAdapterV3(IStrategy): return False last_candle = df.iloc[-1] entry_price_fluctuation_threshold = ( - last_candle["natr_labeling_window"] * self.entry_natr_ratio + last_candle["natr_label_period_candles"] * self.entry_natr_ratio ) if ( side == "long" -- 2.43.0