"""Simulazione LEVA 1x/2x/3x su COMBO (TP01+GTAA) e TP01-solo, da $2k e $5k.

Leva modellata onestamente: ritorno_giorno = L*r - (L-1)*financing/252 (costo del nozionale preso a
prestito ~8%/anno blended: perp funding crypto + margin IB). MaxDD calcolato sul PERCORSO LEVATO REALE
(non scalato: il compounding peggiora il DD oltre ×L). Check RUINA/margin-call: se l'equity tocca la
soglia di liquidazione (perdita cumulata >= 1/L del picco -> margin call).

CLAUDE.md: la leva NON e' la scorciatoia; raddoppia (e oltre) il drawdown. Caso base = 1x.
"""
import sys
from pathlib import Path
import numpy as np, pandas as pd
ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(ROOT)); sys.path.insert(0, str(ROOT / "scripts" / "research"))
from combo_yearly_report import combo_daily
from src.portfolio.sleeves import _tp01_returns

FIN = 0.08   # costo finanziamento annuo sul nozionale preso a prestito (perp funding + margin IB), blended


def lever(ret: pd.Series, L: float) -> pd.Series:
    return L * ret - (L - 1) * FIN / 252.0


def analyze(ret: pd.Series, L: float, cap0: float):
    r = lever(ret.dropna().sort_index(), L)
    curve = cap0 * np.cumprod(1 + r.values)
    peak = np.maximum.accumulate(curve)
    dd = (peak - curve) / peak
    maxdd = float(np.max(dd))
    # margin call: perdita dal picco >= 1/L (a leva L, un drawdown del sottostante di 1/L azzera il margine)
    ruin = bool(np.any(dd >= 1.0 / L - 1e-9)) if L > 1 else False
    yrs = (r.index[-1] - r.index[0]).days / 365.25
    cagr = (curve[-1] / cap0) ** (1 / yrs) - 1 if yrs > 0 and curve[-1] > 0 else -1
    sh = float(r.mean() / r.std() * np.sqrt(252)) if r.std() > 0 else 0
    worst_y = min((np.prod(1 + r[r.index.year == y].values) - 1) for y in sorted(set(r.index.year)))
    return dict(L=L, final=float(curve[-1]), cagr=cagr, maxdd=maxdd, sharpe=sh, ruin=ruin,
                worst_y=float(worst_y), perday=(curve[-1] - cap0) / yrs / 365)


def main():
    print("=" * 92)
    print("  LEVA su COMBO vs TP01-solo — percorso reale (fin 8%/anno sul prestito), 2019-2026 (~7.3y)")
    print("=" * 92)
    strat = {"COMBO TP01+GTAA": combo_daily(), "TP01 solo (crypto)": _tp01_returns()}
    for nm, r in strat.items():
        if r.index.tz is None:
            r.index = r.index.tz_localize("UTC")
    for cap0 in (2000.0, 5000.0):
        print(f"\n  ##### capitale iniziale ${cap0:,.0f} #####")
        print(f"  {'strategia':20}{'leva':>5}{'CAGR':>8}{'MaxDD':>8}{'Sharpe':>8}{'pegg.anno':>10}{'$/giorno':>10}{'eq fine':>12}{'  RUINA?':>9}")
        for nm, r in strat.items():
            for L in (1, 2, 3):
                a = analyze(r, L, cap0)
                flag = "MARGIN-CALL" if a["ruin"] else "ok"
                print(f"  {nm:20}{L:>4}x{a['cagr']*100:>7.1f}%{a['maxdd']*100:>7.1f}%{a['sharpe']:>8.2f}"
                      f"{a['worst_y']*100:>9.1f}%{('$'+format(a['perday'],',.0f')):>10}{('$'+format(a['final'],',.0f')):>12}{flag:>11}")
    # per-anno del COMBO a 2x e 3x da 2k (dettaglio)
    print(f"\n  ##### COMBO per-anno a leva, da $2.000 #####")
    cd = combo_daily()
    for L in (2, 3):
        print(f"\n  --- COMBO {L}x ---")
        print(f"  {'anno':6}{'PnL %':>9}{'MaxDD %':>9}{'eq fine':>11}")
        eq = 2000.0; r = lever(cd, L)
        for y in sorted(set(r.index.year)):
            ry = r[r.index.year == y]
            if len(ry) < 5: continue
            eq0 = eq; curve = eq0 * np.cumprod(1 + ry.values); peak = np.maximum.accumulate(curve)
            ddp = float(np.max((peak - curve) / peak)); eq = float(curve[-1])
            print(f"  {y:<6}{(eq/eq0-1)*100:>+8.1f}%{ddp*100:>8.1f}%{('$'+format(eq,',.0f')):>11}")


if __name__ == "__main__":
    main()
