"""Resoconto anno-per-anno CON PROTEZIONE (soft-guard DD -4%) — combo e singoli.

Mette combo (TP01+GTAA 50/50), TP01 e GTAA sulla STESSA griglia giorni-di-borsa (come dentro al
combo), applica la guardia-DD -4% a ciascuna serie (de-risk 1.0->0.4 a -4% dal picco, ri-rischia a
-1.6%), e per ogni anno riporta: NL (net liquidation da $2000), DD intra-anno, rendimento (=CAGR
1y), Sharpe. Riga TOT con CAGR e Sharpe complessivi.
"""
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))
from src.portfolio.sleeves import _tp01_returns
from src.portfolio.gtaa import gtaa_returns

INITIAL = 2000.0
ANN = np.sqrt(252.0)
DD_TRIG = 0.04


def dd_guard(r, dd_trigger=DD_TRIG):
    """De-risk: esposizione 1.0->0.4 se DD da picco > dd_trigger; ri-rischia a dd_trigger*0.4."""
    r = r.values; n = len(r); eq = np.cumprod(1 + r); pk = np.maximum.accumulate(eq)
    expo = np.ones(n); on = True
    for i in range(1, n):
        ddi = (pk[i - 1] - eq[i - 1]) / pk[i - 1]
        if ddi > dd_trigger: on = False
        if ddi < dd_trigger * 0.4: on = True
        expo[i] = 1.0 if on else 0.4
    return pd.Series(expo * r, index=_idx)  # set below


def legs_on_grid(wc=0.5):
    """TP01(crypto, compoundato sul grid) e GTAA(equity) sulla stessa griglia giorni-di-borsa."""
    tp = _tp01_returns()
    if tp.index.tz is None:
        tp.index = tp.index.tz_localize("UTC")
    eq = gtaa_returns().dropna()
    grid = eq.index[eq.index >= tp.index[0]]
    cum = (1 + tp).cumprod()
    tpg = cum.reindex(cum.index.union(grid)).ffill().reindex(grid).pct_change()
    J = pd.concat({"c": tpg, "e": eq.reindex(grid)}, axis=1).dropna()
    combo = wc * J["c"] + (1 - wc) * J["e"]
    return combo, J["c"], J["e"]


def sh(r): r = r.dropna().values; return float(np.mean(r) / np.std(r) * ANN) if len(r) > 5 and np.std(r) > 0 else 0.0
def maxdd(curve): pk = np.maximum.accumulate(curve); return float(np.max((pk - curve) / pk)) if len(curve) else 0.0


def yearly(ret, label):
    ret = ret.dropna().sort_index()
    print(f"\n  ===== {label} (guardia-DD -4%) =====")
    print(f"  {'anno':6}{'NL inizio':>11}{'NL fine':>11}{'rend%':>9}{'DD%':>8}{'Sharpe':>9}")
    eq = INITIAL
    for y in sorted(set(ret.index.year)):
        r = ret[ret.index.year == y]
        if len(r) < 5: continue
        eq0 = eq
        curve = eq0 * np.cumprod(1 + r.values)
        eq = float(curve[-1])
        print(f"  {y:<6}{eq0:>11,.0f}{eq:>11,.0f}{(eq/eq0-1)*100:>+8.1f}%{maxdd(curve)*100:>7.1f}%{sh(r):>9.2f}")
    yrs = (ret.index[-1] - ret.index[0]).days / 365.25
    cagr = (eq / INITIAL) ** (1 / yrs) - 1 if yrs > 0 else 0
    full_curve = INITIAL * np.cumprod(1 + ret.values)
    print(f"  {'TOT':<6}{INITIAL:>11,.0f}{eq:>11,.0f}{(eq/INITIAL-1)*100:>+8.1f}%{maxdd(full_curve)*100:>7.1f}%{sh(ret):>9.2f}"
          f"   |  CAGR {cagr*100:+.1f}%  ({yrs:.1f}y)")


def main():
    global _idx
    print("=" * 78)
    print("  RESOCONTO PROTETTO (soft-guard DD -4%) — da $2.000, anno per anno")
    print("  Tutte e tre sulla griglia giorni-di-borsa del combo (dal 2019), esposizione 1x.")
    print("=" * 78)
    combo, tp, g = legs_on_grid()
    for ret, lbl in [(combo, "COMBO TP01+GTAA 50/50"), (tp, "solo TP01 (crypto)"), (g, "solo GTAA (equity)")]:
        _idx = ret.index
        yearly(dd_guard(ret), lbl)
    # confronto NON protetto (baseline) in coda, una riga TOT per riferimento
    print("\n  --- riferimento NON protetto (baseline, TOT) ---")
    for ret, lbl in [(combo, "COMBO"), (tp, "TP01"), (g, "GTAA")]:
        yrs = (ret.index[-1] - ret.index[0]).days / 365.25
        eqf = INITIAL * np.prod(1 + ret.values)
        print(f"  {lbl:6} CAGR {((eqf/INITIAL)**(1/yrs)-1)*100:>+5.1f}%  DD {maxdd(INITIAL*np.cumprod(1+ret.values))*100:>4.1f}%  Sharpe {sh(ret):.2f}")


if __name__ == "__main__":
    main()
