"""GIUDICE DEI CONTENDER — valuta un segnale candidato a livello PORTAFOGLIO vs TP01.

Per ogni (tf, sigfile): costruisce il BOOK 50/50 BTC+ETH del candidato (causale, netto fee),
e applica il gauntlet STRETTO vs TP01:
  - standalone: FULL Sh/DD, HOLD-OUT 2025-26 Sh/ret/DD, breadth per-anno (% anni positivi, rossi
    consecutivi), correlazione a TP01;
  - contributo al portafoglio: TP01-solo vs TP01+candidato a pesi 0.2/0.3/0.5 (Δ FULL e Δ HOLD).
VERDETTO WINNER se: (A) batte TP01 standalone (book FULL Sh>1.30, hold-out Sh>~0.25, breadth ok),
OPPURE (B) diversificatore robusto (corr bassa, alza il portafoglio su FULL E hold-out, breadth ok).

    uv run python scripts/portfolio/verify_contender.py 1d /tmp/beat_sig_0.py 12h /tmp/beat_sig_10.py ...
"""
from __future__ import annotations
import sys
import importlib.util
from pathlib import Path
PROJECT_ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(PROJECT_ROOT))
import numpy as np
import pandas as pd

from scripts.analysis.research_lab import load_tf, _net_series
from src.portfolio.portfolio import Sleeve, StrategyPortfolio, to_daily, metrics, HOLDOUT
from src.portfolio.sleeves import tp01_sleeve

TP01_FULL_SH = 1.30
TP01_HOLD_SH = 0.31


def load_signal(path):
    spec = importlib.util.spec_from_file_location("csig_" + Path(path).stem, path)
    m = importlib.util.module_from_spec(spec); spec.loader.exec_module(m)
    return m.signal


def book_perbar(signal, tf) -> pd.Series:
    s = {}
    for a in ("BTC", "ETH"):
        df = load_tf(a, tf)
        net, _, _, _ = _net_series(df, np.asarray(signal(df, a, tf), float))
        s[a] = pd.Series(net, index=pd.to_datetime(df["timestamp"], unit="ms", utc=True))
    J = pd.concat(s, axis=1, join="inner").fillna(0.0)
    return pd.Series(0.5 * J["BTC"].values + 0.5 * J["ETH"].values, index=J.index)


def breadth(daily):
    pre = daily[daily.index < HOLDOUT]
    yr = [float((1 + g).prod() - 1) for _, g in pre.groupby(pre.index.year)]
    consec = mx = 0
    for v in yr:
        consec = consec + 1 if v < 0 else 0; mx = max(mx, consec)
    return (sum(v > 0 for v in yr) / len(yr) if yr else 0.0), mx, yr


def main():
    args = sys.argv[1:]
    pairs = [(args[i], args[i + 1]) for i in range(0, len(args) - 1, 2)]
    tp = tp01_sleeve(1.0)
    tp_daily = tp.daily()
    base = StrategyPortfolio([tp01_sleeve(1.0)]).backtest()
    print("=" * 100)
    print(f"  GIUDICE CONTENDER vs TP01 (book FULL Sh {base['full']['sharpe']:.2f} / HOLD {base['holdout']['sharpe']:.2f})")
    print("=" * 100)

    winners = []
    for tf, sig in pairs:
        name = Path(sig).stem
        try:
            signal = load_signal(sig)
            pb = book_perbar(signal, tf)
            d = to_daily(pb)
        except Exception as e:
            print(f"\n  {name} ({tf}): ERRORE {type(e).__name__}: {str(e)[:80]}"); continue
        f = metrics(d); h = metrics(d[d.index >= HOLDOUT])
        J = pd.concat({"tp": tp_daily, "x": d}, axis=1, join="inner").dropna()
        corr = float(J["tp"].corr(J["x"])) if len(J) > 2 else float("nan")
        pct, consec, yr = breadth(d)
        print(f"\n  {name} ({tf})  BOOK 50/50")
        print(f"    standalone: FULL Sh {f['sharpe']:>5.2f} DD {f['maxdd']*100:>4.1f}% | HOLD Sh {h['sharpe']:>5.2f} ret {h['ret']*100:>+6.1f}% DD {h['maxdd']*100:>4.1f}%"
              f" | anni+ {pct*100:>3.0f}% rossi-consec {consec} | corr_TP01 {corr:+.2f} | turn n/a")
        # contributo al portafoglio
        contrib = []
        for w in (0.2, 0.3, 0.5):
            sl = Sleeve(name, w, lambda pb=pb: pb)
            bt = StrategyPortfolio([tp01_sleeve(1 - w), sl]).backtest()
            dF = bt["full"]["sharpe"] - base["full"]["sharpe"]
            dH = bt["holdout"]["sharpe"] - base["holdout"]["sharpe"]
            contrib.append((w, bt["full"]["sharpe"], dF, bt["holdout"]["sharpe"], dH))
            print(f"    +TP01 w{w:.0%}: FULL {bt['full']['sharpe']:.2f} ({dF:+.2f}) | HOLD {bt['holdout']['sharpe']:.2f} ({dH:+.2f})")
        breadth_ok = pct >= 0.6 and consec <= 1
        standalone_beats = f["sharpe"] > TP01_FULL_SH and h["sharpe"] > 0.25 and breadth_ok
        # diversificatore: corr<0.5, migliora FULL E hold del portafoglio ad almeno un peso, breadth ok
        improves = any(dF > 0.05 and dH > 0.0 for _, _, dF, _, dH in contrib)
        diversifier = (not np.isnan(corr) and corr < 0.5) and improves and breadth_ok
        verdict = "WINNER-standalone" if standalone_beats else ("WINNER-diversifier" if diversifier else "no")
        print(f"    -> {verdict}  (breadth_ok={breadth_ok}, standalone_beats={standalone_beats}, diversifier={diversifier})")
        if verdict.startswith("WINNER"):
            winners.append((name, tf, verdict))

    print("\n" + "=" * 100)
    print(f"  WINNERS: {len(winners)}")
    for n, tf, v in winners:
        print(f"    {n} ({tf}): {v}")
    if not winners:
        print("    nessuno batte TP01 con criterio onesto -> serve un'altra ondata.")


if __name__ == "__main__":
    main()
