]> Piment Noir Git Repositories - freqai-strategies.git/commitdiff
perf(qav3): readd stoploss guard protection with sensible configuration
authorJérôme Benoit <jerome.benoit@piment-noir.org>
Sun, 3 Aug 2025 12:53:24 +0000 (14:53 +0200)
committerJérôme Benoit <jerome.benoit@piment-noir.org>
Sun, 3 Aug 2025 12:53:24 +0000 (14:53 +0200)
Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
ReforceXY/user_data/strategies/RLAgentStrategy.py
quickadapter/user_data/strategies/QuickAdapterV3.py
quickadapter/user_data/strategies/Utils.py

index a4f4f53748fabb543d71ed994c50b98b689e0b92..fa14346aa221d4d79df53387db4e175f82c07f8a 100644 (file)
@@ -37,8 +37,24 @@ class RLAgentStrategy(IStrategy):
 
     # @cached_property
     # def protections(self) -> list[dict[str, Any]]:
-    #     fit_live_predictions_candles = self.freqai_info.get(
-    #         "fit_live_predictions_candles", 100
+    #     fit_live_predictions_candles = int(
+    #         self.freqai_info.get("fit_live_predictions_candles", 100)
+    #     )
+    #     estimated_trade_duration_candles = int(
+    #         self.config.get("estimated_trade_duration_candles", 36)
+    #     )
+    #     stoploss_guard_lookback_period_candles = int(fit_live_predictions_candles / 2)
+    #     stoploss_guard_trade_limit = max(
+    #         1,
+    #         int(
+    #             round(
+    #                 (
+    #                     stoploss_guard_lookback_period_candles
+    #                     / estimated_trade_duration_candles
+    #                 )
+    #                 * 0.75
+    #             )
+    #         ),
     #     )
     #     return [
     #         {"method": "CooldownPeriod", "stop_duration_candles": 4},
@@ -51,9 +67,9 @@ class RLAgentStrategy(IStrategy):
     #         },
     #         {
     #             "method": "StoplossGuard",
-    #             "lookback_period_candles": int(fit_live_predictions_candles / 2),
-    #             "trade_limit": 1,
-    #             "stop_duration_candles": int(fit_live_predictions_candles / 2),
+    #             "lookback_period_candles": stoploss_guard_lookback_period_candles,
+    #             "trade_limit": stoploss_guard_trade_limit,
+    #             "stop_duration_candles": stoploss_guard_lookback_period_candles,
     #             "only_per_pair": True,
     #         },
     #     ]
index 0cbf0b9e6ea4e336eadfe86eef74a7505596282f..6c8f11bbd17df8a99bc062c25eb9ab049fa795f2 100644 (file)
@@ -31,7 +31,7 @@ from Utils import (
     top_change_percent,
     get_distance,
     get_odd_window,
-    get_gaussian_std_from_window,
+    get_gaussian_std,
     zlema,
 )
 
@@ -64,7 +64,7 @@ class QuickAdapterV3(IStrategy):
     INTERFACE_VERSION = 3
 
     def version(self) -> str:
-        return "3.3.127"
+        return "3.3.128"
 
     timeframe = "5m"
 
@@ -130,8 +130,24 @@ class QuickAdapterV3(IStrategy):
 
     @cached_property
     def protections(self) -> list[dict[str, Any]]:
-        fit_live_predictions_candles = self.freqai_info.get(
-            "fit_live_predictions_candles", 100
+        fit_live_predictions_candles = int(
+            self.freqai_info.get("fit_live_predictions_candles", 100)
+        )
+        estimated_trade_duration_candles = int(
+            self.config.get("estimated_trade_duration_candles", 36)
+        )
+        stoploss_guard_lookback_period_candles = int(fit_live_predictions_candles / 2)
+        stoploss_guard_trade_limit = max(
+            1,
+            int(
+                round(
+                    (
+                        stoploss_guard_lookback_period_candles
+                        / estimated_trade_duration_candles
+                    )
+                    * 0.75
+                )
+            ),
         )
         return [
             {"method": "CooldownPeriod", "stop_duration_candles": 4},
@@ -142,13 +158,13 @@ class QuickAdapterV3(IStrategy):
                 "stop_duration_candles": fit_live_predictions_candles,
                 "max_allowed_drawdown": 0.2,
             },
-            {
-                "method": "StoplossGuard",
-            #     "lookback_period_candles": int(fit_live_predictions_candles / 2),
-            #     "trade_limit": 1,
-            #     "stop_duration_candles": int(fit_live_predictions_candles / 2),
-                "only_per_pair": True,
-            },
+            {
+                "method": "StoplossGuard",
+                "lookback_period_candles": stoploss_guard_lookback_period_candles,
+                "trade_limit": stoploss_guard_trade_limit,
+                "stop_duration_candles": stoploss_guard_lookback_period_candles,
+                "only_per_pair": True,
+            },
         ]
 
     use_exit_signal = True
@@ -1035,7 +1051,7 @@ class QuickAdapterV3(IStrategy):
         window: int,
     ) -> Series:
         extrema_smoothing = str(self.freqai_info.get("extrema_smoothing", "gaussian"))
-        std = get_gaussian_std_from_window(window)
+        std = get_gaussian_std(window)
         extrema_smoothing_beta = float(
             self.freqai_info.get("extrema_smoothing_beta", 8.0)
         )
index 350d453a9ec3d49822880fa973cd4fb1c7d3d241..5bd0d734b8f034c1465f3963739b625e1642f8d8 100644 (file)
@@ -30,7 +30,7 @@ def get_odd_window(window: int) -> int:
 
 
 @lru_cache(maxsize=8)
-def get_gaussian_std_from_window(window: int) -> float:
+def get_gaussian_std(window: int) -> float:
     # Assuming window = 6 * std + 1 => std = (window - 1) / 6
     return (window - 1) / 6.0 if window > 1 else 0.5