import freqtrade.vendor.qtpylib.indicators as qtpylib
import talib.abstract as ta
from functools import reduce
from freqtrade.strategy import IStrategy
from pandas import DataFrame

class MeanReversionStrategy(IStrategy):
    INTERFACE_VERSION = 2

    # Configuración para Hyperopt
    minimal_roi = {"0": 0.10}
    stoploss = -0.03
    timeframe = '1m'

    # Hyperopt parameters
    @property
    def hyperopt_parameters(self):
        return [
            # Bollinger Bands parameters
            {"name": "bbands_timeperiod", "type": "int", "min": 10, "max": 30},
            {"name": "bbands_devup", "type": "float", "min": 1.5, "max": 3.5, "decimals": 1},
            {"name": "bbands_devdown", "type": "float", "min": 1.5, "max": 3.5, "decimals": 1},
            # RSI parameters
            {"name": "rsi_buy", "type": "int", "min": 20, "max": 40},
            {"name": "rsi_sell", "type": "int", "min": 60, "max": 80}
        ]

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        # Asegurarse de que los parámetros de hyperopt se utilicen para los indicadores
        bbands_timeperiod = self.config.get('bbands_timeperiod', 20)
        bbands_devup = self.config.get('bbands_devup', 2.0)
        bbands_devdown = self.config.get('bbands_devdown', 2.0)
        
        # Bollinger Bands
        bollinger = ta.BBANDS(dataframe, timeperiod=bbands_timeperiod,
                              nbdevup=bbands_devup,
                              nbdevdn=bbands_devdown)
        dataframe['bb_upperband'] = bollinger['upperband']
        dataframe['bb_middleband'] = bollinger['middleband']
        dataframe['bb_lowerband'] = bollinger['lowerband']
        
        # RSI
        dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14)
        
        return dataframe

    def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        conditions = []
        rsi_buy = self.config.get('rsi_buy', 30)
        
        # Buy when price is below lower Bollinger Band and RSI is below rsi_buy
        conditions.append(dataframe['close'] < dataframe['bb_lowerband'])
        conditions.append(dataframe['rsi'] < rsi_buy)
        
        dataframe.loc[
            reduce(lambda x, y: x & y, conditions),
            'buy'] = 1
        
        return dataframe

    def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        conditions = []
        rsi_sell = self.config.get('rsi_sell', 70)
        
        # Sell when price is above upper Bollinger Band and RSI is above rsi_sell
        conditions.append(dataframe['close'] > dataframe['bb_upperband'])
        conditions.append(dataframe['rsi'] > rsi_sell)
        
        dataframe.loc[
            reduce(lambda x, y: x & y, conditions),
            'sell'] = 1
        
        return dataframe
