From 52f5a9786994896cf4cddc915448b2b49dea3b30 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Sat, 17 May 2025 02:32:05 +0200 Subject: [PATCH] perf(qav3): refine pivot labeling confirmation MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Jérôme Benoit --- .../freqaimodels/QuickAdapterRegressorV3.py | 21 ++++++++++--------- .../user_data/strategies/QuickAdapterV3.py | 2 +- quickadapter/user_data/strategies/Utils.py | 19 +++++++++-------- 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py b/quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py index bd52743..26af86e 100644 --- a/quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py +++ b/quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py @@ -45,7 +45,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel): https://github.com/sponsors/robcaulk """ - version = "3.7.34" + version = "3.7.35" @cached_property def _optuna_config(self) -> dict: @@ -900,8 +900,9 @@ def zigzag( candidate_pivot_pos: int, next_confirmation_pos: int, direction: TrendDirection, - extrema_threshold: float = 0.95, + extrema_threshold: float = 0.85, min_slope_strength: float = 0.5, + min_slope_volatility: float = 0.001, move_away_ratio: float = 0.25, ) -> bool: next_start = next_confirmation_pos + 1 @@ -916,35 +917,35 @@ def zigzag( next_highs = highs[next_slice] next_lows = lows[next_slice] previous_slice = slice(previous_start, previous_end) - previous_closes = closes[previous_slice] + previous_highs = highs[previous_slice] + previous_lows = lows[previous_slice] local_extrema_ok = False if direction == TrendDirection.DOWN: valid_next = ( - np.sum(next_closes < highs[candidate_pivot_pos]) / len(next_closes) + np.sum(next_highs < highs[candidate_pivot_pos]) / len(next_highs) >= extrema_threshold ) valid_previous = ( - np.sum(previous_closes < highs[candidate_pivot_pos]) - / len(previous_closes) + np.sum(previous_highs < highs[candidate_pivot_pos]) + / len(previous_highs) >= extrema_threshold ) local_extrema_ok = valid_next and valid_previous elif direction == TrendDirection.UP: valid_next = ( - np.sum(next_closes > lows[candidate_pivot_pos]) / len(next_closes) + np.sum(next_lows > lows[candidate_pivot_pos]) / len(next_lows) >= extrema_threshold ) valid_previous = ( - np.sum(previous_closes > lows[candidate_pivot_pos]) - / len(previous_closes) + np.sum(previous_lows > lows[candidate_pivot_pos]) / len(previous_lows) >= extrema_threshold ) local_extrema_ok = valid_next and valid_previous slope_ok = False next_closes_std = np.std(next_closes) - if len(next_closes) >= 2 and next_closes_std > np.finfo(float).eps: + if len(next_closes) >= 2 and next_closes_std > min_slope_volatility: weights = np.linspace(0.5, 1.5, len(next_closes)) next_slope = np.polyfit(range(len(next_closes)), next_closes, 1, w=weights)[ 0 diff --git a/quickadapter/user_data/strategies/QuickAdapterV3.py b/quickadapter/user_data/strategies/QuickAdapterV3.py index f6f458d..65c612d 100644 --- a/quickadapter/user_data/strategies/QuickAdapterV3.py +++ b/quickadapter/user_data/strategies/QuickAdapterV3.py @@ -58,7 +58,7 @@ class QuickAdapterV3(IStrategy): INTERFACE_VERSION = 3 def version(self) -> str: - return "3.3.30" + return "3.3.31" timeframe = "5m" diff --git a/quickadapter/user_data/strategies/Utils.py b/quickadapter/user_data/strategies/Utils.py index 6c11c81..fc91306 100644 --- a/quickadapter/user_data/strategies/Utils.py +++ b/quickadapter/user_data/strategies/Utils.py @@ -396,8 +396,9 @@ def zigzag( candidate_pivot_pos: int, next_confirmation_pos: int, direction: TrendDirection, - extrema_threshold: float = 0.95, + extrema_threshold: float = 0.85, min_slope_strength: float = 0.5, + min_slope_volatility: float = 0.001, move_away_ratio: float = 0.25, ) -> bool: next_start = next_confirmation_pos + 1 @@ -412,35 +413,35 @@ def zigzag( next_highs = highs[next_slice] next_lows = lows[next_slice] previous_slice = slice(previous_start, previous_end) - previous_closes = closes[previous_slice] + previous_highs = highs[previous_slice] + previous_lows = lows[previous_slice] local_extrema_ok = False if direction == TrendDirection.DOWN: valid_next = ( - np.sum(next_closes < highs[candidate_pivot_pos]) / len(next_closes) + np.sum(next_highs < highs[candidate_pivot_pos]) / len(next_highs) >= extrema_threshold ) valid_previous = ( - np.sum(previous_closes < highs[candidate_pivot_pos]) - / len(previous_closes) + np.sum(previous_highs < highs[candidate_pivot_pos]) + / len(previous_highs) >= extrema_threshold ) local_extrema_ok = valid_next and valid_previous elif direction == TrendDirection.UP: valid_next = ( - np.sum(next_closes > lows[candidate_pivot_pos]) / len(next_closes) + np.sum(next_lows > lows[candidate_pivot_pos]) / len(next_lows) >= extrema_threshold ) valid_previous = ( - np.sum(previous_closes > lows[candidate_pivot_pos]) - / len(previous_closes) + np.sum(previous_lows > lows[candidate_pivot_pos]) / len(previous_lows) >= extrema_threshold ) local_extrema_ok = valid_next and valid_previous slope_ok = False next_closes_std = np.std(next_closes) - if len(next_closes) >= 2 and next_closes_std > np.finfo(float).eps: + if len(next_closes) >= 2 and next_closes_std > min_slope_volatility: weights = np.linspace(0.5, 1.5, len(next_closes)) next_slope = np.polyfit(range(len(next_closes)), next_closes, 1, w=weights)[ 0 -- 2.43.0