# source: https://raw.githubusercontent.com/TraderAlice/Auto-Quant/d143ee67871be35fcadfe8a010020b483f230469/versions/0.3.0/strategies/BTCLeaderBreakX.py
"""
Github_TraderAlice_Auto_Quant__BTCLeaderBreakX__20260424_110040 — fork of BTCLeaderBreak: tighter Donchian-15 + faster SMA20 exit

Paradigm: breakout
Hypothesis: BTCLeaderBreak hit 0.88 on Donchian-20 breaks + SMA50 exit. The
            Donchian-20 catches "established" breakouts but may miss earlier,
            higher-edge moves. Tighter Donchian-15 catches breaks 25% earlier;
            faster SMA20 exit closes faded breakouts before the SMA50 breach
            confirms. Risk: more chop entries, tighter exit may cut winners.
            This is a riskier variant testing whether earlier-and-faster
            outperforms BTCLeaderBreak's slower-and-stronger configuration.
Parent: BTCLeaderBreak
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__BTCLeaderBreakX__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

    startup_candle_count: int = 200

    @informative("4h", "BTC/USDT")
    def populate_indicators_btc_4h(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        # Donchian-10 (peak — established as local optimum at r27, confirmed by r28's regression at 7)
        dataframe["dc_high10"] = dataframe["high"].rolling(10).max()
        dataframe["atr"] = ta.ATR(dataframe, timeperiod=14)
        dataframe["atr_ma20"] = dataframe["atr"].rolling(20).mean()
        return dataframe

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        # Faster local-pair exit reference: SMA20 (was 50 in parent)
        dataframe["sma20"] = ta.SMA(dataframe, timeperiod=20)
        dataframe["sma50"] = ta.SMA(dataframe, timeperiod=50)  # kept for entry guard
        dataframe["vol_ma20"] = dataframe["volume"].rolling(20).mean()
        return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        btc_break = (
            dataframe["btc_usdt_close_4h"] > dataframe["btc_usdt_dc_high10_4h"].shift(1)
        ) & (
            dataframe["btc_usdt_close_4h"].shift(1) <= dataframe["btc_usdt_dc_high10_4h"].shift(1)
        )
        dataframe.loc[
            btc_break
            & (dataframe["btc_usdt_atr_4h"] > dataframe["btc_usdt_atr_ma20_4h"])
            & (dataframe["close"] > dataframe["sma50"])              # entry guard kept on slower SMA
            & (dataframe["volume"] > dataframe["vol_ma20"] * 1.5),
            "enter_long",
        ] = 1
        return dataframe

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        # Restore SMA50 exit to isolate whether it was the entry or the exit that hurt
        dataframe.loc[
            dataframe["close"] < dataframe["sma50"],
            "exit_long",
        ] = 1
        return dataframe
