"""Single-factor D48 experiment: require an elevated short-horizon RV regime."""

from __future__ import annotations

import sys
from pathlib import Path

import numpy as np
from pandas import DataFrame

VOLATILITY_STRATEGY_DIR = Path(__file__).resolve().parents[1] / "volatility_breakout"
if str(VOLATILITY_STRATEGY_DIR) not in sys.path:
    sys.path.insert(0, str(VOLATILITY_STRATEGY_DIR))

from v5_d48_riskcap import VolatilityBreakoutRiskCap  # noqa: E402


class VolatilityBreakoutRvWarmupBaseline(VolatilityBreakoutRiskCap):
    """Unchanged RiskCap with the same startup window as the RV variant."""

    startup_candle_count = 7 * 24 * 12 + 12 + 1

    def version(self) -> str:
        return "research-d48-riskcap-rv7d-warmup-baseline"


class VolatilityBreakoutRvFloorV1(VolatilityBreakoutRiskCap):
    """Keep D48 entries only when 1h RV exceeds its rolling 40th percentile."""

    rv_bars = 12
    rv_percentile_window = 7 * 24 * 12
    rv_percentile_min_periods = rv_percentile_window // 4
    rv_percentile_floor = 0.40
    startup_candle_count = rv_percentile_window + rv_bars + 1

    def version(self) -> str:
        return "research-d48-riskcap-rv7d-floor40-v1"

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe = super().populate_indicators(dataframe, metadata)

        close_return = np.log(dataframe["close"] / dataframe["close"].shift(1))
        dataframe["rv_fast_1h"] = (
            close_return.pow(2)
            .rolling(self.rv_bars, min_periods=self.rv_bars)
            .sum()
            .pow(0.5)
        )
        dataframe["rv_fast_percentile_7d"] = dataframe["rv_fast_1h"].rolling(
            self.rv_percentile_window,
            min_periods=self.rv_percentile_min_periods,
        ).rank(pct=True)
        return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe = super().populate_entry_trend(dataframe, metadata)
        rv_ok = dataframe["rv_fast_percentile_7d"] > self.rv_percentile_floor
        dataframe.loc[~rv_ok, ["enter_long", "enter_short"]] = 0
        return dataframe
