Files
PythagorasGoal/scripts/strategies/PORT03_all_master.py
Adriano 9ebdfc7a7a feat(ROT02): riduce il DD diversificando (top_k 2 -> 3)
ROT02 concentrava il book su 2 soli asset (DD 40%). top_k=3 dimezza quasi il DD
(40% -> 26%) e ALZA il ritorno full (+1095 -> +1303%, ret/DD da 27 a 50). Il
vol-target abbassa il DD ma sacrifica ritorno (de-leverage) -> tenuto top_k=3
senza VT. Caveat: OOS di ROT02 cala (+98 -> +68%, DD 12 -> 14%), ma il portafoglio
MASTER migliora lo Sharpe full (3.95 -> 4.23). Applicato a ROT02_dual_momentum.py
e a _rot_daily_equity (usata da PORT01/PORT03). Docstring/CLAUDE/diario aggiornati.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 00:30:55 +02:00

79 lines
3.5 KiB
Python

"""PORT03 — Portafoglio MASTER: accorpa TUTTE le strategie (fade + honest).
Unisce le due famiglie del progetto, quasi scorrelate (correlazione cross-famiglia
~0.05), in un unico portafoglio diversificato:
FADE (reversione intraday 1h, long/short, BTC/ETH, col filtro trend):
MR01 Bollinger · MR02 Donchian · MR07 Return-reversal -> 6 sleeve
HONEST (long-only multi-regime multi-crypto):
DIP01 dip-buy (1h) · TR01 EMA-trend (4h basket) · ROT02 dual-momentum (1d) -> 3 sleeve
Combinare le due famiglie migliora il rischio/rendimento rispetto a ciascuna da
sola: il DD scende e lo Sharpe sale (la honest, da sola piu' lumpy, viene
stabilizzata dalle fade ad alta frequenza). Vedi scripts/analysis/combine_portfolio.py.
Risultato (netto, equal-weight daily, finestra comune 2021-2026, OOS = ultimo 30%;
ROT02 ora top_k=3 -> DD piu' basso):
FADE only (6) DD 8.2% Sharpe 3.95 (OOS DD 5.9 / Shrp 4.09)
HONEST only (3) DD 12.6% Sharpe 2.20 (OOS DD 7.8 / Shrp 2.02)
MASTER eq (9) DD 5.2% Sharpe 4.23 (OOS DD 4.7 / Shrp 4.33) <- miglior Sharpe
MASTER 50/50 DD 5.0% Sharpe 3.69 (OOS DD 4.5) <- miglior DD
CAGR ~47% mantenuta in entrambe le varianti combinate.
Due varianti operative selezionabili:
weighting="equal" -> equal-weight sui 9 sleeve (massimo Sharpe)
weighting="5050" -> 50% famiglia fade + 50% famiglia honest (minimo 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 ( # noqa: E402
build_all_sleeves, port_returns, metrics, yearly_returns, SPLIT, OOS_DATE, IDX,
)
def master_returns(sleeves: dict, weighting: str = "equal"):
"""Rendimenti giornalieri del portafoglio master.
equal = equal-weight su tutti gli 11 sleeve; 5050 = media fra le due famiglie."""
fade = {k: v for k, v in sleeves.items() if k.startswith("MR")}
honest = {k: v for k, v in sleeves.items() if not k.startswith("MR")}
if weighting == "5050":
return (port_returns(fade) + port_returns(honest)) / 2
return port_returns(sleeves)
def run():
sleeves = build_all_sleeves()
fade = {k: v for k, v in sleeves.items() if k.startswith("MR")}
honest = {k: v for k, v in sleeves.items() if not k.startswith("MR")}
print("=" * 90)
print(f" PORT03 — MASTER (fade + honest) | {IDX[0].date()} -> {IDX[-1].date()} | OOS da {OOS_DATE}")
print("=" * 90)
print(f" {'portafoglio':<22s}{'Ret%':>9s}{'CAGR':>7s}{'DD%':>7s}{'Shrp':>7s}"
f" | {'oRet%':>9s}{'oDD%':>7s}{'oShrp':>7s}")
print(" " + "-" * 86)
def line(label, pr):
f, o = metrics(pr), metrics(pr, lo=SPLIT)
print(f" {label:<22s}{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}")
line(f"FADE only ({len(fade)})", port_returns(fade))
line(f"HONEST only ({len(honest)})", port_returns(honest))
line(f"MASTER equal ({len(sleeves)})", master_returns(sleeves, "equal"))
line("MASTER 50/50 fam", master_returns(sleeves, "5050"))
print(" " + "-" * 86)
pa = yearly_returns(master_returns(sleeves, "equal"))
print(" MASTER equal per-anno: " + " ".join(f"{y}:{v:+.0f}%" for y, v in pa.items()))
print(" -> combinare le due famiglie scorrelate (~0.05) abbassa il DD e alza lo Sharpe.")
if __name__ == "__main__":
run()