refactor(explore): irrobustimento anti-overfit di pairs/TSM01/master
Giro di validazione scettica (walk-forward, plateau, stress, scomposizione): - PAIRS: config PER-COPPIA -> config UNIVERSALE (n50 z2 zx0.75 mb72), niente cherry-picking. Plateau confermato (heatmap 20/20 Sharpe>1) + walk-forward (ETH/BTC 11/12 finestre+, BTC/LTC 9/10). Scartata BNB/ETH (overfit). 5 coppie robuste. - TSM01: gross 0.45->0.30 (stesso Sharpe, DD 22->15%); corr reale con ROT02 = 0.62 (non 0.53); diversificatore, non motore. Robusto (36/36 config OOS+). - Confluenza multi-TF SCARTATA: overfit (taglia 97% trade, ~40 in 8 anni, Sharpe crolla). - MASTER: numeri sobri onesti -> OOS Sharpe 7.7/DD 2.3% e' regime calmo 2024-25 (ottimistico ~50%); worst-DD 90g ~6%, Sharpe atteso ~5, regge leva 2x+slippage. Config robusta: equal-weight, leva 2x, cap pairs ~30-35% (sono ~57% del rischio). Quanto trovato regge l'esame anti-overfit; numeri comunicati sobri. Doc/CLAUDE/memoria aggiornati. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -152,17 +152,23 @@ Come `PORT01`, sono meta-portafogli (script `run()` di report), non `Strategy` c
|
|||||||
cross-sectional reversal, opening-range breakout, lead-lag BTC→alt, continuation intraday —
|
cross-sectional reversal, opening-range breakout, lead-lag BTC→alt, continuation intraday —
|
||||||
quest'ultima riconferma la dominanza mean-reversion). Due edge reali:
|
quest'ultima riconferma la dominanza mean-reversion). Due edge reali:
|
||||||
- **PR01 Pairs** (`scripts/strategies/PR01_pairs_reversion.py`): spread reversion
|
- **PR01 Pairs** (`scripts/strategies/PR01_pairs_reversion.py`): spread reversion
|
||||||
market-neutral sul log-ratio z-score. **6 coppie robuste**: ETH/BTC (Sharpe 4.04),
|
market-neutral sul log-ratio z-score, **config UNIVERSALE** `n=50 z_in=2.0 z_exit=0.75
|
||||||
LTC/ETH, ADA/ETH, BTC/LTC (robusta anche 4h), ETH/SOL, BNB/ETH (Sharpe 2.2-2.5).
|
max_bars=72` (anti-overfit, niente tuning per-coppia). **5 coppie robuste**: ETH/BTC
|
||||||
Pattern: sempre alt-liquido vs major (mai alt/alt). Corr col mercato ~0.02-0.08. Fee su
|
(Sharpe 4.36), LTC/ETH (3.08), ADA/ETH (2.69), BTC/LTC (2.36, robusta anche 4h), ETH/SOL
|
||||||
**2 gambe** (worker da estendere prima del live). Verifica: `pairs_research.py`.
|
(1.96, la più debole). Pattern: sempre alt-liquido vs major. Plateau confermato
|
||||||
|
(heatmap 20/20 Sharpe>1) + walk-forward (ETH/BTC 11/12 finestre+). **BNB/ETH scartata**
|
||||||
|
(overfit). Corr col mercato ~0.02-0.08. Fee su **2 gambe** (worker da estendere). Verifica: `pairs_research.py`.
|
||||||
- **TSM01** (`scripts/analysis/tsmom_research.py`): TSMOM multi-orizzonte 3/6/12m + risk-off,
|
- **TSM01** (`scripts/analysis/tsmom_research.py`): TSMOM multi-orizzonte 3/6/12m + risk-off,
|
||||||
marginale ma distinto (corr 0.53 con ROT02), DD 22%/12% OOS, mai un anno negativo.
|
**gross 0.30**, distinto da ROT02 (corr 0.62), DD 15-22%, mai un anno negativo. Robusto
|
||||||
|
(36/36 config OOS+) ma diversificatore, non motore di ritorno (rende meno di ROT02).
|
||||||
|
|
||||||
Aggiungere i **6 pairs** al MASTER (quasi scorrelati, ~0.02-0.08) è il free-lunch più
|
Aggiungere i **5 pairs** al MASTER (quasi scorrelati, ~0.02-0.09) è il free-lunch più
|
||||||
grande: MASTER+6pairs (15 sleeve) → CAGR 47→71%, **OOS DD 4.7→2.3%**, Sharpe OOS
|
grande (`scripts/analysis/combine_v2.py`). **Numeri sobri onesti** (l'OOS singolo 2024-25
|
||||||
4.33→**7.71**, tutti gli anni positivi (`scripts/analysis/combine_v2.py`). Caveat:
|
è regime calmo → ottimistico ~50%): worst-DD su 90g rolling **~6%** (non 2.3%), Sharpe
|
||||||
backtest leva 3x, OOS ~1.6 anni, 2024 cripto eccezionale; i pairs richiedono 2 gambe.
|
atteso **~5** (mediana semestrale), ogni anno positivo dal 2021, regge **leva 2x +
|
||||||
|
slippage doppio** (CAGR 36%, Sharpe 5.1). Config robusta raccomandata: **MASTER-esteso
|
||||||
|
equal-weight, leva 2x, cap pairs ~30-35%** (i pairs sono ~57% del rischio e non ancora
|
||||||
|
validati col worker live a 2 gambe). La confluenza multi-TF è stata SCARTATA (overfit).
|
||||||
|
|
||||||
**Metodologia obbligatoria per ogni nuova strategia** (per non ripetere l'errore squeeze):
|
**Metodologia obbligatoria per ogni nuova strategia** (per non ripetere l'errore squeeze):
|
||||||
1. Ingresso eseguibile: direzione e prezzo decisi con dati **fino a `close[i]`**, mai `close[i-1]` con direzione da `i`.
|
1. Ingresso eseguibile: direzione e prezzo decisi con dati **fino a `close[i]`**, mai `close[i-1]` con direzione da `i`.
|
||||||
|
|||||||
@@ -113,6 +113,41 @@ MASTER (corr 0.02-0.08). MASTER + 6 pairs:
|
|||||||
Aggiungere i 6 pairs porta l'**OOS DD a 2.2-2.3%** (da 4.7%) con Sharpe OOS ~7.7 e tutti
|
Aggiungere i 6 pairs porta l'**OOS DD a 2.2-2.3%** (da 4.7%) con Sharpe OOS ~7.7 e tutti
|
||||||
gli anni positivi: il guadagno di diversificazione da fonti market-neutral scorrelate.
|
gli anni positivi: il guadagno di diversificazione da fonti market-neutral scorrelate.
|
||||||
|
|
||||||
|
## Quarto giro — validazione anti-overfitting e irrobustimento
|
||||||
|
|
||||||
|
Tre audit scettici paralleli (walk-forward, plateau, stress, scomposizione):
|
||||||
|
|
||||||
|
**Pairs — de-overfittati.** Sostituita la config per-coppia (cherry-picking di z_exit/n)
|
||||||
|
con **una config universale `n=50 z_in=2.0 z_exit=0.75 max_bars=72`**. Verifiche:
|
||||||
|
- plateau (non picco): heatmap n×z_in → 20/20 celle Sharpe>1 su ETH/BTC e BTC/LTC;
|
||||||
|
- walk-forward (train 2y / test 6m rolling): ETH/BTC 11/12 finestre positive, BTC/LTC
|
||||||
|
9/10 → edge distribuito su tutta la storia, non un regime singolo;
|
||||||
|
- **BNB/ETH scartata** (era robusta solo coi suoi parametri → overfit; crolla con la
|
||||||
|
universale e muore per prima allo stress costi). Famiglia ridotta a **5 pairs**.
|
||||||
|
- stress: 5/6 reggono fee+slippage realistici; solo ETH/BTC regge fee 6x (coda fee-fragile).
|
||||||
|
|
||||||
|
**Master — numeri sobri.** L'OOS Sharpe 7.7 / DD 2.3% è **ottimistico ~50%** perché l'OOS
|
||||||
|
cade nel bull calmo 2024-25. Numeri onesti da usare:
|
||||||
|
- worst-DD su finestra mobile 90g (2021-2026) = **5.7%** (bear FTX) → budget DD ~6%, non 2.3%;
|
||||||
|
- Sharpe per-semestre: mediana **~5** (min 1.2, max 12) → atteso ~5, non 7.7;
|
||||||
|
- ogni anno e ogni semestre dal 2021 positivo (anche il 2022 bear, grazie alle gambe short);
|
||||||
|
- equal-weight ≈ inverse-vol (non dipende da pesi fortunati);
|
||||||
|
- regge **leva 2x + slippage doppio** (CAGR 36%, Sharpe 5.1);
|
||||||
|
- **rischio concentrato: i pairs portano ~57% del rischio** → cap consigliato ~30-35%.
|
||||||
|
- Config robusta raccomandata: **MASTER-esteso, equal-weight, leva 2x, cap pairs ~30-35%**.
|
||||||
|
|
||||||
|
**TSM01 — confermato robusto** (36/36 config OOS+, walk-forward stabile) ma corr reale con
|
||||||
|
ROT02 = **0.62** (non 0.53), e gran parte del DD basso viene dall'overlay risk-off condiviso.
|
||||||
|
Tenuto come diversificatore con **gross 0.30** (stesso Sharpe, DD 22%→15%).
|
||||||
|
|
||||||
|
**Confluenza multi-TF — SCARTATA: era overfit.** Taglia il 97% dei trade (restano ~40 in
|
||||||
|
8 anni = non significativo), distrugge lo Sharpe (1.58→0.27 su BTC) e il caso "bello" non
|
||||||
|
sopravvive alle perturbazioni. Per abbassare il DD di MR01 meglio ridurne la leva, non il filtro 4h.
|
||||||
|
|
||||||
|
**Risultato del giro:** quanto trovato regge l'esame anti-overfit (NON è l'errore squeeze),
|
||||||
|
ma i numeri vanno comunicati sobri (Sharpe ~5, DD ~6%) e con leva 2x + cap pairs. Famiglia
|
||||||
|
pairs consolidata a 5 coppie con config universale; confluenza MTF rimossa dai vincitori.
|
||||||
|
|
||||||
## File creati (branch strategy_explore)
|
## File creati (branch strategy_explore)
|
||||||
|
|
||||||
`scripts/analysis/explore_lab.py` (harness onesto condiviso), `pairs_research.py`
|
`scripts/analysis/explore_lab.py` (harness onesto condiviso), `pairs_research.py`
|
||||||
|
|||||||
@@ -5,8 +5,15 @@ dei segni del momentum su più orizzonti lunghi (3/6/12 mesi); si tengono equal-
|
|||||||
gli asset con consenso pieno positivo. Overlay risk-off: cash se BTC < SMA100.
|
gli asset con consenso pieno positivo. Overlay risk-off: cash se BTC < SMA100.
|
||||||
|
|
||||||
Distinta da ROT02 (cross-sectional ranking): qui conta la PERSISTENZA assoluta lenta
|
Distinta da ROT02 (cross-sectional ranking): qui conta la PERSISTENZA assoluta lenta
|
||||||
di ogni asset, non la classifica relativa. Correlazione con ROT02 ~0.53 -> fattore
|
di ogni asset, non la classifica relativa. Correlazione con ROT02 ~0.62 -> fattore
|
||||||
parzialmente indipendente, utile come diversificatore. DD basso (22% full / 12% OOS).
|
parzialmente indipendente, utile come diversificatore (NON come motore di ritorno:
|
||||||
|
rende meno di ROT02 a parita' di OOS). DD basso.
|
||||||
|
|
||||||
|
Anti-overfit: edge su ALTOPIANO (36/36 config orizzonti x thr x regime_n restano OOS+),
|
||||||
|
walk-forward stabile (4 anni up, 2 piatti per risk-off, mai un anno negativo), regge
|
||||||
|
fee 0.40% RT. Gran parte del DD basso viene dall'overlay risk-off SMA100 (condiviso),
|
||||||
|
la struttura multi-orizzonte aggiunge ~+38pp OOS e alza lo Sharpe 0.58->1.07.
|
||||||
|
Default gross=0.30 (era 0.45): stesso Sharpe ma DD 22%->15% (scelta robusta, non la piu' redditizia).
|
||||||
|
|
||||||
Engine onesto: pesi a close[i] da soli rendimenti passati, realizzo i->i+1, fee
|
Engine onesto: pesi a close[i] da soli rendimenti passati, realizzo i->i+1, fee
|
||||||
one-way fee_rt/2 sul turnover. NETTO, leva implicita gross. OOS = ultimo 30%.
|
one-way fee_rt/2 sul turnover. NETTO, leva implicita gross. OOS = ultimo 30%.
|
||||||
@@ -25,7 +32,7 @@ sys.path.insert(0, str(PROJECT_ROOT))
|
|||||||
from scripts.analysis.honest_lab import available_assets, FEE_RT
|
from scripts.analysis.honest_lab import available_assets, FEE_RT
|
||||||
from scripts.analysis.honest_rotation import build_panel
|
from scripts.analysis.honest_rotation import build_panel
|
||||||
|
|
||||||
GROSS, OOS_FRAC = 0.45, 0.30
|
GROSS, OOS_FRAC = 0.30, 0.30 # gross 0.30 (anti-overfit): stesso Sharpe di 0.45, DD piu' basso
|
||||||
|
|
||||||
|
|
||||||
def tsmom_sim(horizons=(63, 126, 252), thr=1.0, regime_n=100, gross=GROSS,
|
def tsmom_sim(horizons=(63, 126, 252), thr=1.0, regime_n=100, gross=GROSS,
|
||||||
|
|||||||
@@ -11,13 +11,20 @@ Logica (engine onesto verificato in scripts/analysis/pairs_research.py):
|
|||||||
EXIT: |z| <= z_exit (rientro) o time-limit max_bars. Ingresso/uscita a close.
|
EXIT: |z| <= z_exit (rientro) o time-limit max_bars. Ingresso/uscita a close.
|
||||||
Fee su 2 GAMBE = 2*fee_rt*lev (0.20% RT/coppia). Filtro candele sporche (salto>8%).
|
Fee su 2 GAMBE = 2*fee_rt*lev (0.20% RT/coppia). Filtro candele sporche (salto>8%).
|
||||||
|
|
||||||
Validazione (netto, fee 0.20% RT/coppia reale a 2 gambe, leva 3x, OOS = ultimo 30%,
|
Validazione anti-overfit (netto, fee 0.20% RT/coppia a 2 gambe, leva 3x, OOS = ultimo
|
||||||
n=50 z_in=2.0 z_exit=0.5 max_bars=72, 1h):
|
30%, CONFIG UNIVERSALE n=50 z_in=2.0 z_exit=0.75 max_bars=72, 1h):
|
||||||
ETH/BTC : CAGR 144% / OOS DD 17% / Sharpe 4.04 / win 74% / 8/9 anni positivi
|
ETH/BTC : CAGR 158% / Sharpe 4.36 / 8/9 anni+ (regge fee 6x)
|
||||||
LTC/ETH : CAGR 71% / OOS DD 10% / Sharpe 2.52 / 7/8 anni positivi
|
LTC/ETH : CAGR 92% / Sharpe 3.08 / 8/8 anni+
|
||||||
ADA/ETH : CAGR 77% / OOS DD 11% / Sharpe 2.16 / 7/8 anni positivi
|
ADA/ETH : CAGR 91% / Sharpe 2.69 / 7/8 anni+
|
||||||
No look-ahead verificato (z[i] invariato perturbando il futuro). Regge fee 0.40% RT/coppia.
|
BTC/LTC : CAGR 60% / Sharpe 2.36 / 7/8 anni+ (robusta anche a 4h)
|
||||||
Correlazione con BTC daily ~0.02 -> davvero market-neutral.
|
ETH/SOL : CAGR 74% / Sharpe 1.96 / 5/7 anni+ (la piu' debole, DD ~63%)
|
||||||
|
- No look-ahead verificato (z[i] invariato perturbando il futuro).
|
||||||
|
- PLATEAU non picco: heatmap n x z_in -> 20/20 celle Sharpe>1 (ETH/BTC, BTC/LTC).
|
||||||
|
- WALK-FORWARD (rolling train 2y / test 6m): ETH/BTC 11/12 finestre positive,
|
||||||
|
BTC/LTC 9/10 -> edge distribuito su tutta la storia, non un regime singolo.
|
||||||
|
- Stress costi: 5/6 reggono fee+slippage realistici; solo ETH/BTC regge fee 6x.
|
||||||
|
- Correlazione con BTC daily ~0.02-0.08 -> market-neutral.
|
||||||
|
- SCARTATA BNB/ETH: robusta solo coi suoi parametri (overfit), crolla con la universale.
|
||||||
|
|
||||||
LIMITE OPERATIVO: e' una strategia a 2 gambe (long un perp + short l'altro), il worker
|
LIMITE OPERATIVO: e' una strategia a 2 gambe (long un perp + short l'altro), il worker
|
||||||
attuale e' single-leg. Per tradarla serve: (a) eseguibilita' short del perp B su
|
attuale e' single-leg. Per tradarla serve: (a) eseguibilita' short del perp B su
|
||||||
@@ -34,15 +41,20 @@ sys.path.insert(0, str(PROJECT_ROOT))
|
|||||||
|
|
||||||
from scripts.analysis.pairs_research import pairs_sim, OOS_FRAC # noqa: E402
|
from scripts.analysis.pairs_research import pairs_sim, OOS_FRAC # noqa: E402
|
||||||
|
|
||||||
# Coppie robuste (config migliore per ognuna). Sempre alt-liquido vs major (mai alt/alt).
|
# CONFIG UNIVERSALE (anti-overfit): un'unica terna per TUTTE le coppie, niente
|
||||||
# Le prime 3 dal primo lotto; BTC/LTC (anche 4h), ETH/SOL, BNB/ETH dall'espansione.
|
# cherry-picking per-coppia. Validata come ALTOPIANO (heatmap n x z_in: 20/20 celle
|
||||||
|
# Sharpe>1 su ETH/BTC e BTC/LTC) e walk-forward (ETH/BTC 11/12 finestre+, BTC/LTC 9/10).
|
||||||
|
UNIV = dict(n=50, z_in=2.0, z_exit=0.75, max_bars=72)
|
||||||
|
|
||||||
|
# Coppie robuste con la config universale. Sempre alt-liquido vs major (mai alt/alt).
|
||||||
|
# BNB/ETH SCARTATA: era robusta solo coi suoi parametri (n=30, z_exit=1.0) -> overfit;
|
||||||
|
# con la config universale crolla (Sharpe 1.5, DD 71%) ed e' la prima a morire allo stress costi.
|
||||||
PAIRS = [
|
PAIRS = [
|
||||||
("ETH", "BTC", dict(n=50, z_in=2.0, z_exit=0.5, max_bars=72)),
|
("ETH", "BTC", UNIV), # la migliore (Sharpe 4.4 univ), regge fee 6x
|
||||||
("LTC", "ETH", dict(n=50, z_in=2.0, z_exit=0.5, max_bars=72)),
|
("LTC", "ETH", UNIV),
|
||||||
("ADA", "ETH", dict(n=50, z_in=2.0, z_exit=0.5, max_bars=72)),
|
("ADA", "ETH", UNIV),
|
||||||
("BTC", "LTC", dict(n=50, z_in=2.0, z_exit=0.5, max_bars=72)), # NUOVA: robusta 1h E 4h
|
("BTC", "LTC", UNIV), # robusta anche a 4h
|
||||||
("ETH", "SOL", dict(n=50, z_in=2.0, z_exit=1.0, max_bars=72)), # NUOVA: solo 1h
|
("ETH", "SOL", UNIV), # piu' debole (DD ~63%, storia SOL corta) -> peso ridotto
|
||||||
("BNB", "ETH", dict(n=30, z_in=2.0, z_exit=1.0, max_bars=72)), # NUOVA: solo 1h
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user