]> Piment Noir Git Repositories - freqai-strategies.git/commitdiff
refactor(qav3): add more tunables for reversal confirmation heuristic
authorJérôme Benoit <jerome.benoit@piment-noir.org>
Sat, 25 Oct 2025 14:24:43 +0000 (16:24 +0200)
committerJérôme Benoit <jerome.benoit@piment-noir.org>
Sat, 25 Oct 2025 14:24:43 +0000 (16:24 +0200)
Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
README.md
quickadapter/user_data/strategies/QuickAdapterV3.py

index e9af9e27e446e63f3a7941441f93f8d3f044a656..6ab09c146a97e4565c7418c938681d36f26eea68 100644 (file)
--- a/README.md
+++ b/README.md
@@ -44,7 +44,9 @@ docker compose up -d --build
 | exit_pricing.thresholds_calibration.decline_quantile | 0.90             | float (0,1) | PNL decline quantile threshold.                                                 |
 | _Reversal confirmation_ |                  |  |                                                                                 |
 | reversal_confirmation.lookback_period | 0                | int >= 0 | Prior confirming candles; 0 = none.                                             |
-| reversal_confirmation.decay_ratio | 0.5              | float (0,1] | Geometric per-step relaxation factor.                                           |
+| reversal_confirmation.decay_ratio | 0.5              | float (0,1] | Geometric per-candle relaxation factor.                                           |
+| reversal_confirmation.min_natr_ratio_percent | 0.009           | float [0,1] | Lower bound fraction for volatility adjusted reversal threshold.                          |
+| reversal_confirmation.max_natr_ratio_percent | 0.035           | float [0,1] | Upper bound fraction (>= lower bound) for volatility adjusted reversal threshold.         |
 | _Regressor model_ |                  |  |                                                                                 |
 | freqai.regressor | `xgboost`        | enum {`xgboost`,`lightgbm`} | Machine learning regressor algorithm.                                           |
 | _Extrema smoothing_ |                  |  |                                                                                 |
index a23ac73d982c82557f9bf4ae9597274b59982fb8..1e79bc999e4143849ad3aba0fab04877c2bf41cd 100644 (file)
@@ -98,6 +98,8 @@ class QuickAdapterV3(IStrategy):
     default_reversal_confirmation: dict[str, int | float] = {
         "lookback_period": 0,
         "decay_ratio": 0.5,
+        "min_natr_ratio_percent": 0.009,
+        "max_natr_ratio_percent": 0.035,
     }
 
     position_adjustment_enable = True
@@ -1156,11 +1158,11 @@ class QuickAdapterV3(IStrategy):
         rate: float,
         lookback_period: int,
         decay_ratio: float,
-        min_natr_ratio_percent: float = 0.009,
-        max_natr_ratio_percent: float = 0.035,
+        min_natr_ratio_percent: float,
+        max_natr_ratio_percent: float,
     ) -> bool:
         """Confirm a directional reversal using a volatility-adaptive current-candle
-        threshold and (optionally) a backward confirmation chain with geometric decay.
+        threshold and optionally a backward confirmation chain with geometric decay.
 
         Overview
         --------
@@ -1546,13 +1548,33 @@ class QuickAdapterV3(IStrategy):
         decay_ratio: float = self.config.get("reversal_confirmation", {}).get(
             "decay_ratio", QuickAdapterV3.default_reversal_confirmation["decay_ratio"]
         )
+        min_natr_ratio_percent: float = self.config.get(
+            "reversal_confirmation", {}
+        ).get(
+            "min_natr_ratio_percent",
+            QuickAdapterV3.default_reversal_confirmation["min_natr_ratio_percent"],
+        )
+        max_natr_ratio_percent: float = self.config.get(
+            "reversal_confirmation", {}
+        ).get(
+            "max_natr_ratio_percent",
+            QuickAdapterV3.default_reversal_confirmation["max_natr_ratio_percent"],
+        )
         if (
             trade.trade_direction == "short"
             and last_candle.get("do_predict") == 1
             and last_candle.get("DI_catch") == 1
             and last_candle.get(EXTREMA_COLUMN) < last_candle.get("minima_threshold")
             and self.reversal_confirmed(
-                df, pair, "long", "exit", current_rate, lookback_period, decay_ratio
+                df,
+                pair,
+                "long",
+                "exit",
+                current_rate,
+                lookback_period,
+                decay_ratio,
+                min_natr_ratio_percent,
+                max_natr_ratio_percent,
             )
         ):
             return "minima_detected_short"
@@ -1562,7 +1584,15 @@ class QuickAdapterV3(IStrategy):
             and last_candle.get("DI_catch") == 1
             and last_candle.get(EXTREMA_COLUMN) > last_candle.get("maxima_threshold")
             and self.reversal_confirmed(
-                df, pair, "short", "exit", current_rate, lookback_period, decay_ratio
+                df,
+                pair,
+                "short",
+                "exit",
+                current_rate,
+                lookback_period,
+                decay_ratio,
+                min_natr_ratio_percent,
+                max_natr_ratio_percent,
             )
         ):
             return "maxima_detected_long"
@@ -1702,6 +1732,14 @@ class QuickAdapterV3(IStrategy):
                 "decay_ratio",
                 QuickAdapterV3.default_reversal_confirmation["decay_ratio"],
             ),
+            self.config.get("reversal_confirmation", {}).get(
+                "min_natr_ratio_percent",
+                QuickAdapterV3.default_reversal_confirmation["min_natr_ratio_percent"],
+            ),
+            self.config.get("reversal_confirmation", {}).get(
+                "max_natr_ratio_percent",
+                QuickAdapterV3.default_reversal_confirmation["max_natr_ratio_percent"],
+            ),
         ):
             return True
         return False