# source: https://raw.githubusercontent.com/emanuelverardi/EuroEdge/acd93339b973f828a9331988f5c1dfc5a7475ff9/user_data/strategies/TrendSwing.py
from freqtrade.strategy import IStrategy
from pandas import DataFrame
import talib.abstract as ta
import freqtrade.vendor.qtpylib.indicators as qtpylib

class Github_emanuelverardi_EuroEdge__TrendSwing__20250824_013912(IStrategy):
    """
    Daily Swing Strategy - Original Clean Version
    - Higher timeframe (1d candles) 
    - Captures medium-term trends
    - Few trades, but each with realistic profit potential
    """

    INTERFACE_VERSION = 3
    timeframe = "1d"
    can_short = False
    startup_candle_count = 100

    # Risk management - optimal for crypto volatility
    stoploss = -0.08  # -8% stop loss (crypto needs room)
    
    # Higher profit targets to overcome fees and volatility
    minimal_roi = {
        "0": 0.05,   # 5% immediate target
        "3": 0.035,  # 3.5% after 3 days
        "7": 0.025,  # 2.5% after 7 days
        "14": 0.015  # 1.5% long-term hold
    }

    trailing_stop = True
    trailing_stop_positive = 0.01      # lock profit after +1%
    trailing_stop_positive_offset = 0.02  # starts trailing after +2%
    trailing_only_offset_is_reached = True

    def populate_indicators(self, df: DataFrame, metadata: dict) -> DataFrame:
        # Moving Averages
        df["ema20"] = ta.EMA(df, timeperiod=20)
        df["ema50"] = ta.EMA(df, timeperiod=50)

        # MACD for momentum confirmation
        macd = ta.MACD(df)
        df["macd"] = macd["macd"]
        df["macdsignal"] = macd["macdsignal"]

        # RSI for filtering extremes
        df["rsi"] = ta.RSI(df, timeperiod=14)

        # Bollinger Bands for volatility filtering
        bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(df), window=20, stds=2)
        df['bb_lowerband'] = bollinger['lower']
        df['bb_middleband'] = bollinger['mid']
        df['bb_upperband'] = bollinger['upper']
        df['bb_percent'] = (df['close'] - df['bb_lowerband']) / (df['bb_upperband'] - df['bb_lowerband'])

        return df

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """
        Entry signals for Github_emanuelverardi_EuroEdge__TrendSwing__20250824_013912Bot
        """
        dataframe.loc[
            (
                # Trend Confirmation
                (dataframe['ema20'] > dataframe['ema50']) &  # Short EMA above long EMA
                (dataframe['close'] > dataframe['ema20']) &   # Price above short EMA
                
                # Momentum Confirmation
                (dataframe['macd'] > dataframe['macdsignal']) &  # MACD bullish
                (dataframe['macd'] > 0) &                         # MACD above zero line
                
                # Volatility Filter - avoid extreme volatility
                (dataframe['bb_percent'] < 0.95) &  # Not at extreme BB high
                (dataframe['bb_percent'] > 0.05) &  # Not at extreme BB low
                
                # RSI Filter (refined)
                (dataframe['rsi'] > 45) &   # Some momentum but not oversold
                (dataframe['rsi'] < 75) &   # Not extremely overbought
                
                # Volume confirmation
                (dataframe['volume'] > dataframe['volume'].rolling(20).mean()) &
                
                # Basic safety
                (dataframe['volume'] > 0)
            ),
            ['enter_long', 'enter_tag']
        ] = [1, 'trend_momentum']

        return dataframe

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        # Only exit on major trend reversal - let ROI and trailing stop handle most exits
        dataframe.loc[
            (
                # Major trend breakdown
                (dataframe["ema20"] < dataframe["ema50"]) &
                # MACD confirms breakdown  
                (dataframe["macd"] < dataframe["macdsignal"]) &
                # Strong overbought condition
                (dataframe["rsi"] > 80)
            ),
            'exit_long'
        ] = 1
        
        return dataframe
