# pragma pylint: disable=missing-docstring, invalid-name, too-few-public-methods """ HyperStrategy — stratégie paramétrable pour optimisation (hyperopt). Indicateurs fixes (EMA/RSI/ADX/MACD), conditions d'entrée et gestion de sortie PARAMÉTRÉES → Freqtrade peut optimiser les seuils, le ROI, le stoploss et le trailing. Méthode honnête : on optimise sur une période d'entraînement puis on VALIDE sur une période hors-échantillon (test) pour détecter le sur-apprentissage. """ from __future__ import annotations import talib.abstract as ta from pandas import DataFrame from freqtrade.strategy import ( IStrategy, IntParameter, BooleanParameter, ) class HyperStrategy(IStrategy): INTERFACE_VERSION = 3 timeframe = "1h" # Valeurs par défaut — surchargées par les résultats d'hyperopt. minimal_roi = {"0": 0.10, "240": 0.05, "720": 0.02, "1440": 0} stoploss = -0.08 trailing_stop = True trailing_stop_positive = 0.02 trailing_stop_positive_offset = 0.04 trailing_only_offset_is_reached = True startup_candle_count: int = 60 process_only_new_candles = True use_exit_signal = True # --- Paramètres optimisables (espace "buy") --- buy_rsi_max = IntParameter(60, 80, default=70, space="buy", optimize=True) buy_adx_min = IntParameter(15, 40, default=25, space="buy", optimize=True) buy_require_trend = BooleanParameter(default=True, space="buy", optimize=True) buy_require_macd = BooleanParameter(default=True, space="buy", optimize=True) # --- Paramètres optimisables (espace "sell") --- sell_rsi_min = IntParameter(20, 50, default=35, space="sell", optimize=True) def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: dataframe["ema_fast"] = ta.EMA(dataframe, timeperiod=9) dataframe["ema_slow"] = ta.EMA(dataframe, timeperiod=21) dataframe["ema_trend"] = ta.EMA(dataframe, timeperiod=50) dataframe["adx"] = ta.ADX(dataframe, timeperiod=14) dataframe["rsi"] = ta.RSI(dataframe, timeperiod=14) macd = ta.MACD(dataframe) dataframe["macd"] = macd["macd"] dataframe["macdsignal"] = macd["macdsignal"] return dataframe def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: cond = ( (dataframe["ema_fast"] > dataframe["ema_slow"]) & (dataframe["ema_fast"].shift(1) <= dataframe["ema_slow"].shift(1)) & (dataframe["rsi"] < self.buy_rsi_max.value) & (dataframe["adx"] > self.buy_adx_min.value) & (dataframe["volume"] > 0) ) if self.buy_require_trend.value: cond &= dataframe["close"] > dataframe["ema_trend"] if self.buy_require_macd.value: cond &= dataframe["macd"] > dataframe["macdsignal"] dataframe.loc[cond, "enter_long"] = 1 return dataframe def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: dataframe.loc[ ( (dataframe["ema_fast"] < dataframe["ema_slow"]) & (dataframe["rsi"] < self.sell_rsi_min.value) & (dataframe["volume"] > 0) ), "exit_long", ] = 1 return dataframe