# source: https://raw.githubusercontent.com/witrer/fre-strategy/6e1fc511c4485342aee25175f0c75ec3fd772d00/defult.py
import freqtrade.vendor.qtpylib.indicators as qtpylib
import numpy as np
import talib.abstract as ta
from freqtrade.persistence import Trade
from freqtrade.strategy.interface import IStrategy
from pandas import DataFrame
from datetime import datetime, timedelta
from freqtrade.strategy import merge_informative_pair, CategoricalParameter, DecimalParameter


###########################################################################################################
##                Github_witrer_fre_strategy__defult__20250606_113140 by witrer (倪世通)                                           ##
##                                                                                                       ##
##    Combined strategy integrating V5, V6, V9 features with enhanced bull/bear/sideways detection       ##
##    Multi-dimensional signal analysis with adaptive position management                                ##
##    Based on ilya's strategies: https://github.com/i1ya/freqtrade-strategies                           ##
##                                                                                                       ##
##    GitHub: https://github.com/witrer                                                                 ##
##    Version: 1.0.0                                                                                     ##
##    Date: 2024-12-19                                                                                   ##
##                                                                                                       ##
###########################################################################################################

def SSLChannels(dataframe, length=7):
    """SSL Channels indicator for trend detection"""
    df = dataframe.copy()
    df['ATR'] = ta.ATR(df, timeperiod=14)
    df['smaHigh'] = df['high'].rolling(length).mean() + df['ATR']
    df['smaLow'] = df['low'].rolling(length).mean() - df['ATR']
    df['hlv'] = np.where(df['close'] > df['smaHigh'], 1, np.where(df['close'] < df['smaLow'], -1, np.NAN))
    df['hlv'] = df['hlv'].ffill()
    df['sslDown'] = np.where(df['hlv'] < 0, df['smaHigh'], df['smaLow'])
    df['sslUp'] = np.where(df['hlv'] < 0, df['smaLow'], df['smaHigh'])
    return df['sslDown'], df['sslUp']

def market_direction(dataframe):
    """Detect market direction: Bull (1), Bear (-1), Sideways (0)"""
    bull_condition = (
        (dataframe['ema_50'] > dataframe['ema_200']) &
        (dataframe['ema_20'] > dataframe['ema_50']) &
        (dataframe['close'] > dataframe['ema_20']) &
        (dataframe['ssl_up'] > dataframe['ssl_down']) &
        (dataframe['ema_50_1h'] > dataframe['ema_200_1h'])
    )
    
    bear_condition = (
        (dataframe['ema_50'] < dataframe['ema_200']) &
        (dataframe['ema_20'] < dataframe['ema_50']) &
        (dataframe['close'] < dataframe['ema_20']) &
        (dataframe['ssl_up'] < dataframe['ssl_down']) &
        (dataframe['ema_50_1h'] < dataframe['ema_200_1h'])
    )
    
    return np.where(bull_condition, 1, np.where(bear_condition, -1, 0))

class Github_witrer_fre_strategy__defult__20250606_113140(IStrategy):
    INTERFACE_VERSION = 2

    minimal_roi = {
        "0": 0.029,
        "10": 0.021,
        "40": 0.008,
        "120": 0.005,
        "300": 0.002,
    }

    stoploss = -0.99
    timeframe = '5m'
    inf_1h = '1h'
    inf_4h = '4h'

    use_sell_signal = True
    sell_profit_only = False
    sell_profit_offset = 0.001
    ignore_roi_if_buy_signal = False

    trailing_stop = False
    trailing_only_offset_is_reached = False
    trailing_stop_positive = 0.01
    trailing_stop_positive_offset = 0.025

    use_custom_stoploss = True
    process_only_new_candles = False
    startup_candle_count: int = 200

    order_types = {
        'buy': 'market',
        'sell': 'market',
        'stoploss': 'market',
        'stoploss_on_exchange': False
    }

    # Parameters
    buy_params = {
        "buy_condition_bull_1_enable": True,
        "buy_condition_bull_2_enable": True,
        "buy_condition_bull_3_enable": True,
        "buy_condition_bear_1_enable": True,
        "buy_condition_bear_2_enable": True,
        "buy_condition_bear_3_enable": True,
        "buy_condition_sideways_1_enable": True,
        "buy_condition_sideways_2_enable": True,
        "buy_condition_universal_1_enable": True,
        "buy_condition_universal_2_enable": True,
        "buy_condition_extreme_dip_enable": False,
        "buy_condition_breakout_enable": True,
        "buy_condition_diamond_hands_enable": True,
    }

    # Categorical parameters
    buy_condition_bull_1_enable = CategoricalParameter([True, False], default=True, space='buy', optimize=False, load=True)
    buy_condition_bull_2_enable = CategoricalParameter([True, False], default=True, space='buy', optimize=False, load=True)
    buy_condition_bull_3_enable = CategoricalParameter([True, False], default=True, space='buy', optimize=False, load=True)
    buy_condition_bear_1_enable = CategoricalParameter([True, False], default=True, space='buy', optimize=False, load=True)
    buy_condition_bear_2_enable = CategoricalParameter([True, False], default=True, space='buy', optimize=False, load=True)
    buy_condition_bear_3_enable = CategoricalParameter([True, False], default=True, space='buy', optimize=False, load=True)
    buy_condition_sideways_1_enable = CategoricalParameter([True, False], default=True, space='buy', optimize=False, load=True)
    buy_condition_sideways_2_enable = CategoricalParameter([True, False], default=True, space='buy', optimize=False, load=True)
    buy_condition_universal_1_enable = CategoricalParameter([True, False], default=True, space='buy', optimize=False, load=True)
    buy_condition_universal_2_enable = CategoricalParameter([True, False], default=True, space='buy', optimize=False, load=True)
    buy_condition_extreme_dip_enable = CategoricalParameter([True, False], default=False, space='buy', optimize=False, load=True)
    buy_condition_breakout_enable = CategoricalParameter([True, False], default=True, space='buy', optimize=False, load=True)
    buy_condition_diamond_hands_enable = CategoricalParameter([True, False], default=True, space='buy', optimize=False, load=True)

    # Bollinger Bands parameters
    buy_bb20_close_bblowerband_bull = DecimalParameter(0.98, 1.02, default=0.99, space='buy', optimize=False, load=True)
    buy_bb20_close_bblowerband_bear = DecimalParameter(0.94, 0.98, default=0.975, space='buy', optimize=False, load=True)
    buy_bb20_close_bblowerband_sideways = DecimalParameter(0.96, 1.00, default=0.985, space='buy', optimize=False, load=True)

    # Volume parameters
    buy_volume_pump_1 = DecimalParameter(0.1, 0.9, default=0.4, space='buy', decimals=1, optimize=False, load=True)
    buy_volume_drop_1 = DecimalParameter(1, 10, default=4, space='buy', decimals=1, optimize=False, load=True)

    # RSI parameters
    buy_rsi_1h_bull = DecimalParameter(20.0, 45.0, default=35.0, space='buy', decimals=1, optimize=False, load=True)
    buy_rsi_1h_bear = DecimalParameter(10.0, 25.0, default=15.0, space='buy', decimals=1, optimize=False, load=True)
    buy_rsi_1h_sideways = DecimalParameter(15.0, 35.0, default=25.0, space='buy', decimals=1, optimize=False, load=True)
    
    buy_rsi_bull = DecimalParameter(25.0, 45.0, default=35.0, space='buy', decimals=1, optimize=False, load=True)
    buy_rsi_bear = DecimalParameter(7.0, 25.0, default=14.2, space='buy', decimals=1, optimize=False, load=True)
    buy_rsi_sideways = DecimalParameter(15.0, 35.0, default=25.0, space='buy', decimals=1, optimize=False, load=True)

    # MACD parameters
    buy_macd_bull = DecimalParameter(0.01, 0.05, default=0.02, space='buy', decimals=2, optimize=False, load=True)
    buy_macd_bear = DecimalParameter(0.02, 0.08, default=0.03, space='buy', decimals=2, optimize=False, load=True)

    # Additional parameters
    buy_extreme_rsi_threshold = DecimalParameter(15.0, 25.0, default=20.0, space='buy', decimals=1, optimize=False, load=True)
    buy_breakout_volume_threshold = DecimalParameter(1.2, 2.0, default=1.5, space='buy', decimals=1, optimize=False, load=True)
    buy_diamond_hands_dip_threshold = DecimalParameter(1.02, 1.08, default=1.05, space='buy', decimals=2, optimize=False, load=True)

    # Sell parameters
    sell_bull_profit_threshold = DecimalParameter(1.01, 1.03, default=1.015, space='sell', decimals=3, optimize=False, load=True)
    sell_bear_profit_threshold = DecimalParameter(1.003, 1.01, default=1.005, space='sell', decimals=3, optimize=False, load=True)
    sell_sideways_profit_threshold = DecimalParameter(1.005, 1.02, default=1.01, space='sell', decimals=3, optimize=False, load=True)

    def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime,
                        current_rate: float, current_profit: float, **kwargs) -> float:
        """Enhanced stoploss function combining V6 and V9 features"""
        if current_profit > 0.05:
            return 0.03
        elif current_profit > 0.02:
            return 0.01
        elif current_profit > 0:
            return 0.99
        else:
            if (current_time - timedelta(minutes=240) > trade.open_date_utc):
                return 0.01
            
            trade_time_50 = current_time - timedelta(minutes=50)
            if (trade_time_50 > trade.open_date_utc):
                try:
                    number_of_candle_shift = int((trade_time_50 - trade.open_date_utc).total_seconds() / 300)
                    dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
                    candle = dataframe.iloc[-number_of_candle_shift].squeeze()
                    
                    if current_rate * 1.015 < candle['open']:
                        return 0.01
                except IndexError:
                    return 0.01
        
        return 0.99

    def informative_pairs(self):
        pairs = self.dp.current_whitelist()
        informative_pairs = [(pair, '1h') for pair in pairs]
        informative_pairs += [(pair, '4h') for pair in pairs]
        return informative_pairs

    def informative_1h_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        assert self.dp, "DataProvider is required for multiple timeframes."
        informative_1h = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe=self.inf_1h)
        
        informative_1h['ema_20'] = ta.EMA(informative_1h, timeperiod=20)
        informative_1h['ema_50'] = ta.EMA(informative_1h, timeperiod=50)
        informative_1h['ema_200'] = ta.EMA(informative_1h, timeperiod=200)
        informative_1h['rsi'] = ta.RSI(informative_1h, timeperiod=14)
        
        ssl_down_1h, ssl_up_1h = SSLChannels(informative_1h, 20)
        informative_1h['ssl_down'] = ssl_down_1h
        informative_1h['ssl_up'] = ssl_up_1h
        
        macd, macdsignal, macdhist = ta.MACD(informative_1h)
        informative_1h['macd'] = macd
        informative_1h['macdsignal'] = macdsignal
        informative_1h['macdhist'] = macdhist
        
        return informative_1h

    def informative_4h_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        assert self.dp, "DataProvider is required for multiple timeframes."
        informative_4h = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe=self.inf_4h)
        
        informative_4h['ema_50'] = ta.EMA(informative_4h, timeperiod=50)
        informative_4h['ema_200'] = ta.EMA(informative_4h, timeperiod=200)
        informative_4h['rsi'] = ta.RSI(informative_4h, timeperiod=14)
        
        return informative_4h

    def normal_tf_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        # Bollinger Bands
        bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
        dataframe['bb_lowerband'] = bollinger['lower']
        dataframe['bb_middleband'] = bollinger['mid']
        dataframe['bb_upperband'] = bollinger['upper']
        
        # BinHV45 indicators from V5
        bb_40 = qtpylib.bollinger_bands(dataframe['close'], window=40, stds=2)
        dataframe['lower'] = bb_40['lower']
        dataframe['mid'] = bb_40['mid']
        dataframe['bbdelta'] = (bb_40['mid'] - dataframe['lower']).abs()
        dataframe['closedelta'] = (dataframe['close'] - dataframe['close'].shift()).abs()
        dataframe['tail'] = (dataframe['close'] - dataframe['low']).abs()

        # Volume analysis
        dataframe['volume_mean_slow'] = dataframe['volume'].rolling(window=30).mean()
        dataframe['volume_mean_fast'] = dataframe['volume'].rolling(window=10).mean()

        # Moving averages
        dataframe['ema_12'] = ta.EMA(dataframe, timeperiod=12)
        dataframe['ema_20'] = ta.EMA(dataframe, timeperiod=20)
        dataframe['ema_26'] = ta.EMA(dataframe, timeperiod=26)
        dataframe['ema_50'] = ta.EMA(dataframe, timeperiod=50)
        dataframe['ema_200'] = ta.EMA(dataframe, timeperiod=200)

        dataframe['sma_5'] = ta.SMA(dataframe, timeperiod=5)
        dataframe['sma_20'] = ta.SMA(dataframe, timeperiod=20)

        # Momentum indicators
        dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14)
        dataframe['rsi_fast'] = ta.RSI(dataframe, timeperiod=7)

        # SSL Channels
        ssl_down, ssl_up = SSLChannels(dataframe, 7)
        dataframe['ssl_down'] = ssl_down
        dataframe['ssl_up'] = ssl_up

        # MACD
        macd, macdsignal, macdhist = ta.MACD(dataframe)
        dataframe['macd'] = macd
        dataframe['macdsignal'] = macdsignal
        dataframe['macdhist'] = macdhist

        # Market direction detection
        dataframe['market_direction'] = market_direction(dataframe)

        return dataframe

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        informative_1h = self.informative_1h_indicators(dataframe, metadata)
        dataframe = merge_informative_pair(dataframe, informative_1h, self.timeframe, self.inf_1h, ffill=True)

        informative_4h = self.informative_4h_indicators(dataframe, metadata)
        dataframe = merge_informative_pair(dataframe, informative_4h, self.timeframe, self.inf_4h, ffill=True)

        dataframe = self.normal_tf_indicators(dataframe, metadata)

        return dataframe

    def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        
        dataframe.loc[
            # 🐂 BULL MARKET CONDITIONS
            (
                self.buy_condition_bull_1_enable.value &
                (dataframe['market_direction'] == 1) &
                (dataframe['close'] > dataframe['ema_200']) &
                (dataframe['close'] > dataframe['ema_200_1h']) &
                (dataframe['ema_50_4h'] > dataframe['ema_200_4h']) &
                (dataframe['close'] < dataframe['bb_lowerband'] * self.buy_bb20_close_bblowerband_bull.value) &
                (dataframe['volume_mean_slow'] > dataframe['volume_mean_slow'].shift(30) * self.buy_volume_pump_1.value) &
                (dataframe['volume'] < (dataframe['volume'].shift() * self.buy_volume_drop_1.value)) &
                (dataframe['rsi_1h'] < self.buy_rsi_1h_bull.value) &
                (dataframe['volume'] > 0)
            )
            |
            (
                self.buy_condition_bull_2_enable.value &
                (dataframe['market_direction'] == 1) &
                (dataframe['close'] > dataframe['ema_200']) &
                (dataframe['ssl_up_1h'] > dataframe['ssl_down_1h']) &
                (dataframe['ema_26'] > dataframe['ema_12']) &
                ((dataframe['ema_26'] - dataframe['ema_12']) > (dataframe['open'] * self.buy_macd_bull.value)) &
                (dataframe['close'] < dataframe['bb_lowerband']) &
                (dataframe['rsi'] < self.buy_rsi_bull.value) &
                (dataframe['volume'] < (dataframe['volume'].shift() * self.buy_volume_drop_1.value)) &
                (dataframe['volume'] > 0)
            )
            |
            (
                self.buy_condition_bull_3_enable.value &
                (dataframe['market_direction'] == 1) &
                (dataframe['close'] < dataframe['sma_5']) &
                (dataframe['ssl_up_1h'] > dataframe['ssl_down_1h']) &
                (dataframe['ema_50'] > dataframe['ema_200']) &
                (dataframe['ema_50_1h'] > dataframe['ema_200_1h']) &
                (dataframe['rsi'] < dataframe['rsi_1h'] - 20) &
                (dataframe['volume'] > 0)
            )
            |
            # 🐻 BEAR MARKET CONDITIONS  
            (
                self.buy_condition_bear_1_enable.value &
                (dataframe['market_direction'] == -1) &  # Bear market detected
                (dataframe['close'] < dataframe['bb_lowerband'] * self.buy_bb20_close_bblowerband_bear.value) &
                (dataframe['rsi_1h'] < self.buy_rsi_1h_bear.value) &
                (dataframe['rsi'] < self.buy_rsi_bear.value) &
                (dataframe['volume'] < (dataframe['volume'].shift() * self.buy_volume_drop_1.value)) &
                (dataframe['volume_mean_slow'] > dataframe['volume_mean_slow'].shift(30) * self.buy_volume_pump_1.value) &
                (dataframe['volume'] > 0)
            )
            |
            (
                self.buy_condition_bear_2_enable.value &
                (dataframe['market_direction'] == -1) &  # Bear market
                (dataframe['ema_26'] > dataframe['ema_12']) &
                ((dataframe['ema_26'] - dataframe['ema_12']) > (dataframe['open'] * self.buy_macd_bear.value)) &
                (dataframe['close'] < dataframe['bb_lowerband']) &
                (dataframe['rsi_1h'] < self.buy_rsi_1h_bear.value) &
                (dataframe['volume'] < (dataframe['volume'].shift() * self.buy_volume_drop_1.value)) &
                (dataframe['volume'] > 0)
            )
            |
            (
                self.buy_condition_bear_3_enable.value &
                (dataframe['market_direction'] == -1) &  # Bear market
                (dataframe['close'] < dataframe['bb_lowerband']) &
                (dataframe['bbdelta'] > dataframe['close'] * 0.008) &  # V5 BinHV45 condition
                (dataframe['closedelta'] > dataframe['close'] * 0.0175) &
                (dataframe['tail'] < dataframe['bbdelta'] * 0.25) &
                (dataframe['close'] < dataframe['lower'].shift()) &
                (dataframe['close'] <= dataframe['close'].shift()) &
                (dataframe['volume'] > 0)
            )
            |
            # 📊 SIDEWAYS MARKET CONDITIONS
            (
                self.buy_condition_sideways_1_enable.value &
                (dataframe['market_direction'] == 0) &  # Sideways market detected
                (dataframe['close'] < dataframe['bb_lowerband'] * self.buy_bb20_close_bblowerband_sideways.value) &
                (dataframe['rsi_1h'] < self.buy_rsi_1h_sideways.value) &
                (dataframe['rsi'] < self.buy_rsi_sideways.value) &
                (dataframe['volume'] < (dataframe['volume'].shift() * self.buy_volume_drop_1.value)) &
                (dataframe['volume'] > 0)
            )
            |
            (
                self.buy_condition_sideways_2_enable.value &
                (dataframe['market_direction'] == 0) &  # Sideways market
                (dataframe['close'] < dataframe['sma_20']) &
                (dataframe['rsi_fast'] < 30) &
                (dataframe['macdhist'] < 0) &
                (dataframe['volume_mean_fast'] > dataframe['volume_mean_slow']) &
                (dataframe['volume'] > 0)
            )
            |
            # 🌐 UNIVERSAL CONDITIONS (work in any market)
            (
                self.buy_condition_universal_1_enable.value &
                (dataframe['close'] < dataframe['bb_lowerband']) &
                (dataframe['rsi'] < 30) &
                (dataframe['rsi_1h'] < 40) &
                (dataframe['volume'] < (dataframe['volume'].shift() * self.buy_volume_drop_1.value)) &
                (dataframe['volume'] > 0)
            )
            |
            (
                self.buy_condition_universal_2_enable.value &
                (dataframe['close'] < dataframe['sma_5']) &
                (dataframe['ssl_up'] > dataframe['ssl_down']) &
                (dataframe['rsi'] < 35) &
                (dataframe['volume'] > dataframe['volume_mean_slow'] * 1.2) &
                (dataframe['volume'] > 0)
            )
            |
            # 🔥 EXTREME DIP CONDITIONS (high risk, high reward)
            (
                self.buy_condition_extreme_dip_enable.value &
                (dataframe['rsi'] < 20) &
                (dataframe['rsi_1h'] < 25) &
                (dataframe['close'] < dataframe['bb_lowerband'] * 0.95) &
                (dataframe['volume'] > dataframe['volume_mean_slow'] * 2) &
                (dataframe['close'] < dataframe['close'].shift(5) * 0.97) &  # 3% drop in 5 candles
                (dataframe['volume'] > 0)
            )
            |
            # 🎯 BREAKOUT CONDITIONS (momentum plays)
            (
                self.buy_condition_breakout_enable.value &
                (dataframe['close'] > dataframe['bb_middleband']) &
                (dataframe['close'] > dataframe['close'].shift()) &
                (dataframe['volume'] > dataframe['volume_mean_slow'] * 1.5) &
                (dataframe['rsi'] > 50) & (dataframe['rsi'] < 65) &
                (dataframe['ssl_up'] > dataframe['ssl_down']) &
                (dataframe['ema_12'] > dataframe['ema_26']) &
                (dataframe['volume'] > 0)
            )
            |
            # 💎 DIAMOND HANDS CONDITIONS (long-term holders)
            (
                self.buy_condition_diamond_hands_enable.value &
                (dataframe['ema_200'] > dataframe['ema_200'].shift(10)) &  # Long-term uptrend
                (dataframe['ema_50_4h'] > dataframe['ema_200_4h']) &  # 4h uptrend
                (dataframe['close'] < dataframe['ema_200'] * 1.05) &  # Near major support
                (dataframe['rsi_4h'] < 40) &  # 4h oversold
                (dataframe['volume'] > 0)
            ),
            'buy'
        ] = 1

        return dataframe
    def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """
        Enhanced market-adaptive sell logic with multiple exit strategies
        """
        dataframe.loc[
            (
                # 🐂 BULL MARKET SELL CONDITIONS (less aggressive)
                (
                    (dataframe['market_direction'] == 1) &
                    (
                        # Take profit conditions for bull market
                        (dataframe['close'] > dataframe['bb_middleband'] * 1.015) |
                        (dataframe['rsi'] > 75) |
                        (dataframe['close'] > dataframe['bb_upperband']) |
                        # Momentum reversal in bull market
                        (
                            (dataframe['rsi'] > 65) &
                            (dataframe['rsi'].shift() > dataframe['rsi']) &
                            (dataframe['close'] > dataframe['bb_middleband'])
                        )
                    )
                )
                |
                # 🐻 BEAR MARKET SELL CONDITIONS (more aggressive)
                (
                    (dataframe['market_direction'] == -1) &
                    (
                        # Quick profit taking in bear market
                        (dataframe['close'] > dataframe['bb_middleband'] * 1.005) |
                        (dataframe['rsi'] > 60) |
                        # Any sign of weakness
                        (
                            (dataframe['close'] > dataframe['bb_middleband']) &
                            (dataframe['volume'] > dataframe['volume_mean_slow'] * 1.5)
                        ) |
                        # Dead cat bounce protection
                        (
                            (dataframe['rsi'] > 55) &
                            (dataframe['close'] > dataframe['sma_20'])
                        )
                    )
                )
                |
                # 📊 SIDEWAYS MARKET SELL CONDITIONS (balanced)
                (
                    (dataframe['market_direction'] == 0) &
                    (
                        # Standard profit taking
                        (dataframe['close'] > dataframe['bb_middleband'] * 1.01) |
                        (dataframe['rsi'] > 70) |
                        # Range trading exits
                        (
                            (dataframe['close'] > dataframe['bb_upperband'] * 0.98) &
                            (dataframe['rsi'] > 60)
                        )
                    )
                )
                |
                # 🚨 UNIVERSAL EMERGENCY SELLS
                (
                    # Extreme overbought
                    (dataframe['rsi'] > 85) |
                    (dataframe['rsi_1h'] > 80) |
                    # Parabolic move
                    (dataframe['close'] > dataframe['bb_upperband'] * 1.05) |
                    # Volume spike with reversal
                    (
                        (dataframe['volume'] > dataframe['volume_mean_slow'] * 3) &
                        (dataframe['close'] < dataframe['open']) &
                        (dataframe['rsi'] > 65)
                    ) |
                    # MACD bearish divergence
                    (
                        (dataframe['macd'] < dataframe['macdsignal']) &
                        (dataframe['rsi'] > 60) &
                        (dataframe['close'] > dataframe['bb_middleband'])
                    ) |
                    # SSL channel reversal
                    (
                        (dataframe['ssl_up'] < dataframe['ssl_down']) &
                        (dataframe['close'] > dataframe['bb_middleband']) &
                        (dataframe['rsi'] > 50)
                    )
                )
                |
                # 💰 PROFIT PROTECTION SELLS
                (
                    # Protect profits in any market condition
                    (dataframe['close'] > dataframe['ema_12'] * 1.02) &
                    (dataframe['rsi'] > 65) &
                    (dataframe['volume'] > dataframe['volume_mean_slow'] * 1.2)
                )
            ) &
            (dataframe['volume'] > 0),  # Always ensure volume > 0
            'sell'
        ] = 1
        
        return dataframe
    def leverage_tier(self, pair: str, current_time: datetime, current_rate: float) -> float:
        """
        Dynamic leverage based on market conditions and volatility
        Note: This is for futures trading platforms that support leverage
        """
        try:
            dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
            latest = dataframe.iloc[-1].squeeze()
            
            # Base leverage
            base_leverage = 1.0
            
            # Market direction adjustment
            if latest['market_direction'] == 1:  # Bull market
                base_leverage = 1.2
            elif latest['market_direction'] == -1:  # Bear market  
                base_leverage = 0.8
            else:  # Sideways
                base_leverage = 1.0
                
            # Volatility adjustment
            atr_pct = latest.get('atr', 0) / current_rate if current_rate > 0 else 0
            if atr_pct > 0.05:  # High volatility
                base_leverage *= 0.7
            elif atr_pct < 0.02:  # Low volatility
                base_leverage *= 1.1
                
            # Volume confirmation
            volume_ratio = latest['volume'] / latest['volume_mean_slow']
            if volume_ratio > 2:  # High volume
                base_leverage *= 1.1
            elif volume_ratio < 0.5:  # Low volume
                base_leverage *= 0.8
                
            return max(0.1, min(base_leverage, 2.0))  # Cap between 0.1 and 2.0
            
        except Exception:
            return 1.0  # Default leverage

    def confirm_trade_entry(self, pair: str, order_type: str, amount: float,
                           rate: float, time_in_force: str, current_time: datetime,
                           **kwargs) -> bool:
        """
        Advanced trade entry confirmation with risk management
        """
        try:
            dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
            latest = dataframe.iloc[-1].squeeze()
            
            # Market condition checks
            market_dir = latest['market_direction']
            
            # Risk score calculation
            risk_score = 0
            
            # Volume spike risk
            volume_ratio = latest['volume'] / latest['volume_mean_slow']
            if volume_ratio > 3:
                risk_score += 30
            elif volume_ratio > 2:
                risk_score += 15
                
            # Volatility risk
            candle_size = abs(latest['close'] - latest['open']) / latest['open']
            if candle_size > 0.05:
                risk_score += 25
            elif candle_size > 0.03:
                risk_score += 10
                
            # RSI extremes
            if latest['rsi'] < 10 or latest['rsi'] > 90:
                risk_score += 20
                
            # Market timing risk
            hour = current_time.hour
            if hour in [0, 1, 2, 23]:  # Low liquidity hours
                risk_score += 15
                
            # Bear market additional caution
            if market_dir == -1:
                risk_score += 10
                
            # Reject trade if risk score too high
            if risk_score > 60:
                return False
                
            # Additional quality checks
            quality_score = 0
            
            # Technical setup quality
            if latest['close'] < latest['bb_lowerband']:
                quality_score += 20
            if latest['rsi'] < 30:
                quality_score += 15
            if latest['ssl_up'] > latest['ssl_down']:
                quality_score += 10
                
            # Trend alignment
            if market_dir == 1 and latest['ema_50'] > latest['ema_200']:
                quality_score += 15
                
            # Require minimum quality score
            return quality_score >= 25
            
        except Exception:
            # If analysis fails, err on side of caution
            return True

    def confirm_trade_exit(self, pair: str, trade: Trade, order_type: str, amount: float,
                          rate: float, time_in_force: str, sell_reason: str,
                          current_time: datetime, **kwargs) -> bool:
        """
        Confirm trade exit with additional logic
        """
        try:
            dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
            latest = dataframe.iloc[-1].squeeze()
            
            # Always allow stoploss and ROI exits
            if sell_reason in ['stoploss', 'roi']:
                return True
                
            # Market-specific exit confirmation
            market_dir = latest['market_direction']
            
            # In bear markets, be more aggressive with exits
            if market_dir == -1:
                return True
                
            # In bull markets, allow more room for growth
            if market_dir == 1 and trade.calc_profit_ratio(rate) < 0.02:
                # Don't exit early in bull market unless good reason
                if latest['rsi'] < 70 and latest['close'] < latest['bb_upperband']:
                    return False
                    
            return True
            
        except Exception:
            return True

# Additional utility functions for enhanced strategy performance

def calculate_support_resistance(dataframe, window=20):
    """
    Calculate dynamic support and resistance levels
    """
    # Rolling max/min for resistance/support
    dataframe['resistance'] = dataframe['high'].rolling(window=window).max()
    dataframe['support'] = dataframe['low'].rolling(window=window).min()
    
    # Pivot points
    dataframe['pivot'] = (dataframe['high'] + dataframe['low'] + dataframe['close']) / 3
    dataframe['r1'] = 2 * dataframe['pivot'] - dataframe['low']
    dataframe['s1'] = 2 * dataframe['pivot'] - dataframe['high']
    
    return dataframe

def market_structure_analysis(dataframe):
    """
    Analyze market structure for better entries
    """
    # Higher highs and higher lows detection
    dataframe['higher_high'] = (
        (dataframe['high'] > dataframe['high'].shift(1)) &
        (dataframe['high'].shift(1) > dataframe['high'].shift(2))
    )
    
    dataframe['higher_low'] = (
        (dataframe['low'] > dataframe['low'].shift(1)) &
        (dataframe['low'].shift(1) > dataframe['low'].shift(2))
    )
    
    # Lower highs and lower lows
    dataframe['lower_high'] = (
        (dataframe['high'] < dataframe['high'].shift(1)) &
        (dataframe['high'].shift(1) < dataframe['high'].shift(2))
    )
    
    dataframe['lower_low'] = (
        (dataframe['low'] < dataframe['low'].shift(1)) &
        (dataframe['low'].shift(1) < dataframe['low'].shift(2))
    )
    
    return dataframe

# Performance monitoring and statistics
class StrategyStats:
    """
    Track strategy performance metrics
    """
    def __init__(self):
        self.total_trades = 0
        self.winning_trades = 0
        self.losing_trades = 0
        self.bull_market_trades = 0
        self.bear_market_trades = 0
        self.sideways_market_trades = 0
        
    def update_trade(self, profit, market_direction):
        self.total_trades += 1
        if profit > 0:
            self.winning_trades += 1
        else:
            self.losing_trades += 1
            
        if market_direction == 1:
            self.bull_market_trades += 1
        elif market_direction == -1:
            self.bear_market_trades += 1
        else:
            self.sideways_market_trades += 1
            
    def get_win_rate(self):
        return self.winning_trades / self.total_trades if self.total_trades > 0 else 0
        
    def get_market_distribution(self):
        total = self.total_trades
        if total == 0:
            return {"bull": 0, "bear": 0, "sideways": 0}
        return {
            "bull": self.bull_market_trades / total,
            "bear": self.bear_market_trades / total,
            "sideways": self.sideways_market_trades / total
        }

# Configuration templates for different market conditions
STRATEGY_CONFIGS = {
    "aggressive": {
        "max_open_trades": 5,
        "buy_conditions_enabled": 10,
        "roi_multiplier": 1.2,
        "risk_tolerance": "high"
    },
    "conservative": {
        "max_open_trades": 2,
        "buy_conditions_enabled": 6,
        "roi_multiplier": 0.8,
        "risk_tolerance": "low"
    },
    "balanced": {
        "max_open_trades": 3,
        "buy_conditions_enabled": 8,
        "roi_multiplier": 1.0,
        "risk_tolerance": "medium"
    }
}

# Additional parameters for the strategy class
# (These would be added to the main class)

# Additional buy conditions that were referenced
buy_condition_extreme_dip_enable = CategoricalParameter([True, False], default=False, space='buy', optimize=False, load=True)
buy_condition_breakout_enable = CategoricalParameter([True, False], default=True, space='buy', optimize=False, load=True)  
buy_condition_diamond_hands_enable = CategoricalParameter([True, False], default=True, space='buy', optimize=False, load=True)

# Advanced parameters for fine-tuning
buy_extreme_rsi_threshold = DecimalParameter(15.0, 25.0, default=20.0, space='buy', decimals=1, optimize=False, load=True)
buy_breakout_volume_threshold = DecimalParameter(1.2, 2.0, default=1.5, space='buy', decimals=1, optimize=False, load=True)
buy_diamond_hands_dip_threshold = DecimalParameter(1.02, 1.08, default=1.05, space='buy', decimals=2, optimize=False, load=True)

# Sell parameters for fine-tuning
sell_bull_profit_threshold = DecimalParameter(1.01, 1.03, default=1.015, space='sell', decimals=3, optimize=False, load=True)
sell_bear_profit_threshold = DecimalParameter(1.003, 1.01, default=1.005, space='sell', decimals=3, optimize=False, load=True)
sell_sideways_profit_threshold = DecimalParameter(1.005, 1.02, default=1.001, space='sell', decimals=3, optimize=False, load=True)