# source: https://raw.githubusercontent.com/4tie/fortiesr/d5cc40760e3cbaff381058a0ea8733d2be469578/user_data/strategies/IntradayAdaptive_v1.py
# Auto-generated by Strategy Lab — Auto-Quant Factory (Adaptive Regime Edition)
# Regime is detected from ATR vs its rolling median (high ATR → trending).
# Hyperopt should use: freqtrade hyperopt --strategy Github_4tie_fortiesr__IntradayAdaptive_v1__20260709_213639 --spaces buy roi stoploss

from freqtrade.strategy import IntParameter, DecimalParameter, IStrategy
from pandas import DataFrame
import talib.abstract as ta
import freqtrade.vendor.qtpylib.indicators as qtpylib
import numpy as np


class Github_4tie_fortiesr__IntradayAdaptive_v1__20260709_213639(IStrategy):
    INTERFACE_VERSION: int = 3

    minimal_roi = {
        "0": 0.08,
        "30": 0.04,
        "60": 0.02,
        "120": 0,
    }

    stoploss = -0.05
    timeframe = "5m"
    trailing_stop = False
    process_only_new_candles = True

    # ── Regime-adaptive entry parameters ─────────────────────────────────────
    # Trending (high ATR) thresholds — more aggressive
    rsi_entry_trend   = IntParameter(20, 40, default=28, space="buy", optimize=True)
    macd_hist_min_trend = DecimalParameter(0.0, 0.005, default=0.001, space="buy", optimize=True)

    # Ranging (low ATR) thresholds — more conservative
    rsi_entry_range   = IntParameter(25, 45, default=35, space="buy", optimize=True)
    bb_entry_pct      = DecimalParameter(0.95, 1.0, default=0.98, space="buy", optimize=True)

    # ATR regime window
    atr_regime_window = IntParameter(30, 100, default=50, space="buy", optimize=False)

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        # ATR + rolling median for regime detection
        dataframe["atr"] = ta.ATR(dataframe, timeperiod=14)
        dataframe["atr_median"] = (
            dataframe["atr"]
            .rolling(window=self.atr_regime_window.value, min_periods=1)
            .median()
        )
        # 1 = trending (ATR above median), 0 = ranging
        dataframe["regime"] = np.where(
            dataframe["atr"] > dataframe["atr_median"], 1, 0
        )

        # MACD
        macd = ta.MACD(dataframe, fastperiod=12, slowperiod=26, signalperiod=9)
        dataframe["macd"]       = macd["macd"]
        dataframe["macdsignal"] = macd["macdsignal"]
        dataframe["macdhist"]   = macd["macdhist"]

        # RSI
        dataframe["rsi"] = ta.RSI(dataframe, timeperiod=14)

        # Bollinger Bands
        bollinger = qtpylib.bollinger_bands(
            qtpylib.typical_price(dataframe), window=20, stds=2
        )
        dataframe["bb_lowerband"] = bollinger["lower"]
        dataframe["bb_upperband"] = bollinger["upper"]

        return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        # Trending regime: MACD cross + RSI filter
        trend_cond = (
            (dataframe["regime"] == 1)
            & (dataframe["macdhist"] > self.macd_hist_min_trend.value)
            & qtpylib.crossed_above(dataframe["macd"], dataframe["macdsignal"])
            & (dataframe["rsi"] < self.rsi_entry_trend.value + 30)
            & (dataframe["volume"] > 0)
        )

        # Ranging regime: RSI oversold + price near lower BB
        range_cond = (
            (dataframe["regime"] == 0)
            & (dataframe["rsi"] < self.rsi_entry_range.value)
            & (dataframe["close"] <= dataframe["bb_lowerband"] * (1 + (1 - self.bb_entry_pct.value)))
            & (dataframe["volume"] > 0)
        )

        dataframe.loc[trend_cond | range_cond, "enter_long"] = 1
        return dataframe

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        return dataframe
