# source: https://raw.githubusercontent.com/Vinylether/okx/71f225cd973d057f7b1f3c1a95c3ac5a6674df76/user_data/strategies/OkxFutures15mProtectedShortBreakout.py
from datetime import datetime

from pandas import DataFrame

import talib.abstract as ta

from freqtrade.persistence import Trade
from freqtrade.strategy import IStrategy


class Github_Vinylether_okx__OkxFutures15mProtectedShortBreakout__20260601_075127(IStrategy):
    INTERFACE_VERSION = 3

    can_short = True
    timeframe = "15m"
    startup_candle_count = 420
    process_only_new_candles = True

    minimal_roi = {"0": 0.50}
    stoploss = -0.055

    trailing_stop = False
    use_exit_signal = True
    exit_profit_only = False
    ignore_roi_if_entry_signal = False

    donchian_window = 48
    ema_window = 96
    adx_min = 12
    atr_min = 0.0015
    atr_max = 0.04
    volume_mult = 0.5
    exit_minutes = 960
    take_profit = 0.20

    protections = [
        {
            "method": "CooldownPeriod",
            "stop_duration_candles": 8,
        },
        {
            "method": "StoplossGuard",
            "lookback_period_candles": 96,
            "trade_limit": 2,
            "stop_duration_candles": 96,
            "only_per_pair": True,
            "only_per_side": True,
        },
        {
            "method": "MaxDrawdown",
            "lookback_period_candles": 384,
            "trade_limit": 20,
            "stop_duration_candles": 96,
            "max_allowed_drawdown": 0.08,
        },
    ]

    order_types = {
        "entry": "limit",
        "exit": "limit",
        "stoploss": "market",
        "stoploss_on_exchange": False,
    }

    order_time_in_force = {
        "entry": "GTC",
        "exit": "GTC",
    }

    def leverage(
        self,
        pair: str,
        current_time,
        current_rate: float,
        proposed_leverage: float,
        max_leverage: float,
        entry_tag: str | None,
        side: str,
        **kwargs,
    ) -> float:
        return min(2.0, max_leverage)

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe["donchian_low"] = (
            dataframe["low"].rolling(self.donchian_window).min().shift(1)
        )
        dataframe["ema"] = ta.EMA(dataframe, timeperiod=self.ema_window)
        dataframe["adx"] = ta.ADX(dataframe, timeperiod=14)
        dataframe["atr"] = ta.ATR(dataframe, timeperiod=14)
        dataframe["atr_pct"] = dataframe["atr"] / dataframe["close"]
        dataframe["volume_mean_48"] = dataframe["volume"].rolling(48).mean()
        return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe.loc[
            (
                (dataframe["volume"] > 0)
                & (dataframe["volume"] > dataframe["volume_mean_48"] * self.volume_mult)
                & (dataframe["atr_pct"] > self.atr_min)
                & (dataframe["atr_pct"] < self.atr_max)
                & (dataframe["adx"] > self.adx_min)
                & (dataframe["close"] < dataframe["donchian_low"])
                & (dataframe["close"] < dataframe["ema"])
            ),
            "enter_short",
        ] = 1
        return dataframe

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        return dataframe

    def custom_exit(
        self,
        pair: str,
        trade: Trade,
        current_time: datetime,
        current_rate: float,
        current_profit: float,
        **kwargs,
    ) -> str | bool | None:
        if current_profit >= self.take_profit:
            return "take_profit"
        if (current_time - trade.open_date_utc).total_seconds() >= self.exit_minutes * 60:
            return "time_exit"
        return None
