Files
PythagorasGoal/docs/diary/2026-09-09b-debito-18-cblib-causale.md
T
Adriano Dal Pastro 0a2f780d3c cblib causale: spot +1h e DVOL +1 giorno (debito §5.18); §11 rimisurato 0,714 → 0,712, verdetti invariati
- cblib.causale(s, cadenza): spot_series e dvol_series escono causali (asof = ultima chiusura NOTA);
  il DVOL giornaliero era una seconda serie con lo stesso difetto (fino a 24h avanti), verificato contro
  l'API pubblica a 1h. Regolamento ST alle 08:00 invece delle 09:00.
- §11 riprodotto al millesimo su worktree HEAD (0,714 [0,690-0,779], n=19, flag --al) e rimisurato:
  0,712 [0,664-0,732]; solo spot 0,721, solo DVOL 0,693, DVOL orario di controllo 0,717. Mediana onesta
  BTC 1,45 → 2,12, fee 1,51x/1,87x. r0730: 0,73 → 0,71. §75: ETH pre 0,76, BTC durante 0,89 (orario 0,83).
  skew panel ≤0,005. vrp_f_watch: f canonico 0,732 → 0,706, differenza +0,097 [+0,042, +0,140].
- r0909 senza doppio shift, contesto sul DVOL del giorno; r0822 regime su date di calendario; r0901
  join riallineato (bit-exact). Aperti con costo: DVOL orario (−0,04/+0,06 nel crollo), spot 5m (≤25 min).
- test: +3 causalita' in test_cb_chain_vrp, anti-doppio-shift in test_r0909; suite 1011/1011.
- revisione fable: 16 segnalazioni, tutte applicate (fra cui un «−1,8% in un'ora» che era +3,9%).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Bjj5vPEBoAJrB23P6RjKzs
2026-09-09 21:41:23 +00:00

14 KiB
Raw Blame History

2026-09-09b — Debito §5.18 riparato: cblib causale (spot +1h, DVOL +1 giorno) e §11 rimisurato

Richiesta dell'operatore: "ripara il debito §5.18 su cblib e rimisura §11". Revisione col modello fable (agente fresco), come da regola.

Esito in una riga: riparato in cblib — spot e DVOL escono gia' causali — e §11 rimisurato allo stesso taglio: 0,714 [0,690-0,779] → 0,712 [0,664-0,732] (n=19). Il numero non si muove perche' le due correzioni hanno segno opposto; nessun verdetto cambia; riparando la prima serie ne e' uscita una seconda con lo stesso difetto (il DVOL giornaliero, fino a 24 ore avanti); il DVOL orario resta un passo aperto con costo misurato. Libro, config, cron: invariati. Nessun ordine.

0. Il difetto, verificato prima di ripararlo (D6: si controlla col lag, non si assume)

serie come e' etichettata prova look-ahead di asof(ts)
feed 1h certificato all'apertura: la barra T contiene la chiusura di T+1h chiusura 1h a T == chiusura 5m a T+55 nel 100% delle barre (BTC ed ETH, 1-5/06); a T5 nell'1,7% / 0% +1 ora
dvol_{asset}.parquet (giornaliero, fetch_dvol, resolution=86400) al giorno D contiene la chiusura delle 23:00 di D API pubblica a risoluzione 1h, 1-4/06: close 1D del giorno D == close 1h delle 23:00 di D, e open 1D di D+1 == close di D fino a +24 ore

La seconda riga non era nel debito: e' uscita controllando la convenzione dell'altra serie di contesto che cblib legge con lo stesso asof. Il sleeve (_vrp_weekly_asset) non ha il difetto: lavora a cadenza giornaliera e accosta la chiusura del giorno D al DVOL del giorno D, che a quella cadenza e' coerente. Il difetto e' solo di chi entra a un'ora con una serie giornaliera.

1. La riparazione

cblib.causale(s, cadenza) sposta le etichette (mai i valori) dall'apertura all'istante in cui la chiusura e' nota. spot_seriescausale(·, "1h"), dvol_seriescausale(·, "1D"). Conseguenze:

  • asof(ts) = ultima chiusura conosciuta a ts (prima della prima chiusura nota: NaN, non un valore).
  • il regolamento ST = S.asof(exp) alle 08:00 e' ora la chiusura della barra 07:00, cioe' il prezzo delle 08:00 — prima era la chiusura della barra 08:00, cioe' il prezzo delle 09:00, un'ora dopo la scadenza. Deribit regola su una TWAP dei 30 minuti prima delle 08:00: l'approssimazione e' ora dalla parte giusta dell'ora.
  • r0909_crash_catturato non ri-sposta (lo spot_causale locale della mattina e' rimosso: applicato due volte darebbe la chiusura di due ore prima — lo stesso errore col segno opposto). Test di non-regressione sul sorgente.
  • chi usa cblib: r0822_vrp_real_quotes (§11), r0822_skew (§5), r0909 (§75), vrp_f_watch (cron giornaliero, data/vrp_f_watch/state.json), e — trovati dal revisore, non da me — r0730_vrp_real_quotes (il f 0,73 [0,706-0,805] di CLAUDE.md §2: rigirato stampa 0,71 [0,680-0,756], n=27, 0/27 ≥ 1, f gamba lunga 1,66 → 1,49; verdetto invariato, numero dichiarato in §2) e r0901_btc_collar (join del DVOL per giorno: con la serie causale avrebbe accostato l'IV di D al DVOL di D1 — riallineato con causale(·, "-1D"), bit-exact a prima, §71 non si muove). options_vrp_calibrate.py ha una copia propria di spot_series (numeri del 20/06): non toccato, dichiarato.
  • la sezione di REGIME di r0822 (date di calendario: «ultimo giorno aperto», IV-rank per anno) e la tabella di contesto di r0909 usano causale(V, "-1D"): li' serve il DVOL del giorno, non l'etichetta causale — altrimenti ogni data stampata slitta di un giorno (trovato dal revisore).
  • r0822_vrp_real_quotes ha ora il flag --al <data> (taglio delle scadenze) per riprodurre una misura a una data: senza, "riprodurre il 22/08" era impossibile perche' la catena cresce ogni ora.

2. Prima di pubblicare il numero nuovo, la macchina ha riprodotto quello vecchio (M23)

Worktree di HEAD (git worktree add, data/raw in symlink), stesso script con --al 2026-08-22: pooled 0,714 (IC95 [0,690, 0,779], n=19) — al millesimo, IC compreso. Poi lo stesso comando sul codice riparato.

3. Scomposizione: due correzioni di segno opposto (M26) e un controllo orario

taglio spot DVOL pooled f IC95 n
22/08 grezzo grezzo (com'era) 0,714 [0,690, 0,779] 19
22/08 causale grezzo 0,721 [0,685, 0,758] 19
22/08 grezzo causale (giornaliero) 0,693 [0,670, 0,748] 19
22/08 causale causale (giornaliero) = cblib oggi 0,712 [0,664, 0,732] 19
22/08 causale causale orario (controllo, API pubblica) 0,717 [0,667, 0,732] 19
09/09 grezzo grezzo 0,720 [0,717, 0,952] 23
09/09 causale causale (giornaliero) 0,712 [0,677, 0,741] 23
09/09 causale causale orario 0,726 [0,680, 0,738] 23

Il DVOL di fine giornata alzava f: nel rally la vol scende dentro il giorno, la chiusura di D sta sotto quella di D1 (+1,05 pt di vol mediana su 19/19 trade, misura del revisore) → denominatore piu' basso → f piu' alto; causale: 0,021. Lo spot di un'ora dopo, invece, non e' un meccanismo ma rumore: lo scarto per trade ha segno misto (mediana 0,02% BTC / 0,11% ETH, banda 0,6…+0,9%) e sposta f fino a ±0,15 per trade (lo spread δ−0,28/0,10 ha delta netto ~0,18: 0,5% di spot vale 15-20% del credito modellato); il +0,007 netto e' la somma di 19 segni. ⚠️ Corollario: lo spot causale resta stantio fino a 25 minuti (snapshot al :25, chiusura nota al :00), cioe' ±0,05-0,10 di f per osservazione; il feed 5m certificato lo porterebbe a ≤5 minuti. Non fatto: dichiarato in §6. Il DVOL giornaliero causale e' stantio fino a 23 ore (agli ingressi delle 08:00: 8 ore): scarto mediano dall'orario 0,2 punti di vol, max 1,1 (22/08) / 3,0 (oggi). Su §11 vale 0,005 di f.

4. Cosa cambia in §11 (taglio 22/08, stesso campione)

grandezza prima dopo perche'
f pooled 0,714 [0,690-0,779] 0,712 [0,664-0,732] §3
f BTC / ETH 0,706 / 0,715 0,720 / 0,692
Sharpe canonico BTC (titolo, non citabile) 32,58 29,61 regolamento alle 08:00
mediana onesta BTC (9 ancore) 1,45 2,12 banda [0,19, 29,61] (era [0,35, 32,58])
Sharpe canonico ETH → mediana onesta 3,90 → 2,41 7,64 → 3,35 una settimana ETH cambia taglia: 26/06 27,38 → 12,84 $ (BTC: 31/07 19,88 → 31,69, 14/08 12,94 → 8,68)
media BTC fra le ancore 1,35% → +11,22% 0,66% → +11,44% cambia ancora segno; sd 11,1× → 9,2×
forfait fee vs listino 1,44× / 1,80× 1,51× / 1,87× credito modellato a DVOL causale
peggior mark: mediana / minimo / minimo fra le vincenti 6,4% / 91,0% / 56,9% 6,4% / 91,5% / 55,2%
P&L somma 19 settimane $2.733 $2.822 (+3,3%) tutto dal regolamento
sottostante nel campione +25,1% / +44,2% +21,1% / +40,1% il vecchio regolamento del 21/08 era il prezzo delle 09:00, che sta +3,9% sopra quello delle 08:00 (76.311 → 79.316): un numero a due estremi pesa un'ora intera. (La prima stesura diceva «−1,8%»: avevo letto l'ora dopo, 09:00 → 10:00. Corretto dal revisore)

Verdetto di §11: SCARTATO, per le stesse quattro ragioni (il campione non contiene la strategia; il titolo non sopravvive all'ora d'ingresso; la famiglia con storia non e' quella eseguibile; lo spread e' il costo dominante). Nessuna delle quattro dipende da un'ora di spot. Il testo del verdetto nello script riporta i numeri nuovi con i vecchi accanto.

5. Effetti collaterali, misurati (tutto cio' che legge cblib)

§75, crollo catturato (r0909, rigirato): ETH pre-crollo f_net 0,74 [0,65-0,82] → 0,76 [0,71-0,86]; peggior MTM 1,08 [1,07-1,31] → 1,08 [1,06-1,27]; put δ−0,10 1,92× → 1,98×; al picco 0,94 → 0,99; BTC durante 0,79 → 0,89 [0,74-1,05], ETH durante 0,71 → 0,78. Con il DVOL orario BTC durante fa 0,83: nel crollo il DVOL sale di 5-6 punti al giorno, quindi il giornaliero di fine giornata (com'era) sottostima f e quello del giorno prima (causale) lo sovrastima — 0,04/+0,06 di f e' il prezzo della stantiezza in un crollo, ed e' l'argomento per il feed orario. DVOL "pre" 37,3 → 36,4 (BTC): il 37,3 era la chiusura del primo giorno di crollo (01/06, 3,5%), non del giorno prima — IV-rank pre 0,05 → 0,03. Picco e percentili invariati (49,1 / 69,2; 29° / 46°) dopo aver corretto la tabella di contesto (§7). Verdetto invariato.

§5, skew (r0822_skew, rigirato, 66 s): la scomposizione sul panel si muove di ≤0,005 per fattore (term 0,880 · skew 0,917 · spread 0,910 · fit 0,995 · f_tot 0,729); Q1/Q2 (lag prezzo/skew) non si toccano (serie proprie ancorate a ts_max). Agli ingressi il controllo f_markfit passa da 1,045 a 0,991 e le osservazioni che lo superano da 22/28 a 25/28: l'ora di spot in piu' stava nel controllo, non nell'effetto — riparare ha reso il controllo piu' pulito, non il risultato diverso.

vrp_f_watch (sorvegliante in cron_daily, criteri pre-registrati il 30/07 e non toccati):

prima (state.json del 09/09 mattina) dopo
coppie 28 28
f canonico 0,732 [0,702-0,784] 0,706 [0,678-0,745]
f candidato 0,803 [0,741-0,842] 0,805 [0,771-0,840]
differenza +0,054 [0,027, +0,105], 18/28 > 0 +0,097 [+0,042, +0,140], 21/28 > 0
ampiezza IC95 (b ≤ 0,12) 0,131 — no 0,098 — OK
coppie (a ≥ 40) no no
ready False False

Lo state.json e' stato riscritto dal mio lancio (21:14Z, senza --quiet; nessun Telegram: notifica solo a ready); il «prima» completo e' la colonna qui sopra (n_positive 18, esclude_zero False), e il cron lo rigenera domani. La differenza ora esclude lo zero. Non decide niente: (a) non e' soddisfatto e il candidato resta bocciato sul deflated-Sharpe, che non dipende da f. Si registra perche' fra un mese qualcuno leggera' "esclude lo zero" e deve sapere da quando e perche'.

6. Cosa resta aperto, col suo costo

voce costo di non farlo costo di farlo
DVOL orario nel feed (fetch_dvol --res 3600, riga in cron_daily, cblib che lo legge) su §11 0,005 di f; su un crollo ±0,05; ogni misura oraria su opzioni a DVOL giornaliero eredita lo scarto un fetch pubblico gratuito (3.163 barre da maggio in 2 chiamate), una riga di cron, e una decisione: e' un feed nuovo dentro il perimetro (D1, certificazione, backup)
spot causale stantio ≤25 min (snapshot :25, chiusura :00): ±0,05-0,10 di f per osservazione cblib.spot_series sul feed 5m certificato (causale(·, "5m")): cambia di nuovo ogni numero di cblib, quindi con rimisura dichiarata
options_vrp_calibrate.spot_series (copia, 20/06) i numeri del 20/06 (f 0,73) restano con l'ora in piu'; §11 li ha gia' sostituiti riscriverlo su cblib
la tabella pubblicata di §5 (x0,869 / x0,904 / x0,920) ≤0,005 per fattore: sotto la risoluzione del campione (14+14 scadenze) nulla: nota aggiunta

7. Errori dell'autore in sessione

  • asi8 in microsecondi scrivendo il test della causalita' (pandas 3): i timestamp sintetici finivano nel 1970 e il test falliva per la fixture, non per il codice. E' la trappola del debito 1, ripagata scrivendo un test sul debito 18. Corretto con (idx epoch) // Timedelta(ms), la convenzione di load_tf.
  • La tabella di contesto di r0909 si e' spostata di un giorno dopo la riparazione: mostrava il DVOL del giorno D1 accanto al prezzo del giorno D, e il picco del crollo cambiava (69,2 → 68,3, 46° → 43°) non per una misura ma per un'etichetta. Trovato col diff degli output, non da un test: una tabella per umani non ha test. Ora il contesto usa la chiusura del giorno (causale(V, "-1D"), dichiarato nel commento) e dvol_pre / ivr_pre restano causali.
  • Il verdetto §7 di r0822_vrp_real_quotes era prosa con numeri cablati: sarebbe rimasto a 0,714 per sempre (N11 al contrario). Aggiornato con i vecchi accanto; il difetto di forma resta (i numeri del verdetto andrebbero calcolati, non scritti).

8. Revisione (fable, agente fresco) — 16 segnalazioni, verdetto «correggi e committa»

Ha riverificato in proprio la convenzione delle due serie (1h vs 5m su 120 barre: 100%; DVOL contro l'API oraria) e riprodotto ogni numero dei documenti lanciando gli script. Applicate: #2 «−1,8% in un'ora» era falso (avevo letto 09:00 → 10:00; il fatto e' +3,9% 08:00 → 09:00) · #3 due delle tre settimane «ETH» erano BTC · #4 la parentesi sul DVOL era invertita (la chiusura di D e' piu' BASSA, non piu' alta) · #5 lo spot non e' un meccanismo ma rumore, e resta stantio ≤25 min · #6/#7 due lettori di cblib non dichiarati: r0730 (0,73 → 0,71, ora in CLAUDE.md §2) e r0901 (riallineato) · #8 le date di calendario di r0822 §1 slittavano di un giorno · #9 il test anti-doppio-shift non catturava causale(spot_series, "1h"): ora conta i causale( · #10 ancora 0,74 → 0,76 nel test d'integrazione · #11 teste di §75 e memoria 20 §5 con i numeri vecchi come correnti (M28) · #12 «±0,05» → «−0,04/+0,06» · #13 state.json riscritto: dichiarato · #15 lo skew agli ingressi cambia piu' del panel (correlazioni che cambiano segno): dichiarato in §5. Non applicate: nessuna. Confermati senza rilievo (#1, #14, #16): verso e taglia degli shift, nessun doppio spostamento, ST alle 08:00 coerente con la TWAP 07:30-08:00, tutti i numeri di §3-§5.

9. Test

tests/test_cb_chain_vrp.py: +3 (causale; spot_series causale sul feed 1h con controllo positivo sulla serie grezza; dvol_series causale sul giornaliero). tests/test_r0909_crash_catturato.py: il test dello shift locale diventa "lo script usa le serie di cblib senza ri-spostarle" (sorgente + controllo positivo su cblib.causale). Suite intera: 1011 passati, 0 falliti (erano 1008), rilanciata dopo le correzioni della revisione: 1011/1011.