]> Piment Noir Git Repositories - freqai-strategies.git/commitdiff
feat: add tunable for leverage
authorJérôme Benoit <jerome.benoit@piment-noir.org>
Wed, 5 Nov 2025 15:28:23 +0000 (16:28 +0100)
committerJérôme Benoit <jerome.benoit@piment-noir.org>
Wed, 5 Nov 2025 15:28:23 +0000 (16:28 +0100)
Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
README.md
ReforceXY/user_data/config-template.json
ReforceXY/user_data/strategies/RLAgentStrategy.py
quickadapter/user_data/config-template.json
quickadapter/user_data/strategies/QuickAdapterV3.py

index be9a4ded47a7df03e60d2635735b9ff8dc691d42..04ee891507680164e37c7b906bfe1426b3124ba4 100644 (file)
--- a/README.md
+++ b/README.md
@@ -39,6 +39,8 @@ docker compose up -d --build
 |------|------------------|-------------|---------------------------------------------------------------------------------|
 | _Protections_ |                  |  |                                                                                 |
 | estimated_trade_duration_candles | 48               | int >= 1 | Heuristic for StoplossGuard tuning.                                             |
+| _Leverage_ |                  |  |                                                                                 |                              |
+| leverage | proposed_leverage | float [1.0, max_leverage] | Leverage. Fallback to proposed_leverage for the pair. |
 | _Exit pricing_ |                  |  |                                                                                 |
 | exit_pricing.trade_price_target | `moving_average` | enum {`moving_average`,`interpolation`,`weighted_interpolation`} | Trade NATR computation method.                                                  |
 | exit_pricing.thresholds_calibration.decline_quantile | 0.90             | float (0,1) | PNL decline quantile threshold.                                                 |
@@ -62,7 +64,7 @@ docker compose up -d --build
 | freqai.feature_parameters.max_label_natr_ratio | 12.0             | float > 0 | Maximum labeling NATR ratio used for reversals labeling HPO.                                     |
 | freqai.feature_parameters.label_frequency_candles | `auto`            | int >= 2 \| `auto` | Reversals labeling frequency. `auto` = max(2, 2 * number of whitelisted pairs). |
 | freqai.feature_parameters.label_metric | `euclidean`      | string (supported: `euclidean`,`minkowski`,`cityblock`,`chebyshev`,`mahalanobis`,`seuclidean`,`jensenshannon`,`sqeuclidean`,...) | Metric used in distance calculations to ideal point.                            |
-| freqai.feature_parameters.label_weights | [0.5,0.5]        | list[float] | Per-objective weights used in distance calculations to ideal point.             |
+| freqai.feature_parameters.label_weights | [0.5,0.5]        | list[float] | Per-objective weights used in distance calculations to ideal point. First objective is the median threshold of Zigzag reversals (reversals quality). Second objective is the number of detected reversals.             |
 | freqai.feature_parameters.label_p_order | `None`           | float | p-order used by Minkowski / power-mean calculations (optional).                 |
 | freqai.feature_parameters.label_medoid_metric | `euclidean`      | string | Metric used with `medoid`.                                                      |
 | freqai.feature_parameters.label_kmeans_metric | `euclidean`      | string | Metric used for k-means clustering.                                             |
index 9faedfc0d1b92ce47933dab5d3f00f1b141b3e73..0a58257806c4e740f52319a29b0394b8a6cef758 100644 (file)
@@ -14,6 +14,7 @@
   "cancel_open_orders_on_exit": false,
   // "trading_mode": "futures",
   // "margin_mode": "isolated",
+  // "leverage": 2.0,
   "trading_mode": "spot",
   "stoploss": -0.99,
   "unfilledtimeout": {
index 4d8849ba4f06d57af7a6a2a0af378aebca0f420c..af9251e392a7e421c16404388ca877ed91873a2a 100644 (file)
@@ -1,6 +1,7 @@
+import datetime
 import logging
 from functools import cached_property, reduce
-from typing import Any
+from typing import Any, Optional
 
 # import talib.abstract as ta
 from freqtrade.persistence import Trade
@@ -118,6 +119,33 @@ class RLAgentStrategy(IStrategy):
 
         return dataframe
 
+    def leverage(
+        self,
+        pair: str,
+        current_time: datetime.datetime,
+        current_rate: float,
+        proposed_leverage: float,
+        max_leverage: float,
+        entry_tag: Optional[str],
+        side: str,
+        **kwargs: Any,
+    ) -> float:
+        """
+        Customize leverage for each new trade. This method is only called in trading modes
+        which allow leverage (margin / futures). The strategy is expected to return a
+        leverage value between 1.0 and max_leverage.
+
+        :param pair: Pair that's currently analyzed
+        :param current_time: datetime object, containing the current datetime
+        :param current_rate: Rate, calculated based on pricing settings in exit_pricing.
+        :param proposed_leverage: A leverage proposed by the bot.
+        :param max_leverage: Max leverage allowed on this pair
+        :param entry_tag: Optional entry_tag (buy_tag) if provided with the buy signal.
+        :param side: 'long' or 'short' - indicating the direction of the proposed trade
+        :return: A leverage amount, which will be between 1.0 and max_leverage.
+        """
+        return min(self.config.get("leverage", proposed_leverage), max_leverage)
+
     def is_short_allowed(self) -> bool:
         trading_mode = self.config.get("trading_mode")
         if trading_mode in {"margin", "futures"}:
index f9cf594e9de511c05facbd227e83506c2ced6e4d..e10093359e5d6e9b7e9f7812d6824d4ba96130ad 100644 (file)
@@ -14,6 +14,7 @@
   "cancel_open_orders_on_exit": false,
   // "trading_mode": "futures",
   // "margin_mode": "isolated",
+  // "leverage": 2.0,
   "trading_mode": "spot",
   "unfilledtimeout": {
     "entry": 10,
index 8f894817e6563b332265a59a9b4f05b68b4041b9..f61bad55d04269e8631912db973a01ca015685a0 100644 (file)
@@ -1780,6 +1780,33 @@ class QuickAdapterV3(IStrategy):
         else:
             raise ValueError(f"Invalid trading_mode: {trading_mode}")
 
+    def leverage(
+        self,
+        pair: str,
+        current_time: datetime.datetime,
+        current_rate: float,
+        proposed_leverage: float,
+        max_leverage: float,
+        entry_tag: Optional[str],
+        side: str,
+        **kwargs: Any,
+    ) -> float:
+        """
+        Customize leverage for each new trade. This method is only called in trading modes
+        which allow leverage (margin / futures). The strategy is expected to return a
+        leverage value between 1.0 and max_leverage.
+
+        :param pair: Pair that's currently analyzed
+        :param current_time: datetime object, containing the current datetime
+        :param current_rate: Rate, calculated based on pricing settings in exit_pricing.
+        :param proposed_leverage: A leverage proposed by the bot.
+        :param max_leverage: Max leverage allowed on this pair
+        :param entry_tag: Optional entry_tag (buy_tag) if provided with the buy signal.
+        :param side: 'long' or 'short' - indicating the direction of the proposed trade
+        :return: A leverage amount, which will be between 1.0 and max_leverage.
+        """
+        return min(self.config.get("leverage", proposed_leverage), max_leverage)
+
     def optuna_load_best_params(
         self, pair: str, namespace: str
     ) -> Optional[dict[str, Any]]: