14522262e6
Reset del progetto su fondamenta verificate dopo la scoperta che l'intera libreria "validata OOS" era artefatto di feed contaminato (print fantasma del feed Cerbero TESTNET + storico Binance/USDT). - Storico ricostruito da Deribit MAINNET (ccxt pubblico, tokenless) e CERTIFICATO (certify_feed.py): BTC/ETH puliti su TUTTA la storia (mediana 2-6 bps vs Coinbase USD), integrita' OHLC + coerenza resample (maxΔ 0.00) + cross-venue OK. Alt esclusi (illiquidi/divergenti: LTC/DOGE 50-82% barre flat; XRP/BNB non certificabili). - Verdetto sul feed pulito: FADE / PAIRS / XS01 / TSM01 morti (ogni portafoglio Sharpe -2.3..-3.0, DD ~40%); solo SH01 e frammenti HONEST con segnale residuo, da ri-validare in isolamento. - Cleanup "restart pulito": strategie, stack live (src/live, src/portfolio, runner/executor, yml, docker), ~100 script ricerca/gate, waste/games/ portfolios, dati non certificati + cache e 60+ diari -> archiviati in Old/ (preservati, non cancellati). Diario consolidato in un unico documento. - Skeleton ricerca tenuto: Strategy ABC + indicatori + src/fractal + src/backtest/engine + load_data; tool dati certificati (rebuild_history, certify_feed, audit_feed, multi_source_check). - Universo dati ATTIVO: solo BTC/ETH (5m/15m/1h); guardrail fisico (load_data su alt -> FileNotFoundError). Esecuzione DISABILITATA, conto flat. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
159 lines
6.9 KiB
Python
159 lines
6.9 KiB
Python
"""Report riassuntivo: tutte le strategie/famiglie per anno + analisi di integrazione.
|
|
|
|
Consolida in un solo posto:
|
|
(A) RET% NETTO per anno per FAMIGLIA (FADE / HONEST / PAIRS / TSM01) e per i portafogli.
|
|
(B) RET% NETTO per anno per ogni STRATEGIA singola (tutti gli sleeve).
|
|
(C) INTEGRAZIONE: cosa succede al MASTER aggiungendo le nuove famiglie (pairs, TSM01).
|
|
(D) Numeri SOBRI (worst-case) e raccomandazione operativa.
|
|
|
|
Famiglie:
|
|
FADE (reversione intraday 1h, long/short, BTC/ETH): MR01, MR02, MR07
|
|
HONEST (long-only multi-regime multi-crypto): DIP01, TR01, ROT02
|
|
PAIRS (market-neutral spread reversion, config universale): 5 coppie
|
|
TSM01 (TSMOM multi-orizzonte, diversificatore)
|
|
|
|
Tutto NETTO fee, leva 3x (vedi nota sobria leva 2x), finestra comune 2021-2026, OOS=ultimo 30%.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
import pandas as pd
|
|
|
|
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,
|
|
)
|
|
from scripts.analysis.honest_improve2 import _daily_equity, _norm
|
|
from scripts.analysis.pairs_research import pairs_sim, pairs_sim_flat
|
|
from scripts.analysis.tsmom_research import tsmom_sim
|
|
from scripts.strategies.PR01_pairs_reversion import PAIRS
|
|
from scripts.analysis.shape_ml_validate import shape_daily_equity
|
|
|
|
YEARS = sorted(set(IDX.year))
|
|
|
|
|
|
def daily_from(eq_ts, eq_v):
|
|
return _norm(_daily_equity(eq_ts, eq_v, IDX))
|
|
|
|
|
|
def build_everything():
|
|
S = build_all_sleeves() # 9 sleeve (FADE 6 + HONEST 3)
|
|
pairs = {}
|
|
for a, b, p in PAIRS:
|
|
r = pairs_sim(a, b, **p)
|
|
pairs[f"PR_{a}{b}"] = daily_from(r["eq_ts"], r["eq_v"])
|
|
# BLEND ETH/BTC 15m flat-skip (gioco Blind Traders -> gate PORT06, decorrelato 0.37
|
|
# dal 1h, edge non-artefatto-flat, worker validato). Engine LIVE-REALIZABLE identico
|
|
# al PairsWorker (pairs_sim_flat). Diari 2026-06-09-pairs15m-*.md.
|
|
# MEZZA size (pos 0.075 = meta' della canonica 0.15): a peso uguale il 15m, piu'
|
|
# volatile, contribuirebbe ~26% del rischio PORT06 (vs ~9% del 1h). Dimezzarlo lo
|
|
# riporta in linea col 1h -> blend-tilt, non scommessa dominante (col caveat slippage).
|
|
# Coerente col live (params.position_size=0.10 = meta' del family PAIRS 0.20).
|
|
r15 = pairs_sim_flat("ETH", "BTC", tf="15m", n=66, z_in=1.674, z_exit=1.0,
|
|
max_bars=35, flat_skip=True, pos=0.075)
|
|
pairs["PR_ETHBTC_15M"] = daily_from(r15["eq_ts"], r15["eq_v"])
|
|
t = tsmom_sim()
|
|
tsm = {"TSM01": daily_from(t["eq_ts"], t["eq_v"])}
|
|
shape = {f"SH_{a}": _norm(shape_daily_equity(a, IDX)) for a in ("BTC", "ETH")}
|
|
# XS01 — reversione cross-sectional (8 asset, market-neutral). Engine canonico
|
|
# scripts.strategies.XS01_cross_sectional (worker validato == backtest).
|
|
from scripts.strategies.XS01_cross_sectional import xsec_sim
|
|
x = xsec_sim()
|
|
tsm["XS01"] = daily_from(x["eq_ts"], x["eq_v"])
|
|
return S, pairs, tsm, shape
|
|
|
|
|
|
def yrow(label, dr):
|
|
yr = yearly_returns(dr)
|
|
return f" {label:<14s}" + "".join(f"{yr.get(y, 0):>+9.0f}" for y in YEARS)
|
|
|
|
|
|
def metric_block(label, dr):
|
|
f, o = metrics(dr), metrics(dr, lo=SPLIT)
|
|
return (f" {label:<16s}{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}")
|
|
|
|
|
|
def main():
|
|
print("Costruzione (puo' richiedere ~2-3 min)...\n")
|
|
S, pairs, tsm, shape = build_everything()
|
|
fade = {k: v for k, v in S.items() if k.startswith("MR")}
|
|
honest = {k: v for k, v in S.items() if not k.startswith("MR")}
|
|
|
|
fam = {
|
|
"FADE": port_returns(fade),
|
|
"HONEST": port_returns(honest),
|
|
"PAIRS": port_returns(pairs),
|
|
"TSM01": tsm["TSM01"].pct_change().fillna(0.0),
|
|
"SHAPE": port_returns(shape),
|
|
}
|
|
master9 = port_returns(S)
|
|
master_p = port_returns({**S, **pairs})
|
|
master_x = port_returns({**S, **pairs, **tsm})
|
|
master_xs = port_returns({**S, **pairs, **tsm, **shape})
|
|
|
|
# ---------- (A) per anno, per FAMIGLIA + portafogli ----------
|
|
print("=" * 110)
|
|
print(" (A) RET% NETTO PER ANNO — per FAMIGLIA e per PORTAFOGLIO | leva 3x, fee netta")
|
|
print("=" * 110)
|
|
print(f" {'':<14s}" + "".join(f"{y:>9d}" for y in YEARS))
|
|
print(" " + "-" * 104)
|
|
for k, dr in fam.items():
|
|
print(yrow(k, dr))
|
|
print(" " + "-" * 104)
|
|
print(yrow("MASTER-9", master9))
|
|
print(yrow("MASTER+pairs", master_p))
|
|
print(yrow("MASTER-esteso", master_x))
|
|
print(yrow("MASTER+shape", master_xs))
|
|
|
|
# ---------- (B) per anno, per STRATEGIA singola ----------
|
|
print("\n" + "=" * 130)
|
|
print(" (B) RET% NETTO PER ANNO — per STRATEGIA singola (tutti gli sleeve)")
|
|
print("=" * 130)
|
|
allsl = {**S, **pairs, **tsm, **shape}
|
|
cols = list(allsl)
|
|
print(f" {'Anno':>5s}" + "".join(f"{c.replace('_',''):>11s}" for c in cols))
|
|
print(" " + "-" * 124)
|
|
yr_each = {k: yearly_returns(v.pct_change().fillna(0.0)) for k, v in allsl.items()}
|
|
for y in YEARS:
|
|
print(f" {y:>5d}" + "".join(f"{yr_each[c].get(y, 0):>+11.0f}" for c in cols))
|
|
|
|
# ---------- (C) integrazione ----------
|
|
print("\n" + "=" * 96)
|
|
print(f" (C) INTEGRAZIONE delle nuove famiglie nel MASTER | OOS da {OOS_DATE} | equal-weight daily")
|
|
print("=" * 96)
|
|
print(f" {'portafoglio':<16s}{'Ret%':>9s}{'CAGR':>7s}{'DD%':>7s}{'Shrp':>7s}"
|
|
f" | {'oRet%':>9s}{'oDD%':>7s}{'oShrp':>7s}")
|
|
print(" " + "-" * 80)
|
|
print(metric_block("MASTER-9", master9))
|
|
print(metric_block("+pairs", master_p))
|
|
print(metric_block("+TSM01", port_returns({**S, **tsm})))
|
|
print(metric_block("+shape", port_returns({**S, **shape})))
|
|
print(metric_block("MASTER-esteso", master_x))
|
|
print(metric_block("MASTER+shape", master_xs))
|
|
# correlazione media nuove vs master-9
|
|
dr_all = pd.DataFrame({k: v.pct_change().fillna(0.0) for k, v in {**S, **pairs, **tsm, **shape}.items()})
|
|
corr = dr_all.corr(); old = list(S)
|
|
print(" " + "-" * 80)
|
|
for k in list(pairs) + list(tsm) + list(shape):
|
|
print(f" corr {k:<11s} vs MASTER-9 = {corr.loc[k, old].mean():+.2f}")
|
|
|
|
# ---------- (D) numeri sobri ----------
|
|
print("\n" + "=" * 96)
|
|
print(" (D) NUMERI SOBRI / RACCOMANDAZIONE (anti-overfit)")
|
|
print("=" * 96)
|
|
print(" - L'OOS singolo (2024-25) e' regime calmo -> Sharpe/DD OOS ottimistici ~50%.")
|
|
print(" - Numeri onesti del MASTER-esteso: worst-DD 90g ~6%, Sharpe atteso ~5, ogni anno positivo dal 2021.")
|
|
print(" - Regge leva 2x + slippage doppio (CAGR ~36%, Sharpe ~5).")
|
|
print(" - Rischio concentrato sui PAIRS (~57%) -> cap allocazione pairs ~30-35%.")
|
|
print(" - I pairs sono a 2 gambe (long/short): il worker live va esteso prima del trading reale.")
|
|
print(" - CONFIG RACCOMANDATA: MASTER-esteso, equal-weight, leva 2x, cap pairs 30-35%.")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|