Files
PythagorasGoal/docs/diary/2026-07-26-wave-tp01-partial-gates.md
T
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

173 lines
9.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 parziale* — `c[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.