"""Resoconto anno-per-anno della strategia combo (TP01+GTAA) + componenti, da $2.000.

Per anno: PnL ($ e %), MaxDD (intra-anno), NumTrades, equity di fine anno (compounding da 2k).
Combo = blend 50/50 TP01(Deribit) + GTAA(IB) (crypto compoundato su grid giorni-di-borsa).
NumTrades: TP01 = cambi di target BTC/ETH (>0.05); GTAA = ribilanci MENSILI per-gamba (>2%).
Onesto: il combo parte dal 2019 (crypto). GTAA-solo dato anche su 10y come contesto.
"""
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" / "live"))
from src.data.downloader import load_data
from src.strategies.trend_portfolio import TrendPortfolio, CANONICAL, resample_1d
from src.portfolio.sleeves import _tp01_returns
from src.portfolio.gtaa import gtaa_returns, _exposure, _close, EQ_UNIVERSE
INITIAL = 2000.0


def tp01_trades_per_year():
    tp = TrendPortfolio(**CANONICAL); cnt = {}
    for a in ("BTC", "ETH"):
        df = resample_1d(load_data(a, "1h")); tgt = tp.target_series(df)
        idx = pd.DatetimeIndex(pd.to_datetime(df["datetime"]))
        chg = pd.Series(np.abs(np.diff(tgt, prepend=tgt[0])) > 0.05, index=idx)
        for y, c in chg.groupby(idx.year).sum().items():
            cnt[int(y)] = cnt.get(int(y), 0) + int(c)
    return cnt


def gtaa_trades_per_year():
    # pesi giornalieri -> ribilancio MENSILE realistico -> conta gambe cambiate >2%
    W = {}
    for a in EQ_UNIVERSE:
        ex = _exposure(_close(a)) / len(EQ_UNIVERSE)
        W[a] = ex
    Wd = pd.concat(W, axis=1).dropna()
    Wm = Wd.resample("ME").last()                       # peso a fine mese
    chg = (Wm.diff().abs() > 0.02).sum(axis=1)          # gambe ribilanciate quel mese
    return chg.groupby(chg.index.year).sum().astype(int).to_dict()


def yearly(ret: pd.Series, trades: dict, label: str, start_capital=INITIAL):
    ret = ret.dropna().sort_index()
    print(f"\n  ===== {label} =====")
    print(f"  {'anno':6}{'eq inizio':>12}{'PnL $':>12}{'PnL %':>9}{'MaxDD %':>9}{'NumTrades':>11}{'eq fine':>12}")
    eq = start_capital
    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)
        peak = np.maximum.accumulate(curve)
        dd = float(np.max((peak - curve) / peak)) if len(curve) else 0.0
        eq = float(curve[-1])
        pnl = eq - eq0
        nt = trades.get(y, None)
        print(f"  {y:<6}{eq0:>12,.0f}{pnl:>+12,.0f}{(eq/eq0-1)*100:>+8.1f}%{dd*100:>8.1f}%"
              f"{(str(nt) if nt is not None else '—'):>11}{eq:>12,.0f}")
    tot = eq / start_capital - 1
    yrs = (ret.index[-1] - ret.index[0]).days / 365.25
    cagr = (eq / start_capital) ** (1 / yrs) - 1 if yrs > 0 else 0
    sh = float(r.mean()) if False else float(ret.mean() / ret.std() * np.sqrt(252))
    print(f"  {'TOT':<6}{start_capital:>12,.0f}{eq-start_capital:>+12,.0f}{tot*100:>+8.1f}%"
          f"{'':>9}{sum(v for v in trades.values()) if trades else 0:>11}{eq:>12,.0f}")
    print(f"  -> da ${start_capital:,.0f} a ${eq:,.0f} in {yrs:.1f}y | CAGR {cagr*100:+.1f}% | Sharpe {sh:.2f}")


def combo_daily(wc=0.5):
    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()
    return (wc * J["c"] + (1 - wc) * J["e"]).dropna()


def main():
    print("=" * 80)
    print("  RESOCONTO STRATEGIA — da $2.000, anno per anno")
    print("=" * 80)
    tpt = tp01_trades_per_year(); gtt = gtaa_trades_per_year()
    combo_tr = {y: tpt.get(y, 0) + gtt.get(y, 0) for y in set(tpt) | set(gtt)}
    # COMBO (la strategia deployata)
    yearly(combo_daily(), combo_tr, "COMBO TP01+GTAA 50/50 (deployabile, dal 2019)")
    # componenti
    tp = _tp01_returns(); tp.index = tp.index.tz_localize("UTC") if tp.index.tz is None else tp.index
    yearly(tp, tpt, "solo TP01 (crypto, Deribit)")
    g = gtaa_returns(); g10 = g[g.index >= (g.index[-1] - pd.Timedelta(days=3660))]
    yearly(g10, gtt, "solo GTAA (equity, IB) — ULTIMI 10 ANNI")


if __name__ == "__main__":
    main()
