# source: https://raw.githubusercontent.com/AlexEisie/GeniusTraderTaffy/782b201c5a48e7b21748de9d631ae9f0ef369154/strategies/PanicPounce2.py
# directory_url: https://github.com/AlexEisie/GeniusTraderTaffy/blob/main/strategies/
# User: AlexEisie
# Repository: GeniusTraderTaffy
# --------------------"""
Github_AlexEisie_GeniusTraderTaffy__PanicPounce2__20260819_144029 — 波动率闸门恐慌接刀 v2（现货 / 只做多 / 1h / OKX）
====================================================================
v1 教训与 v2 修正（见 analysis/dip_regime.py 的事件研究，保守成交假设）：

  v1 败因：止盈 4.5% / 止损 8% —— 不对称方向反了。事件的收益分布
  右偏严重（暴跌后偶发 +10~20% 反弹），截掉右尾、保留左尾必亏。

  v2 结构（2026 年 79 个闸门事件，网格邻域稳健）：
    * 止盈 10%（骑住右尾）  * 止损 5%（砍掉左尾）  * 36h 强制离场
    * 单笔期望 +2.68%、胜率 ~60%（扣 0.2% 费后）
  波动率闸门：BTC 7 日年化波动率 >= 40% 才允许接刀。
    2026 年内：无闸门 +1.72%/笔 -> 40 闸门 +2.21% -> 50 闸门 +4.15%。
    取 40 保留足够频率；低波动平静期自动休眠。
  已证伪并排除的选项：
    * 放量下跌过滤（反效果，放量的刀更钝）
    * 挂深限价单等更低价（逆向选择，只有最烂的刀才成交）
    * 等反弹确认再进（错过均值回归的主要部分）

  事件在崩盘期高度聚集（2026-06 单月 54 次），max_open_trades
  与仓位划分天然限制单波暴露。
====================================================================
"""

import numpy as np
from pandas import DataFrame

import freqtrade.vendor.qtpylib.indicators as qtpylib
from freqtrade.strategy import DecimalParameter, IStrategy, merge_informative_pair


class Github_AlexEisie_GeniusTraderTaffy__PanicPounce2__20260819_144029(IStrategy):
    INTERFACE_VERSION = 3

    timeframe = "1h"
    can_short = False

    # 右偏分布：高目标骑右尾；2160 分钟(36h)后无条件离场
    minimal_roi = {
        "0": 0.10,
        "2160": -1,
    }

    stoploss = -0.05
    use_custom_stoploss = False
    trailing_stop = False

    process_only_new_candles = True
    use_exit_signal = False
    exit_profit_only = False
    ignore_roi_if_entry_signal = False

    # BTC 波动率需要 168h + 缓冲
    startup_candle_count = 220

    # ---------------- 可调参数 ----------------
    dip_ret24 = DecimalParameter(-0.16, -0.07, default=-0.10, decimals=2, space="buy", optimize=True)
    # 全史重放中 gate>=50 每年为正 (2023 +11%, 2024 +67%, 2025 +13%, 2026 +18%),
    # gate 40-50 段的边际已在 2025-2026 衰减为负, 只保留极端段
    btc_vol_gate = DecimalParameter(40.0, 60.0, default=50.0, decimals=0, space="buy", optimize=True)

    @property
    def protections(self):
        return [
            {"method": "CooldownPeriod", "stop_duration_candles": 4},
            {
                # 48h 内 5 次止损 -> 暂停 12h（无底崩盘断路器）
                "method": "StoplossGuard",
                "lookback_period_candles": 48,
                "trade_limit": 5,
                "stop_duration_candles": 12,
                "only_per_pair": False,
            },
        ]

    def informative_pairs(self):
        return [("BTC/USDT", "1h")]

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe["ret24"] = dataframe["close"].pct_change(24)
        bb = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
        dataframe["bb_lower"] = bb["lower"]

        # BTC 7 日年化波动率（政权闸门）
        btc = self.dp.get_pair_dataframe("BTC/USDT", "1h")
        btc = btc[["date", "close"]].copy()
        btc["btc_vol7"] = (
            btc["close"].pct_change().rolling(168, min_periods=100).std()
            * np.sqrt(24 * 365) * 100
        )
        dataframe = merge_informative_pair(
            dataframe, btc[["date", "btc_vol7"]], self.timeframe, "1h", ffill=True
        )
        dataframe.rename(columns={"btc_vol7_1h": "btc_vol7"}, inplace=True)
        return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe.loc[
            (dataframe["ret24"] < self.dip_ret24.value)
            & (dataframe["close"] < dataframe["bb_lower"])
            & (dataframe["btc_vol7"] >= self.btc_vol_gate.value)
            & (dataframe["volume"] > 0),
            ["enter_long", "enter_tag"],
        ] = (1, "panic_dip_v2")
        return dataframe

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

    plot_config = {
        "main_plot": {"bb_lower": {"color": "grey"}},
        "subplots": {
            "ret24": {"ret24": {"color": "purple"}},
            "btc_vol7": {"btc_vol7": {"color": "orange"}},
        },
    }
