# source: https://raw.githubusercontent.com/Alexuresp/F1/c1a099d964ffe244a3fdc1818780e15b78be123b/E0V1EN-5min.py
from datetime import datetime, timedelta
import talib.abstract as ta
from freqtrade.persistence import Trade
from freqtrade.strategy.interface import IStrategy
from pandas import DataFrame
from freqtrade.strategy import DecimalParameter, IntParameter, informative
import warnings

warnings.simplefilter(action="ignore", category=RuntimeWarning)


class Github_Alexuresp_F1__E0V1EN_5min__20251011_114949(IStrategy):
    minimal_roi = {
        "0": 0.5  # Static backup exit at 50% PNL
    }
    timeframe = '5m'

    process_only_new_candles = True
    startup_candle_count = 20

    order_types = {
        'entry': 'limit',
        'exit': 'market',
        'emergency_exit': 'market',
        'force_entry': 'market',
        'force_exit': "market",
        'stoploss': 'market',
        'stoploss_on_exchange': False,
        'stoploss_on_exchange_interval': 60,
        'stoploss_on_exchange_market_ratio': 0.99
    }

    # Fixed stop loss at 3% PNL as in Pine Script
    stoploss = -0.3

    # Optimization parameters for BB and ADX
    bb_len_5m = IntParameter(15, 25, default=20, space='buy', optimize=True)
    bb_mult_5m = DecimalParameter(1.5, 3.0, default=2.0, decimals=1, space='buy', optimize=True)

    adx_len = IntParameter(10, 20, default=14, space='buy', optimize=True)
    adx_threshold = IntParameter(15, 30, default=22, space='buy', optimize=True)

    # Stochastic parameters
    stoch_k_len = IntParameter(3, 10, default=5, space='sell', optimize=True)
    stoch_k_smooth = IntParameter(1, 5, default=1, space='sell', optimize=True)
    stoch_d_smooth = IntParameter(1, 5, default=3, space='sell', optimize=True)
    stoch_mode = IntParameter(0, 1, default=1, space='sell', optimize=True)  # 0 = K<D, 1 = crossover

    # Entry price offset
    entry_offset = DecimalParameter(-0.10, 0.10, default=-0.004, decimals=3, space='buy', optimize=True)

    leverage_optimize = True
    leverage_num = IntParameter(low=1, high=10, default=10, space='buy', optimize=leverage_optimize)

    @property
    def protections(self):
        return [
{
            "method": "CooldownPeriod",
            "stop_duration_candles": 10
        },
        {
            "method": "StoplossGuard",
            "lookback_period_candles": 48,
            "trade_limit": 2,
            "stop_duration_candles": 20
        },
        {
            "method": "MaxDrawdown",
            "lookback_period_candles": 144,
            "trade_limit": 1,
            "stop_duration_candles": 36,
            "max_allowed_drawdown": 0.3
        }
        ]


    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        # 5m Bollinger Bands
        bb_basis_5m = ta.SMA(dataframe['close'], timeperiod=self.bb_len_5m.value)
        bb_std_5m = ta.STDDEV(dataframe['close'], timeperiod=self.bb_len_5m.value)
        dataframe['bb_lower_5m'] = bb_basis_5m - (self.bb_mult_5m.value * bb_std_5m)

        # 5m ADX
        adx = ta.ADX(dataframe['high'], dataframe['low'], dataframe['close'], timeperiod=self.adx_len.value)
        dataframe['adx'] = adx

        # 5m percentage change (relative to open)
        dataframe['pct_change_5m'] = ((dataframe['close'] - dataframe['open']) / dataframe['open']) * 100
        dataframe['is_red_5m'] = dataframe['close'] < dataframe['open']

        # 5m Stochastic
        slowk, slowd = ta.STOCH(dataframe['high'], dataframe['low'], dataframe['close'],
                               fastk_period=self.stoch_k_len.value, slowk_period=self.stoch_k_smooth.value,
                               slowd_period=self.stoch_d_smooth.value)
        dataframe['stoch_k_smooth'] = slowk
        dataframe['stoch_d_smooth'] = slowd

        return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe.loc[:, 'enter_tag'] = ''

        # Entry conditions exactly as in Pine Script
        cond_drop_5m = (dataframe['is_red_5m']) & (dataframe['pct_change_5m'] <= -1.0)  # Red candle with >=1% drop
        cond_adx = dataframe['adx'] > self.adx_threshold.value
        cond_bb_5m = dataframe['close'] < dataframe['bb_lower_5m']

        # Combine all entry conditions
        entry_signal = cond_drop_5m & cond_adx & cond_bb_5m

        dataframe.loc[entry_signal, 'enter_long'] = 1
        dataframe.loc[entry_signal, 'enter_tag'] = 'bb_adx_entry'

        return dataframe

    def custom_exit(self, pair: str, trade: 'Trade', current_time: 'datetime', current_rate: float,
                    current_profit: float, **kwargs):
        dataframe, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe)
        current_candle = dataframe.iloc[-1].squeeze()

        # Take profit at 10% PNL with Stochastic condition
        if current_profit >= 0.1:  # 10% PNL profit
            stoch_k = current_candle['stoch_k_smooth']
            stoch_d = current_candle['stoch_d_smooth']

            if self.stoch_mode.value == 0:
                # Simple mode: K < D
                if stoch_k < stoch_d:
                    return "take_profit_stoch"
            else:
                # Crossover mode
                previous_candle = dataframe.iloc[-2].squeeze()
                prev_stoch_k = previous_candle['stoch_k_smooth']
                prev_stoch_d = previous_candle['stoch_d_smooth']

                if prev_stoch_k >= prev_stoch_d and stoch_k < stoch_d:
                    return "take_profit_stoch"

        return None

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe.loc[:, ['exit_long', 'exit_tag']] = (0, 'long_out')
        return dataframe

    def leverage(self, pair: str, current_time: datetime, current_rate: float,
                 proposed_leverage: float, max_leverage: float, side: str,
                 **kwargs) -> float:
        return self.leverage_num.value
