Files
PythagorasGoal/docs/diary/2026-07-26-wave-tp01-partial-gates.md
Adriano Dal Pastro 37be1df838 research: ondata 26/07-bis — TP01 su barra parziale + i 2 gate mai costruiti
0 sleeve nuovi. Book, pesi, cron, config INVARIATI.

T1 — anche TP01 legge una barra giornaliera PARZIALE nel live, ma non conta.
Stesso fatto strutturale di SKH01: resample_tf non scarta il giorno in corso e
current_target prende [-1]; il feed si ricostruisce alle 00:30 UTC, quindi per
tutta la giornata il book vede oggi come 1 barra oraria su 24 (verificato).
Il docstring "ultima barra CHIUSA" era falso: corretto.

Tre path a un grado di liberta' per volta, 24 ancore, differenze appaiate:
  barra parziale   ΔFULL -0.031 (pos 7/24)  ΔHOLD +0.118 (pos 19/24)
  ritardo 1h       ΔFULL -0.004 (pos 11/24 = moneta)
  leva LIVE/MODEL  1.004
-> trascurabile, nessun cambio al live.

All'ancora canonica sembra peggio del vero: a offset 0 la parziale costa -0.230
di hold-out, che e' il MINIMO della banda (mediana +0.118). Speculare alla
lezione del 26/07: li' l'ancora canonica nascondeva un vantaggio, qui inventa
un danno.

REGOLA: la parzialita' dell'ultima barra conta in proporzione a quanto il
segnale pesa la barra piu' recente. Donchian breakout su 230m (la barra corrente
E' il segnale) -> +0.38; TSMOM 30/90/180g -> ±0.03. Non si trasferisce.

T2 — implausible_sharpe e anchor_luck_band codificati in altlib (debito
raccomandato 3 volte e mai scritto), piu' anchor_luck_delta che codifica
l'errore di stamattina (mediana delle differenze appaiate, non differenza
delle mediane).

Il gate ha segnalato VRP01 e il difetto era MIO: perdite contate su tutte le
barre, ma VRP01 e' settimanale su griglia giornaliera (94.2% di zeri) -> "0.96%,
coda assente" su uno sleeve in produzione. Sulle barre ATTIVE e' 16.5%, la forma
giusta di un credit spread a rischio definito. La lezione era gia' cablata il
giorno prima nel monitor DVOLSPREAD ("barre attive, non giorni di calendario").

Applicazione retroattiva 7/7 tutti ok, con controlli positivi obbligatori
superati (firme CC01 e deep-OTM segnalate, rumore Sh 0.62 no).

Replica indipendente del finding d'ancora del 02/07: il gate applicato alla
cieca a TP01 ritrova canonica +0.237 = 92 pctl delle 24, mediana onesta +0.056,
fortuna +0.182 — contro mediana 0.04 misurata il 02/07 con implementazione
separata. L'hold-out onesto di TP01 e' ~+0.05, non 0.31.

NON fatto: il book ricalcolato sul path live, bloccato da incompatibilita' di
lenti (simulatore per-trade vs sleeve vol-targeted). Follow-up dichiarato.

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

9.8 KiB
Raw Permalink Blame History

2026-07-26-bis — Ondata: TP01 su barra parziale + i due gate mai costruiti

Richiesta: "fai un'altra ondata di ricerca". Esito: 0 sleeve nuovi, 1 audit sul libro live, 2 gate codificati, 1 falso positivo del mio stesso gate su uno sleeve in produzione (catturato e corretto), 1 replica indipendente di un finding di tre settimane fa. Book, pesi, cron, config: INVARIATI.

Script: scripts/research/r0726_tp01_partial_day.py, scripts/research/r0726_gates_retro.py. Test: tests/test_gates_implausible_anchor.py (13). Gate in scripts/research/alt/altlib.py.

Da dove nasce: il 26/07 ho misurato che il path live di SKH01 divergeva dal modello su entrambi i lati (uscite e ingressi) e che il modello era pessimistico. Due domande restavano aperte, ed erano piu' interessanti di un'ennesima caccia al segnale: lo stesso difetto esiste sullo sleeve che pesa il 75% del book? e perche' i gate che il progetto si e' raccomandato tre volte non esistono ancora?


T1 — TP01 nel live legge una barra giornaliera fatta di UN'ORA

Il fatto, verificato non dedotto. resample_tf(..., label="left", closed="left") non scarta il giorno in corso; TrendPortfolio.current_target prende target_series(df)[-1]. Il feed certificato si ricostruisce alle 00:30 UTC, quindi per tutta la giornata il book vede il giorno corrente come 1 barra oraria su 24 (misurato: barre1h=1/24). Il docstring diceva "ultima barra CHIUSA": falso nel live, ed e' la terza volta in due giorni che un docstring di produzione afferma una causalita' che il codice non ha.

Due canali con segno atteso opposto, quindi vanno separati:

  • esecuzione ritardata — il modello ribilancia al confine 00:00, il live al primo cron dopo il rebuild (~01:00);
  • barra parzialec[t] e' il prezzo delle 01:00 e r[t] e' un rendimento di un'ora contato come giornaliero nella finestra di vol a 30 barre → vol sottostimata → sovra-leva sistematica.

Tre path, un grado di liberta' per volta, su griglia oraria (i confini sono diversi: solo l'orario li rende confrontabili):

offset 0 (ancora canonica) FULL HOLD maxDD
MODEL — tgt[t-1] dal confine 00:00 1.30 0.24 16.7%
CLOSED@+1h — scarta la parziale, ora del live 1.27 0.16 17.5%
LIVE — tgt[t] da barra parziale, +1h 1.25 0.07 17.5%

Banda delle 24 ancore, mediana delle DIFFERENZE APPAIATE:

effetto FULL HOLD
barra parziale (LIVE CLOSED) 0.031 [0.135,+0.065], pos. 7/24 +0.118 [0.230,+0.277], pos. 19/24
ritardo 1h (CLOSED MODEL) 0.004 [0.053,+0.034], pos. 11/24 0.007, pos. 9/24
totale (LIVE MODEL) 0.046, pos. 7/24 +0.128, pos. 18/24

Leva LIVE/MODEL: 1.004 (mediana, invariata su tutta la banda).

Verdetto: trascurabile. Il ritardo d'esecuzione e' letteralmente una moneta (11/24). La barra parziale muove ±0.03 su FULL e la sua "vittoria" su HOLD (+0.118) e' su una finestra sola e con segno opposto su FULL — cioe' esattamente il profilo che il progetto ha gia' codificato come sospetto. La sovra-leva prevista esiste ma vale 0.4%. Nessun cambio al live.

⚠️ Da notare: all'ancora canonica il quadro sembra peggiore del vero. A offset 0 la barra parziale costa 0.230 sull'hold-out, che e' il minimo dell'intera banda — mentre la mediana e' +0.118. Guardando solo l'ancora canonica avrei concluso "il live degrada TP01 di 0.23 sull'hold-out" e sarebbe stato l'artefatto di un'ancora. E' la stessa lezione del 26/07 in versione speculare (li' l'ancora canonica nascondeva un vantaggio, qui inventa un danno).

Il risultato trasferibile non e' il numero, e' il perche'. La parzialita' dell'ultima barra conta in proporzione a quanto il segnale pesa la barra piu' recente:

SKH01 e' un Donchian breakout su barra 230m: la barra corrente E' il segnale → stesso difetto, +0.38 di Sharpe mediano. TP01 e' un TSMOM 30/90/180 giorni: l'ora mancante e' 1/24 di una osservazione su 30-180 → ±0.03.

Corollario operativo: la conclusione di uno sleeve su questo tema non si trasferisce all'altro, e la domanda "il mio live legge barre parziali?" ha una risposta diversa per ogni sleeve a seconda della lunghezza del lookback. Cablato nei docstring di current_target e resample_tf.


T2 — I due gate raccomandati tre volte e mai scritti

Debito dichiarato: implausible_sharpe (raccomandato il 26/06 su CC01, ri-raccomandato "con piu' forza" il 02/07 su Albimarini) e anchor_luck_band (dichiarato "candidato gate futuro" il 02/07, dopo il timing-luck trovato su 4/4 sleeve ancorati). Tre occorrenze, tre diagnosi a mano, zero codice.

implausible_sharpe

Uno Sharpe/track troppo bello significa che il rischio e' fuori dal dataset, non che la strategia sia buona. Trigger: Sharpe > 3, frazione di barre attive in perdita < 2%, Calmar > 20 o maxDD ~0, e la regola del tre (0 perdite su N trade lascia un tasso vero fino a ~3/N — su un payoff deep-OTM basta a ribaltare l'expectancy: e' il motivo per cui "0/142" non si legge come "senza rischio").

anchor_luck_band + anchor_luck_delta

La griglia di ancore non e' una griglia di parametri, quindi il deflated-Sharpe non la conta: e' multiple-testing invisibile. Il gate riporta la stima onesta (mediana della banda) e la fortuna (canonica mediana). anchor_luck_delta codifica l'errore che ho commesso stamattina: fra offset appaiati la statistica e' la mediana delle differenze, non la differenza delle mediane — le due mediane cadono su offset diversi e il verdetto puo' ribaltarsi.

⚠️ Il gate ha segnalato VRP01. Il difetto era MIO.

Prima stesura: perdite contate su tutte le barre. VRP01 e' settimanale su griglia giornaliera → 94.2% di zeri → "0.96% di perdite, coda sinistra assente" su uno sleeve in produzione al 12%. Sulle barre ATTIVE le perdite sono 16.5%, che e' esattamente la forma attesa di un credit spread a rischio definito.

Verifica: zeri per sleeve — VRP01 94.2%, SKH01 87.6%, XS01 39.6%, GTAA01 31.9%, TP01 30.7%. Un gate che conta gli zeri come "non perdite" avrebbe finito per segnalare mezzo book.

Ed e' la parte che vale la pena ricordare: avevo gia' imparato questa lezione ieri, cablando la contabilita' a 3 stati del monitor DVOLSPREAD ("finestra misurata in barre attive, non giorni di calendario"), e l'ho ripetuta il giorno dopo in un contesto diverso. Ora e' un test.

Esito dell'applicazione retroattiva — copertura 7/7

Sharpe maxDD perdite/attive esito
TP01 1.29 14.3% 48.7% (1865) ok
XS01 1.36 10.9% 46.6% (566) ok
VRP01 1.08 11.9% 16.5% (109) ok
SKH01 1.45 18.1% 55.6% (333) ok
GTAA01 1.01 8.9% 45.2% (1831) ok
XSR01 (monitor) 1.79 2.5% 47.8% (892) ok
DVOLSPREAD (monitor) 0.68 25.5% 50.8% (1949) ok

Controlli positivi (obbligatori: un gate che non segnala nulla puo' essere semplicemente rotto): firma CC01 e firma deep-OTM segnalate con le motivazioni giuste; rumore a Sharpe 0.62 non segnalato.

Nota che vale per XSR01, il cui gate di deploy scade il 23/10: il suo maxDD del 2.5% non e' una coda mancante — il 47.8% delle barre attive e' in perdita. Il DD basso viene da vol bassa (2.3%) e dollar-neutrality. Il rischio #1 di XSR01 resta lo slippage non modellato, non un modo di perdita nascosto.

Replica indipendente del finding d'ancora del 02/07

Il gate, applicato alla cieca a TP01 sulle 24 ancore orarie, ritrova da solo cio' che il 02/07 era stato diagnosticato a mano:

canonica (00:00) +0.237 = 92° percentile delle 24 | mediana onesta +0.056 | banda [0.087, +0.247] | fortuna +0.182

Il 02/07 riportava mediana 0.04 e banda [0.13, +0.30] con un'implementazione separata. Accordo buono. Il numero onesto dell'hold-out di TP01 e' ~+0.05, non 0.31. (Il valore del sleeve resta quello gia' stabilito e non ancorato: il taglio del drawdown ~6× vs buy&hold.)


Cosa NON e' stato fatto, e perche'

Il book ricalcolato sul path LIVE. Sarebbe la sintesi naturale (SKH01 live > modello su entrambi i lati; TP01 live ≈ modello) e cambierebbe la stima de-luckata del book, che oggi applica un ×0.6 assunto. Non l'ho fatto perche' le due misure vivono su lenti diverse: il simulatore di SKH01 compone per-trade a nozionale unitario, lo sleeve di sleeves.py e' vol-targeted. Combinarle produrrebbe un numero che sembra preciso e non lo e'. Follow-up dichiarato con l'ostacolo nominato: serve una versione vol-targeted del path live di SKH01 prima di toccare il fattore di de-luck.

Resta pero' una conseguenza qualitativa gia' solida: il ×0.6 fu scelto assumendo che il live degradi. Su SKH01 e' misurato il contrario, su TP01 e' ~zero. Il ×0.6 e' probabilmente conservativo, e la nota gia' presente in CLAUDE.md ("il ×0.6 sopra il path live rischia di contare due volte la degradazione SKH01") va letta come confermata, non come cautela ipotetica.


Regole nuove

  1. La parzialita' dell'ultima barra conta in proporzione a quanto il segnale pesa la barra piu' recente. Breakout/livelli: massima. Momentum a lookback lungo: ~nulla. Non trasferire la conclusione fra sleeve.
  2. Ogni statistica di "frazione in perdita" si calcola sulle barre ATTIVE. Uno sleeve flat la maggior parte del tempo non ha una coda assente, ha meno osservazioni. (E: una lezione imparata in un contesto non si applica da sola in un altro — questa era gia' cablata nel monitor DVOLSPREAD il giorno prima.)
  3. Un gate nuovo si valida su un controllo positivo prima di credere ai suoi "ok". Un gate rotto e un gate soddisfatto producono lo stesso output.
  4. Anche un DANNO misurato a un'ancora sola e' fortuna d'ancora. A offset 0 la barra parziale sembrava costare 0.23 di hold-out: era il minimo della banda, mediana +0.12.