# Filename: CombinedVwapMomentumStrategy.py

from freqtrade.strategy import IStrategy
from pandas import DataFrame
import talib.abstract as ta
import numpy as np

class CombinedVwapMomentumStrategy(IStrategy):
    """
    Estrategia combinada de tendencia, VWAP, momentum y volatilidad.
    """

    timeframe = "5m"

    minimal_roi = {"0": 0.03}
    stoploss = -0.015
    trailing_stop = False
    position_adjustment_enable = False

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """
        Calcula indicadores.
        """
        if dataframe.empty:
            return dataframe

        # VWAP
        typical_price = (dataframe["high"] + dataframe["low"] + dataframe["close"]) / 3
        cumulative_tp_vol = (typical_price * dataframe["volume"]).cumsum()
        cumulative_vol = dataframe["volume"].cumsum()
        dataframe["vwap_middleband"] = cumulative_tp_vol / cumulative_vol

        # SMA 200
        dataframe["200sma"] = ta.SMA(dataframe, timeperiod=200)

        # RSI
        dataframe["rsi"] = ta.RSI(dataframe, timeperiod=14)

        # ROCR
        dataframe["rocr"] = ta.ROCR(dataframe, timeperiod=10)

        # OBV
        dataframe["obv"] = ta.OBV(dataframe, volume=dataframe["volume"])
        dataframe["obv_diff"] = dataframe["obv"].diff()

        # ATR
        dataframe["atr"] = ta.ATR(dataframe, timeperiod=14)

        # Chopiness Index
        hl_range = dataframe["high"] - dataframe["low"]
        max_close = dataframe["close"].rolling(window=14).max()
        min_close = dataframe["close"].rolling(window=14).min()
        chop = 100 * np.log10(
            hl_range.rolling(window=14).sum() /
            (max_close - min_close)
        ) / np.log10(14)
        dataframe["chopiness"] = chop

        # Tamaño del cuerpo de la vela
        dataframe["body_size"] = (dataframe["close"] - dataframe["open"]).abs()
        dataframe["range_size"] = dataframe["high"] - dataframe["low"]

        # Limpieza de NaNs
        dataframe.fillna(method="ffill", inplace=True)
        dataframe.fillna(0, inplace=True)

        return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """
        Señal de entrada.
        """
        dataframe["enter_long"] = 0

        dataframe.loc[
            (
                (dataframe["close"] > dataframe["200sma"]) &
                (dataframe["close"].shift(1) < dataframe["vwap_middleband"].shift(1)) &
                (dataframe["close"] > dataframe["vwap_middleband"]) &
                (
                    (dataframe["rsi"] < 35) |
                    (dataframe["rocr"] > 1.005)
                ) &
                (dataframe["obv_diff"] > 0) &
                (dataframe["body_size"] > (dataframe["range_size"] * 0.4)) &
                (dataframe["chopiness"] < 50)
            ),
            "enter_long"
        ] = 1

        return dataframe

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """
        Señal de salida.
        """
        dataframe["exit_long"] = 0

        dataframe.loc[
            (
                (dataframe["rsi"] > 65) |
                (
                    (dataframe["close"].shift(1) > dataframe["vwap_middleband"].shift(1)) &
                    (dataframe["close"] < dataframe["vwap_middleband"])
                )
            ),
            "exit_long"
        ] = 1

        return dataframe
