From 93147a95c8d3b04b4bfbb39f70e3e3ccd1655b03 Mon Sep 17 00:00:00 2001 From: Adriano Dal Pastro Date: Sat, 22 Aug 2026 18:02:22 +0000 Subject: [PATCH] =?UTF-8?q?diary(2026-08-22):=20ondata=20multi-agente=20?= =?UTF-8?q?=E2=80=94=2020=20filoni,=200=20candidati,=201=20difetto=20di=20?= =?UTF-8?q?produzione,=203=20soglie=20falsificate?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/diary/2026-08-22-wave-multiagente.md | 152 ++++++++++++++++++++++ scripts/research/r0822_prop_alloc.py | 29 +++++ 2 files changed, 181 insertions(+) create mode 100644 docs/diary/2026-08-22-wave-multiagente.md diff --git a/docs/diary/2026-08-22-wave-multiagente.md b/docs/diary/2026-08-22-wave-multiagente.md new file mode 100644 index 0000000..b16c0d0 --- /dev/null +++ b/docs/diary/2026-08-22-wave-multiagente.md @@ -0,0 +1,152 @@ +# Ondata multi-agente 2026-08-22 — 20 filoni, branch `research/wave-0822` + +**Mandato dell'operatore:** *"metti decine di agenti a fare analisi di nuove strategie possibili. +Lavora su branch separato. Lo scopo e' sempre lo stesso arrivare ai 50 giornalieri velocemente."* + +**Esito in una riga: 0 candidati promossi, 1 difetto di produzione che avrebbe falsato un gate fra +36 giorni, 3 soglie pubblicate falsificate, 1 leva strutturale che nessun gate del progetto sa +vedere. Book, pesi, cron, config INVARIATI.** + +Ledger completo per filone: `docs/research/RESULTS-0822.md`. Briefing dato agli agenti: +`docs/research/BRIEF-0822.md`. 21 script in `scripts/research/r0822_*.py` (15.295 righe, compilano +tutti, ognuno gira da solo). + +## 0. Come e' stata condotta (e perche' conta) + +Vincolo di macchina: **2 core**, 7 GB, e sulla stessa VPS gira il libro con **soldi veri** +(`cron_book` al minuto :07). Il briefing imponeva `nice -n 19`, budget 15 min/run, sola lettura su +`config/`, `data/live/`, `src/live/`, `scripts/live/`, cron. **Ha tenuto**: al picco di carico +(load 14 su 2 core) il giro delle 17:07 del libro e' girato in **18 secondi**, feed fresco, nessuna +azione, nessun OOM. +⚠️ **Fatto operativo da ricordare: il cron gira dal working tree.** Con questo branch attivo, +stanotte alle 00:30 il cron esegue il codice di QUESTO branch. Verificato che il diff vs `main` +tocca **solo** `scripts/research/` e `docs/research/` -> produzione identica. **E' anche il motivo +per cui nessuna riparazione e' stata applicata qui: sarebbe andata live senza una decisione.** + +Il briefing dava agli agenti, **in anticipo**, i dieci modi in cui questo progetto si e' gia' +ingannato (null del de-levering, TP01 travestito, selezione sull'hold-out, fortuna d'ancora, Sharpe +implausibile, win-rate come knob, ...) e la lista dei filoni morti. **Sette agenti hanno catturato +un errore proprio prima di pubblicare**, e tre hanno refutato una propria ipotesi in corsa. + +## 1. Il risultato che va agito — 4 monitor forward su 6 sono rotti + +`fetch_hyperliquid` (e `resample_tf`) scrivono la barra del **giorno in corso**; `advance()` dei +monitor la consuma e **porta `last_ts` su di essa** -> le ore restanti di ogni giorno non entrano in +nessun rendimento registrato. + +| monitor | barre coincidenti col replay | **min/giorno registrati** | gate | +|---|---|---|---| +| `paper_statarb` | **0/46** | **4** | **STATARB 27/09** | +| `paper_dvolspread` | 0/28 | **2** | DVOLSPREAD 24/10 | +| `paper_xsr` | 1/28 | **41** | XSR01 23/10 | +| `paper_portfolio` | 7/56 | 19 | — | +| `paper_prevday` | 1259/1319 | 1.438 | — | +| `paper_combo` | 7/37 | 1.402 | — (sano **per caso**: aspetta una borsa) | + +**Il gate STATARB del 27/09 si ribalta su 2 criteri su 3**: Sharpe registrato **+1,96** contro +**−2,02** ricostruito, maxDD **2,2% contro 15,3%** (guardia <10%). +✅ **Ma la finestra non va persa**, ed e' misurato due volte in modo indipendente: il feed **non +riscrive le barre chiuse** (`paper_prevday` 1427/1488 barre identiche al bit dopo 62 notti; e le 6 +barre di `paper_statarb` recuperate dopo il guasto EPERM del 09-15/07 coincidono al bit). +**-> La riparazione e' "riparare `advance()` + RIGENERARE", non "riparare e azzerare": nessuna data +di gate si sposta.** +**Guardia raccomandata** (non implementata): `ts_ultima_barra + cadenza <= mtime del file`, grazia +5 min. O(1), segnala 5/6, **tace sul sano**, controllo positivo sintetico 6/6 nei due versi. +⚠️ `monitor_health` non poteva vederlo: **una serie fresca, completa e sbagliata passa ogni controllo +di freschezza**. E `implausible_sharpe` esiste dal 26/07 ma **non e' mai stato puntato sulle serie +forward** (avrebbe segnalato Sharpe −15,8 su 28 barre). + +## 2. Tre soglie pubblicate, falsificate con misure + +1. **"XS01 serve ~$20k"** -> **non esiste soglia da min-order**. L'origine del numero era *"rumore di + arrotondamento"*, una stima a occhio del 19/06. Haircut ~0 gia' a **$200-600 allocati**. + **Meccanismo**: gli ordini sono **due popolazioni** — il ribilanciamento del segnale e' il 13% + degli ordini ma il **75% del nozionale** (ticket $13,65, passa sempre); la deriva del vol-target + e' l'87% degli ordini ma il **25% del nozionale** (ticket $0,64, il pavimento la taglia **ed e' + gratis**). *Contare gli ordini da' 16% e sembra un disastro; contare il nozionale da' 75%.* + Due agenti indipendenti ci sono arrivati per strade diverse. + ⚠️ **Il "$20k di XS01" e il "$20k della decisione di venue" erano due cose diverse conflate in + CLAUDE.md.** Il primo cade; **il secondo regge intatto** — e' una decisione dell'operatore + sull'asse della rovina, non sull'eseguibilita'. +2. **"Slippage = rischio #1 di XSR01"** -> **refutato con margine 21x** al livello di liquidita' + odierno (mezzo-spread 0,7-1,0 bps contro i ~16 che servirebbero a uccidere l'edge). +3. **"BTC opzioni fuori a $3.000 (min 0.1 = $6.210/lotto)"** -> misurato sulla famiglia **inverse**, + che il conto (in USDC) **non puo' marginare**. La famiglia USDC-lineare ha lotti **10x piu' + piccoli**. Il muro resta, ma per il **prezzo del lotto**, non per quello che si credeva. + +## 3. La leva: l'unica variabile che nessun gate del progetto sa vedere + +**Lo Sharpe e' invariante alla scala** (misurato: 1,31 a ogni cella del knob) -> `deflated_sharpe` e +`marginal_vs_tp01` non falliscono sulla leva, **non la vedono**. E' per questo che in due mesi la +scala non e' mai stata esaminata. +Il libro gira al **7% di Kelly** e raccoglie il **15%** della crescita massima in log. Il gradino +eseguibile 1,00x -> 1,25-1,50x vale **14,7 anni -> 12,9-11,6** al capitale-rendita (€500/mese, netto +fisco). **Lo scettico ha confermato il risultato di testa** e ha tolto la sua condizione bloccante: +sotto la lente wick accoppiata il maxDD prende un **ricarico moltiplicativo costante del ~3,5%**, non +un'amplificazione (il maxDD e' multi-giorno, il wick e' di un giorno). +**Il gradino resta NON autorizzato**: cadono una riserva su tre. Restano il drift stimato su 7,4 anni +(k* e' lineare nel suo errore) e la **coda assente dal dataset** — un solo giorno a −10% all'anno +porta k* da ~10x a **2x**. +📌 **Ma la lezione del 25/07 e' vera e non si trasferisce:** su una regola a **UN giorno** +(daily-loss, stop di conto) close-only e' **esattamente cieca** — 0,00 breach/anno contro 0,40-1,21 +veri, rapporto **INF**. **Sul canale prop/funded la lente accoppiata resta obbligatoria.** + +## 4. Cosa e' morto, e come + +**Filoni chiusi con autopsia** (l'elenco per esteso e' nel ledger): adaptive-horizon (il "vincitore +adattivo" e' un lookback **costante** travestito), dealer-gamma (la gamba tradeable e' **incoerente**: +BTC non separa, ETH separa **al rovescio**), ortho-screen **7/7**, oi-pin (il max-pain **non batte +mai** la media a 7 giorni dello spot), term-structure (la pendenza e' un **termometro contemporaneo**), +skew direzionale (**il prezzo muove lo skew**, t 3,1-9,4 su 8/8 — non il contrario), flow-squeeze, +basis-calendar (il basis dei datati **E'** il funding del perp), alt-options (alt), xs-lite, +vrp-quote-vere. + +Tre chiusure di famiglia che valgono per le prossime ondate: +- **Il filone funding si chiude sul QUARTO lato** (affollamento): misurato su **53.430 ore / 3 anni**, + non predice ne' direzione ne' volatilita'. E i futures datati non sono un quinto lato: sono lo + stesso lato quotato diversamente (+7,33% implicito contro +6,48% realizzato, premio incassabile + +0,85%/anno con **IC95 che contiene lo zero**). +- **La mean-reversion non risorge** sotto due conditioner mai provati (volume, shock 3σ): la selezione + in-sample sceglie il ramo di **continuazione** in entrambi i casi. +- 📌 **Uno screen largo su BTC/ETH direzionale NON PUO' passare il proprio gate.** Su 168 trial il + massimo Sharpe atteso dal **puro rumore** e' **1,572**, sopra il soffitto direzionale misurato + (~1,3). Non e' sfortuna, e' aritmetica. **Le prossime ondate o dichiarano famiglie molto piu' + piccole in anticipo, o cambiano meccanismo.** + +⚠️ **Tre volte in questa ondata l'eseguibilita' a $600 NON e' stata il vincolo** (haircut 0,00-0,01; +lotti $7-242; margine ~$148). Dopo due mesi in cui il muro era sempre il capitale, adesso muoiono +tutti sull'edge. **E' un'informazione sul dove cercare.** + +## 5. Regole nuove, e una ritirata + +**Nuove:** +- **L'open interest non misura la negoziabilita'** — su Deribit USDC sono quasi **anti-correlati + (rho di rango −0,77)**: SOL_USDC e' 1ª per OI e ultima per quote a due lati (**9%**); BTC_USDC ha + **5** strumenti con OI>=100 e il **93%** dei put quotati. +- **Il deflated-Sharpe va calcolato DI SCREEN, non solo di famiglia** (168 trial, non 24). +- **Un placebo si controlla per BILANCIAMENTO DEL SEGNO prima di usarlo**: un null che concorda col + segnale solo nel 14% dei casi non e' un null, e' la strategia invertita — e fabbrica celle + "significative". +- **Il null del de-levering e' DEGENERE quando la variante e' una ri-scalatura** (`sh(k*base) === + sh(base)`): il test che serve e' **iso-peso sullo Sharpe**. +- **Un gate che stampa `None` va verificato prima di dichiararlo "non girato".** +- **Su una finestra interamente post-hold-out, `marginal_vs_tp01` non puo' dare ADDS per + costruzione** — un NEUTRAL li' non e' un giudizio. + +**Ritirata (era stata pubblicata poche ore prima, in questa stessa ondata):** +❌ *"Su equity a gradino un overlay giornaliero e' non-causale"* — **falso su questo motore**: +`backtest_signals` contabilizza al giorno d'**ingresso** in **291/293** trade, e la "riparazione" e' +un **no-op bit-exact**. Il "+0,04 fantasma" era la differenza fra due varianti **entrambe causali**, +e quella scartata era la **migliore sull'hold-out**. *Il costo di una regola derivata da un difetto +inesistente e' gia' stato pagato.* + +## 6. Cio' che resta aperto (decisioni dell'operatore, non mie) + +1. **Riparare `advance()` + rigenerare** le serie forward, prima del 27/09. +2. **Cablare la guardia D2** (`ts_ultima_barra + cadenza <= mtime`) in `monitor_health`. +3. **Il collettore della catena** raccoglie la famiglia inverse; ETH_USDC costa **+587 chiamate/giro + (+90%)** ed e' una decisione sul rate limit per-IP, che il 29/07 e' gia' costata un guasto. +4. **Rimisurare `f` di VRP01 term-structure-consistent** (il 42% del difetto e' li', e la regola per + prenderlo era gia' scritta il 03/07). +5. **XS01 e' eseguibile a ~$1.300 di conto**, non a $20k. Resta fuori **per la decisione di venue**, + che e' un'altra cosa. Se il piano cambia, si riapre prima. diff --git a/scripts/research/r0822_prop_alloc.py b/scripts/research/r0822_prop_alloc.py index 6069fb7..5b45f6b 100644 --- a/scripts/research/r0822_prop_alloc.py +++ b/scripts/research/r0822_prop_alloc.py @@ -937,6 +937,35 @@ def main() -> None: print(" usarlo ancora sarebbe sbagliato, ma il salto da 1.7% a 41.7% e' il prodotto di due") print(" correzioni, non di una scoperta.") + hr("I-ter. LA STESSA SCALA, MA CON GLI STRESS DI E-bis/E-quater DENTRO") + print(" La tabella qui sopra gira al drift PIENO di XS01 e SKH01. E-bis mostra che il vantaggio") + print(" vive quasi tutto sul drift di XS01; E-quater che il taglio congiunto lo azzera. Il") + print(" numero operativo va quindi dato con gli stress dentro, non a parte.") + print(" (meccanica: le tuple stressate vengono INIETTATE nella cache di `pc.book_tuples`, cosi'") + print(" la simulazione della scala e' letteralmente la stessa del 25/07, con un input diverso.)") + print(f"\n {'stress':>24} {'allocazione':>16} {'leva':>6} {'EUR/g med':>10} " + f"{'P(>=10/g)':>10} {'P(>=50/g)':>10} {'P(zero)':>8}") + for dmt, lab in (((), "nessuno (pieno)"), + ((("SKH01", 0.50), ("XS01", 0.50)), "SKH x0.50 XS x0.50"), + ((("SKH01", 0.33), ("XS01", 0.00)), "SKH x0.33 XS x0.00")): + for cfg, alab in ((cfg_best, f"argmax-J {best['w']}"), (cfg_live, "LIVE 75/25")): + wdic = dict(zip(CRYPTO_PROP, cfg)) + R_, G_ = book_RG(wdic, drift_mult=dmt) + key = (float(cfg[0]), float(cfg[1]), float(cfg[2]), "shared") + saved = pc._TUP_CACHE.pop(key, None) + pc._TUP_CACHE[key] = (R_, G_, _panel_index(START_WIN)) + r = pc.simulate([cfg], [0] * pl.MAX_CONCURRENT, n_paths=1500, lev=0.75, + seed=20260822, lens="coupled", start=START_WIN) + pc._TUP_CACHE.pop(key, None) + if saved is not None: + pc._TUP_CACHE[key] = saved + print(f" {lab:>24} {alab:>16} {0.75:>6.2f} {r['med']:>10.2f} " + f"{r['p_ge10']:>10.1%} {r['p_target']:>10.1%} {r['p_zero']:>8.1%}") + print("\n Questa e' la riga da citare: non il 41.7% pieno, ma la BANDA fra la riga piena e la") + print(" riga del taglio congiunto. Lo stress non e' un'ipotesi pessimista arbitraria: e' la") + print(" fortuna d'ancora MISURATA su SKH01 (26/07) e la finestra di scoperta di XS01 (dichiarata") + print(" in CLAUDE.md come 'taglia del guadagno ottimista').") + print("\n" + "=" * 104) print(f" fatto in {time.time()-t0:.0f}s") print("=" * 104)