From 8c12d863543c6e4e5087bfa6f71056bec578146c Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Sun, 4 May 2025 20:19:27 +0200 Subject: [PATCH] fix(qav3): revert candle pattern usage to label reversal pivots MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Jérôme Benoit --- .../freqaimodels/QuickAdapterRegressorV3.py | 42 ++++++------------- .../user_data/strategies/QuickAdapterV3.py | 2 +- quickadapter/user_data/strategies/Utils.py | 40 ++++++------------ 3 files changed, 26 insertions(+), 58 deletions(-) diff --git a/quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py b/quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py index ce4c0fc..d2b91de 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.27" + version = "3.7.28" @cached_property def _optuna_config(self) -> dict: @@ -840,12 +840,6 @@ def hp_objective( return error -class TrendDirection(IntEnum): - NEUTRAL = 0 - UP = 1 - DOWN = -1 - - def find_fractals(df: pd.DataFrame, fractal_period: int) -> tuple[list[int], list[int]]: if len(df) < 2 * fractal_period + 1: return [], [] @@ -876,26 +870,22 @@ def find_fractals(df: pd.DataFrame, fractal_period: int) -> tuple[list[int], lis ) +class TrendDirection(IntEnum): + NEUTRAL = 0 + UP = 1 + DOWN = -1 + + def zigzag( df: pd.DataFrame, natr_period: int = 14, natr_ratio: float = 1.0, - fractal_period: int = 2, confirmation_window: int = 2, depth: int = 12, ) -> tuple[list[int], list[float], list[int]]: - if ( - df.empty - or len(df) < max(natr_period, 2 * fractal_period + 1) + confirmation_window - ): + if df.empty or len(df) < natr_period + confirmation_window: return [], [], [] - fractal_high_indices, fractal_low_indices = find_fractals(df, fractal_period) - is_fractal_high = np.zeros(len(df), dtype=bool) - is_fractal_high[fractal_high_indices] = True - is_fractal_low = np.zeros(len(df), dtype=bool) - is_fractal_low[fractal_low_indices] = True - indices = df.index.tolist() thresholds = ( (ta.NATR(df, timeperiod=natr_period) * natr_ratio).fillna(method="bfill").values @@ -930,7 +920,7 @@ def zigzag( return all(c > lows[pos] for c in next_closes) return False - start_pos = fractal_period + start_pos = 0 initial_high_pos = start_pos initial_low_pos = start_pos initial_high = highs[initial_high_pos] @@ -943,18 +933,14 @@ def zigzag( initial_move_from_high = (initial_high - lows[i]) / initial_high initial_move_from_low = (highs[i] - initial_low) / initial_low - if ( - initial_move_from_high >= thresholds[i] - and is_fractal_high[initial_high_pos] - and is_reversal_confirmed(initial_high_pos, TrendDirection.DOWN) + if initial_move_from_high >= thresholds[i] and is_reversal_confirmed( + initial_high_pos, TrendDirection.DOWN ): add_pivot(initial_high_pos, initial_high, TrendDirection.UP) state = TrendDirection.DOWN break - elif ( - initial_move_from_low >= thresholds[i] - and is_fractal_low[initial_low_pos] - and is_reversal_confirmed(initial_low_pos, TrendDirection.UP) + elif initial_move_from_low >= thresholds[i] and is_reversal_confirmed( + initial_low_pos, TrendDirection.UP ): add_pivot(initial_low_pos, initial_low, TrendDirection.DOWN) state = TrendDirection.UP @@ -972,7 +958,6 @@ def zigzag( elif ( (last_pivot_val - current_low) / last_pivot_val >= thresholds[i] and (i - last_pivot_pos) >= depth - and is_fractal_low[i] and is_reversal_confirmed(i, TrendDirection.DOWN) ): add_pivot(i, current_low, TrendDirection.DOWN) @@ -983,7 +968,6 @@ def zigzag( elif ( (current_high - last_pivot_val) / last_pivot_val >= thresholds[i] and (i - last_pivot_pos) >= depth - and is_fractal_high[i] and is_reversal_confirmed(i, TrendDirection.UP) ): add_pivot(i, current_high, TrendDirection.UP) diff --git a/quickadapter/user_data/strategies/QuickAdapterV3.py b/quickadapter/user_data/strategies/QuickAdapterV3.py index 9d830a6..d2e8f88 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.21" + return "3.3.22" timeframe = "5m" diff --git a/quickadapter/user_data/strategies/Utils.py b/quickadapter/user_data/strategies/Utils.py index 9179897..615c21c 100644 --- a/quickadapter/user_data/strategies/Utils.py +++ b/quickadapter/user_data/strategies/Utils.py @@ -299,12 +299,6 @@ def alligator( return jaw, teeth, lips -class TrendDirection(IntEnum): - NEUTRAL = 0 - UP = 1 - DOWN = -1 - - def find_fractals(df: pd.DataFrame, fractal_period: int) -> tuple[list[int], list[int]]: if len(df) < 2 * fractal_period + 1: return [], [] @@ -335,26 +329,22 @@ def find_fractals(df: pd.DataFrame, fractal_period: int) -> tuple[list[int], lis ) +class TrendDirection(IntEnum): + NEUTRAL = 0 + UP = 1 + DOWN = -1 + + def zigzag( df: pd.DataFrame, natr_period: int = 14, natr_ratio: float = 1.0, - fractal_period: int = 2, confirmation_window: int = 2, depth: int = 12, ) -> tuple[list[int], list[float], list[int]]: - if ( - df.empty - or len(df) < max(natr_period, 2 * fractal_period + 1) + confirmation_window - ): + if df.empty or len(df) < natr_period + confirmation_window: return [], [], [] - fractal_high_indices, fractal_low_indices = find_fractals(df, fractal_period) - is_fractal_high = np.zeros(len(df), dtype=bool) - is_fractal_high[fractal_high_indices] = True - is_fractal_low = np.zeros(len(df), dtype=bool) - is_fractal_low[fractal_low_indices] = True - indices = df.index.tolist() thresholds = ( (ta.NATR(df, timeperiod=natr_period) * natr_ratio).fillna(method="bfill").values @@ -389,7 +379,7 @@ def zigzag( return all(c > lows[pos] for c in next_closes) return False - start_pos = fractal_period + start_pos = 0 initial_high_pos = start_pos initial_low_pos = start_pos initial_high = highs[initial_high_pos] @@ -402,18 +392,14 @@ def zigzag( initial_move_from_high = (initial_high - lows[i]) / initial_high initial_move_from_low = (highs[i] - initial_low) / initial_low - if ( - initial_move_from_high >= thresholds[i] - and is_fractal_high[initial_high_pos] - and is_reversal_confirmed(initial_high_pos, TrendDirection.DOWN) + if initial_move_from_high >= thresholds[i] and is_reversal_confirmed( + initial_high_pos, TrendDirection.DOWN ): add_pivot(initial_high_pos, initial_high, TrendDirection.UP) state = TrendDirection.DOWN break - elif ( - initial_move_from_low >= thresholds[i] - and is_fractal_low[initial_low_pos] - and is_reversal_confirmed(initial_low_pos, TrendDirection.UP) + elif initial_move_from_low >= thresholds[i] and is_reversal_confirmed( + initial_low_pos, TrendDirection.UP ): add_pivot(initial_low_pos, initial_low, TrendDirection.DOWN) state = TrendDirection.UP @@ -431,7 +417,6 @@ def zigzag( elif ( (last_pivot_val - current_low) / last_pivot_val >= thresholds[i] and (i - last_pivot_pos) >= depth - and is_fractal_low[i] and is_reversal_confirmed(i, TrendDirection.DOWN) ): add_pivot(i, current_low, TrendDirection.DOWN) @@ -442,7 +427,6 @@ def zigzag( elif ( (current_high - last_pivot_val) / last_pivot_val >= thresholds[i] and (i - last_pivot_pos) >= depth - and is_fractal_high[i] and is_reversal_confirmed(i, TrendDirection.UP) ): add_pivot(i, current_high, TrendDirection.UP) -- 2.43.0