Files
PythagorasGoal/docs/diary/2026-07-26-wave-esecuzione-dvolspread-xsr-equity.md
T
Adriano Dal Pastro 841f48c319 ops(live): cabla il forward-monitor DVOLSPREAD nel cron + gate pre-registrato
Chiude la lezione (c) dell'ondata 26/07: "un lead in forward-monitor senza
monitor e senza scadenza e' un lead perso" — DVOLSPREAD era in limbo da 35
giorni. Ora ha config congelata, monitor nel cron e gate con data.

Config congelata = la cella scelta IN-SAMPLE (zwin=180 k=2.0 lw=0.6 zw=1.1
tgt=0.17 svw=60), NON quella pubblicata dall'agente: quella era 83a/729
sull'hold-out ma 471a/729 in-sample e fallisce il deflated-Sharpe (0.947),
la congelata lo passa (0.953). Riusa make_book di r0726_dvolspread_gate,
nessuna reimplementazione.

Strumentazione specifica: il book va flat quando manca il DVOL, quindi un feed
rotto produrrebbe zeri che contati come evidenza direbbero "nessuna perdita"
invece di "nessuna misura". Contabilita' a 3 stati (attive / flat-da-segnale /
flat-senza-dato), finestra misurata in barre ATTIVE, e guardia che esce 1 se
FROZEN diverge dallo stato salvato.

Gate pre-registrato: kill 2026-10-24 se Sharpe < -0.50; decisione 2027-01-24
solo se Sharpe>0 E marginale ADDS E deflated-Sharpe>=0.95 E weights_tilt_null;
veto d'integrita' se barre attive <80% (si estende, non si decide su dati
mancanti). La soglia su Sharpe e' debole di proposito: con ~180 barre
SE(Sharpe)~1.4, una soglia alta sarebbe finta precisione.

Inception 2026-07-25, apertura +0.184 = $111/gamba (cap $300).
Book/pesi INVARIATI. Suite 255 verdi.

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

15 KiB
Raw Blame History

2026-07-26 — Ondata a 3 filoni: esecuzione SKH01, DVOLSPREAD, XSR01 fuori dal crypto

Script: r0726_skh_onbook.py · r0726_dvolspread_gate.py · r0726_xsr_equity.py Test: tests/test_wave_0726.py (11 casi) · suite completa 245 verdi Book / pesi / cron: INVARIATI. Una raccomandazione operativa aperta (T1), nessuna modifica fatta.

Tre filoni scelti non per esplorare aree nuove — quelle sono in gran parte sature — ma perché il progetto stesso aveva lasciato tre questioni aperte e decidibili oggi:

filone questione aperta esito
T1 il degrado del path live di SKH01 (~0.35 Sh) è recuperabile? ⚠️ il degrado era a sua volta fortuna d'ancora; metà del fix funziona, l'altra metà no
T2 DVOLSPREAD, in limbo dal 21/06, è sleeve o falso positivo? regge i gate che non esistevano allora — promosso a forward-monitor con parametri onesti
T3 XSR01 regge fuori dal crypto e da 2.6 anni monoregime? no — e si scopre perché

T1 — Il degrado d'esecuzione di SKH01 era anch'esso un artefatto d'ancora

La domanda

Il book live gira SKH01 con cron orario e uscite software. Costo misurato (audit 02/07, riconfermato il 24/07): sleeve FULL 1.46→1.19, HOLD 1.64→1.15, DD 18%→25%. È il buco singolo più grande del progetto, e il 24/07 aveva già stabilito che un cron più veloce non lo recupera.

L'angolo mai testato è l'unico meccanismo che non è un cron: gli ordini resting on-book, dove esiste un'asimmetria che nessuno aveva sfruttato:

  • il TP è un limit order: se il prezzo ci arriva, il fill è al livello per costruzione (sei il maker), e per giunta a fee maker invece che taker;
  • lo SL è uno stop-market: al trigger diventa un ordine a mercato, e in un gap riempie peggio.

Ipotesi: il grosso del degrado sta sul lato TP, quindi è recuperabile senza rischio nuovo.

Il risultato, e la trappola che ha nascosto

A offset 0 — la griglia che gira davvero — il quadro sembrava trionfale: l'on-book completo recupera il 94% del degrado. Ma l'offset 0 è già noto essere al 93-98° percentile dei 23 offset a priori, quindi la lente onesta è la banda.

E qui c'è stato un mio errore di statistica, corretto in corso: avevo confrontato mediana(canonical) mediana(hourly), che confronta offset diversi fra loro. Gli offset sono coppie appaiate: la statistica giusta è la mediana delle differenze. Con quella:

modalità ΔFULL mediana [min,max] ΔHOLD mediana migliora in
canonical (tetto teorico) +0.054 [0.05,+0.12] +0.099
solo TP a limite +0.054 [0.03,+0.07] +0.061 FULL 19/23 · HOLD 21/23 · DD 19/23
TP + SL on-book +0.024 [0.07,+0.11] +0.031 FULL 17/23 · HOLD 14/23
contributo del solo lato SL 0.010 [0.13,+0.08] 11/23 = una moneta

Due conclusioni, entrambe diverse da quella che cercavo.

(1) Il "0.35 del path live" è a sua volta un artefatto dell'offset 0. L'audit del 02/07 aveva de-luckato i numeri headline di SKH01 ma aveva misurato il degrado solo a offset 0. Sulla banda appaiata il degrado massimo recuperabile è +0.054 di Sharpe sul book, non +0.35 sullo sleeve. Il buco più grande del progetto era in buona parte fortuna d'ancora anche lui.

(2) Lo stop on-book PEGGIORA. Mettere lo SL sul book cristallizza la perdita al livello, mentre l'uscita software ritardata a volte incassa il rimbalzo: contributo mediano 0.010, positivo in 11/23 offset = indistinguibile da una moneta. La sensibilità lo conferma: sopra lo 0.50% di slippage sullo stop l'on-book è peggio del live di oggi.

Il meccanismo è misurato, non ipotizzato: sulle uscite TP il fill orario batte il livello nel 42% dei casi (vantaggio medio 0.035%) — è quasi una moneta, quindi il limit TP converte una lotteria in una certezza più che aggiungere ritorno. E solo l'1% degli SL gappa davvero dentro la barra 5m: il gap-through dei crash è reale ma raro.

Raccomandazione (NON eseguita)

Appoggiare il TP come limit resting reduce-only; NON mettere lo SL strategico sul book. Guadagno atteso +0.054 FULL / +0.061 HOLD sul book, positivo in 19-21 offset su 23, più il risparmio taker→maker su un quarto dei trade.

È un cambio di esecuzione, non di strategia, quindi non passa da weights_tilt_null. Ma è piccolo, e va pesato contro il costo operativo vero: ordini orfani se il cron muore, gestione del reduce-only, doppio fill. Non l'ho implementato: è una decisione dell'operatore, non un fatto compiuto. Il disaster-SL on-book a 30% resta com'è (è un'altra cosa: protezione, non exit).


T2 — DVOLSPREAD regge i gate che nel giugno non esistevano

Chi è, e perché era in limbo

agent_14_dvol_spread (onda ortho, 21/06) è l'unico sopravvissuto al marginal scorer indurito: dei 18 book relative-value che facevano ADDS con lo scorer vecchio, l'indurito ne lasciò in piedi uno, questo. Da allora non è mai stato ripreso — non è nel book, non è in un monitor, non è stato rifiutato. Era semplicemente lì.

Il segnale: log(DVOL_btc) log(DVOL_eth), tilt verso la gamba con vol implicita più ricca (tesi VRP / fear-reversal), market-neutral per costruzione, eseguibile a $600.

Nel frattempo il progetto ha codificato due gate che il 21/06 non c'erano, ed erano proprio quelli che colpivano le sue riserve dichiarate:

  1. deflated_sharpe (29/06) — l'agente dichiara da sé uno sweep di celle. Nel giugno "72/72 celle ADDS" si leggeva come robustezza; il DSR dice che sono anche 72 tentativi.
  2. select_cell_insample (29/06) — il plateau dell'agente è descritto in termini di uplift_hold, cioè la cella è stata guardata sull'hold-out. È la firma esatta che il gate selection-on-holdout fu scritto per catturare.

Esito

⚠️ Prima osservazione: la griglia dichiarata è sbagliata. Il docstring dice "72-cell sweep", ma il plateau che descrive è 6 assi × 3 valori = 729 combinazioni. Le ho valutate tutte e 729 — scelta conservativa, perché più trial abbassano il DSR.

Il plateau è reale e larghissimo: FULL in [0.60, 0.71], HOLD in [0.68, 0.97], e 729/729 celle con hold-out positivo. Non è una cella fortunata.

La selection-on-holdout c'è, ma è mite. La cella pubblicata è 83ª/729 sull'hold-out ma 471ª/729 in-sample — la firma è inequivocabile. Solo che, essendo il plateau così piatto, scegliere onestamente la cella in-sample costa poco:

cella FULL IS HOLD DSR (729 trial)
scelta IN-SAMPLE (onesta) 0.68 0.70 0.69 0.953 PASS
scelta sull'hold-out (proibita) 0.68 0.58 0.97
pubblicata dall'agente 0.66 0.57 0.93 0.947 FAIL

Cioè: l'hold-out onesto è 0.69, non il 0.93 pubblicato — un haircut reale — ma resta chiaramente positivo. E la cella onesta passa il deflated-Sharpe (0.953) mentre quella pubblicata lo fallisce (0.947), il che è di per sé una conferma che il gate fa il suo lavoro.

Marginale vs TP01 sulla cella onesta: ADDS, robust_oos ✓, multicut_persistent ✓, is_hedge ✗, has_insample_edge ✓, beats_noise_null ✓; corr +0.11, alpha annua +7.4%, beta a TP01 +0.117, jackknife_min_uplift +0.069; dSharpe sul book +0.08 FULL / +0.17 HOLD a w=15%, +0.11 / +0.25 a w=25%.

Verdetto: promosso, ma non nel book

DVOLSPREAD esce dal limbo e diventa un candidato in forward-monitor con parametri ONESTI (zwin=180, k=2.0, lw=0.6, zw=1.1, tgt=0.17, svw=60 — la cella in-sample), non quelli pubblicati.

Monitor CABLATO (stessa sessione)

scripts/live/paper_dvolspread.py, in cron_daily.sh dopo fetch_dvol.py (quindi con DVOL fresco), stato in data/paper_dvolspread/ (gitignored), test tests/test_paper_dvolspread.py (10 casi). Inception 2026-07-25, posizione d'apertura +0.184 → $111/gamba (cap $300).

Strumentazione specifica di questo lead — la ragione per cui non bastava copiare paper_statarb: il book va flat quando il DVOL manca, quindi un feed rotto produrrebbe una fila di zeri che, contati come evidenza, direbbero "nessuna perdita" invece di "nessuna misura". Il monitor tiene una contabilità a tre stati — ATTIVE / flat-da-segnale / flat-senza-dato — e la finestra forward si misura in barre attive, non in giorni di calendario. C'è anche una guardia sulla config: se FROZEN diverge dallo stato salvato il monitor esce con codice 1 invece di continuare su una finestra non più valida (verificato; nel cron non c'è set -e, quindi segnala senza rompere la catena).

Gate pre-registrato (scritto oggi, prima di vedere qualsiasi barra forward):

  • kill anticipato 2026-10-24 (~90g): Sharpe forward < 0.50 → ritiro;
  • decisione 2027-01-24 (~180g): promozione solo se tutte e quattro — (a) Sharpe > 0, (b) marginale ancora ADDS + robust_oos + has_insample_edge, (c) deflated-Sharpe ricalcolato sul campione esteso ≥ 0.95, (d) weights_tilt_null superato;
  • veto d'integrità: barre attive < 80% → la finestra non conta, si estende invece di decidere su dati mancanti.

⚠️ La soglia (a) è deliberatamente debole — necessaria, non sufficiente. Con ~180 barre attive l'errore standard dello Sharpe è ≈1.4: una soglia più alta sarebbe finta precisione. Il peso della decisione sta su (c) — se il margine 0.953, già sul filo, non migliora con più dati, l'edge non c'è.

Perché NON entra nel book, dichiarato:

  • campione ATTIVO 1949 giorni su 2691 (72%): prima del 2021-03 non esiste DVOL e il book è correttamente flat. L'hold-out attivo è 1.6 anni;
  • margine DSR sul filo (0.953 vs soglia 0.95) — un passaggio, non un'assoluzione;
  • non ha ancora affrontato weights_tilt_null, che ogni cambio di pesi deve superare;
  • il numero headline che circolava (HOLD 0.93) era gonfiato dalla selezione: va citato 0.69.

T3 — XSR01 non generalizza fuori dal crypto (e si capisce perché)

La domanda

XSR01 ha superato tutto ciò che gli è stato chiesto, ma la sua debolezza numero uno è dichiarata: 2.6 anni monoregime, con l'edge crescente nel tempo (Sharpe 2024 1.03 / 2025 1.98 / 2026 3.11). Con 2.6 anni non si distingue un meccanismo da un regime fortunato. L'unico modo di guadagnare potenza senza aspettare è portare il meccanismo congelato su un pannello lungo decenni.

Non è il test del 25/07. r0725_statarb_eq.py aveva già scartato le azioni, ma testava il meccanismo a coppie. XSR01 è la versione DEMEANATA cross-sezionalmente, ed è proprio il demeaning ad aver creato l'edge (ampiezza effettiva 4.5 → 37.4). Testare il demean sulle azioni è una domanda diversa, mai posta.

Esito

Meccanismo congelato (W=45, sgn=+1, residuo OLS causale vs SPY, z-score, tanh, vol-target 20%, demean giornaliero), split IWM/EFA riparati in lettura, annualizzazione a √252 (giorni di borsa):

universo variante ampiezza eff. Sharpe LORDA Sharpe netta maxDD
SECT9 (9 settoriali, 1998+, 26 anni) coppie 5.3 0.05 1.67 91%
SECT9 DEMEAN (= XSR01) 6.2 +0.24 1.61 89%
ALL28 (tutti gli ETF, 30 anni) coppie 8.4 0.20 1.61 92%
ALL28 DEMEAN 11.3 0.14 1.82 91%
XSR01 crypto (25/07, riferimento) DEMEAN 37.4 +2.70 +1.82 2.6%

Null di permutazione cross-sezionale a fee zero (la lezione XSR01: permutare un segnale ne fa esplodere il turnover, quindi a fee piena il null perderebbe per costo e regalerebbe un p-value trionfale e falso): SECT9 candidato +0.24 vs null medio 0.00, p = 0.193; ALL28 0.14, p = 0.747.

Per decennio (DEMEAN, lordo): SECT9 0.88 / +0.49 / +0.29 / +0.74 · ALL28 0.88 / +0.46 / +0.38 / +0.05. Stesso profilo nei due universi: fortemente negativo 1998-2005, debolmente positivo poi — il che somiglia più a un cambio di regime che a un edge.

Il risultato più interessante non è il Sharpe, è l'ampiezza

Il demeaning non fa sulle azioni quello che fa sul crypto. Sul crypto porta l'ampiezza effettiva da 4.5 a 37.4 (8×); sulle azioni da 5.3 a 6.2 e da 8.4 a 11.3 (1.2-1.35×).

Il perché è strutturale, e spiega XSR01 meglio di quanto lo spiegasse la sua scoperta: il residuo OLS rimuove già il beta al fattore comune. Sul crypto, dopo aver residualizzato su BTC, alle gambe resta un enorme fattore comune (ampiezza 4.5 su 50 gambe = quasi una gamba sola) — ed è quello che il demeaning toglie. Sulle azioni il residuo-vs-SPY è già quasi indipendente (5.3 su 9 gambe), quindi il demeaning non ha molto da togliere e non c'è guadagno.

Cosa significa per il gate del 2026-10-23

Il 25/07 aveva già scritto che «il gate non può appoggiarsi all'argomento fenomeno universale». Questo test lo conferma e chiude la scappatoia che il test a coppie lasciava aperta: nemmeno la versione demeanata — quella vera di XSR01 — funziona sulle azioni.

Onestà su cosa NON prova: non prova che XSR01 sia falso. Prova che è crypto-specifico, e suggerisce quale sia il meccanismo (l'esistenza di un fattore comune residuo che sopravvive alla residualizzazione, cosa che le azioni non hanno). Il gate del 23/10 resta interamente appoggiato sulla finestra forward e sull'haircut di eseguibilità a $5.000, come pre-registrato. Nessuna soglia toccata.


Lezioni da portare avanti

  1. Se si de-lucka una strategia, va de-luckato anche il suo DEGRADO. L'audit del 02/07 ha corretto i numeri headline di SKH01 per la fortuna d'ancora ma ha misurato il costo d'esecuzione a offset 0 — e quel costo si è rivelato fortunato quanto i numeri che correggeva. Ogni Δ fra due varianti misurato su una griglia ancorata eredita la fortuna dell'ancora.

  2. Su una griglia di offset appaiati, la statistica è la mediana delle DIFFERENZE, non la differenza delle mediane. La seconda confronta offset diversi fra loro e qui ribaltava il verdetto (faceva sembrare l'on-book completo migliore del solo TP, mentre è il contrario).

  3. Un lead lasciato "in forward-monitor" senza monitor e senza data di scadenza è un lead perso. DVOLSPREAD è stato in limbo 35 giorni. La disciplina che il progetto applica ai candidati nuovi (config congelata + gate pre-registrato + cron) non era stata applicata a lui.

  4. Il claim di multiple-testing di un agente va ricontato, non creduto. Il docstring diceva 72 celle; la griglia descritta ne contiene 729. Ricontare è conservativo e costa poco.

  5. Quando un meccanismo non generalizza, chiedersi PERCHÉ vale più del fatto che non generalizzi. Il fallimento di XSR01 sulle azioni ha prodotto la spiegazione migliore di come funziona sul crypto: il demeaning vale quanto vale il fattore comune residuo dopo la residualizzazione, ed è una proprietà dell'asset class, non del segnale.