# source: https://raw.githubusercontent.com/IvPalmer/Master-Trader/f9137953b7c7a06fbcac0c616bf0698329aac0c2/ft_userdata/user_data/strategies/MACDTrendV1.py
# directory_url: https://github.com/IvPalmer/Master-Trader/blob/main/ft_userdata/user_data/strategies/
# User: IvPalmer
# Repository: Master-Trader
# --------------------import logging
from freqtrade.strategy import IStrategy
from pandas import DataFrame
import talib.abstract as ta
import freqtrade.vendor.qtpylib.indicators as qtpylib

logger = logging.getLogger(__name__)


class Github_IvPalmer_Master_Trader__MACDTrendV1__20261001_225854(IStrategy):
    """
    MACD momentum-resumption within uptrend — V2 optimized.

    Changes from original:
    - Entry: MACD below signal (not necessarily below zero) — catches more setups
    - Entry: RSI 40-70 filter — confirms momentum without overbought
    - Entry: Volume > SMA(volume,20) — requires conviction
    - Entry: ADX > 25 (raised from 20) — stronger trend requirement
    - Exit: close < ema100 (was low < ema100) — requires confirmed close, not just a wick
    - Exit: require 2 consecutive closes below EMA100 for extra safety

    Based on paulcpk/MACDCrossoverWithTrend, adapted with regime detection,
    proper stoploss, trailing, and protections.
    """
    INTERFACE_VERSION: int = 3

    timeframe = '1h'
    startup_candle_count = 120

    minimal_roi = {
        "0": 0.05, "360": 0.03, "720": 0.02, "1440": 0.01
    }

    stoploss = -0.07
    trailing_stop = True
    trailing_stop_positive = 0.02
    trailing_stop_positive_offset = 0.03
    trailing_only_offset_is_reached = True

    @property
    def protections(self):
        return [
            {"method": "CooldownPeriod", "stop_duration_candles": 2},
            {"method": "StoplossGuard", "lookback_period_candles": 48,
             "trade_limit": 2, "stop_duration_candles": 24, "only_per_pair": True},
            {"method": "LowProfitPairs", "lookback_period_candles": 288,
             "trade_limit": 4, "stop_duration_candles": 48, "required_profit": -0.05},
            {"method": "MaxDrawdown", "lookback_period_candles": 48,
             "max_allowed_drawdown": 0.20, "stop_duration_candles": 12, "trade_limit": 1},
        ]

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        # MACD (12, 26, 9 defaults)
        macd = ta.MACD(dataframe)
        dataframe['macd'] = macd['macd']
        dataframe['macdsignal'] = macd['macdsignal']

        # RSI for momentum confirmation
        dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14)

        # Trend filter — dual EMA for golden cross confirmation
        dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
        dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)

        # EMA threshold exit — 2.5% below EMA100 (same concept as EMACrossoverV1's success)
        dataframe['ema_exit_threshold'] = dataframe['ema100'] * 0.975

        # Regime detection — only trade in trending markets
        dataframe['adx'] = ta.ADX(dataframe, timeperiod=14)

        # Volume filter — require above-average volume
        dataframe['volume_sma'] = dataframe['volume'].rolling(window=20).mean()

        # Volatility filter — skip extreme volatility
        dataframe['atr'] = ta.ATR(dataframe, timeperiod=14)
        dataframe['atr_sma'] = dataframe['atr'].rolling(50).mean()
        dataframe['volatile'] = (dataframe['atr'] > 2.0 * dataframe['atr_sma']).astype(int)

        return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe.loc[
            (
                (dataframe['macd'].shift(1) < 0) &                                     # MACD was below zero (deep pullback recovery)
                (qtpylib.crossed_above(dataframe['macd'], dataframe['macdsignal'])) &   # Bullish MACD crossover
                (dataframe['close'] > dataframe['ema100']) &                            # Price above trend EMA
                (dataframe['ema50'] > dataframe['ema100']) &                            # Golden cross confirmed
                (dataframe['adx'] > 20) &                                               # Trending market
                (dataframe['rsi'] > 40) &                                               # Momentum present
                (dataframe['rsi'] < 70) &                                               # Not overbought
                (dataframe['volatile'] == 0) &                                          # Not extreme volatility
                (dataframe['volume'] > 0)
            ),
            'enter_long'] = 1
        return dataframe

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe.loc[
            (qtpylib.crossed_below(dataframe['close'], dataframe['ema_exit_threshold'])) &  # Confirmed break below EMA - 2.5%
            (dataframe['volume'] > 0),
            'exit_long'] = 1
        return dataframe
