"""SH01 EXIT policy 11 — disaster_wide_intrabar (COMPLETENESS PROBE).

Le 10 policy precedenti hanno tutte fallito. Diagnosi ricorrente:
 - close-confirm (02,08) ALLARGA la coda su momentum-continuation (caso live
   ETH 2026-06-05): il close corre oltre il livello.
 - intrabar fisso (01) cappa AL livello (worst limitato) ma degrada BTC anche a k=5.

QUESTA probe chiude il buco: intrabar cap MOLTO LARGO (k=6..12), gap-aware,
il cui UNICO scopo e' tagliare la coda catastrofica (la -14.9% ETH / il crash
live -15.6%) SENZA mai toccare i normali pullback. E' la domanda diretta:
"esiste un k cosi' largo che NON tocca BTC ma cappa la coda ETH?".

Anti-look-ahead: sl = entry - d*k*ATR14[i], congelato in open_trade (dati<=i);
levels restituisce il livello costante, fill gap-aware nell'engine. mode=intrabar
cappa AL livello (a differenza del close-confirm che lascia correre il close).

    cd /opt/docker/PythagorasGoal && uv run python scripts/analysis/sh01_exit_policies/11_disaster_wide_intrabar.py
"""
from __future__ import annotations

import sys

sys.path.insert(0, "/opt/docker/PythagorasGoal")

from scripts.analysis.sh01_exit_lab import (  # noqa: E402
    ExitPolicy, OOS_START_MS, load_sleeves, simulate,
)


class DisasterWideIntrabar(ExitPolicy):
    def __init__(self, k: float):
        self.k = float(k)
        self.name = f"disaster_wide_intrabar k={k:.1f}"

    def open_trade(self, ctx, i, d):
        atr = ctx["atr14"][i]
        entry = ctx["close"][i]
        sl = entry - d * self.k * atr if atr == atr and atr > 0 else None
        return {"sl": sl}

    def levels(self, ctx, i, d, j, st):
        return st["sl"], "intrabar"


BASELINE = {
    "BTC": {"train": dict(ret=127, dd=23, sharpe=2.09, worst=-5.5),
            "oos":   dict(ret=41, dd=8, sharpe=2.18, worst=-3.1)},
    "ETH": {"train": dict(ret=-26, dd=61, sharpe=-0.16, worst=-14.9),
            "oos":   dict(ret=143, dd=7, sharpe=3.60, worst=-4.6)},
}


def _row(tag, a, r):
    print(f"    {tag:<7s} {a}: ret={r['ret']:>+7.0f}% dd={r['dd']:>4.0f}% "
          f"shrp={r['sharpe']:>5.2f} worst={r['worst']:>+6.1f}% "
          f"stop={r['stop_rate']:>4.1f}% trades={r['trades']}")


def main():
    sleeves = load_sleeves()
    KS = [5.0, 6.0, 7.0, 8.0, 10.0, 12.0]

    print("=" * 78)
    print("TRAIN GRID (intrabar cap LARGO, fill gap-aware)")
    print("=" * 78)
    train = {}
    for k in KS:
        pol = DisasterWideIntrabar(k)
        row = {a: simulate(sleeves[a], pol, t_hi=OOS_START_MS) for a in ("BTC", "ETH")}
        train[k] = row
        print(f"  k={k:.1f}")
        _row("TRAIN", "BTC", row["BTC"])
        _row("TRAIN", "ETH", row["ETH"])

    b_btc, b_eth = BASELINE["BTC"]["train"], BASELINE["ETH"]["train"]
    improving = []
    for k in KS:
        bt, et = train[k]["BTC"], train[k]["ETH"]
        eth_ok = (et["sharpe"] > b_eth["sharpe"] and et["dd"] < b_eth["dd"]
                  and et["worst"] > b_eth["worst"])
        btc_ok = (bt["sharpe"] >= 0.95 * b_btc["sharpe"]
                  and bt["ret"] >= 0.80 * b_btc["ret"])
        if eth_ok and btc_ok:
            improving.append(k)
        print(f"  k={k:.1f} ETH_ok={eth_ok} BTC_ok={btc_ok} "
              f"(BTC shrp={bt['sharpe']:.2f} ret={bt['ret']:.0f} | "
              f"ETH shrp={et['sharpe']:.2f} dd={et['dd']:.0f} worst={et['worst']:.1f})")
    print(f"\n  improving cells (train): {improving}")

    if not improving:
        print("  -> NESSUNA cella migliorativa: NO pulito, OOS non guardato.")
        return

    # plateau >=3 adiacenti? poi OOS
    print("\n  Plateau candidate -> OOS verdetto:")
    for k in improving:
        oos = {a: simulate(sleeves[a], DisasterWideIntrabar(k), t_lo=OOS_START_MS)
               for a in ("BTC", "ETH")}
        print(f"  k={k:.1f}")
        _row("OOS", "BTC", oos["BTC"])
        _row("OOS", "ETH", oos["ETH"])


if __name__ == "__main__":
    main()
