# source: https://raw.githubusercontent.com/TraderAlice/Auto-Quant/d143ee67871be35fcadfe8a010020b483f230469/versions/0.3.0/strategies/MTFTrendStack.py
"""
Github_TraderAlice_Auto_Quant__MTFTrendStack__20260424_110040 — multi-timeframe trend-following with 1d regime + 4h trend + 1h entry

Paradigm: trend-following
Hypothesis: v0.2.0's TrendEMAStack capped at Sharpe 0.36 on 1h-only because trend
            signals on 1h crypto see too much noise. Stacking a 1d EMA200 regime
            filter (only trade when above 200d) plus a 4h EMA9>EMA21 trend
            confirmation should let the 1h entry trigger fire only inside genuine
            multi-timeframe uptrends, lifting Sharpe and tightening DD.
Parent: root (paradigm-inspired by v0.2.0's TrendEMAStack but structurally different)
Created: pending — fill in after first commit
Status: active
Uses MTF: yes
"""

from pandas import DataFrame
import talib.abstract as ta

from freqtrade.strategy import IStrategy, informative


class Github_TraderAlice_Auto_Quant__MTFTrendStack__20260424_110040(IStrategy):
    INTERFACE_VERSION = 3

    timeframe = "1h"
    can_short = False

    minimal_roi = {"0": 100}
    stoploss = -0.99
    trailing_stop = False
    process_only_new_candles = True
    use_exit_signal = True
    exit_profit_only = False
    ignore_roi_if_entry_signal = False

    # 1d EMA200 needs 200 daily bars warmup ≈ 4800 hourly bars
    startup_candle_count: int = 250

    @informative("4h")
    def populate_indicators_4h(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        # Slower 4h EMA pair (13/34 vs prior 9/21) — clearer trend signal at 4h
        dataframe["ema_fast"] = ta.EMA(dataframe, timeperiod=13)
        dataframe["ema_slow"] = ta.EMA(dataframe, timeperiod=34)
        dataframe["atr"] = ta.ATR(dataframe, timeperiod=14)
        dataframe["atr_ma20"] = dataframe["atr"].rolling(20).mean()
        return dataframe

    @informative("1d")
    def populate_indicators_1d(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe["ema200"] = ta.EMA(dataframe, timeperiod=200)
        return dataframe

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe["ema9"] = ta.EMA(dataframe, timeperiod=9)
        dataframe["ema21"] = ta.EMA(dataframe, timeperiod=21)
        dataframe["sma50"] = ta.SMA(dataframe, timeperiod=50)
        dataframe["rsi"] = ta.RSI(dataframe, timeperiod=14)
        return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe.loc[
            (dataframe["close"] > dataframe["ema200_1d"])      # 1d bull regime
            & (dataframe["ema_fast_4h"] > dataframe["ema_slow_4h"])   # 4h trend up (13/34)
            & (dataframe["atr_4h"] > dataframe["atr_ma20_4h"])  # 4h ATR expansion (conviction)
            & (dataframe["close"] > dataframe["ema9"])         # 1h pullback closed back above
            & (dataframe["close"].shift(1) < dataframe["ema9"].shift(1)),  # event-only (dropped redundant ema9>ema21 state)
            "enter_long",
        ] = 1
        return dataframe

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe.loc[
            (dataframe["ema9"] < dataframe["ema21"])           # 1h trend break (responsive exit — patient exit hurts trend per r36)
            | (dataframe["close"] < dataframe["ema200_1d"]),   # regime break
            "exit_long",
        ] = 1
        return dataframe
