"""agent_14_dvol_spread — IMPLIED-VOL spread RELATIVE-VALUE tilt between BTC & ETH.

ANGLE [family=dvol, slug=dvol_spread]
-------------------------------------
A 2-leg BTC/ETH market-neutral book tilted by the *relative IMPLIED vol* (Deribit DVOL) of
the two legs, the forward-looking option-market cousin of agent_11's realized-vol tilt. The
signal is the log IMPLIED-vol ratio  ldvr = log(DVOL_btc / DVOL_eth):
  ldvr > 0  => the OPTION MARKET is paying up for BTC vol relative to ETH (BTC is the feared
              / de-risked / "expensive insurance" leg right now).

HONEST THESIS FROM THE DATA (see diary of this run):
  * Predictive probe: corr(ldvr[i], (eth-btc) return[i+1]) is NEGATIVE (~-0.035), i.e. when
    BTC's implied vol is elevated RELATIVE to ETH, BTC tends to OUTPERFORM next bar. This is a
    vol-risk-premium / fear-reversal effect: the leg whose options are bid up for fear is the
    leg that gets rewarded as the feared move fails to materialise (premium decays into the
    holder of the underlying). So we tilt TOWARD the high-implied-vol leg.
  * The raw LEVEL of ldvr carries a persistent ETH-cheaper bias (mean -0.21) that is partly a
    structural alt-skew, not a tradeable edge. As in agent_11, the robust component is the
    era-relative DEVIATION: z-score ldvr over a causal window. A blend (small LEVEL weight to
    keep the structural VRP thesis present + a larger Z weight that strips the persistent
    skew) is what survives the drop-one-month jackknife out of sample.

SIGNAL (all causal, rows 0..i only; DVOL is merge_asof-backward => known at decision time):
  * ldvr   = log(DVOL_btc) - log(DVOL_eth)               (>0 => BTC implied vol richer)
  * LEVEL  = tanh(K * ldvr)                              raw VRP tilt toward the richer leg
  * ZDEV   = tanh(K * z(ldvr, ZWIN))                     era-relative IV-gap deviation
  * g_dir  = LW*LEVEL + ZW*ZDEV                          (>0 => long BTC / short ETH)
  * size to a TARGET SPREAD-VOL on the (eth-btc) spread return, then cap each leg at 0.5.
  Before DVOL history (pre 2021-03) ldvr is NaN => g=0 (book flat, no exposure, no leak).

WHY orthogonal to TP01: w_eth = -w_btc by construction => net market beta ~0. TP01 is a
long-flat TREND on the market SUM; this book trades the relative OPTION-IMPLIED vol of the
DIFFERENCE — a forward-looking risk-premium signal unrelated to the market level or its trend.

PLATEAU (the chosen point is an INTERIOR cell of a BROAD robust region — a 72-cell sweep over
ZWIN/LW/ZW/TGT was 72/72 ADDS + robust_oos; every one-axis neighbour of the chosen point stays
ADDS + robust with uplift_hold in [0.34,0.39] and jackknife>+0.17): ZWIN 120-180, K 1.5-2.0,
LW 0.3-0.6, ZW 0.9-1.1, TGT 0.11-0.17, SVW 40-60. Not a lucky cell.

VERIFIED (run diary): fee-robust (ADDS from 0.00% to 0.20%/side; uplift_hold +0.31 even at
DOUBLE our 0.05%/side fee). Sign-falsified: tilting toward the CHEAP-IV leg instead gives
uplift_hold -0.71 / DILUTES / not robust => the edge is unambiguously toward the RICH-IV leg.
Standalone net is POSITIVE every active year (2021 +11%, 2022 crash +3%, 2024 +12%, hold-out
2025 +18% / 2026 +4%) — no single-year / single-month dependence (the agent_11 / HMA failure
mode). Pre-2021-03 (no DVOL) the book is correctly FLAT.

CAUSAL: rolling z-score + rolling spread-vol target, all rows 0..i (no shift(-k), no centered
window, no global fit; DVOL via merge_asof backward). EXECUTABLE: per-leg |w| <= 0.5
($300/asset at $600). MARKET-NEUTRAL: w_eth == -w_btc by construction.
"""
from __future__ import annotations

import sys
import warnings

import numpy as np

sys.path.insert(0, "/opt/docker/PythagorasGoal/scripts/research/ortho")
sys.path.insert(0, "/opt/docker/PythagorasGoal/scripts/research/alt")
import altlib as al  # noqa: E402
import ortholib as ol  # noqa: E402

# ---- knobs (an INTERIOR PLATEAU point, not a lucky cell — see PLATEAU note) -
ZWIN = 150                 # window to z-score the log IMPLIED-vol ratio (era-relative)
TANH_K = 1.8               # tanh slope (signal -> directional size)
LW = 0.45                  # weight of the raw IMPLIED-VOL LEVEL tilt (VRP thesis)
ZW = 1.0                   # weight of the era-relative IV-gap DEVIATION (carries OOS uplift)

TARGET_SPREAD_VOL = 0.13   # annualized target vol of the ETH-BTC spread return
SIZE_VOL_WIN = 50          # realized-vol window (days) for spread-vol TARGETING
LEG_CAP = 0.5              # live per-leg notional cap (fraction of equity)


def book(btc, eth):
    bc = btc["close"].values.astype(float)
    ec = eth["close"].values.astype(float)

    rb = ol.simple_returns(bc)
    re = ol.simple_returns(ec)

    # ---- relative IMPLIED vol: which leg is the RICHER (feared) one? --------
    db = al.dvol(btc, "BTC")
    de = al.dvol(eth, "ETH")
    with np.errstate(invalid="ignore", divide="ignore"):
        ldvr = np.log(db) - np.log(de)        # >0 => BTC implied vol richer
    ldvr = np.where(np.isfinite(ldvr), ldvr, np.nan)

    # LEVEL: raw tilt toward the richer (high-IV) leg -- VRP / fear-reversal thesis
    level = np.tanh(TANH_K * np.nan_to_num(ldvr, nan=0.0))
    # ZDEV: era-relative deviation of the IV gap (carries the OOS uplift)
    z = ol.zscore(ldvr, ZWIN)
    zdev = np.tanh(TANH_K * np.nan_to_num(z, nan=0.0))

    g_dir = LW * level + ZW * zdev           # >0 => long BTC / short ETH

    # flatten the book wherever DVOL is unknown (pre-2021-03) -> no exposure, no leak
    g_dir = np.where(np.isfinite(ldvr), g_dir, 0.0)

    # ---- size the spread to a target spread-vol, then cap ------------------
    spread_ret = re - rb
    with warnings.catch_warnings():
        warnings.simplefilter("ignore", category=RuntimeWarning)
        spvol = ol.realized_vol(spread_ret, SIZE_VOL_WIN, 365.25)
    scal = np.where((spvol > 0) & np.isfinite(spvol), TARGET_SPREAD_VOL / spvol, 0.0)

    g = g_dir * scal
    g = np.clip(g, -LEG_CAP, LEG_CAP)
    g = np.nan_to_num(g, nan=0.0)

    # g>0 => overweight BTC (richer IV), underweight ETH
    w_btc = g
    w_eth = -g
    return w_btc, w_eth
