from freqtrade.strategy import IStrategy
from freqtrade.persistence import Trade
import talib as ta
from pandas import DataFrame


class HeikinAshiStrategy(IStrategy):
    """
    Estrategia Heikin Ashi con DCA correcto:
    - Compra inicial si hay 1 vela verde tras 3 rojas.
    - Hasta 4 lotes en total añadiendo uno por cada nueva vela verde.
    - Sale en vela roja.
    """
    timeframe = '1m'
    minimal_roi = {
        "0": 0.006
    }
    stoploss = -0.004
    trailing_stop = False

    position_adjustment_enable = True

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        ha = self.heikin_ashi(dataframe)
        dataframe['ha_open'] = ha['open']
        dataframe['ha_close'] = ha['close']
        dataframe['ha_green'] = dataframe['ha_close'] > dataframe['ha_open']
        dataframe['ha_red'] = dataframe['ha_close'] < dataframe['ha_open']
        dataframe['rsi'] = ta.RSI(dataframe['close'], timeperiod=14)
        return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe['enter_long'] = (
            (dataframe['ha_green']) &
            (dataframe['ha_red'].shift(1)) &
            (dataframe['ha_red'].shift(2)) &
            (dataframe['ha_red'].shift(3)) & 
            (dataframe['rsi'] <= 40)
        ).astype('int')
        return dataframe

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        # dataframe['exit_long'] = dataframe['ha_red'].astype('int')
        dataframe['exit_long'] = (dataframe['rsi'] >= 65).astype('int')
        return dataframe

    def adjust_trade_position(self, trade: Trade, current_time, current_rate, current_profit, **kwargs):
        """
        Añade hasta 4 lotes si salen velas verdes.
        """
        # Obtener el dataframe actualizado
        dataframe, _ = self.dp.get_analyzed_dataframe(trade.pair, self.timeframe)
        if dataframe is None or dataframe.empty:
            return None
    
        row = dataframe.iloc[-1]
    
        # Contar cuántas compras ejecutadas hay
        num_entries = len([o for o in trade.orders if o.side == 'buy' and o.status == 'closed'])
    
        if num_entries >= 4:
            return None
    
        if row['ha_green']:
            print(f"[{current_time}] Añadiendo lote extra. Lote nº {num_entries + 1}")
            return 1
    
        return None

    def custom_stoploss(self, pair: str, trade: Trade, current_time, current_rate, current_profit, **kwargs) -> float:
        """
        Stoploss absoluto sobre el primer precio de entrada (no el promedio).
        """
        # Precio de la primera compra
        first_entry_price = sorted([o for o in trade.orders if o.side == 'buy' and o.status == 'closed'], key=lambda o: o.order_date)[0].price
    
        # Si el precio cae más del 0.4% desde el primer lote, cierra
        if current_rate <= first_entry_price * (1 - 0.004):
            return 0.01  # Ejecuta venta inmediata
        
        return 1  # Mantiene abierto



    @staticmethod
    def heikin_ashi(df: DataFrame) -> DataFrame:
        ha_df = DataFrame(index=df.index)
        ha_df['close'] = (df['open'] + df['high'] + df['low'] + df['close']) / 4
        ha_df['open'] = (df['open'] + df['close']) / 2

        ha_open = [ha_df['open'].iloc[0]]
        for i in range(1, len(df)):
            ha_open.append((ha_open[i - 1] + ha_df['close'].iloc[i - 1]) / 2)

        ha_df['open'] = ha_open
        ha_df['high'] = df[['high', 'open', 'close']].max(axis=1)
        ha_df['low'] = df[['low', 'open', 'close']].min(axis=1)
        return ha_df
