"""
================================================================================
Strategy **D006** — ``s006``
================================================================================

Theme
-----
**Drawdown from 52-week close proxy + fear mean-reversion (short put spread).**

Economic idea
-------------
When SPY is materially below its trailing **252-session max close** (``dist_roll_high_252``
very negative), markets have often already repriced left-tail risk. This sleeve sells a
**put vertical** (defined risk) only when **VIX is falling** over five sessions, i.e.
fear is not still accelerating. This is distinct from “always sell puts in a dip”.

Entry
-----
1. ``dist_roll_high_252 <= -0.08`` (at least **8%** below the rolling max close).
2. ``vix_chg_5 < -0.5`` (five-session drop in VIX close).
3. ``VIX <= 35`` (avoid extreme panic where verticals gap).
4. ``n_contracts[i] >= 90``.

Exit
----
Put credit spread: short **-0.24** delta put, long put **5** points lower, ~35 DTE,
hold **12** sessions.
================================================================================
"""

from __future__ import annotations

import math

import pandas as pd

from RenTech.core.options_data_loader import OptionChain
from RenTech.strategy_stack.diverse_theta_strategies_v1.context import ResearchContext

META = {
    "sid": "D006",
    "theme": "drawdown_contrarian",
    "title": "Deep vs 252d high + VIX falling put credit spread",
}

HOLD_SESSIONS = 12
TRADE_KIND = "vert"
TRADE_PARAMS = (35, -0.24, 5.0)


def wants_entry(i: int, row: pd.Series, ch: OptionChain, spy: float, ctx: ResearchContext) -> bool:
    d = row.get("dist_roll_high_252")
    dv = row.get("vix_chg_5")
    if d is None or pd.isna(d) or float(d) > -0.08:
        return False
    if dv is None or pd.isna(dv) or float(dv) >= -0.5:
        return False
    vx = ctx.vix(i)
    if not math.isfinite(vx) or vx > 35.0:
        return False
    if ctx.chain_contracts(i) < 90:
        return False
    if not ch.contracts:
        return False
    _ = spy
    return True
