"""
================================================================================
Strategy **D015** — ``s015``
================================================================================

Theme
-----
**Low vol-of-vol ratio + mild VRP (short straddle).**

Economic idea
-------------
When **VVIX/VIX** is **below 1.03**, the embedded uncertainty about volatility is low
relative to VIX. Paired with ``iv_atm(30) > 1.08 * rv21``, this sells straddle premium in
a “calm about calm” regime. Distinct gate from D014 (opposite tail of ratio).

Entry
-----
1. ``vvix_over_vix < 1.03`` (must exist).
2. ``iv_atm(30) > 1.08 * rv21``.
3. ``VIX`` between **12 and 18**.
4. ``n_contracts[i] >= 90``.

Exit
----
Short straddle 30 DTE, hold **6** 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": "D015", "theme": "vol_of_vol", "title": "Low VVIX/VIX + mild VRP short straddle"}

HOLD_SESSIONS = 6
TRADE_KIND = "ss"
TRADE_PARAMS = (30,)


def wants_entry(i: int, row, ch: OptionChain, spy: float, ctx: ResearchContext) -> bool:
    r = ctx.vvix_over_vix(i)
    if r is None or r >= 1.03:
        return False
    vx = ctx.vix(i)
    if not math.isfinite(vx) or vx < 12.0 or vx > 18.0:
        return False
    rv = float(row["rv21"]) if pd.notna(row.get("rv21")) else float("nan")
    if not math.isfinite(rv) or rv <= 0:
        return False
    iv = ctx.iv_atm_dte(i, 30)
    if iv is None or iv <= 1.08 * rv:
        return False
    if ctx.chain_contracts(i) < 90:
        return False
    if not ch.contracts:
        return False
    _ = spy
    return True
