"""Statistica storica PER ANNO degli sleeve TUTTORA in LIVE REALE (no paper). Config live = micro-test mainnet PORT06 Fase 1 (portfolios.yml): nel POOL reale ci sono SOLO i 7 single-leg con esecuzione reale su Deribit mainnet: - 6 FADE 15m: MR01/MR02/MR07 x BTC/ETH - DIP01 (BTC 1h) Tutto il resto (pairs PR01, SH01, TR01/ROT02/TSM01/XS01) e' PAPER -> escluso. Backtest NETTO fee, leva 3x, pos 15%/sleeve, finestra 2021-2026, OOS = ultimo 30%. NB: i fade live girano col filtro trend 3.0 (gia' applicato in fade_daily_equity); i guard live (EXIT-16 confirm, freeze-gate, ecc.) agiscono SOLO sul path live -> il backtest canonico NON e' filtrato (il live fa MEGLIO sul DD). """ from __future__ import annotations import sys from pathlib import Path PROJECT_ROOT = Path(__file__).resolve().parents[2] sys.path.insert(0, str(PROJECT_ROOT)) from scripts.analysis.combine_portfolio import ( build_all_sleeves, port_returns, metrics, yearly_returns, SPLIT, OOS_DATE, IDX, ) YEARS = sorted(set(IDX.year)) # I 7 sleeve eseguiti reale (vedi portfolios.yml -> execution.sleeves + DIP01). LIVE_REAL = ["MR01_BTC", "MR01_ETH", "MR02_BTC", "MR02_ETH", "MR07_BTC", "MR07_ETH", "DIP01_BTC"] def main(): print("Costruzione equity giornaliere (puo' richiedere ~1-2 min)...\n") S = build_all_sleeves() live = {k: S[k] for k in LIVE_REAL} # filtra ai soli 7 reali # ---------- (A) RET% NETTO per anno, per sleeve ---------- print("=" * 96) print(" (A) RET% NETTO PER ANNO — sleeve in LIVE REALE (no paper) | leva 3x, fee netta, pos 15%") print("=" * 96) print(f" {'sleeve':<14s}" + "".join(f"{y:>9d}" for y in YEARS)) print(" " + "-" * 90) yr_each = {k: yearly_returns(v.pct_change().fillna(0.0)) for k, v in live.items()} for k in LIVE_REAL: print(f" {k.replace('_',' '):<14s}" + "".join(f"{yr_each[k].get(y, 0):>+9.0f}" for y in YEARS)) # pool equal-weight dei 7 (== il pool reale del micro-test) pool = port_returns(live) print(" " + "-" * 90) yr_pool = yearly_returns(pool) print(f" {'POOL-7 (eq)':<14s}" + "".join(f"{yr_pool.get(y, 0):>+9.0f}" for y in YEARS)) # ---------- (B) metriche FULL / OOS per sleeve + pool ---------- print("\n" + "=" * 96) print(f" (B) METRICHE — FULL (2021->) | OOS da {OOS_DATE} (ultimo 30%)") print("=" * 96) print(f" {'sleeve':<14s}{'Ret%':>9s}{'CAGR':>7s}{'DD%':>7s}{'Shrp':>7s}" f" | {'oRet%':>9s}{'oDD%':>7s}{'oShrp':>7s}") print(" " + "-" * 80) for k in LIVE_REAL: dr = live[k].pct_change().fillna(0.0) f, o = metrics(dr), metrics(dr, lo=SPLIT) print(f" {k.replace('_',' '):<14s}{f['ret']:>+9.0f}{f['cagr']:>7.0f}{f['dd']:>7.1f}{f['sharpe']:>7.2f}" f" | {o['ret']:>+9.0f}{o['dd']:>7.1f}{o['sharpe']:>7.2f}") print(" " + "-" * 80) f, o = metrics(pool), metrics(pool, lo=SPLIT) print(f" {'POOL-7 (eq)':<14s}{f['ret']:>+9.0f}{f['cagr']:>7.0f}{f['dd']:>7.1f}{f['sharpe']:>7.2f}" f" | {o['ret']:>+9.0f}{o['dd']:>7.1f}{o['sharpe']:>7.2f}") print("\n NB: il backtest canonico NON applica i guard live (EXIT-16 confirm, freeze-gate,") print(" TP_PHANTOM, ...) -> sul DD il live fa MEGLIO del backtest. Numeri leva 3x.") if __name__ == "__main__": main()