"""Tabella per-anno (PnL% e DD% intra-anno) delle versioni MIGLIORATE: ROT02 (dual-momentum), le 3 sleeve e il PORTAFOGLIO combinato. Tutto NETTO. Riusa gli engine di honest_improve / honest_improve2. """ from __future__ import annotations import sys from pathlib import Path import numpy as np import pandas as pd PROJECT_ROOT = Path(__file__).resolve().parents[2] sys.path.insert(0, str(PROJECT_ROOT)) from scripts.analysis.honest_improve2 import ( # noqa: E402 dip_market_gated, _daily_equity, _norm, _tr_basket_daily, _rot_daily_equity, ) def _year_dd(eq: pd.Series) -> dict[int, float]: out = {} for y, g in eq.groupby(eq.index.year): peak = g.iloc[0]; dd = 0.0 for v in g: peak = max(peak, v); dd = max(dd, (peak - v) / peak if peak > 0 else 0.0) out[int(y)] = dd * 100 return out def _year_pnl(eq: pd.Series) -> dict[int, float]: out = {} for y, g in eq.groupby(eq.index.year): out[int(y)] = (g.iloc[-1] / g.iloc[0] - 1) * 100 return out def table(name, eq): eq = _norm(eq) dd = _year_dd(eq); pnl = _year_pnl(eq) print(f"\n {name}") print(f" {'Anno':>6s}{'PnL%':>9s}{'DD%':>7s}") print(" " + "-" * 22) for y in sorted(pnl): print(f" {y:>6d}{pnl[y]:>+9.0f}{dd[y]:>7.0f}") tot = (eq.iloc[-1] / eq.iloc[0] - 1) * 100 print(f" {'TOT':>6s}{tot:>+9.0f}{_year_dd(eq) and max(_year_dd(eq).values()):>7.0f}(max anno)") if __name__ == "__main__": print("=" * 60) print(" RISULTATI PER ANNO — versioni migliorate (NETTO)") print("=" * 60) # ROT02 dal 2020 (dati paniere) idx_rot = pd.date_range("2020-09-01", "2026-05-26", freq="1D", tz="UTC") eq_rot = _rot_daily_equity(idx_rot) table("ROT02 — dual-momentum rotation (1d)", eq_rot) # sleeve + portafoglio dal 2021 idx = pd.date_range("2021-01-01", "2026-05-26", freq="1D", tz="UTC") d = dip_market_gated("BTC", market_n=0, return_equity=True) eq_dip = _norm(_daily_equity(d["eq_ts"], d["eq_v"], idx)) eq_tr = _norm(_tr_basket_daily(["BNB", "BTC", "DOGE", "SOL", "XRP"], idx)) eq_r2 = _norm(_rot_daily_equity(idx)) table("Sleeve DIP01 — BTC (1h)", eq_dip) table("Sleeve TR01 — basket (4h)", eq_tr) table("Sleeve ROT02 (1d)", eq_r2) drets = pd.DataFrame({"DIP": eq_dip.pct_change().fillna(0), "TR": eq_tr.pct_change().fillna(0), "ROT": eq_r2.pct_change().fillna(0)}) combo = (1 + drets.mean(axis=1)).cumprod() table("PORTAFOGLIO equal-weight (daily rebal)", combo)