]> Piment Noir Git Repositories - freqai-strategies.git/commitdiff
refactor(qav3): cleanup label period candles handling
authorJérôme Benoit <jerome.benoit@piment-noir.org>
Fri, 4 Apr 2025 20:58:17 +0000 (22:58 +0200)
committerJérôme Benoit <jerome.benoit@piment-noir.org>
Fri, 4 Apr 2025 20:58:17 +0000 (22:58 +0200)
Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py
quickadapter/user_data/strategies/QuickAdapterV3.py

index fbea95e9c8083be2fcee0f1726716b1e3ea0cc15..ea9f6dde6517fe128f640c232301e3f91f677e41 100644 (file)
@@ -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)
index c642cf2240946b1a15311603e20f341dbc4c5114..c748216f02071154bb949b53b051d7411678fd09 100644 (file)
@@ -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"