# source: https://raw.githubusercontent.com/remiotore/freqtrade/44beaeb6a420cd8e9f2e4ea93e11d6cfa192ee03/strategies/universal_trend_strategy.py
from freqtrade.strategy import IStrategy, IntParameter, DecimalParameter
from pandas import DataFrame
import talib.abstract as ta


class Github_remiotore_freqtrade__universal_trend_strategy__20260111_210550(IStrategy):
    """
    Universal Trend Strategy for Freqtrade:
    - Detects bull, bear, and sideways markets using EMA and ADX
    - Buys on RSI oversold in bull or price dip in sideways (lower Bollinger Band)
    - Sells on RSI overbought in bull or price peak in sideways (upper Bollinger Band)
    - Hyperopt-friendly parameters
    """

    # Minimal ROI table: adjust via hyperopt if desired
    minimal_roi = {
        "0": 0.10,
        "30": 0.05,
        "60": 0.02,
        "120": 0
    }

    # Optimal stoploss (10%)
    stoploss = -0.10

    # Trailing stop settings
    trailing_stop = True
    trailing_stop_positive = 0.01
    trailing_stop_positive_offset = 0.02

    # Use exit signal instead of default ROI/stoploss
    use_exit_signal = True
    process_only_new_candles = True
    timeframe = '5m'

    # Hyperopt parameters
    fast_ema = IntParameter(10, 50, default=20, space='buy')
    slow_ema = IntParameter(100, 200, default=100, space='buy')
    rsi_period = IntParameter(7, 14, default=14, space='buy')
    rsi_buy = IntParameter(20, 40, default=30, space='buy')
    rsi_sell = IntParameter(60, 80, default=70, space='sell')
    adx_period = IntParameter(14, 14, default=14, space='buy')
    adx_trend = IntParameter(20, 40, default=25, space='buy')
    bb_period = IntParameter(20, 30, default=20, space='buy')
    bb_dev = DecimalParameter(1.5, 3.0, default=2.0, space='buy')

    def populate_indicators(self, df: DataFrame, metadata: dict) -> DataFrame:
        # EMAs for trend detection
        df['ema_fast'] = ta.EMA(df, timeperiod=self.fast_ema.value)
        df['ema_slow'] = ta.EMA(df, timeperiod=self.slow_ema.value)

        # RSI for momentum
        df['rsi'] = ta.RSI(df, timeperiod=self.rsi_period.value)

        # Bollinger Bands for potential range trades
        upper, middle, lower = ta.BBANDS(
            df['close'],
            timeperiod=self.bb_period.value,
            nbdevup=self.bb_dev.value,
            nbdevdn=self.bb_dev.value
        )
        df['bb_upper'] = upper
        df['bb_middle'] = middle
        df['bb_lower'] = lower

        # ADX for trend strength
        df['adx'] = ta.ADX(df, timeperiod=self.adx_period.value)

        return df

    def populate_entry_trend(self, df: DataFrame, metadata: dict) -> DataFrame:
        df['enter_long'] = False

        # Bull trend: fast EMA above slow EMA and ADX indicates strong trend
        bull = (df['ema_fast'] > df['ema_slow']) & (df['adx'] > self.adx_trend.value)
        cond1 = bull & (df['rsi'] < self.rsi_buy.value)

        # Sideways: EMAs converged and low ADX; buy at lower BB
        side = (abs(df['ema_fast'] - df['ema_slow']) < (df['ema_slow'] * 0.001)) & (df['adx'] < self.adx_trend.value)
        cond2 = side & (df['close'] < df['bb_lower'])

        df.loc[cond1 | cond2, 'enter_long'] = True
        return df

    def populate_exit_trend(self, df: DataFrame, metadata: dict) -> DataFrame:
        df['exit_long'] = False

        # Exit in bull: RSI overbought
        bull = (df['ema_fast'] > df['ema_slow']) & (df['adx'] > self.adx_trend.value)
        df.loc[bull & (df['rsi'] > self.rsi_sell.value), 'exit_long'] = True

        # Exit in sideways: price above upper BB
        side = (abs(df['ema_fast'] - df['ema_slow']) < (df['ema_slow'] * 0.001)) & (df['adx'] < self.adx_trend.value)
        df.loc[side & (df['close'] > df['bb_upper']), 'exit_long'] = True

        return df
