Files
PythagorasGoal/scripts/strategies/PORT02_fade_master.py
Adriano bcccfde9a0 feat(strategie): portafogli master (PORT02/PORT03) + waste delle peggiori (MR03, ROT01)
Crea gli artefatti accorpati e migliorati:
- PORT02_fade_master: 3 fade (MR01/MR02/MR07) x BTC/ETH = 6 sleeve, filtro trend,
  equal-weight daily. DD 8.2% full / 5.9% OOS, Sharpe 3.95/4.09, CAGR ~46%.
- PORT03_all_master: portafoglio MASTER fade+honest (9 sleeve), varianti equal
  (max Sharpe: DD 5.2%/4.7% OOS, Sharpe 3.95/4.42) e 50/50 (min DD 5.1%/4.3%).

Sposta in scripts/waste/ le due peggiori:
- MR03 keltner_fade: fade piu' debole (BTC Sharpe 1.22), ridondante con MR01, il
  filtro trend la peggiorava; rimuoverla MIGLIORA il portafoglio fade.
- ROT01 xsect_rotation: strettamente dominata da ROT02 (stesso meccanismo, ROT02
  meglio su tutto), non usata da alcun portafoglio.

Sganciata MR03 da strategy_loader, strategies.yml e dal motore portafogli
(risk_management.STRATS). La funzione keltner_fade resta in strategy_research_v2
come record. CLAUDE.md aggiornato.

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

53 lines
2.2 KiB
Python

"""PORT02 — Portafoglio FADE accorpato e migliorato (6 sleeve, equal-weight daily).
Accorpa le 3 strategie fade mean-reversion su BTC e ETH, ciascuna MIGLIORATA con
il filtro trend (salta i fade contro trend estremi: |close-EMA200|/ATR > 3.0):
MR01 Bollinger fade · MR02 Donchian fade · MR07 Return-reversal
x {BTC, ETH} -> 6 sleeve indipendenti, pos 0.15 ciascuna, leva 3x.
(MR03 Keltner spostata in waste: fade piu' debole e ridondante con MR01.)
Le curve sono poco correlate fra loro (corr media intra-fade ~0.18): la
diversificazione abbatte il DD aggregato ben sotto quello del singolo sleeve.
Risultato (netto fee 0.10% RT, equal-weight ribilanciato ogni giorno, finestra
comune 2021-2026, OOS = ultimo 30%):
Ret +666% / CAGR 46% / DD 8.2% FULL · OOS DD 5.9% / Sharpe 3.95 FULL / 4.09 OOS.
Ricostruzione e confronto: scripts/analysis/combine_portfolio.py.
"""
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 run():
sleeves = {k: v for k, v in build_all_sleeves().items() if k.startswith("MR")}
pr = port_returns(sleeves)
full, oos = metrics(pr), metrics(pr, lo=SPLIT)
print("=" * 84)
print(f" PORT02 — FADE master (8 sleeve, equal-weight daily) | {IDX[0].date()} -> {IDX[-1].date()}")
print("=" * 84)
print(f" {'sleeve':<14s}{'Ret%':>9s}{'DD%':>7s}{'Shrp':>7s}")
for name, s in sleeves.items():
m = metrics(s.pct_change().fillna(0.0))
print(f" {name:<14s}{m['ret']:>+9.0f}{m['dd']:>7.1f}{m['sharpe']:>7.2f}")
print(" " + "-" * 80)
print(f" {'PORTAFOGLIO':<14s}{full['ret']:>+9.0f}{full['dd']:>7.1f}{full['sharpe']:>7.2f}"
f" CAGR {full['cagr']:.0f}%")
print(f" {' di cui OOS':<14s}{oos['ret']:>+9.0f}{oos['dd']:>7.1f}{oos['sharpe']:>7.2f}"
f" (da {OOS_DATE})")
pa = yearly_returns(pr)
print(" Per-anno: " + " ".join(f"{y}:{v:+.0f}%" for y, v in pa.items()))
if __name__ == "__main__":
run()