# source: https://raw.githubusercontent.com/mlsys-io/PortfolioBench/fb47ffc7b262e80c8b0b2f9bc0445b210cb475ec/strategy/EmaCrossStrategy.py
from datetime import datetime

from freqtrade.strategy import (
    IntParameter,
    IStrategy,
)
from pandas import DataFrame
from technical import qtpylib

from alpha.SimpleEmaFactors import EmaAlpha


class Github_mlsys_io_PortfolioBench__EmaCrossStrategy__20260414_143359(IStrategy):
    """
    Strategy adapted from paper: http://arxiv.org/abs/2511.00665 
    """

    # Strategy interface version - allow new iterations of the strategy interface.
    # Check the documentation or the Sample strategy to get the latest version.
    INTERFACE_VERSION = 3

    # Can this strategy go short?
    can_short: bool = False

    # Minimal ROI designed for the strategy.
    # This attribute will be overridden if the config file contains "minimal_roi".
    minimal_roi = {}

    # Optimal stoploss designed for the strategy.
    # This attribute will be overridden if the config file contains "stoploss".
    stoploss = -99

    # Trailing stoploss
    trailing_stop = False
    # trailing_only_offset_is_reached = False
    # trailing_stop_positive = 0.01
    # trailing_stop_positive_offset = 0.0  # Disabled / not configured

    # Run "populate_indicators()" only for new candle.
    process_only_new_candles = True

    # These values can be overridden in the config.
    use_exit_signal = True
    exit_profit_only = False
    ignore_roi_if_entry_signal = False
    startup_candle_count: int = 30

    ema_fast_length = IntParameter(5, 15, default=12, space="buy")
    ema_slow_length = IntParameter(20, 30, default=26, space="buy")
    ema_exit_length = IntParameter(5, 10, default=6, space="sell")

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        # dataframe["ema_fast"] = ta.EMA(dataframe, timeperiod=self.ema_fast_length.value)
        # dataframe["ema_slow"] = ta.EMA(dataframe, timeperiod=self.ema_slow_length.value)
        # dataframe["ema_exit"] = ta.EMA(dataframe, timeperiod=self.ema_exit_length.value)
        # dataframe["mean-volume"] = dataframe["volume"].rolling(20).mean()
        dataframe = EmaAlpha(dataframe, metadata).process()
        return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe.loc[
            (
                (qtpylib.crossed_above(dataframe["ema_fast"], dataframe["ema_slow"]))
                & (dataframe["mean-volume"] > 0.75)
            ),
            "enter_long",
        ] = 1

        return dataframe

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe.loc[
            (qtpylib.crossed_below(dataframe["ema_exit"], dataframe["ema_fast"])), "exit_long"
        ] = 1
        return dataframe

    def confirm_trade_entry(self, pair: str, order_type: str, amount: float, rate: float,
                            time_in_force: str, current_time: datetime, entry_tag: str | None,
                            side: str, **kwargs) -> bool:
        dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
        last_close = dataframe.iloc[-1]["close"]
        max_deviation = 0.01  # 1% deviation allowed
        deviation = abs(rate - last_close) / last_close

        if deviation > max_deviation:
            return False

        return True