Files
PythagorasGoal/docs/diary/2026-07-25-mat01-statarb-generalization.md
T
Adriano Dal Pastro ec1501caa6 docs: diario ondata 2026-07-25 + CLAUDE.md — XSR01, 2 refutazioni, fix split equity
Diario docs/diary/2026-07-25-mat01-statarb-generalization.md (6 sezioni):
MAT01 scartato col null de-levering a pari volatilita'; STATARB-MULTI
(ETH/BTC non e' un outlier: 58° pctl) e STATARB-EQ (non si trasferisce alle
azioni, il lordo e' -0.17 e il resto e' turnover); lo split non aggiustato di
IWM/EFA con impatto quantificato su GTAA01; l'addendum pre-registrato al gate
del 27/09; e XSR01 col suo scettico e le sue tre debolezze dichiarate.

Registrati anche i due errori di metodo miei corretti in sessione (null statico
con look-ahead; null a fee piene contro un segnale permutato ad alto turnover):
entrambi avrebbero prodotto numeri piu' belli e sbagliati.

CLAUDE.md: nuove voci XSR01 (candidato in monitor, gate 2026-10-23), ondata
2026-07-25, e il difetto SPLIT-NON-AGGIUSTATI con la regola nuova — ogni soglia
di certificazione tarata su un valore tondo va controllata contro il difetto che
genera esattamente quel valore.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-25 09:48:23 +00:00

18 KiB
Raw Blame History

2026-07-25 — Caccia a strategie nuove: MAT01 (trend multi-asset) + generalizzazione di STATARB, e uno SPLIT non aggiustato nel feed equity

Goal di sessione: trovare nuove strategie. Tre filoni scelti cercando i vuoti reali nella mappa (89 diari, famiglie calendario/funding/VRP/CRT gia' dichiarate sature). Esito: 0 sleeve nuovi, 2 refutazioni pulite, 1 difetto di dato che tocca il libro live trovato e riparato, 1 addendum pre-registrato al gate STATARB del 27/09.

Book e pesi INVARIATI.


(1) MAT01 — trend difensivo su 18 ETF multi-asset-class invece di 6 → SCARTATO

Script: scripts/research/r0725_mat01_multiasset_trend.py, r0725_mat01b_regime.py.

Il vuoto. GTAA01 gira su 6 ETF (SPY QQQ IWM TLT GLD HYG), 4 su 6 azionari US. I 12 ETF multi-classe (DIA EFA EEM FXI EWJ AGG LQD IEF USO SLV DBC VNQ) sono su disco certificati dal 2026-06-22 con 9-30 anni di storia, ma erano stati usati SOLO per il test lead-lag crypto→X (diario 2026-06-23-crossmarket-beyond-sp500), mai per un programma di trend. Il TSMOM multi-asset-class e' l'anomalia meglio replicata della finanza quantitativa: valeva il test.

Disciplina. Meccanismo CONGELATO (import di _exposure da src/portfolio/gtaa.py: orizzonti 21/63/126/252, vol-target 12%, long-flat, EW, fee 2bps/lato). Cambia SOLO l'universo. L'universo ALL18 e' definito a priori per classe d'attivo: a k=18 la liberta' di selezione e' zero (esiste un solo sottoinsieme di 18 su 18), quindi il confronto ALL18-vs-GTAA6 non e' selezionabile.

Risultati.

Sh FULL Sh IS<2015 Sh OOS2015+ maxDD OOS vol
GTAA6 (incumbent) 0.62 0.49 0.89 8.2% 6.05%
MAT18 (candidato) 0.56 0.43 0.80 6.9% 4.62%
MAT18-CLS (per classe) 0.57 0.73 4.38%

corr(GTAA6, MAT18) = 0.91. Sostituzione nel book a peso invariato 20%: Sharpe FULL 2.22→2.19, HOLD 2.36→2.38, DD 6.2%→6.6%. Corr→crypto praticamente identica (0.110 vs 0.116): nessun guadagno di diversificazione, che era l'unica ragione plausibile per farlo.

Perche' scartato — quattro ragioni indipendenti:

  1. Finestre disgiunte: MAT18 perde 3/4 (1998-2004 0.28 vs 0.40; 2005-2011 0.63 vs 0.54 — unica vittoria; 2012-2018 0.55 vs 0.72; 2019-2026 0.99 vs 1.13). Non e' regime-luck dell'incumbent: GTAA6 vince anche nella finestra che contiene dot-com e GFC.
  2. A PARI VOLATILITA' il vantaggio di DD sparisce e si inverte: MAT18 va scalato ×1.31 per eguagliare la vol di GTAA6, e a quel punto maxDD 20.6% contro 15.4%. Il suo DD piu' basso era solo de-levering — replicabile meglio abbassando target_vol. → 3ª occorrenza della stessa lezione (overlay DD del VRP01 2026-07-03: 4/4 refutati dal null de-levering; TP01×DVOL 2026-06-26: il taglio di DD era de-levering). Il null de-levering e' ormai il primo test da fare su ogni claim di "meno drawdown".
  3. Beta azionario e alpha quasi identici (GTAA6 beta 0.19 / alpha 1.56%; MAT18 0.14 / 0.97%): MAT18 non e' meno "equity travestito", e' solo piu' piccolo.
  4. Nei bear MAT18 e' migliore (GFC 3.0% vs 5.1%, 2022 3.2% vs 6.1%) ma paga quel conforto con Sharpe piu' basso in ogni altro regime.

Il risultato POSITIVO da conservare — l'ampiezza funziona, ma il soffitto e' gia' raggiunto. La curva di ampiezza (400 sottoinsiemi casuali per k, Sharpe OOS) e' monotona in 13/17 passi: mediana 0.44 a k=1 → 0.80 a k=18, DD mediano 16.0% → 6.9%, satura verso k≈10-12. Cioe': allargare l'universo di un trend difensivo e' un meccanismo reale. Ma GTAA6 sta al 95° percentile dei 6-subset casuali — e non perche' sia un best-of cherry-picked (contiene TLT, il PEGGIORE dei 18 con Sh OOS 0.03): e' la sua composizione (equity US + oro + credito HY) a stare sopra il soffitto d'ampiezza. Non c'e' piu' ampiezza da raccogliere su questo sleeve.


(2) STATARB-MULTI — il meccanismo generalizza fuori da ETH/BTC? → si', debolmente; nessuno sleeve nuovo

Script: scripts/research/r0725_statarb_multi.py.

Perche'. STATARB-RESID e' il miglior lead del progetto e ha un gate di deploy al 2026-09-27, ma e' stato scoperto su UNA coppia dentro uno sweep. Test out-of-pair-sample: meccanismo congelato (W=45, sgn=+1) su tutte le 50 coppie alt/BTC di Hyperliquid, che non hanno partecipato alla scoperta.

Cosa regge:

  • 82% delle 50 coppie ha Sharpe netta > 0 (media 0.38, mediana 0.32).
  • 0/50 coppie degeneri: il segno del segnale e' quasi bilanciato (mono medio 53%) → NON e' la scommessa statica "short alt vs BTC" travestita, che era il modo di fallire pre-registrato.
  • p-permutazione a blocchi < 0.05 nel 18% delle coppie (atteso 5% per caso).
  • ETH/BTC e' al rango 22/50, 58° percentile: la coppia scopritrice NON e' un outlier. E' l'informazione piu' utile per il gate del 27/09: l'ipotesi "fortuna di una coppia" non regge.
  • Paniere EW delle 50 coppie: Sharpe 0.82, maxDD 6.0%, corr a XS01 solo 0.207 (non ridondante).

Cosa NON regge — e perche' non e' uno sleeve:

  • Ampiezza effettiva ~4.5, non 50 (corr media fra coppie 0.204: condividono la gamba BTC).
  • Block-bootstrap sul paniere: IC95% [0.12, +1.72], t ≈ 1.31 → non distinguibile da zero su 2.6 anni. Il t cross-coppie apparente di 5.05 e' gonfiato dalla dipendenza.
  • Contro il null "sempre short alt vs BTC" (a priori, nessun parametro stimato) l'uplift medio e' 0.11 e solo il 40% delle coppie lo batte: una parte del rendimento e' beta di regime 2024-2026, non timing.
  • Eseguibilita': 50 coppie = 51 gambe → STAT-MODE come XS01, fuori portata a $600.

Correzione a un mio errore di metodo, dentro questa stessa sessione. La prima stesura del null statico usava sign(mean(segnale)) sull'INTERO campione: un null che conosce gia' la direzione giusta, cioe' look-ahead. Rifatto in due versioni oneste — (a) causale con media espandente, (b) a priori sempre-short. L'uplift vs la versione causale e' mediana +0.10 / 58% positivo (debolmente favorevole); vs sempre-short e' negativo. Il numero pubblicabile e' questo, non quello della prima stesura.


(3) STATARB-EQ — lo stesso meccanismo su coppie ETF con 20-30 anni di storia → SCARTATO, e il crypto non ne esce rafforzato

Script: scripts/research/r0725_statarb_eq.py.

Perche'. La debolezza di STATARB-RESID non e' il segno dei numeri, e' la statistica: 2.6 anni, ampiezza effettiva 4.5. Le coppie ETF la attaccano frontalmente — 12 coppie definite a priori dentro la stessa classe d'attivo (DIA/SPY, IWM/SPY, QQQ/SPY, EEM/EFA, EWJ/EFA, FXI/EEM, EFA/SPY, SLV/GLD, IEF/TLT, HYG/LQD, LQD/AGG, USO/DBC), 28.5 anni, ampiezza effettiva 9.9, 4 regimi completi. Nessun data-mining di cointegrazione: cercare le coppie piu' cointegrate sugli stessi dati sarebbe selezione.

Esito: il meccanismo NON si trasferisce.

valore
Sharpe LORDA media / mediana 0.17 / 0.16 (25% positive)
Sharpe NETTA media / mediana 0.50 / 0.51 (8% positive)
paniere EW, 28.5 anni Sharpe 1.00, IC95% [1.36, 0.64], t 5.33
per decade 0.56 / 1.61 / 1.83 / 0.78 — negativo in 4/4
p-permutazione < 0.05 0% delle coppie
turnover 0.40/giorno → drag di fee 0.33 Sharpe
borrow 0 / 30 / 100 bps 1.00 / 1.06 / 1.21

La lettura corretta e' nella decomposizione lordo/netto, non nel netto. La lorda e' 0.17, non 1.00: due terzi del disastro sono drag di turnover. Quindi non esiste una "strategia specchio" da girare: sgn=1 avrebbe lorda ≈ +0.17 e netta ≈ 0.16, morta anch'essa sui costi. Il segno lordo dice pero' una cosa vera e interessante: sulle coppie azionarie il residuo REVERTE debolmente, mentre sul crypto CONTINUA (sgn=+1 vince). Il meccanismo di STATARB e' quindi plausibilmente specifico del crypto, non universale.

Onesta' sull'inferenza: che non funzioni sulle azioni NON dimostra che non funzioni sul crypto — gli indici azionari sono efficienti e le coppie alt/BTC hanno microstruttura e flussi diversi. Il punto e' negativo in modo preciso: il gate del 27/09 non puo' appoggiarsi all'argomento "e' un fenomeno universale, quindi e' reale". Non lo e'.


(4) ⚠ DIFETTO DI DATO: split NON aggiustati nel feed equity — trovato, riparato, gate chiuso

Emerso mentre diagnosticavo ritorni giornalieri impossibili in (3) (min 99.9%, max +112%).

Il fatto. data/raw/eq_iwm_1d.parquet e eq_efa_1d.parquet avevano uno split non aggiustato il 2005-06-09 (tornata di split iShares): IWM 94.13→47.53 (49.5%, rapporto 1.981 ≈ 2:1), EFA 85.91→28.76 (66.5%, rapporto 2.987 ≈ 3:1). IB ADJUSTED_LAST non li aveva aggiustati.

Perche' la certificazione non li vedeva — ed e' un punto cieco strutturale, non sfortuna. L'unica guardia sui salti era maxret > 50% → SPIKE?. Uno split 2:1 non aggiustato produce esattamente 50%: cade sul filo della soglia. IWM passava a 49.5% con status OK. La soglia era tarata precisamente sul valore che il difetto piu' comune genera.

Perche' importa: IWM e' una delle 6 gambe di GTAA01, sleeve in PRODUZIONE. Impatto misurato:

GTAA6 FULL Sh IS<2015 Sh OOS2015+ Sh maxDD
con difetto 0.61 0.49 0.86 15.38%
riparato 0.64 0.54 0.86 15.38%

Il difetto sottostimava lo sleeve (l'artefatto e' nel 2005, fuori dall'hold-out) → nessuna decisione presa va rivista, ma il dato e' ora corretto.

Il discriminante split-vs-crollo (la parte riusabile). Non basta il rapporto: SLV il 2026-01-30 ha fatto 28.5% con rapporto 1.3994, a 4 bps da 1.4. Il discriminante e' il range intraday:

  • SPLIT: la barra APRE gia' al nuovo livello, range intraday normale. IWM 2005-06-09: open 47.00, range 1.7%. Un crollo del 50% con range 1.7% non esiste.
  • CROLLO VERO: il movimento avviene DENTRO la barra. SLV: open 89.33, low 69.12, range 33%, volume raddoppiato, e GLD 10.3% lo stesso giorno. Stessa verifica su EEM 2008-10-28 (+26%, reale).

Cosa e' stato fatto:

  • Nuovo modulo src/data/eq_splits.pydetect_unadjusted_splits() (tre condizioni congiunte: |ret|>20% AND rapporto entro 1.5% da un fattore comune AND range intraday <5%) e repair_splits() (riscala i prezzi precedenti; split multipli si compongono; volume opposto).
  • Riparazione in lettura in entrambi i loader: src/portfolio/gtaa.py::_close (produzione) e scripts/research/eqlib.py::load_eq (ricerca).
  • Certificazione indurita: fetch_ib_equities.certify() ha ora lo status SPLIT-NON-AGG e riporta gli split rilevati.
  • Test tests/test_eq_splits.py (8 casi): i due split reali, il falso positivo SLV, un crollo 50% esatto con range grande, split multipli componibili, serie pulita invariata, ed end-to-end sui parquet. Suite completa: 180 passed.

Regola nuova: ogni soglia di certificazione tarata su un valore tondo va controllata contro il difetto che genera esattamente quel valore. Una soglia a 50% non puo' sorvegliare gli split 2:1.


(5) Addendum PRE-REGISTRATO al gate STATARB del 27/09

Registrato oggi, forward-day 26 di 90, 64 giorni prima della decisione — pre-registrazione vera, non selezione a posteriori. Motivo: il null "sempre short alt vs BTC" batte il segnale sul 60% delle coppie crypto, e su ETH/BTC (finestra HL 2024-2026) il pareggio e' quasi esatto (segnale 0.46 vs statica 0.48).

r0724_statarb_deploy_gate.py ora calcola e riporta anche lo Sharpe della statica sempre-short a pari vol-target sulla stessa finestra forward. Le soglie pre-registrate il 2026-07-24 (Sharpe≥0.5, DD<10%, haircut<0.5pp) NON sono state toccate: il benchmark e' una diagnostica obbligatoria da leggere insieme, e la decisione se renderlo binding spetta all'operatore.

Lettura di oggi (26 barre, da non sovrainterpretare): STATARB +5.70 contro benchmark statico 4.98. La posizione forward corrente e' LONG lo spread (+0.61), cioe' opposta alla scommessa statica → la finestra forward sta testando il segnale in un modo che il beta di regime non spiega. Prima lettura favorevole.


(6) XSR01 — il candidato che e' uscito dal filone (2): CROSS-SECTIONAL RESIDUAL

Script: r0725_statarb_basket_gate.py (gate), r0725_statarb_demean_skeptic.py (scettico), monitor scripts/live/paper_xsr.py, gate r0725_xsr_deploy_gate.py, test tests/test_paper_xsr.py.

Il paniere di coppie del punto (2) non era uno sleeve per un motivo diagnosticato, non subito: ampiezza effettiva 4.5 invece di 50, perche' le 50 coppie condividono la gamba BTC. Da qui una variante pre-registrata per ragione strutturale (prima di guardare i risultati): demeanare le posizioni cross-sezionalmente ogni giorno. L'algebra dice cosa succede:

sum_i (p_i  p̄)(r_i  r_btc) = sum_i (p_i  p̄) r_i        perche' sum_i (p_i  p̄) = 0

la gamba BTC si annulla, e con essa il fattore comune. Il risultato non e' piu' un paniere di coppie: e' una strategia cross-sectional dollar-neutral sui 50 alt con pesi (p_i p̄)/N.

V1 ALL50 V2 MAJ19 V3 DEMEAN
Sharpe netta 0.82 0.75 1.82
maxDD 6.0% 8.1% 2.6%
ampiezza effettiva 4.5 4.0 37.4
marginale vs TP01 ADDS NOISE ADDS
deflated-Sharpe 0.701 0.660 0.985 PASS

Gate superati. Marginale ADDS con robust_oos, beats_noise_null, is_hedge=False, has_insample_edge=True. Deflated-Sharpe 0.985 (soglia 0.95) su 3 varianti pre-registrate — e la config W=45/sgn=+1 viene da un altro studio, su questi dati non e' stata cercata. Correlazione ~0 a TUTTI e 5 gli sleeve attivi: TP01 0.060, XS01 0.019, VRP01 0.001, SKH01 0.001, GTAA01 0.071. Book a w=15%: HOLD 2.36 → 2.51, DD invariato.

Verifica avversariale (r0725_statarb_demean_skeptic.py) — numeri cosi' puliti sono, in questo progetto, il momento in cui di solito si trova l'artefatto. Quattro attacchi:

  • Tre null a fee-neutrale (permutazione cross-sezionale delle etichette-asset; posizioni casuali; permutazione temporale a blocchi 20g): tutti centrati a ~0.01 con p95 1.0-1.3, e il candidato LORDO 2.70 sopra il massimo di 300 estrazioni → p < 0.004 su tutti e tre. ⚠ Correzione di metodo: la prima stesura confrontava a fee piene, e i null uscivano a 3.7/4.2 perche' permutare fa esplodere il turnover → il null perdeva per COSTO, non per assenza di segnale, dando un p-value trionfale e falso. A fee zero il confronto isola l'informazione.
  • Lag: 1.82 → 1.19 → 0.81 → 0.51 a +0/1/2/3 giorni. Decadimento dolce = segnale lento reale; un look-ahead crollerebbe a zero al primo giorno di ritardo.
  • Ridondanza: contro un momentum cross-sectional semplice sugli stessi 50 (che fa Sharpe 0.03/0.17/0.79 a L=30/45/90) la correlazione e' 0.29/0.17/0.10 → non e' XS01 travestito.
  • Struttura: netto 2e17 (dollar-neutral esatto), 23.8 gambe long su 50 (bilanciato), lordo 14.4% del capitale.

Le tre debolezze, dichiarate — e' per queste che va in MONITOR e non nel book:

  1. Storia 2.6 anni, un regime solo, e il rendimento e' crescente (Sharpe 2024 1.03 / 2025 1.98 / 2026 3.11): la maggior parte dell'edge e' recente.
  2. weights_tilt_null NON passa (gate_pass=False a w=10% e 15%, delta_insample 0.004/0.007). E' un effetto strutturale della storia corta — ma un gate fallito resta fallito.
  3. Margine di costo sottile: 1.82 a 0.05%/gamba, 0.93 a 0.10%, NEGATIVA a 0.20%. Turnover 38.5% del lordo al giorno su 50 alt fra cui illiquidi (GALA, BLUR, JTO, ORDI, WIF) e slippage non modellato: e' il rischio numero uno.

Eseguibilita' — il numero che serve davvero: ticket medio per gamba $1.73 a $600 (sotto il min-order $5: STAT-MODE al capitale attuale), $5.76 a $2000, $14.41 a $5000. Cioe' XSR01 diventa reale intorno ai $5.000, non ai $20.000 di XS01.

Cablato come ogni lead del progetto: scripts/live/paper_xsr.py (config CONGELATA, tre libri paralleli MODELED $2000 / REAL $600 / REAL $5000 con min-order per gamba, stato append-only), inserito in cron_daily.sh, test a 7 casi che bloccano config, dollar-neutralita', causalita' dello step, min-order e la trappola dei timestamp. Gate di decisione pre-registrato oggi a forward-day 0: 2026-10-23, con soglia Sharpe ≥ 1.0 E una guardia di costo esplicita (haircut di eseguibilita' a $5000 ≤ 40%, altrimenti RITIRO a prescindere dallo Sharpe).

⚠ Trappola pandas ri-pagata e ri-documentata: astype("int64") su DatetimeIndex tz-aware dava epoche 1970 nel monitor. E' la gemella di quella dell'ondata 2026-07-01. Ora c'e' un test.


Bilancio

  • 1 candidato nuovo: XSR01, il primo da molte ondate a superare marginale-ADDS, deflated-Sharpe 0.95, tre null avversariali e il test di lag, con corr ~0 a tutti e 5 gli sleeve. In forward-monitor (NON nel book) per tre ragioni dichiarate: storia 2.6 anni, weights_tilt_null fallito, margine di costo sottile. Gate pre-registrato al 2026-10-23. Nota di onesta' su come e' nato: non e' uscito da un'idea nuova, e' uscito dalla DIAGNOSI di un fallimento — l'ampiezza effettiva 4.5 del paniere di coppie indicava un fattore comune da togliere, e toglierlo era una mossa algebrica obbligata, non una ricerca di parametri.
  • 2 refutazioni pulite con diagnostica riusabile: il soffitto d'ampiezza di GTAA01 e' gia' raggiunto; STATARB non e' un fenomeno universale (non si trasferisce alle azioni).
  • 1 difetto di dato sul libro live trovato, quantificato, riparato, testato e chiuso alla fonte.
  • Il gate del 27/09 arriva alla decisione con un'ipotesi alternativa in meno (fortuna di una coppia: refutata, 58° percentile) e un benchmark in piu' (beta statico, gia' favorevole).
  • Due errori di metodo miei, trovati e corretti dentro la sessione: null statico con look-ahead (STATARB-MULTI) e null a fee piene contro un segnale permutato ad alto turnover (scettico XSR01). Entrambi avrebbero prodotto numeri piu' belli e sbagliati.

Script: r0725_mat01_multiasset_trend.py, r0725_mat01b_regime.py, r0725_statarb_multi.py, r0725_statarb_eq.py, r0725_statarb_basket_gate.py, r0725_statarb_demean_skeptic.py, r0725_xsr_deploy_gate.py; monitor scripts/live/paper_xsr.py; modulo src/data/eq_splits.py; test tests/test_eq_splits.py, tests/test_paper_xsr.py.