]> Piment Noir Git Repositories - freqai-strategies.git/commitdiff
perf(qav3): optimize pivot labeling confirmation
authorJérôme Benoit <jerome.benoit@piment-noir.org>
Sat, 17 May 2025 09:59:40 +0000 (11:59 +0200)
committerJérôme Benoit <jerome.benoit@piment-noir.org>
Sat, 17 May 2025 09:59:40 +0000 (11:59 +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
quickadapter/user_data/strategies/Utils.py

index 26af86ec71491ef6fd7c106f607d522bfdd80da3..59beb5c69d9a8e44b222eab23a14b005691b8dfd 100644 (file)
@@ -45,7 +45,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
     https://github.com/sponsors/robcaulk
     """
 
-    version = "3.7.35"
+    version = "3.7.36"
 
     @cached_property
     def _optuna_config(self) -> dict:
@@ -851,7 +851,7 @@ def zigzag(
     natr_period: int = 14,
     natr_ratio: float = 1.0,
     confirmation_window: int = 3,
-    depth: int = 12,
+    initial_depth: int = 12,
 ) -> tuple[list[int], list[float], list[int]]:
     n = len(df)
     if df.empty or n < max(natr_period, 2 * confirmation_window + 1):
@@ -866,6 +866,7 @@ def zigzag(
     lows = df["low"].values
 
     state: TrendDirection = TrendDirection.NEUTRAL
+    depth = initial_depth
 
     last_pivot_pos = -depth - 1
     pivots_indices, pivots_values, pivots_directions = [], [], []
@@ -874,6 +875,19 @@ def zigzag(
     candidate_pivot_value = np.nan
     candidate_pivot_direction: TrendDirection = TrendDirection.NEUTRAL
 
+    def calculate_depth(
+        pivots_indices: list[int],
+        min_depth: int = 6,
+        max_depth: int = 24,
+        depth_scaling_factor: float = 0.75,
+    ) -> int:
+        if len(pivots_indices) < 2:
+            return initial_depth
+        previous_interval = pivots_indices[-1] - pivots_indices[-2]
+        return max(
+            min_depth, min(max_depth, int(previous_interval * depth_scaling_factor))
+        )
+
     def update_candidate_pivot(pos: int, value: float, direction: TrendDirection):
         nonlocal candidate_pivot_pos, candidate_pivot_value, candidate_pivot_direction
         if 0 <= pos < n:
@@ -888,13 +902,14 @@ def zigzag(
         candidate_pivot_direction = TrendDirection.NEUTRAL
 
     def add_pivot(pos: int, value: float, direction: TrendDirection):
-        nonlocal last_pivot_pos
+        nonlocal last_pivot_pos, depth
         if pivots_indices and indices[pos] == pivots_indices[-1]:
             return
         pivots_indices.append(indices[pos])
         pivots_values.append(value)
         pivots_directions.append(direction)
         last_pivot_pos = pos
+        depth = calculate_depth(pivots_indices)
 
     def is_reversal_confirmed(
         candidate_pivot_pos: int,
@@ -942,6 +957,8 @@ def zigzag(
                 >= extrema_threshold
             )
             local_extrema_ok = valid_next and valid_previous
+        if not local_extrema_ok:
+            return False
 
         slope_ok = False
         next_closes_std = np.std(next_closes)
@@ -955,6 +972,8 @@ def zigzag(
                 slope_ok = next_slope_strength < -min_slope_strength
             elif direction == TrendDirection.UP:
                 slope_ok = next_slope_strength > min_slope_strength
+        if not slope_ok:
+            return False
 
         significant_move_away_ok = False
         if direction == TrendDirection.DOWN:
@@ -971,8 +990,7 @@ def zigzag(
                 * (1 + thresholds[candidate_pivot_pos] * move_away_ratio)
             ):
                 significant_move_away_ok = True
-
-        return local_extrema_ok and slope_ok and significant_move_away_ok
+        return significant_move_away_ok
 
     start_pos = 0
     initial_high_pos = start_pos
index 65c612df70334bf94ec7dd151d9d22c197af73ad..d65dd69306414b80b3b9c2431c019524e5572ecb 100644 (file)
@@ -58,7 +58,7 @@ class QuickAdapterV3(IStrategy):
     INTERFACE_VERSION = 3
 
     def version(self) -> str:
-        return "3.3.31"
+        return "3.3.32"
 
     timeframe = "5m"
 
index fc913068d26ac05119b5534a526960b6bd30cc5c..7f238539c1e16072d688fd91eac9fc17b7a82ba1 100644 (file)
@@ -347,7 +347,7 @@ def zigzag(
     natr_period: int = 14,
     natr_ratio: float = 1.0,
     confirmation_window: int = 3,
-    depth: int = 12,
+    initial_depth: int = 12,
 ) -> tuple[list[int], list[float], list[int]]:
     n = len(df)
     if df.empty or n < max(natr_period, 2 * confirmation_window + 1):
@@ -362,6 +362,7 @@ def zigzag(
     lows = df["low"].values
 
     state: TrendDirection = TrendDirection.NEUTRAL
+    depth = initial_depth
 
     last_pivot_pos = -depth - 1
     pivots_indices, pivots_values, pivots_directions = [], [], []
@@ -370,6 +371,19 @@ def zigzag(
     candidate_pivot_value = np.nan
     candidate_pivot_direction: TrendDirection = TrendDirection.NEUTRAL
 
+    def calculate_depth(
+        pivots_indices: list[int],
+        min_depth: int = 6,
+        max_depth: int = 24,
+        depth_scaling_factor: float = 0.75,
+    ) -> int:
+        if len(pivots_indices) < 2:
+            return initial_depth
+        previous_interval = pivots_indices[-1] - pivots_indices[-2]
+        return max(
+            min_depth, min(max_depth, int(previous_interval * depth_scaling_factor))
+        )
+
     def update_candidate_pivot(pos: int, value: float, direction: TrendDirection):
         nonlocal candidate_pivot_pos, candidate_pivot_value, candidate_pivot_direction
         if 0 <= pos < n:
@@ -384,13 +398,14 @@ def zigzag(
         candidate_pivot_direction = TrendDirection.NEUTRAL
 
     def add_pivot(pos: int, value: float, direction: TrendDirection):
-        nonlocal last_pivot_pos
+        nonlocal last_pivot_pos, depth
         if pivots_indices and indices[pos] == pivots_indices[-1]:
             return
         pivots_indices.append(indices[pos])
         pivots_values.append(value)
         pivots_directions.append(direction)
         last_pivot_pos = pos
+        depth = calculate_depth(pivots_indices)
 
     def is_reversal_confirmed(
         candidate_pivot_pos: int,
@@ -438,6 +453,8 @@ def zigzag(
                 >= extrema_threshold
             )
             local_extrema_ok = valid_next and valid_previous
+        if not local_extrema_ok:
+            return False
 
         slope_ok = False
         next_closes_std = np.std(next_closes)
@@ -451,6 +468,8 @@ def zigzag(
                 slope_ok = next_slope_strength < -min_slope_strength
             elif direction == TrendDirection.UP:
                 slope_ok = next_slope_strength > min_slope_strength
+        if not slope_ok:
+            return False
 
         significant_move_away_ok = False
         if direction == TrendDirection.DOWN:
@@ -467,8 +486,7 @@ def zigzag(
                 * (1 + thresholds[candidate_pivot_pos] * move_away_ratio)
             ):
                 significant_move_away_ok = True
-
-        return local_extrema_ok and slope_ok and significant_move_away_ok
+        return significant_move_away_ok
 
     start_pos = 0
     initial_high_pos = start_pos