d95fabf0603b5ed34fc02a9fbfdc608618b72281
164 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
ec8478308f |
GATE SCALA-01: la chiave di scala esiste, ed e' INERTE (SPEC §8 punti 1-4)
Chiude il debito che CLAUDE.md dichiarava da settimane: la regola "ogni cambio di scala passa dal cap di config, non da target_vol" NON era implementabile perche' una chiave di scala non esisteva — qualunque cambio sarebbe finito su WEIGHT/W_TP01/W_SKH, cioe' codice su un percorso con soldi veri e per giunta nel posto sbagliato (W_TP01/W_SKH sono il RAPPORTO 75/25, non la taglia). Specifica gia' scritta in docs/research/SPEC-scale-key.md (618 righe, 9 condizioni di gate, prototipo). Non ho progettato: ho eseguito i punti 1-4. 🚨 config/live.json NON E' STATO TOCCATO. La chiave e' assente, vale 1,00, e T7 dimostra bit-exact che il libro e' quello di ieri (max|diff| = 0.0). Verificato anche a runtime: book_execute in dry-run da' gli stessi target del cron delle 15:47 (BTC $+355, ETH $+214). LE QUATTRO DECISIONI CHE NON SONO DI COMODO - La scala si applica DOPO il clamp. Prima, il cap se la mangerebbe proprio nei giorni di massima convinzione (a tp=1/sg=+1 il grezzo vale esattamente cap => k_eff tornerebbe a 1,00 a ogni k): sarebbe un cambio di FORMA travestito da cambio di taglia, e la curva g(k) con cui il gradino viene autorizzato non descriverebbe quel libro. Prezzo dichiarato: il cap diventa il tetto del libro UNITARIO, e la guardia sulla leva lorda va ricostruita. - Il tetto e' sul PRODOTTO e sta nel CODICE. Sulla sola chiave lascerebbe aperta la porta accanto (frac 0,625 x scala 1,25 = 1,562x); in config sarebbe un lucchetto con la chiave attaccata. LEVA_LORDA_MAX 1,25 in src/live/book.py => il gradino a 1,50 richiede codice, quindi review. - Fuori scaletta o fuori tetto = STOP, non clamp. book_execute si ferma, non invia, allerta (ScalaNonAutorizzata). E SCALA_LADDER (1,00 · 1,25) rende INESPRIMIBILE "solo un po'": 1,05 non e' prudente, e' fuori scaletta. - La scala vive solo sul percorso fidato (equity illeggibile => 1,00), cosi' "il fallback non e' piu' permissivo" e' vero per costruzione. Ma la VALIDAZIONE avviene sempre: una config rotta non si nasconde dietro un giro in cui l'equity non era leggibile. LA GUARDIA CHE MORDE PER PRIMA non e' il peggior giorno (k <= 3,49x) ma il COSTO di un disaster-SL (k <= 1,67x, 2,1x piu' stringente): l'invariante n_asset x frac x scala x disaster_sl_pct <= 0,50 scatta anche se qualcuno allarga lo stop invece di alzare la scala. TEST T1-T11 (tests/test_book_scale.py, 18 verdi). Il piu' importante e' T1b: a k=1 l'implementazione simmetrica e quella asimmetrica danno lo STESSO numero, quindi un test di simmetria scritto sul caso di default ha potenza ZERO. T1b verifica che le due coincidano a k=1 (il rischio e' reale) e che fuori da k=1 l'asserzione le SEPARI, con un'implementazione asimmetrica scritta nel test apposta perche' fallisca. SORVEGLIANTE scale_watch (cron_daily, 3 domande / 3 azioni / 3 stati, una allerta per streak, marcatore scritto solo dopo invio riuscito — debito #2). Riporta la frequenza del ramo di fallback, che sopra il 2% in 90 giorni invaliderebbe la regola: misurata 0/1.676, coi 19 giri "paper capital" (pre-finanziamento, dove il libro non invia) contati e dichiarati a parte. Non puo' impedire la modifica: la rende visibile entro 24h e attribuibile. CHIUDE il debito #5 di §5: T2/T3 sostituiscono il vecchio test_leva_massima_da_config (che misurava frac x n_asset mentre la grandezza vera e' frac x n_asset x scala), e T11 verifica che sia rimasto cancellato. NON FATTO, deliberato: la chiave in config (punto 2 lo vieta), GATE SCALA-01 (A2 richiede >=30 giorni a 1,00 col sorvegliante attivo — "l'unico modo di scoprire che il sorvegliante e' rotto mentre la leva e' ancora 1,00"), r0726_fee_sensitivity rifatto (A7: serve solo al gradino; a 1,25x una liquidazione costerebbe 1,25% non 1,00%, e ereditarlo sarebbe l'errore). Nessun ordine. Suite: 825 passati. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
f151316bdf |
usde: il tetto e' una FRAZIONE dell'equity (~31,2%), non un livello — e ora e' in config
Fonte: articolo ufficiale Deribit "Yield/reward bearing coins" (WebFetch lo prende
403, si legge dall'API Help Center in JSON). Tre correzioni alle conclusioni di
ieri.
1) L'ITALIA e' nella lista delle giurisdizioni escluse dai reward USDC. Lo zero
misurato e' confermato dalla fonte, ma la mia ipotesi MiCA era SBAGLIATA: la
lista contiene Canada e Giappone, non e' il perimetro MiCA. E' policy di
giurisdizione Deribit. M27: una fonte normativa si verifica, non si deduce.
2) La finestra di pagamento USDC e' di DUE SETTIMANE ("within the first two
weeks of the following month"), non tre giorni. Avevo verificato su 8/14 e 3/14
giorni. Rifatto sulle finestre vere: LUGLIO conclusivo (atteso $1,72 contro
un'escursione TOTALE dell'equity di $0,48 in 1-16/08, zero scalini compatibili),
GIUGNO no (il libro opera da meta' mese, rumore della taglia del segnale). La
conclusione non cambia, ma l'evidenza e' UNA finestra piu' la lista ufficiale,
non due: il "172x" del 30/08 era sovra-affermato.
3) IL TETTO NON E' UN LIVELLO, E' UNA FRAZIONE. L'articolo documenta un Cap
ETHENA che diluisce il TASSO a livello di exchange e nessun limite sulle
quantita' detenibili: il muro non aveva base documentale e andava ri-sondato.
Fatto il 31/08 (giorno UTC nuovo -> non e' un limite giornaliero): ieri si
tornava a 644,18, oggi no, con l'equity scesa di $8.
30/08 tetto [644,18 · 645,18) equity $2.063,79 = 31,21-31,26%
31/08 tetto [643,18 · 644,18) equity $2.055,56 = 31,29-31,34%
0,05pp di scarto, dentro il rumore dell'equity (+-$2-8/ora). Candidato pulito
5/16 = 31,25%, ma a questa risoluzione non si distingue da una regola sul
collaterale scontato dell'haircut (~29%): si cita la banda (M25).
=> Il tetto SCALA col conto: la quota resta ~31%, il valore in dollari cresce
col capitale, il 70% non e' raggiungibile ne' ora ne' mai. E, essendo pinnati
al tetto, il rischio emittente resta una frazione COSTANTE del conto.
Cablato (rispondeva a "dove e' scritto il valore del tetto": in tre note di
testo e in nessun posto che il codice leggesse, tanto che usde_convert --quota
0.70 dichiarava "piano valido" per un ordine che il venue rifiuta):
- config/live.json usde.venue_cap_frac 0.312 + venue_cap_misurato
- src/live/usde.py lo porta nei default (unica autorita', P1)
- usde_convert.piano() rifiuta il bersaglio sopra il tetto PRIMA di sparare
e stampa il massimo raggiungibile. Verificato su entrambi i rami.
Anche: l'USDe ha un fee Deribit del 5% mai nominato prima. Il nostro misurato
(~4,5%/anno) e' gia' netto: e' l'unico numero da citare.
Stato: USDE 643,175691 (31,29%, al tetto), USDC $1.412,40, totale $2.055,57.
Suite: 795 passati.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
418f523be7 |
gtaa: la decisione tenere/bloccare va a $15k — gate (A) ritirato, soglia sorvegliata
Decisione dell'operatore: GTAA01 NON si blocca oggi, si decide quando il book arriva a $15k. Il motivo registrato non e' «non contribuisce» — la misura dice il contrario (+0,095/+0,124 di Sharpe a iso-rischio secondo la fase, positivo in tutte e cinque, hold-out +0,247, 6 anni su 8, correlazione col resto +0,087). Il motivo e' che sotto $15k di book lo sleeve NON E' ACCENDIBILE: GTAA_MIN_CAPITAL e' $3.000 allocati, che al peso 20% fa $15.000 contro i $2.068 attuali. Finora era manutenzione senza beneficio incassabile. Registrate anche le due ragioni contro il blocco, che restano valide: N7 (uno sleeve difensivo si giudica sul sinistro, e questa finestra non lo contiene) e N4 (togliendolo il portafoglio di ricerca diventa 100% cripto su un venue solo). E il costo che sarebbe andato pagato: GTAA01 e' uno dei quattro nomi di W_DEPLOY, da cui escono i $313k del muro. PERCHE' LA DECISIONE NON SI DIMENTICHI (N9). Una decisione parcheggiata su un numero che nessuno sorveglia e' parcheggiata per sempre. `journal.SOGLIE_CAPITALE` legge l'equity ogni giorno — il giornale lo fa comunque — e il giorno che supera la soglia la voce dice quale decisione si sblocca e perche'. Seconda riga: $20k, dove si riapre «100% Deribit fino a $20k». Una riga si TOGLIE quando la decisione e' presa. 5 test, incluso «equity non leggibile non e' una soglia superata» (P5). GATE (A) RITIRATO come pass/fail, congelando il MOTIVO e non l'esito — come il 07/08 col confronto fra ranghi, e per la stessa ragione: il criterio decide su un margine piu' piccolo del rumore che lo scuote. In piu' una guardia sulla CAUSA (`test_la_fase_di_ribilanciamento_e_ancora_ancorata_alla_POSIZIONE`) che si rompe il giorno che qualcuno ancorasse la fase al calendario: quel giorno il gate potrebbe tornare decidibile, ed e' un fatto da guardare, non da ignorare. Il test sul margine assoluto si e' auto-ritirato: diceva «se scendesse sotto un centesimo questo criterio smetterebbe di essere una misura», ed e' sceso a 0,0074. CLAUDE.md: §3 nuova riga · §5.2 RISOLTO (trasporto allarmi) · §5.4 riscritto (la domanda fiscale (a) ha una risposta alla fonte: derivati in c-quater al 26%, non c-sexies al 33% — Circolare AdE 30/E del 27/10/2023, citata verbatim) · §5.13 nuovo debito, la fase che ruota — quantificata e dichiarata INNOCUA oggi (D5): 0,029 di Sharpe a livello di portafoglio, dentro la banda [1,81-2,12]. Diario: docs/diary/2026-08-28-gtaa-fase-e-allarmi.md Suite: 789 passati, 0 falliti. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
801bd13f10 |
allarmi: il marcatore "gia' detto" si scrive DOPO l'invio, non prima
Debito §5.2 chiuso su decisione dell'operatore. `run_once` salvava lo stato coi marcatori `alerted` gia' a True e l'invio lo faceva il chiamante DOPO: col 6,9% di invii falliti misurato (2 su 29), un 🚨 perso restava perso per l'EPISODIO INTERO — l'ora dopo lo stato diceva "gia' detto" e usciva WATCH/MUTO. Gli episodi storici durano 200-2.324 ore, quindi il buco non era teorico. - `run_once(state_path, sender=None)`: il sender e' INIETTATO, non importato — e' cio' che tiene la funzione testabile senza rete d'uscita, che era la ragione del disegno precedente. Senza sender il comportamento resta quello di prima e il report lo DICE (`invio`), invece di lasciar credere che qualcosa sia partito. - Su invio fallito si disfano SOLO i marcatori "gia' detto", non le misure: · asset in ALERT -> alerted=False, l'ora dopo ri-allerta; · lock MAINT/ALERT -> alerted_soft/hard=False ma le ORE restano a correre, cosi' una manutenzione che sfora la grazia sale ad ALERT anche col trasporto giu' (disfare anche le ore congelerebbe l'escalation proprio mentre non si riesce a parlare); · lock RIENTRATO -> si ripristina l'intero LockState, perche' il rientro si annuncia una volta sola e senza le ore non ci sarebbe piu' niente da dire. - `notify(..., tentativi=)`: il retry esisteva in `send` e non arrivava qui. venue_watch ora manda con 3 tentativi. - L'esito dell'invio finisce nel log del cron invece di sparire. 5 test nuovi. Il primo e' quello che conta — dopo un invio fallito, l'ora dopo ri-allerta — col suo controllo positivo (un invio riuscito consuma l'allarme UNA volta sola), senza il quale "ri-allerta sempre" passerebbe. Suite: 782 passati, 2 falliti (i due del gate GTAA, non toccati qui). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
05a698a83e |
analista: il motivo di un guasto si prende da stdout E da stderr, o si perde
Il 2026-08-28 alle 00:37:00Z la CLI `claude` e' uscita 1 scrivendo «Failed to authenticate: OAuth session expired and could not be refreshed» su STDOUT, con stderr VUOTO. `interroga()` componeva il motivo dal solo stderr, quindi nel DB e' finito `analisi_stato='errore'`, `analisi_motivi='uscita 1: '` — e su Telegram e' partito «analisi non disponibile (errore): uscita 1:». La meccanica ha retto (nessuna analisi di ieri spacciata per quella di oggi, esito registrato, notifica partita): a mancare era solo il PERCHE'. P4 — un'allerta risponde a due domande, e con la prima sola la causa si ricostruisce aprendo a mano il transcript della sessione headless. P3 — quando la diagnosi serve, il guasto e' gia' rientrato: il motivo si cattura li' o mai. - `motivo_uscita(returncode, stdout, stderr)`: unisce i due canali (stderr per primo), tronca a 300 caratteri. - Silenzio totale su entrambi i canali -> lo DICE, invece di lasciare i due punti a vuoto: «la CLI non ha detto perche'» e «il perche' l'abbiamo perso noi» sono guasti diversi e finora si scrivevano uguali. - 4 test nuovi, fra cui la regressione col messaggio testuale del 28/08. NON risolve la causa a monte: perche' quella refresh sia fallita non sta in nessun log locale. Il refresh token era valido (rinnovo automatico riuscito alle 08:03:35Z dello stesso giorno, scadenza 2026-09-25) e la stessa chiamata rifatta a mano esce 0 -> guasto transitorio, unico su 24 sessioni locali. Da qui in avanti, se ricapita, il motivo si legge dalla notifica. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
e5052a690f |
usde: da patch d'emergenza a struttura — config, modulo unico, sorveglianza
- config/live.json sezione `usde` (unica autorita', P1): indice, haircut 10%, tetto allerta quota 50%, soglie depeg 0.99/0.95 coi criteri dichiarati (P6) - src/live/usde.py: config + catena di prezzo (indice pubblico -> ticker -> 1.0 dichiarato) + valutazione PURA; shadow._collaterale_usde ora deriva da qui - scripts/live/usde_watch.py + cron_usde.sh (12:35 UTC, dopo la finestra reward): reward per delta netto trade (P12: senza inventare attribuzioni), depeg (crit ripetuto, resto a transizione, P9), quota anche per deriva passiva (N4); applica il verdetto di eligibilita' pre-registrato (>=1 reward entro 29/08) - serie data/live/usde_watch.jsonl sotto monitor_health (max 30h, P5: un watch fermo non deve leggersi come "va tutto bene"); baseline 14:17Z registrata - GATE USDE-01 in CLAUDE.md §4; test 775 (+17 in tests/test_usde_watch.py) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01B9UyJLHzR7EJzxR3iQ3RN1 |
||
|
|
631e854b29 |
live: l'equity del book e' il TOTALE cross-collateral — USDE valutato all'indice pubblico
Trovato eseguendo il test di eligibilita' USDE ($500 convertiti alle 13:04Z, fill 1.0003 fee 0): shadow._equity leggeva solo il conto USDC -> il giro successivo avrebbe visto -24,3%, mandato un falso "USCITA DI FONDI" e venduto ~$140 di posizioni. Riparato prima del giro delle 13:47: _collaterale_usde() valuta l'USDE all'indice pubblico usde_usdc (mediana multi-exchange, lezione Binance 10/10/2025), depeg passa nel sizing, clamp a 1.0 sopra la pari, fallback 1.0 dichiarato (mai 0: il fallback si sceglie sul danno, P5). 6 test nuovi in tests/test_shadow_usde.py. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01B9UyJLHzR7EJzxR3iQ3RN1 |
||
|
|
d597fc64e8 |
monitor: advance() consuma solo barre CHIUSE — serie rigenerate, guardia PREMATURO, 4 debiti chiusi
S5.1 RIPARATO E RIGENERATO. Filtro condiviso src/live/paper_guard.py (barra open-labeled chiusa = ts + cadenza <= adesso) importato da tutti e 6 i monitor; serie rigenerate dallo stesso start_ts con scripts/live/paper_regen.py (evidenza in *.pre_regen_20260826.*): statarb +1,95 -> -1,61 (il ribaltamento del gate 27/09 previsto dall'audit), dvolspread -14,73 -> -4,41, xsr -4,98 -> -2,72, prevday invariato. Nessuna data di gate si sposta. Guardia cablata in monitor_health: stato PREMATURO (ultima barra che chiude dopo l'mtime, grazia 5 min, open_labeled=False per collect_chain) — sul dato vivo segnala i 5 rotti e tace sui 2 sani; dopo la rigenerazione 7/7 OK. paper_portfolio non rigenerato (GTAA su ADJUSTED_LAST: replay != serie registrata, P12), tolta la coda non chiusa. D6 pagata di nuovo nel fix: asi8 in pandas 3 e' in us, non ns — blindata con test su tre risoluzioni. S5.12 ESTESO: conftest devia anche trades.db (wrapper su connect: il default e' catturato alla definizione) e docs/journal/; book_executions.jsonl sorvegliato con impronta inizio/fine suite. S5.5 FATTO: test_leva_massima cancellato con nota (misurava frac*n_asset: con una chiave di scala avrebbe continuato a passare smettendo di controllare). S5.9 INDAGATO E RIPARATO (r0826_skh_band_drift): il dato regge (taglio 02/07 riproduce l'audit 1,6376, in-sample identico su ogni taglio); la deriva era la finestra hold-out — e la sola settimana 15-22/08 vale +0,35 di Sharpe hold-out. Il test ora taglia il feed al 02/07 e verifica la riproduzione stretta. Suite: 751 passati, 0 falliti. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01B9UyJLHzR7EJzxR3iQ3RN1 |
||
|
|
a51844875b |
journal: i versamenti non sono piu' P&L — movimenti di capitale scorporati dal trading
Il P&L di giornale era un delta di equity: la voce del 25/08 dichiarava +$1.414,57 di "giorno" quando $1.399,39 erano il deposito USDC, e il cumulato dall'arming avrebbe mentito per sempre. Nuova `movimenti_capitale()`: - soglia IMPORTATA da book.EQUITY_JUMP_ALERT, non ridichiarata (P1); - "movimento" solo se il salto supera di >2x il massimo che il mercato MISURATO (feed certificato, tetto di leva da config) poteva produrre fra le due letture; - altrimenti AMBIGUO: dichiarato con attenzione e NON scorporato (P12 -- un crash vero a tutta leva non deve diventare "prelievo"); idem a feed illeggibile (P5). Scansione dell'intera storia: 1 evento, esattamente il deposito (+209,6% contro mercato max 0,22%), zero falsi positivi. `concentrazione` ora lavora sul cumulato di TRADING; le regole sui movimenti stanno sopra l'early-return "nessun giro". Limite dichiarato (D5): un movimento sotto il 10% dell'equity resta nel P&L. 7 prove nuove (31 -> 37), incluso il controllo M15 al contrario. Voce del 25/08 rigenerata: giorno -> trading +$15,18; cumulato -> trading +$59,14. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01B9UyJLHzR7EJzxR3iQ3RN1 |
||
|
|
426735448e |
live: diagnosi del guasto venue, disaster-SL scoperto, isolamento per asset, cron :47
Nato da "stato trades" durante una manutenzione Deribit (system_maintenance 11051,
08:57-09:20 UTC). Contati i log invece che ricordarli: 1.499 giri dal 23/06, 3 con
manutenzione, 5 traceback duri — e 4 dei 5 sono il NOSTRO gateway, non il venue.
Le release Deribit escono il martedi' alle 09:00 UTC: il cron al :07 ci cadeva dentro
per costruzione (21/07, 11/08, 18/08, 25/08).
DIAGNOSI (src/live/venue_probe.py, nuovo)
Sonda l'API PUBBLICA Deribit senza gateway e senza credenziali, e classifica il guasto:
VENUE_MANUTENZIONE / VENUE_GIU / GATEWAY / IGNOTO. Prima ogni causa stampava la stessa
riga ("conto non leggibile (offline)") con nota di diagnosi CABLATA — P4 violata, e il
18/08 il codice 11051 era gia' dentro il processo senza arrivare a chi decideva la
gravita'. Parte solo dopo un guasto: sul percorso sano costa zero. P1 rispettata: la
firma 11051 si importa da venue_watch.is_maintenance, non si ridichiara.
P9: la manutenzione dentro lo slot declassa il titolo a info, ma solo su EVIDENZA della
sonda (mai sull'orologio) e solo dentro la durata annunciata — oltre, RIALZA. Un gateway
rotto di martedi' mattina resta al massimo.
DISASTER-SL SCOPERTO (src/live/execution.py)
ensure_disaster_sl cancella i bracket incoerenti PRIMA di ripiazzarne uno: fra le due
chiamate la posizione e' senza stop. Se il ripiazzamento sollevava, l'eccezione risaliva
a main() e il guasto peggiore aveva la faccia di un errore qualunque. Ora: due tentativi,
poi stato `naked`, distinto da `place-failed` (P5). Non e' "non sono riuscito a
proteggere": e' "ho tolto la protezione e non sono riuscito a rimetterla" -> allarme
massimo, mai declassato. La SEQUENZA non e' stata invertita: piazza-poi-cancella sembra
piu' sicuro ma "sembra" non basta con soldi veri senza misurarlo.
ISOLAMENTO PER ASSET (scripts/live/book_execute.py)
Il 21/07 un 502 dentro ensure_disaster_sl su BTC ha ucciso il giro intero: nel log ETH
non compare — ne' ribilanciato ne' verificato nella protezione. Ora un asset che esplode
non ferma il ciclo, e il giro degradato esce con codice 2.
CRON :07 -> :47
Il vincolo vero non era ":07" ma "fuori dai ~26s del minuto tondo" (rate-limit per-IP
auto-saturato dal collettore catena, misura del 30/07). Il :47 lo soddisfa e in piu' sta
fuori dallo slot di release. PREVISIONE DICHIARATA (M12): 3 delle 4 finestre osservate
sono rientrate entro l'ora -> il :47 ne avrebbe scavalcate 3 su 4; se martedi' prossimo
becca comunque la manutenzione, la previsione e' sbagliata.
WATERMARK AVVELENATO DAI TEST (tests/conftest.py, nuovo)
Trovato addosso: lanciando la suite, data/live/equity_seen.json passava a $5.000 e il giro
successivo mandava un allarme Telegram FALSO ("USCITA DI FONDI -86,6%"). Non cosmetico:
cap_fallback = min(cap_config, watermark x frac) sarebbe passato da $334 a $2.500/asset,
~7,5x di leva su un conto da $668, sul ramo eq_fallback che allerta e NON blocca — cioe'
i test potevano armare il pericolo che il watermark esiste per impedire. Riparato con una
fixture AUTOUSE, non per-test: chiedere a ogni autore di ricordarsene ha gia' perso il
26/07 e il 21/08. Resta esposto lo stesso errore su trades.db e book_executions.jsonl.
BLOCCATO, NON RINVIATO
Il fallback diretto ai privati Deribit richiede chiavi API create dall'operatore: in
locale esiste solo CERBERO_TOKEN. Il gateway resta un punto singolo di guasto non
aggirabile (CLAUDE.md 5.11). La sonda dice di chi e' il guasto, non lo aggira.
Test: 20 nuovi, nessuno tocca la rete; controllo positivo fatto (5 su 7 falliscono contro
il codice vecchio). Suite 730 passati, 1 fallito — quello gia' noto di 5.9 (deriva dati).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01B9UyJLHzR7EJzxR3iQ3RN1
|
||
|
|
2751a7efd0 |
journal: la voce del giorno IN CORSO non si presenta piu' come una giornata
cron_daily (00:30 UTC) faceva DUE chiamate al giornale: chiudeva IERI (giusto)
e apriva OGGI. La pagina di oggi nasceva con ~30 minuti dentro e nessuno la
aggiornava fino alla notte dopo.
Il difetto non era il dato mancante: era che la pagina non lo diceva dove si
legge. Aveva TUTTE le sezioni di una chiusa -> passava ogni controllo di
completezza e freschezza, e la parzialita' stava solo in §Salute, quinta
sezione su otto. Stessa famiglia di "una barra presente non e' una giornata
presente", in veste nuova: la pagina e' presente, il giorno no.
Taglia misurata sul caso reale di oggi: la pagina congelata alle 00:37 diceva
"giorno: $+0.54 (1 letture)" e la regola [pnl] chiosava "senza operare". Alle
08:54 il libro aveva fatto 3 fill, 2 round-trip e +$25.86 ($642.56 -> $667.88).
Avrebbe raccontato una giornata ferma per tutta una giornata operativa.
Riparato in due pezzi indipendenti:
1. la pagina dichiara la parzialita' nel TITOLO e nella prima riga —
"PARZIALE (giorno in corso)", copertura esplicita (N giri su 24), il fatto
che non si aggiorna da sola, e quali numeri sono di quella frazione;
2. tolta la seconda chiamata dal cron. In docs/journal/ restano solo giorni
chiusi; lo stato corrente si prende da journal.py a mano (pagina marcata)
o da trades.db, che cron_book sincronizza ogni ora.
Scelta dichiarata: NON si rigenera ogni ora. Costerebbe una riga in cron_book
ma riscriverebbe un file tracciato da git 24 volte al giorno per un consumatore
che non esiste (l'analista legge il giorno chiuso). Se un domani servisse, la
strada e' RIGENERARLA, non congelarla: e' scritto nel commento del cron.
Prove (test_journal 28 -> 31): una accende la marcatura, una la tiene spenta su
un giorno chiuso (una marcatura sempre accesa non si legge), una e' guardia sul
SORGENTE di cron_daily.sh — ogni chiamata a journal.py deve avere --giorno
esplicito, perche' senza argomenti scrive OGGI.
Regolare docs/journal/2026-08-25.md rigenerato: ora si dichiara PARZIALE (9/24).
NON riparato, e registrato come debito aperto in CLAUDE.md §5:
test_wave_0726::test_t1_canonical_riproduce_il_backtest_ufficiale fallisce, e
falliva gia' prima di questa modifica (verificato con git stash sull'albero
pulito). Sharpe hold-out SKH01 canonical 1,9223 contro la banda cablata
1.3 < h < 1.9: il codice non e' cambiato, sono cambiati i dati (data/raw e'
gitignored, il cron lo ricostruisce ogni notte). La banda NON e' stata
allargata — lezione 07/08. Suite: 710 passati, 1 fallito.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
12dc04c969 |
analista: modello di default a opus-5
Sonnet-5 ha prodotto due errori di ragionamento in due giri: una frase su un merge di cui nessuno gli aveva parlato, e un round-trip corretto sulla pagina dichiarato inesistente, con una spiegazione inventata per il proprio dubbio. Nessuno dei due contiene una cifra nuova, quindi numeri_non_supportati() non li vede: e' il buco dichiarato quando la guardia e' stata scritta. Primo giro con opus-5 sulla stessa giornata: nessuna affermazione inventata, e le affermazioni numeriche verificate a mano contro il DB tornano tutte (fill 1 contro 2/5/4/3 dei giorni precedenti, equity ferma a $597.12 dal 13 al 18/08, target BTC 189 -> 115). Resta un'imprecisione di nome: chiama "target" un valore che nella fonte era la POSIZIONE. Il numero e' della fonte, la classe di errore e' cambiata. E ha prodotto una riformulazione che le regole non possono dare: la concentrazione del P&L in 7 giorni ha una lettura alternativa altrettanto compatibile — quei sette giorni sono anche gli UNICI in cui il libro e' stato a mercato, quindi la finestra non separa l'edge dal beta a un rialzo del 22-29%. ⚠️ Il campione e' di due osservazioni contro una: e' un tentativo di abbassare un tasso, non una garanzia, ed e' scritto cosi' nel sorgente. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
782c0ce4bc |
analista: manda l'analisi giornaliera su Telegram, con l'esito registrato
La notifica porta una testata coi numeri che si leggono senza aprire nulla
(equity, delta del giorno, cumulato, posizioni, leva, fill e round-trip) e
sotto l'analisi del modello.
Il trasporto Telegram e' pero' il punto singolo di guasto gia' misurato in
questo progetto: un tentativo, nessun retry, esito mai registrato, 6,9% di
invii persi (2/29). Su un messaggio al giorno sono ~25 messaggi persi
all'anno, quindi qui sono state fatte due delle tre riparazioni dichiarate
il 2026-08-23 e mai eseguite:
(a) `send(text, tentativi=1)` — retry OPZIONALE con backoff. Il default resta
1, cosi' il comportamento e' invariato per tutti i chiamanti esistenti:
alzarlo per tutti cambierebbe la latenza degli allarmi di venue_watch e
book_execute su un percorso con soldi veri, e non e' una modifica da fare
di straforo dentro un'altra funzionalita'. L'analista chiede 3.
(b) `ultimo_errore()` — il motivo si registra nel punto in cui l'eccezione
veniva ingoiata, e NON sopravvive a un invio riuscito. Regola gia'
codificata il 29/07 su un altro percorso e mai applicata al notifier.
La terza (marcare `alerted=True` solo a invio riuscito in venue_watch) cambia
il comportamento degli allarmi e resta una decisione dell'operatore.
L'esito finisce nel DB in tre stati: inviata / non configurato / FALLITA col
motivo. Un invio perso che non lascia traccia, il giorno dopo, non si
distingue da "non e' successo niente".
E se l'analisi manca, il messaggio parte lo stesso dicendo PERCHE': senza
quel ramo un guasto del modello si leggerebbe come una giornata senza nulla
da dire. Taglio a 4096 caratteri dichiarato, mai silenzioso; HTML del modello
neutralizzato.
708 test passano. Strategia, pesi, config INVARIATI.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
f5d9409213 |
analista di bordo: un modello scrive la prosa del giorno, in un campo suo
Aggiunto il quarto livello della pagina, tenuto separato dagli altri tre: numeri -> misurati dal feed e dal DB Lettura -> regole deterministiche, ognuna col suo id Analisi -> questo: prosa di un modello, che puo' sbagliare Nota -> l'operatore NON scrive dentro `nota`, che era la richiesta letterale: quel campo e' dell'operatore, ed e' cio' che a rileggere il giornale fra sei mesi permette di sapere chi ha scritto cosa. L'agente ha `analisi`, marcato col modello, con l'ora e con l'esito del controllo sui numeri. Gira via `claude -p` (verificato con env -i che risponda nell'ambiente nudo di cron), una chiamata al giorno sul giorno CHIUSO, tolte le tool. Tre guardie, una per ogni modo in cui una prosa generata rovina un registro: - NUMERO INVENTATO: numeri_non_supportati() estrae ogni cifra dall'analisi e verifica che compaia in cio' che il modello ha ricevuto. Oltre tre numeri liberi l'analisi e' RIFIUTATA e la pagina resta senza. E' un controllo debole per costruzione, e lo dichiara: prende l'invenzione, non il ragionamento sbagliato. - COMMENTO DI SE': senza_analisi() toglie dalla pagina la sezione dell'agente prima di dargliela. Al primo giro reale il modello aveva letto la propria uscita precedente e prodotto un paragrafo sull'avviso che si era preso il giorno prima — un ciclo di retroazione che in poche settimane avrebbe riempito il giornale di meta-commento, e che nessun controllo automatico puo' distinguere da prosa valida. - ANALISI DI IERI SPACCIATA PER OGGI: se il modello non risponde, la pagina resta VUOTA e il perche' viene registrato (stato + motivo). Il silenzio non diventa continuita'. Corretto anche un falso positivo mio: il tripwire validava sulla sola pagina mentre il prompt include anche il blocco storico, quindi bocciava un'equity vera. Una guardia piu' stretta del contratto produce allarmi che si impara a ignorare. Ogni guardia ha un test in entrambe le direzioni. 695 test passano. Strategia, pesi, config INVARIATI. Nessun ordine. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
1803e0ac9f |
giornale: lettura ragionata a regole dichiarate e tracciabili
Non prosa libera: dodici regole, ognuna con un id stampato accanto alla riga che ha prodotto. Combinano solo numeri gia' presenti nella pagina, tacciono sul non misurato e non prevedono niente. Il campo `nota` resta l'unico posto dove puo' finire un giudizio umano. Le regole: stato del libro e PERCHE' e' flat (componente per componente), disaccordo fra orizzonti del trend contro esposizione TP01, incoerenza (trend su ma libro fuori), leva contro il tetto, P&L del giorno, costo che supera il movimento, concentrazione del cumulato, drawdown dal picco, implicita contro realizzata col gate IV-rank di VRP01, giornata oltre 2 deviazioni, giri mancanti e feed vecchio, e la taglia del campione. Ogni regola ha DUE test: uno che la accende e uno che la tiene spenta. Una regola che si accende sempre non sta leggendo niente, una che non si accende mai e' indistinguibile da una rotta. Tre difetti corretti prima di pubblicare, tutti trovati scrivendo i test: - il tetto di leva era RIDICHIARATO (0.5 cablato) invece che letto da config/live.json — quinta occorrenza dello schema che il progetto paga da luglio: un sorvegliante che ridichiara il proprio bersaglio continua a passare il giorno che il bersaglio cambia. Ora deriva, e se il config non si legge lo dice invece di inventare un tetto. - l'IV-rank era il percentile a UN ANNO etichettato col nome del gate di VRP01, che usa un percentile ESPANDENTE. Due statistiche diverse, e oggi danno il verdetto OPPOSTO: 0.52 (sopra la soglia, "il sleeve venderebbe") contro 0.18 (sotto, sleeve fermo). Il valore giusto combacia con quanto gia' misurato il 30/07: 0/8 settimane passano il gate. - la concentrazione si accendeva su $2,08 di cumulato: vera e inutile. Ora ha una soglia di rilevanza, o e' una riga che insegna a saltare la sezione. 62 voci rigenerate. Strategia, pesi, config INVARIATI. 675 test passano. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
10c373075c |
libro di bordo: DB dei trade allineato col tempo + giornale giornaliero
I trade erano salvati, ma non allineati col tempo: book_execute.py scriveva ts_utc = pd.Timestamp(r['last_data']), cioe' la data della BARRA DI SEGNALE. 19 righe su 19 a 00:00:00, e un trade (ETH 0.04 @ 1869.74) registrato SEI GIORNI prima di essere eseguito — fill vero 2026-07-14T14:00, scritto 08/07. L'ora vera esisteva solo in logs/cron_book.log, che e' gitignored, fuori dal backup e ruotabile: la cronologia reale del libro live viveva in un file che una rotazione avrebbe cancellato senza che nessuno se ne accorgesse. - src/live/tradesdb.py: parser del cron log (ora vera + contesto del segnale), FIFO con fee pro-quota, riconciliazione a tre fonti, sqlite in data/live/ (dentro il perimetro del backup). Le tre fonti si INCROCIANO e non si sovrascrivono: reconcile() riporta le divergenze e non ripara niente da solo. Il venue e' autorevole ma TRONCA (1 trade su BTC, 0 su ETH): dichiarato. - scripts/live/trades_db.py: --sync (idempotente, in cron_book ogni ora), --report, --reconcile. - src/live/journal.py + scripts/live/journal.py: una voce al giorno in docs/journal/YYYY-MM-DD.md — mercato (ritorni, RV30, TSMOM sugli orizzonti di produzione, DVOL con eta'), libro (TP01/SKH01, target, posizione, leva), P&L (equity del venue come autorita', scomposizione locale), salute. NIENTE narrativa automatica: il campo `nota` e' l'unico posto per il testo libero ed e' dell'operatore, mai riscritto da un ricalcolo. - book_execute.py: ts_utc = ora vera del fill, bar_ts = barra. Test di regressione sulla sorgente: se qualcuno rimette last_data, il test lo dice. - 62 voci di giornale ricostruite dall'arming a oggi. Tre difetti trovati dai test mentre scrivevo, non a occhio: il renderer cadeva in KeyError se mancava il blocco mercato (un giornale che non si scrive non e' un giornale); "24 giri attesi" su un giorno IN CORSO produceva un allarme a ogni esecuzione; e libro e P&L leggevano due istanti diversi, quindi la stessa pagina mostrava due equity. Strategia, pesi, config INVARIATI. Nessun ordine. 659 test passano. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
c932fab304 |
venue_watch: disciplina degli allarmi, specifiche contratto controllate, terza referenza
Il 18/08 sono usciti quattro 🚨 identici con 'PRIMO PASSO: prelievo di prova' per una manutenzione Deribit annunciata, e tutti e quattro DOPO che il book aveva gia' ripreso a eseguire. Il book si era comportato bene (due giri di astensione, 'non eseguo a cieco'); il difetto era negli allarmi. 1. Il blocco piattaforma era un if secco senza memoria, accanto a un rilevatore tarato con cura che allerta una volta per streak. Ora passa da lock_step(), pura e testata: manutenzione entro tolleranza = un solo avviso morbido, che sfora = un solo 🚨 ('ha SFORATO'), blocco inspiegato = 🚨 subito, rientro annunciato una volta. public/status illeggibile NON e' un rientro. 2. Il messaggio diceva 'locked=true' cablato mentre il parser accetta anche 'partial': dichiarava un valore che non aveva letto, e il runbook manda a controllare proprio quel campo. Ora stampa e salva il valore grezzo. 3. Deribit ha cambiato tick e size dei perpetual lineari USDC il 18/08 e la tabella _CONTRACT, cablata a mano, non se n'era accorta. Nessun ordine rifiutato solo perche' i cambi erano riduzioni: e' andata bene per la direzione, non perche' ce ne fossimo accorti. Tabella aggiornata ai valori verificati e aggiunto check_specs(), che gira nel venue_watch orario (fuori dal percorso ordini) e dichiara la direzione: 'granularita'' = conforme, 'rifiuto' = il venue rifiuta. La tabella dichiarata resta l'autorita' per costruire un ordine, il venue e' il controllore. 4. Aggiunta Kraken come terza referenza: Coinbase ha comprato Deribit, e una referenza che e' la casa madre non misura piu' se Deribit scolla dal mondo. THRESHOLD_BPS e PERSIST_HOURS invariati, ma il consenso ora e' su tre serie e quel numero non e' ri-misurato: dichiarato nel codice e nel diario. La direzione dell'errore e' 'allerta di meno', non 'grida al lupo'. Test 23 -> 35 su venue_watch, suite intera 618 verdi. Book, pesi e config invariati; dry-run del book verificato. Diario: docs/diary/2026-08-19-*. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
d55eb13533 |
feat(chain): assorbita la raccolta catena opzioni, cerbero-bite dismesso
cerbero-bite viene eliminato. L'unica sua parte irreversibile e' il DATO:
una catena opzioni non si ricostruisce a posteriori (Deribit non serve book
storici, non c'e' un secondo venue). Il codice si riscrive; le ore non
raccolte no.
ASSORBITO
- scripts/live/collect_chain.py + scripts/cron_chain.sh (cron 25 * * * *):
raccolta propria, ~570 strumenti/giro, ~3 min.
- scripts/analysis/import_cb_archive.py: archivio 1.23M righe (2026-05-01+)
+ market_snapshots 17.402 righe (2026-03-26+: dealer gamma, gamma flip,
rischio liquidazioni, funding cross — dati che non abbiamo altrove).
- snapshot sqlite integrale in /opt/docker/backups/manual/ (SHA256).
NON ASSORBITO, con motivo: motore credit-spread ETH (regola "niente
short-vol da modello in deploy", conto a $52 contro minimo $720), GUI, kill
switch/dead-man/audit (abbiamo venue_watch/edge_watch/monitor_health/
fee_watch), dvol_history (fetch_dvol.py ha storia PIU' LUNGA: 2020+ contro
2026-05), decisions/positions (0 posizioni).
TRE DIFETTI DI BITE NON REPLICATI, tutti misurati il 30/07:
1. una chiamata per strumento invece di due (get_order_book?depth=3 da' gia'
quote+greche+IV+OI+book+underlying) + prefiltro OI in una chiamata sola:
551 -> ~290 chiamate per asset;
2. pacing invece di raffica. Il carico non e' mai stato il problema: 570
chiamate/ora = 0.16/s DISTRIBUITE; bite le sparava in 26s (~44/s) e si
auto-saturava il rate limit per-IP (12.186 risposte 429 in 26h, 96% al
minuto :00). Primo giro reale: 574 chiamate, 0 risposte 429. Il minuto :25
e' scelto: :00 era la raffica, :07 e' cron_book (feed 5m di SKH01).
3. quote_status esplicito {ok, no_quote, error} e book_depth NULL su errore
mai 0. "Book vuoto" e "chiamata fallita" sono cose diverse: e' per questo
che il guasto del 29/07 (50% di quote perse, 38 ore) non produsse alcun
segnale. Le righe ereditate restano 'unknown': bite non lo registrava e a
posteriori non e' ricostruibile.
Battuta di cuore in data/chain_collect/runs.jsonl anche a giro fallito,
sorvegliata da monitor_health (1h, max_age 3h): un collettore fermo non
produce niente, e il niente si legge come "nessun dato quel giorno".
Difetto trovato per strada: due formati ISO nella stessa colonna (92 righe
di backfill senza microsecondi). pd.to_datetime senza `format` ne inferisce
uno solo e manda gli altri a NaT -> il dropna a valle li toglieva in
silenzio, e la serie di contesto perdeva 5 settimane slittando dal 26/03 al
01/05. Corretto con format="ISO8601" e scarto RUMOROSO.
Book, pesi, config, strategia INVARIATI. 537 test verdi.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
7d64dd4c2b |
live(feed): l'allerta funzionava, la sua CAUSA era una riga cablata
Il 29/07 il feed 5m di SKH01 e' ricaduto sul certificato in 6 giri orari su 8 (eta' 265->685 min, +60 a ogni giro = firma esatta del fallback): latenza d'uscita da ~1h a ~11h, book flat, nessuna posizione esposta. L'allerta del 26/07 ha segnalato 6/6, poi ha stampato un perche' che non aveva misurato — la nota "fetch pubblico KO" era cablata, identica in ogni caso, compreso quello in cui la coda fresca E' attaccata e il vecchio e' il certificato. E la causa vera non era recuperabile per costruzione: _fetch_recent_5m ingoia l'eccezione di pagina con un break e a prima pagina fallita ritorna un frame vuoto, indistinguibile da "il venue non ha barre". Cablato: livefeed.last_fetch_error() (registra E logga nel punto in cui l'errore viene ingoiato) -> book_report.skh_feed_errors -> allerta con la causa. Stesso buco chiuso sul ramo gemello "conto offline", che la ragione l'aveva gia' in mark_src e non la stampava mai. La causa del 29/07 resta IGNOTA e va citata cosi': una prima stesura la attribuiva a un rate limit per-IP come se fosse un fatto -> rimossa, sarebbe stato lo stesso difetto che stavo correggendo scritto meglio. Cron spostato al minuto :07 come ripiego da UNA osservazione, dichiarato tale. Test 11 -> 16 (incluso il caso a meta' paginazione: coda parziale attaccata, mancano le barre PIU' recenti). Book/pesi/config/strategia INVARIATI. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
fd05307c96 |
research(capitale): il lump-sum vale 2.45x, e la protezione dalla rovina non passa da GTAA01
Quattro filoni chiesti dall'operatore ("proposte"). Book, pesi, config: INVARIATI.
1. LUMP-SUM + VENUE (r0727_lumpsum_split.py). Tutte le traiettorie del 25-26/07 avevano
START=600 cablato: mai misurato un versamento iniziale, mentre ~10k EUR stanno fermi
altrove. Macchineria validata: con lump 0 riproduce IDENTICI i numeri del 26/07.
- 10k EUR oggi e mai piu' nulla -> traguardo 17.2a, P 62%, rendita 61.58 EUR/g
- equivalenza onesta: +154 EUR/mese per 13 anni = 24.523 EUR, cioe' 2.45x
(la prima stesura misurava i versamenti risparmiati: numero giusto, domanda sbagliata)
- col rischio venue: a 11.500$ lo split e' possibile (quota IB 26%, non 25%) e taglia
P(perso tutto) da 18.4% a 3.5% a p=1%, costando 1.9-2.6pp di P(arrivare)
- SPLIT-CASSA: seconda gamba ferma costa altri 0.6-0.8pp e protegge IDENTICO
-> la protezione non e' bloccata dal PRIIPs: serve un CONTO, non uno sleeve
2. FEE WATCH (scripts/live/fee_watch.py). Nuovo schema Deribit dal 1 agosto senza numeri
pubblicati -> sorvegliante invece di promemoria. Legge il tier base dall'endpoint
pubblico (oggi taker 5.00 bps), applica la regola congelata e allerta sui cambiamenti.
3. MONITOR HEALTH (src/live/monitor_health.py). Tre gate pre-registrati si decidono su
serie forward di cui una sola era sorvegliata. Misura coda E buchi interni: una serie
bucata ma fresca passa qualunque guardia di freschezza.
4. BANDA GTAA01 25% VALIDATA (r0727_gtaa_band_gate.py). 30 celle, 29.9 anni, dpy=252.
Non e' selection-on-holdout (4/30 IS, 5/30 OOS), DSR 0.999, tracking OK ma AL BORDO.
Il modo di fallire non e' il de-levering (la vol non scende) ma la perdita di tracking.
Impatto sul book: zero -> REBAL_BAND_USD non toccato, si applica al deploy.
Aggiunto anche il bullet edge_watch, cablato il 26/07 e mai finito in CLAUDE.md.
Test: 56 nuovi, 504/504 verdi.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
be4690375f |
research(gtaa): la via UCITS e' aperta e costa ~zero — il broker non e' la variabile
Domanda dell'operatore: "usiamo revolut o degiro". Risposta misurata: cambiare broker non sblocca nulla (il PRIIPs e' una norma, non una politica di IB); cambiare VEICOLO si', e costa ~zero. CORREZIONE A UNA MIA AFFERMAZIONE. La nota in gtaa.py diceva che gli UCITS fanno perdere la validazione a 30 anni. Falso: il PRIIPs vieta di COMPRARE, non di GUARDARE — i prezzi dei 6 ETF USA restano leggibili, quindi il segnale gira sui 30 anni per sempre e cambia solo il veicolo su cui si incassa. Misure (3 lenti, un grado di liberta' per volta, 6.3 anni comuni): L0 segnale USA + rend. USA Sh 0.81 / CAGR 3.96% L2 segnale UCITS + rend. UCITS Sh 0.84 / CAGR 4.08% drag del veicolo +0.10%/anno EW, coerente coi TER; ritenuta USA ~35bps a FAVORE dell'UCITS e non inclusa nel drag. Lo stimatore ovvio sbagliava: la media delle differenze giornaliere dava -0.47%/anno su CSPX contro -0.06% vero (SE ~7%/anno = 15x la quantita' stimata, piu' drag di varianza). La deviazione fra veicoli sullo stesso indice si misura sul RAPPORTO CUMULATO. Il vincolo non e' il broker ma il prezzo di UNA azione, che e' una scelta: CSPX $802 vs VUAA $144 sullo stesso S&P 500. A $3.000 con azioni intere l'insieme STORIA tiene 4/6 gambe (a mercato il 33%), l'insieme DEPLOY 6/6 (65%) -> il frazionamento non serve. Letto su gambe-vive+vol, non su Sharpe: il vincolo intero ALZA lo Sharpe perche' de-leveraggia (null de-levering, 4a occorrenza). Resta da verificare una cosa sola: 77-149 ordini/anno contro soglie $0.90 ($3k) / $2.23 ($10k) / $7.62 ($50k) per ordine. Raccomandazione: restare su IB. Feed equity: aggiunto il CROSS-CHECK che mancava (src/data/eq_crosscheck.py). Il primo veicolo estero ha trovato subito CSPX 2012-01-13 con open/high in USD e low/close in EUR (fattore 1.2797 = EURUSD del giorno), invisibile alla guardia maxret>50% — stesso schema dello split 2:1 del 25/07. Soglia non tarabile sulla deviazione (rumore 9.90%, margine 2.2x): cambiata statistica in |dev|/movimento del gemello -> margine 5.3x. Limite EURUSD 1.09 dichiarato e chiuso sul DANNO (dSharpe mediano -0.003), congelato in un test. Book, pesi, cron, config INVARIATI. 435 test verdi (+24). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XBbYmiXqbUNuGpK9sfbsGp |
||
|
|
6664575e1c |
❌ GTAA01 NON deployabile: blocco PRIIPs CONFERMATO sul conto reale
Il rischio sollevato poche ore fa e' stato verificato tentando l'ordine. Il broker rifiuta: "Trading limitato — Questo prodotto non dispone di un KID in inglese o in una lingua approvata per il vostro Paese. I clienti retail possono negoziare prodotti retail preconfezionati solo se e' disponibile un KID appropriato." Non e' piu' un'ipotesi regolatoria: e' un rifiuto d'ordine documentato. SPY/QQQ/IWM/TLT/GLD/HYG sono ETF domiciliati USA, gli emittenti non pubblicano il KID e i broker UE ne vietano l'ACQUISTO al retail. ⚠️ Le QUOTAZIONI restano visibili — l'operatore vedeva tutti e sei i prezzi in piattaforma, ed e' esattamente cio' che rendeva invisibile l'assunzione. COSA CADE: lo sleeve cosi' com'e' non e' deployabile, e con esso il piano di attivarlo a ~$13k. Restano valide come RICERCA e nulle come DEPLOY: validazione a 30 anni (22/06), fix costi IB (25/07), GTAA_MIN_CAPITAL, e il LOO del 26/07 che lo indicava come l'unico sleeve positivo nel 100% delle estrazioni su tutte e tre le metriche. COSA NON CADE: tutte le traiettorie, i muri e le tabelle di rendita usano book_series(with_gtaa=0) = solo TP01+SKH01 su Deribit -> nessun numero del piano va rifatto. E il book live non lo include. VIA D'USCITA (non percorsa): equivalenti UCITS. NON e' una sostituzione di ticker — storia piu' corta (si perde la validazione a 30 anni, cioe' cio' che lo rendeva credibile), ritenuta/TER/replica diversi (decine di bps su un CAGR del 3.65%), quotazione LSE/Xetra con orari e valuta diversi da uno sleeve che decide sul close USA. Percorso onesto: validare sull'INDICE e negoziare il VEICOLO, dichiarando tracking error e ritenuta come costi. REGOLA: la negoziabilita' sul conto REALE va verificata quando lo sleeve entra in RICERCA, non quando entra nel book. Cinque settimane di misure poggiavano su un'assunzione mai controllata, e il controllo e' costato un ordine di prova. Book, pesi, cron, config INVARIATI. 411 test verdi. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
b3082de9af |
⚠️ GTAA01: negoziabilita' degli strumenti MAI VERIFICATA (rischio aperto)
Domanda dell'operatore ("GTAA01 puo' essere in revolut?") che scopre un'assunzione mai
controllata in 5 settimane di lavoro sullo sleeve.
GTAA01 usa SPY, QQQ, IWM, TLT, GLD, HYG = ETF DOMICILIATI NEGLI USA. Sotto il regolamento
PRIIPs un investitore retail residente nell'UE tipicamente NON puo' acquistarli, perche'
gli emittenti USA non pubblicano il KID; i broker UE — Interactive Brokers incluso, che e'
esattamente il venue che lo sleeve assume — li bloccano in acquisto per la clientela
retail.
COSA POGGIA SU QUESTA ASSUNZIONE: i 30 anni di storia, il fix dei costi IB reali del
25/07, la soglia GTAA_MIN_CAPITAL $3.000, il contributo al book, e il risultato del LOO del
26/07 che lo indica come l'UNICO sleeve positivo nel 100% delle estrazioni su tutte e tre
le metriche. Nessuno di questi numeri e' sbagliato come backtest; quello che non e' mai
stato verificato e' se lo sleeve sia ACQUISTABILE dal conto reale dell'operatore.
DA VERIFICARE PRIMA DEL DEPLOY, non dopo. Se il blocco c'e' servono gli equivalenti UCITS
(CSPX/SXR8, EQQQ/SXRV, IUSN/CSUSS, DTLA/IDTL, SGLN/IGLN, IHYU), che sono strumenti DIVERSI
per domicilio, valuta, TER e replica -> rifetch dei dati e rivalidazione, non una
sostituzione di ticker.
SU REVOLUT nello specifico la domanda resta piu' stretta: universo ETF limitato, prodotto
retail leggero, e un ribilanciamento settimanale a 6 gambe con banda $50 non e' cio' per
cui e' pensato. Il confronto va fatto su esistenza degli strumenti e costo per ordine.
Nota permanente nel sorgente sopra EQ_UNIVERSE + bullet in CLAUDE.md.
REGOLA: la negoziabilita' di uno strumento sul conto REALE va verificata quando lo sleeve
entra in RICERCA, non quando entra nel book. E' l'analogo azionario di cio' che il progetto
gia' fa sul crypto (min-order, haircut small-cap, eseguibilita' a $600): la stessa
disciplina non era stata applicata all'equity.
Book, pesi, cron, config INVARIATI (GTAA01 non e' nel book live).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
95caeb87da |
feat(live): allerta sul salto di equity — conferma il versamento, segnala un prelievo
La verifica "il cap si adegua?" esisteva solo come sorveglianza di sessione, e il
versamento slitta di giorni: una verifica che vive in una chat non e' una verifica. Resa
permanente e generalizzata.
`write_equity_watermark` ora ritorna {prev, new, pct} quando il salto fra due letture
consecutive supera EQUITY_JUMP_ALERT = 10%; `book_report` lo espone come `equity_jump` e
`book_execute` manda un Telegram con il NUOVO DIMENSIONAMENTO accanto (cap/asset, nozionale
lordo, leva), cosi' il messaggio si legge senza aprire il repo.
Il book ha vol ~0.4%/giorno: un salto del 10% fra due giri orari non puo' venire dal
trading. Quindi l'allerta copre DUE casi con un meccanismo solo:
- VERSAMENTO: conferma che e' atterrato e che il sizing lo ha seguito;
- USCITA DI FONDI: un prelievo che non hai chiesto, o una perdita anomala. E' questo il
caso che conta di piu', ed e' il motivo per cui la soglia e' a due code.
Prima lettura in assoluto -> nessun allarme (senza un "prima" non c'e' un salto).
Il watermark si aggiorna ANCHE quando allerta, o il cap resterebbe indietro (test cablato).
411 test verdi (+7). Strategia, pesi, cron, config INVARIATI.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
8b21d29e69 |
fix(dashboard): taglia del book letta dal conto, non cablata
Il cruscotto dichiarava "cap $300/asset · capitale reale ≈ $600" come testo fisso: sarebbe diventato falso al primo deposito, sulla pagina che si guarda per capire cosa sta girando. Ora legge equity reale + max_notional_per_asset_frac + disaster_sl_pct dalla config. Reso dinamico solo il testo di stato del book LIVE. I $600/$2000 restanti in dashboard.py sono i capitali d'inizio CONGELATI dei libri paper (forward-monitor): quelli devono restare fissi o le serie perdono continuita'. Verificato il percorso di ESECUZIONE: nessuna assunzione cablata sulla taglia da $600 (book.py / shadow.py / book_execute.py). Reso: "capitale reale $596.92 · cap $298/asset · disaster-SL on-book −30%". 391 test verdi. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
b023cc2bdf |
fix(live): cap di fallback legato all'ultima equity osservata + cap config 300 -> 3000
L'operatore ha autorizzato "si alza il cap a 3000". Verificato PRIMA di eseguire: il
deposito non era ancora arrivato (equity reale $596.92), e alzare il cap in quel momento
sarebbe stato pericoloso NEL VERSO OPPOSTO.
IL PROBLEMA. Quando l'equity reale non e' leggibile, shadow_report ripiega su paper_cap =
$2.000 NOMINALI, che non e' il conto vero: il sizing diventa 0.5 x 2000 x (...) = fino a
$1.000/asset, e il cap fisso e' l'unica cosa che impedisce a quel nominale di diventare
leva reale.
cap $300 -> fallback $600 lordi su $597 = 1.00x OK
cap $3000 -> fallback $2.000 lordi su $597 = 3.35x NO
Cioe' il cap sarebbe stato troppo alto proprio nel momento in cui non si sa quanto c'e'
sul conto, e con disaster_sl_pct -30% quella e' la configurazione peggiore possibile.
LA CORREZIONE. Invece di alzare un numero da ricordare, il cap di fallback e' legato al
conto: cap_fallback = min(cap_fisso_di_config, ultima_equity_reale_osservata * frac), con
watermark in data/live/equity_seen.json scritto da book_report ogni volta che l'equity
reale e' leggibile. Il cap di config torna a essere un TETTO DICHIARATO.
Senza watermark (primo avvio, file cancellato) -> CAP_UNKNOWN_USD = $300: non si sa niente
del conto, si usa la taglia storicamente sicura.
VERIFICATO SUL CONTO VERO, nei due regimi:
oggi, watermark $596.92 -> $298.46/asset = leva 1.00x
dopo il versamento, $6.047 -> $3,000.00/asset = leva 0.99x
Sicuro in entrambi gli ordini di eventi, senza dipendere da un'azione manuale al deposito.
Questo CHIUDE l'azione pre-registrata il 2026-07-02 ("al deposito alzare il cap a
equity/2"), rimasta ineseguita per 24 giorni — non eseguendola, ma rendendola non
necessaria.
REGOLA: un parametro di sicurezza che va aggiornato a mano a ogni cambio di scala e' un
difetto, non una configurazione. Lo stesso numero era sbagliato in un verso prima del
deposito e nell'altro dopo: la soluzione non era scegliere il valore giusto, era legarlo
alla grandezza che lo determina.
Guardie: tests/test_cap_watermark.py (11), A DUE LATI — il cap non puo' ne' superare il
conto reale (leva nascosta) ne' restare sotto dopo un deposito (strozzatura).
Dry-run sul conto reale: cap/asset $298, book flat, nessun ordine. 391 test verdi (+11).
Strategia, pesi, cron INVARIATI. Cambia solo config/live.json e il calcolo del cap di
fallback.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
ab5bcace16 |
feat: VENUE WATCH — tripwire di fallimento exchange, cablato live
Risposta a "trova un sistema di protezione da fallimento exchange" SOTTO IL VINCOLO della decisione appena presa (100% Deribit fino a $20k). Se non si puo' ridurre l'ESPOSIZIONE, l'unica leva e' il TEMPO: il modello di rischio del mattino assumeva il salto a zero istantaneo, ma i fallimenti reali non lo sono (Mt.Gox mesi, FTX ~72h, e misurato qui: Bitfinex 2018-19 dislocato per 2.324 ore consecutive). SEGNALE: un venue che gata i prelievi rompe l'ARBITRAGGIO -> il prezzo si stacca dal consenso e ci resta. E' |scarto|, non il segno (Mt.Gox a premio, un venue in fuga a sconto: stessa cosa). Consenso = venue USD indipendenti (Coinbase, Bitstamp), mai USDT. Deribit sta a 3 bps dal consenso in mediana su 8 anni (65.043 ore BTC + 64.541 ETH). TARATURA CONGELATA: 100 bps persistenti 4h a segno costante. Criterio DICHIARATO PRIMA, perche' i due ovvi sbagliano in versi opposti (provati entrambi): "minimi bps" -> 25/24h consuma 24 delle ~72h di FTX; "minime ore" -> 500/2h MANCA FTX (margine 0.6x). Regola: zero falsi allarmi in 8 anni + margine >=3x sul caso storico piu' debole -> soglia <=100bps -> poi minima latenza. Margine 3x FTX / 5x Quadriga / 10-20x Mt.Gox, zero falsi allarmi con crash COVID, maggio 2021, LUNA e novembre 2022 inclusi. CONTROLLO POSITIVO SUPERATO (un rilevatore tarato per non segnalare e' indistinguibile da uno rotto): puntato su Bitfinex 2018-19 scatta 22 volte, episodio piu' lungo 2.324h a +447bps. 22 dove il problema c'era, 0 su Deribit. E la durata risponde alla domanda vera: un venue gated resta dislocato per settimane, quindi 4h di latenza sono trascurabili. ECONOMIA: falso allarme = 0.248% atteso (flat 3g misurato sul book reale a ogni data d'inizio); vero positivo = 100% salvato. Break-even p > (falsi/anno) x 0.00248: a 1 ogni 8 anni serve p > 0.031%. Il valore sta nella SPECIFICITA', non nella sensibilita'. CABLATO: src/live/venue_watch.py (nucleo puro) + scripts/live/venue_watch.py, in cron_book.sh PRIMA di book_execute (se Deribit e' in stress l'allarme deve partire anche quando l'esecuzione fallisce per la stessa ragione). Tre stati OK/ALERT/BLIND — "non vedo" non e' "va bene". ALLERTA, NON BLOCCA: l'azione e' prelevare (manuale; una chiave con permesso di prelievo sarebbe essa stessa un rischio) e bloccare non protegge un saldo che e' a rischio anche stando flat. Runbook pre-deciso nel docstring. NON COPRE, e non e' un argomento per riaprire il 26/07: un fallimento SENZA finestra (furto chiavi, sequestro, exit-scam) non lo prende nessun tripwire. ERRORI CATTURATI IN SESSIONE: - break-even calcolato sul p5 invece che sulla media (8.3x piu' severo, conclusione ribaltata); - ipotesi meccanica sbagliata: credevo che i crash dislocassero a segno ALTERNATO. Falso, sono a segno costante anche loro (perp sotto spot per ore in cascata). A separare sono ampiezza e durata, non il segno; - la prima corsa tronco' il campione da 8 anni a 29 GIORNI per un inner-join con Kraken (che serve solo ~700 candele) e la copertura era gia' stampata a video: una diagnostica stampata NON e' un controllo. Ora c'e' una guardia che ferma lo script. 2a occorrenza in un giorno dopo GTAA01; - il controllo positivo era finito dentro il ramo `else` -> non girava mai, cioe' esattamente il difetto che doveva prevenire. Book, pesi, config INVARIATI. 359 test verdi (+23). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
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>
|
||
|
|
031b71bf54 |
ops(live): sorveglianza freschezza feed SKH + correzione dei docstring sulla latenza d'uscita
T1 (TP di SKH01 come limit resting on-book) NON e' stato implementato, per misura.
Leggendo il codice di produzione: TP01 e SKH01 tradano lo stesso strumento con una
sola posizione netta Deribit, quindi un ordine on-book al livello di SKH chiuderebbe
anche quota TP01. Misurati i due ostacoli: (A) segno compatibile nel 97% dei trade
che escono in TP = risolvibile; (B) divergenza modello/live apparentemente bloccante.
Ma (B) non esiste: resample_5m NON scarta il bin 230m in corso (21 barre 5m su 46
nell'ultimo bin) e _skyhook_positions ci itera dentro -> il live rileva gia' SL/TP
intra-barra, entro ~1h dal tocco. I docstring che dicevano "usa solo barre chiuse" e
"latenza fino alla chiusura della barra 230m" erano FALSI e hanno guidato tre analisi
(02/07, 24/07, T1). Corretti sul posto.
Conseguenza: la lente `hourly` sottostima il path live di +0.081 Sharpe FULL di book
(23/23 offset, banda appaiata); il live vero sta sopra il canonical sul FULL, e il fix
richiesto sarebbe un declassamento (+0.054 vs +0.081) in cambio di ordini parziali sul
netto in un percorso con soldi veri.
Cablato invece il problema vero trovato per strada: fresh_5m fallisce in SILENZIO
(fallback al certificato, rigenerato 1x/giorno) -> la latenza d'uscita di SKH01 passa
da ~1h a ~1 giorno senza segnalazione, e nessun controllo esistente scatta (il gate di
staleness guarda il feed di TP01). Stesso schema del feed-freeze del 14/07.
* livefeed.feed_age_minutes: pura, eta' dalla CHIUSURA della barra, None = non
misurata, clamp sugli skew d'orologio
* book_report espone skh_feed_age_min (max fra gli asset)
* book_execute stampa lo stato e allerta su Telegram sopra skh_feed_max_age_min (30m)
Scelta dichiarata: ALLERTA, NON blocca. Bloccare fermerebbe anche TP01 (nettato sullo
stesso strumento) per un guasto di rete; forzare SKH flat chiuderebbe posizioni buone
su un glitch.
Follow-up dichiarato: la stessa barra parziale tocca gli INGRESSI (ent[n-1] da breakout
non confermato). Disaccordo in 1 bin su 112, ma con 3 entry nel campione la taglia non
e' stimabile. E' un cambio di strategia, non di strumentazione -> misura dedicata prima.
Strategia, pesi e cadenza del cron INVARIATI. Nessun ordine inviato. Suite 266 verdi.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
607cd94ecd |
fix(gtaa): costo IB reale (pavimento fisso) + esecuzione a banda — lo sleeve era cieco al capitale
DIFETTO. src/portfolio/gtaa.py modellava il costo come 2bps PROPORZIONALI e il modulo si
dichiarava "eseguibile a basso capitale, switch mensile/basso turnover". Entrambe false:
il vol-target e' CONTINUO (l'esposizione cambia ogni giorno, su 6 gambe) e IB non ha una
fee proporzionale ma un PAVIMENTO FISSO per ordine, min(max($0.35, $0.0035/az), 1% del
controvalore) = ~$530/anno indipendenti dal capitale.
Il modello vecchio era quindi CIECO AL CAPITALE: dava Sharpe 0.64 sia a $50.000 sia a $600.
Alla taglia grande era sostanzialmente giusto (0.64 vs 0.59-0.66 reali); a $600 la realta'
e' -0.55 di Sharpe e -3.5%/anno di CAGR. L'errore era tutto concentrato dove lo sleeve
verrebbe realmente deployato.
FIX. Il modulo ora:
* modella la commissione IB reale (ib_commission);
* esegue a BANDA + CADENZA (settimanale, $50/gamba) — config scelta sul PLATEAU del sweep
(weekly/monthly x banda 25-100 -> Sh 0.45-0.64 a ogni capitale), non sull'argmax
in-sample (banda $50 daily a $600 = cella isolata che crolla a banda 100);
* prende il CAPITALE allocato come parametro: gtaa_returns(capital=...);
* dichiara la soglia di deployabilita': GTAA_MIN_CAPITAL=$3.000 + gtaa_is_deployable();
* espone gtaa_rebalance_plan(held, capital) per l'esecutore — salta le gambe il cui
nozionale non supera la banda (un ordine da $12 costa $0.35 = 2.9%).
sleeves.py dichiara esplicitamente il capitale assunto (GTAA_DEFAULT_CAPITAL=$10.000 allocati
= book ~$50k al peso 20%) invece di nasconderlo.
IMPATTO SUL BOOK (misurato sostituendo la sola gamba GTAA, non citato):
GTAA01 standalone Sh 0.64 -> 0.61 CAGR 3.76% -> 3.65%
book 5 sleeve FULL 2.22 -> 2.22 HOLD 2.36 -> 2.38 maxDD 6.2% -> 6.0%
Trascurabile alla taglia assunta: il fix conta per il DEPLOY (a $600-2k passa da -3.5%/anno
a +3.0%/anno). PESI INVARIATI -> nessun weights_tilt_null richiesto.
CORREZIONE A UN ERRORE DI ANALISI DELLA SESSIONE. Il diario citava il modello vecchio a
"Sharpe 0.77 / CAGR 5.5%": artefatto di annualizzazione: la serie GTAA grezza ha ~252 barre
/anno (soli giorni di borsa) e metrics() annualizza a 365 con years=n/365.25 -> Sharpe x1.20
e CAGR x1.45. Le righe per-capitale erano gia' su calendario 365, quindi era falsata solo la
riga di riferimento. Corretti diario, CLAUDE.md e r0725_capcurve.py.
LEZIONE: una serie su giorni di borsa non si passa a metrics() senza to_daily().
Test: 221 pass (+4 in tests/test_gtaa_sleeve.py: pavimento non proporzionale, dipendenza dal
capitale + soglia, senza-banda-e-distruttivo, piano che salta le gambe sotto banda).
Smoke: scripts/live/paper_combo.py gira invariato.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
741bbc2c09 |
fix(data): split non aggiustati nel feed equity — difetto sul libro live, riparato alla fonte
IWM ed EFA avevano uno split NON aggiustato il 2005-06-09 (IWM 2:1 = -49.5%, EFA 3:1 = -66.5%): IB ADJUSTED_LAST non li aveva aggiustati. La certificazione non li vedeva per un punto cieco STRUTTURALE: l'unica guardia sui salti era `maxret > 50% -> SPIKE?` e uno split 2:1 fa esattamente -50%, cioe' cade sul filo della soglia (IWM passava a 49.5% con status OK). IWM e' una delle 6 gambe di GTAA01, sleeve in PRODUZIONE. Impatto misurato: GTAA6 FULL Sharpe 0.61 -> 0.64, IS (<2015) 0.49 -> 0.54; OOS 2015+ e maxDD INVARIATI (l'artefatto e' nel 2005, fuori hold-out) -> il difetto SOTTOSTIMAVA lo sleeve: nessuna decisione presa va rivista. Discriminante split-vs-crollo: NON il rapporto (SLV 2026-01-30 ha rapporto 1.3994, a 4bps da 1.4, ma e' un crollo vero: GLD -10.3% lo stesso giorno) ma il RANGE INTRADAY — lo split apre gia' al nuovo livello con range normale (IWM: open 47.00, range 1.7%), il crollo si muove DENTRO la barra (SLV: range 33%). - src/data/eq_splits.py: detect_unadjusted_splits() a 3 condizioni congiunte (|ret|>20% AND rapporto ~ fattore comune AND range intraday <5%) + repair_splits() con split multipli componibili; - riparazione in LETTURA in src/portfolio/gtaa.py::_close (produzione) e scripts/research/eqlib.py::load_eq (ricerca); - fetch_ib_equities.certify(): nuovo status SPLIT-NON-AGG + elenco split rilevati; - tests/test_eq_splits.py: 8 casi, inclusi il falso positivo SLV e un crollo -50% esatto con range grande. Regola nuova: ogni soglia di certificazione tarata su un valore tondo va controllata contro il difetto che genera esattamente quel valore. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
67f7b89e4c |
chore(live): ritira paper_trend inerte -> Old/ — sostituito da paper_portfolio
Il paper trader standalone TP01 (paper_trend.py) era inerte dal 2026-06-19 (n_bars=0), non in cron, e sostituito da paper_portfolio (TP01+XS01, gira ogni giorno). Archiviato in Old/scripts/live/ e stato congelato rimosso. Book live INTATTO: shadow.py legge PAPER_STATE con guardia .exists() -> degrada a FALLBACK_CAPITAL=2000 (identico allo stato congelato) e paper_pos=None. Dry-run di book_execute identico prima/dopo (conto online, HOLD su BTC/ETH). - git mv scripts/live/paper_trend.py -> Old/scripts/live/paper_trend.py - rm data/paper_trend/ (state inerte, gitignored) - CLAUDE.md: 3 riferimenti -> paper_portfolio + nota di ritiro - live_trend.py + shadow.py: hint/commento fallback legacy aggiornati Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
cf7de40dc0 |
feat(live): cap/asset dinamico = equity/2 — operazionalizza la decisione frontier (inerte a $600)
Il cap notional per-asset non e' piu' fisso a $300: con max_notional_per_asset_frac in config diventa equity/2, cosi' cresce col capitale e un deposito futuro non resta strozzato (frontiera 2026-07-03). Guardrail: dinamico SOLO con equity reale fidata; su fallback/offline si torna al cap fisso (protezione downside quando E e' ignota). Live dry-run: cap $299 a equity $598 -> inerte oggi. Suite 172 passed (+4 test). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
a74cc69583 |
research(anchor-audit): timing-luck confermato su XS01 e SKH01 — 3/3 sleeve ancorati, book de-luckato HOLD ~2.0
Chiude il pendente dell'ondata timing 2026-07-02. Due audit indipendenti (sanity replica bit-exact, ancore a priori, zero tuning per-fase, bootstrap): - XS01 (10 fasi ciclo H=10): fortuna nel DD (15° pctl: 10.8% vs 15.5% tipico, 29% peggiore) e FULL (85°), non nell'hold-out (65°); P(spike)~0.91-0.94. Lens onesta = ensemble di fase FULL 1.25 / HOLD 1.31 / DD 11%. Ammissione @15% regge, i numeri 1.50/1.71/11% no. - SKH01 (23 offset griglia 230m/690m): canonico = 93-98° pctl di OGNI metrica, minHold/blend/book-HOLD = massimo dei 23; il gate DD<30% (criterio di selezione V2-DD) fallisce in 15/23 offset. Regge: uplift blend positivo a tutte le 23 fasi (min +0.18) + corr ~0.08 -> ADDS ridimensionato. Path live reale (cron orario + exit software): book FULL 1.46->1.19 / HOLD 1.64->1.15 / DD 18->25%, gap-through-stop nei crash (sl2% -> -11/-23%). - Book 5-sleeve: HOLD 2.46 eredita ~+0.10/+0.17/+0.5 di fortuna d'ancora (TP01/XS01/SKH01) -> stima de-luckata HOLD ~1.9-2.1, FULL ~2.0-2.2, DD ~6%. Nessun cambio operativo (pesi/book live invariati; ogni cambio passa weights_tilt_null). Narrativa aggiornata (CLAUDE.md, docstring skyhook). Follow-up: anchor_luck_band() in altlib, cadenza 230m, peso SKH live. 168 test verdi. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
73d74c5e53 |
research(wave-0702): ondata timing + CRT — 8 filoni, 0 nuovi sleeve, finding anchor timing-luck TP01
Goal: "altre strategie su Deribit con timing differenti". 8 filoni multi-agente + scettico: - event-clock bars, expiry calendar Deribit, clock lenti/bande, regime-speed: SCARTATI - CRT (Candle Range Theory) base/multi-TF/contesto: SCARTATA 3/3 (DSR~0, ritest = informazione negativa; sottoprodotto: FOLLOW>FADE sui livelli prior-day ogni anno, conferma il lead prevday) - FINDING (confermato da scettico indipendente): hold-out 0.31 di TP01 = migliore delle 24 ancore orarie (mediana 0.04, banda [-0.13,+0.30]) -> narrativa corretta in CLAUDE.md e docstring: l'hold-out non risolve l'edge di ritorno, regge il taglio DD a ogni ancora. Tranching K=2/4 = solo varianza della stima, no deploy a $600. Audit d'ancora pendente su XS01/SKH01. Book live e portafoglio INVARIATI. Test 168/168. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
e6657fcb16 |
feat(portfolio): GTAA01 promosso a 5° sleeve @20% — FULL 2.12→2.24, HOLD 2.21→2.46, DD 7.8→6.2%
Il diversificatore strutturale validato il 2026-06-22 (trend difensivo equity 6-ETF su IB, 30y storia, OOS 2015+ indipendente dall'hold-out crypto, corr al book ~+0.10) era rimasto in paper_combo senza mai essere valutato come sleeve. Valutazione onesta (r0701_gtaa_5th_sleeve): uplift positivo in-sample e su TUTTE le finestre disgiunte (+0.05/+0.19/+0.25), multi-cut +0.21..+0.25, plateau monotono w10-30% — passa dove EW-STR era morto. Ingresso @20% (IS-best 30%, scelta strutturale dichiarata). Convenzioni: weekend equity=0 (capitale IB fermo, non riciclato), attivazione all'era book 2019-03. Il book live Deribit (TP01+SKH01) NON cambia. Suite 168/168. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
491411ac77 |
research(wave-0701): 6 filoni multi-agente — 0 nuovi sleeve, pesi confermati, gate weights_tilt_null
Ondata onesta su angoli non coperti: funding-TS (chiude il filone funding su 3 lati), breadth alt (non-ridondante ma DSR 0.43, rivisitabile con storia), XS-residmom (REDUNDANT), pesi+guardia-DD (EW-STR refutato dallo scettico come selezione-sull'hold-out di 2° ordine, firma best-of-15), VRP-refine (filone esaurito), stagionalità-XS (morta allo step statistico). Lezione codificata: weights_tilt_null + combine_outer in src/portfolio (ogni cambio-pesi vs null di tilt casuali cap-respecting + delta in-sample>=0); 5 test nuovi, suite 165/165. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
ccf5e38101 |
feat(dashboard): banner alert operativi del book live (SKH/posizione/equity)
Il dashboard non mostrava nessuno dei tre segnali di health introdotti nei commit |
||
|
|
567046953d |
fix(book): gate fail-safe posizione + diagnostica equity — niente errori silenziosi nel path live
Terza+quarta chiusura del pattern "eccezione ingoiata -> stato safe silenzioso"
in src/live, dopo skh_error (
|
||
|
|
31369b358c |
fix(book): esponi skh_error nel book live — niente flat SKH silenzioso
book_report scriveva skh_error in un dict locale MAI incluso nel return ->
r.get("skh_error") era sempre None. E book_execute non lo leggeva comunque.
Risultato: se il feed SKH (fresh_5m) fallisse, il book forzava SKH a flat in
silenzio, indistinguibile da un flat legittimo -> entry SKH reale mancato,
nessun alert.
Fix:
- src/live/book.py: skh_error come variabile esplicita, esposta nel dict di
ritorno (None normalmente). Il fail-safe (SKH->flat, TP01 indipendente sul
suo feed certificato) resta invariato.
- scripts/live/book_execute.py: emette la riga di log + alert Telegram quando
skh_error e' presente.
- tests: book_report cattura-e-flagga l'errore; book_execute lo fa emergere
(log + notify). Suite 148/148.
Contesto: verifica del gate SKH01 dopo 193 run flat dal 06-23 (gate SANO —
335/341 entry storici, shorta i crash; flat legittimo: ultimo entry 06-06
chiuso ~06-08 pre-arming). Questo chiude il rischio latente scoperto durante
la verifica.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
ee82e0a056 |
feat(dashboard): box forward-monitor STATARB-RESID (lead ortogonale+eseguibile)
Aggiunge il forward-monitor STATARB-RESID al dashboard accanto a PREVDAY (sezione ③·c FORWARD-MONITOR): carica data/paper_statarb/state.json, mostra doppio libro MODELED/REAL-$600, ret/maxDD/fill-haircut, posizione spread corrente e giorni forward. Warn aggiornato: LEAD sotto deflated-Sharpe -> forward per confermare l'edge, non deploy. Smoke-test html() OK (box presente, dati live). Test 146/146. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
db738bce3b |
feat(live): arma il BOOK DERIBIT (TP01+SKH01 nettati in software)
Estende l'esecuzione live da TP01-only al book Deribit-only completo. TP01 e SKH01 tradano lo STESSO strumento (una sola posizione netta per conto su Deribit) -> netting in software: un solo ordine/asset verso il target netto. - src/live/book.py: target NETTO per asset = clamp(0.5*E*(0.75*tp_frac + 0.25*skh_sign), ±cap). Riusa current_target (TP01, causale) + _skyhook_positions (segno L/S, book 230m) + conto reale. - src/live/execution.py: rebalance_signed() — reconcile CON SEGNO (long/short, flip via close+open, reduce reduce_only). La close resta sempre permessa (si esce da qualunque posizione). - src/live/livefeed.py: fresh_5m() — feed 5m certificato + coda recente EFFIMERA da Deribit pubblico (stesso simbolo inverse, in-memory, NON scrive su disco -> dati certificati intatti; fallback al certificato su errore). Solo SKH01 ne ha bisogno (e' a 230m); TP01 e' giornaliero. - scripts/live/book_execute.py: executor doppio-gate (config + --execute), disaster-SL on-book sulla posizione netta, log in data/live/book_executions.jsonl. Feed SKH fresco (live_feed=True). - scripts/cron_book.sh + crontab ORARIO: book idempotente ogni ora (riconcilia al netto corrente); rimossa la riga live_execute.py (TP01-only) dal cron daily per non far collidere i due. - config/live.json: ARMATO (execution_enabled=true). cap/asset $300 split 75/25, disaster-SL -30%. Tutto flat all'arming -> nessun ordine finche' un segnale non arma. - tests/test_book_live.py: 20 test (sizing 75/25, cap, flip/close/reduce, parita' pesi backtest, gate-safety, reconcile con trader fittizio, merge/dedup feed + fallback, loader onorato). 76/76 pass. CAVEAT: exit SKH SOFTWARE (latenza fino a fine barra 230m; solo disaster-SL on-book); TP01 scende a peso 0.75 (max $225/asset); SKH01 resta research-grade (equity daily-step, margine DD ETH sottile). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
25a22fc7c1 |
feat(dashboard): riordino LIVE→trades→storico + trade/anno contati
- dashboard riorganizzata in 3 sezioni: ① LIVE (mainnet sola lettura) in alto, ② TRADES ESEGUITI (reali) + frequenza operativa al centro, ③ STORICO (backtest/forward simulato) in fondo (COMBO/BOOK/FORWARD come ③·a/b/c). - book_trade_frequency() in sleeves.py: trade/anno CONTATI sui dati certificati (cache di modulo, una volta per processo). SKH01 round-trip BTC ~37 / ETH ~43 -> ~75/anno combinato; TP01 turnover ~7x/anno. Card "trade/anno" + blocco freq. - fix: collisione var `pos` nel ramo shadow-online (-> shpos) che avrebbe rotto la tabella posizioni se il conto fosse leggibile dal container. - fix: turnover TP01 nan (disallineamento groupby) -> groupby posizionale, 7.2x/anno. - 56 test pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
eeac97dde4 |
feat(dashboard): Deribit-only book panel (TP01+SKH01) + accumulation forecast
New section showing the executable Deribit-only book (TP01 75% + SKH01 25%): combined FULL/HOLD Sharpe+DD, plus the reinvest-winnings accumulation projection (historical & conservative CAGR, €5k→5y/10y, conservative €/day run-rate). Reuses the already-computed sleeve daily series (no extra heavy compute). Honest caveats (bull sample, no leverage, SKH01 not live, ~€177k for €50/day). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
384b9cb0af |
feat(skyhook): pos_fn introspection for SKH01 sleeve (current open trade / flat)
_skyhook_positions(): replays the non-overlap entry+exit logic (TP/SL/max_bars) to the last closed 230m bar and reports, per asset, the current OPEN trade (dir/entry/sl/tp/bars_in) or 'flat'. Wired into skyhook_sleeve(pos_fn=...) so the Deribit book report & web dashboard show Skyhook's live position. Causal (closed bars only). +1 test. Currently flat/flat. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
160ad300be |
feat(portfolio): Deribit-only executable book (TP01+SKH01) + periodic rebalancing
- deribit_book_sleeves(): TP01 75% + SKH01 25% — the two directional BTC/ETH legs on ONE venue (Deribit), both since 2019. Excludes XS01 (Hyperliquid/stat-mode) & VRP01 (modeled options). FULL Sharpe 1.78 / HOLD 1.17 / DD 9.4% (research). - rebalance_sim(): realistic PERIODIC rebalancing (drift between dates, turnover cost at Deribit-taker ~5bps/side) vs the idealized continuous rebalance of combined_daily. period=1 + cost=0 reduces to continuous (tested). - run_deribit_book.py: report — continuous vs weekly/biweekly/monthly rebal, per-year, accumulation €2k & $600-real, min-order $5 note. Finding: turnover is LOW (0.2-0.4x/yr), so monthly rebal (€7,919) ~= continuous (€7,938) — cost is negligible; daily would be sub-min-order fiction at $600 -> use >= weekly. - +2 tests (rebalance_sim continuity & cost). Full suite green. TP01 is the only live-armed leg; SKH01 is the candidate 2nd leg (validate execution code first). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
7eb0f67956 |
feat(dashboard): show SKH01 sleeve in 4-sleeve portfolio view
active_sleeves() already feeds the per-sleeve table & combined metrics, so SKH01 appears automatically. Manual touch-ups: title/docstring -> +SKH01; position label is now sleeve-aware (the None fallback used to mislabel every pos-fn-less sleeve as XS01's "book 19 gambe" — now XS01/SKH01/VRP01 get correct labels); footer note adds SKH01 (quasi-orthogonal @25%, FULL Sharpe 1.68->2.13, DD 14->8%, research/forward-monitor). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
8d1fe173f7 |
feat(portfolio): wire SKH01-V2-DD sleeve @25% effective -> 4-sleeve book
Add Skyhook (SKH01_V2_DD) as a portfolio sleeve. Effective weight 25%: the three existing sleeves scaled into the remaining 0.75 keeping their 55:25:20 ratio (TP01 41.25% / XS01 18.75% / VRP01 15% / SKH01 25%). _skyhook_returns(): 50/50 BTC+ETH daily series of the dual-TF regime+breakout engine (causal, net 0.10% RT), same convention as the marginal lens. Portfolio impact (run_portfolio.py), 3-sleeve -> 4-sleeve: FULL Sharpe 1.68 -> 2.13 (+0.45), FULL maxDD 14.3% -> 7.8% (halved) HOLD-OUT Sharpe 1.63 -> 2.30 (+0.67), HOLD-OUT maxDD ~3.5% (flat) Positive every year 2019-26 (annual DD <=7.8%) vs buy&hold 50/50 FULL Sh 0.93 / DD 76%. Skyhook is quasi-orthogonal (corr ~0.09 to TP01) so it lifts Sharpe AND cuts DD. Research portfolio (fixed weights, no real rebalancing cost at $600; Skyhook daily Sharpe is the step-marked lens convention) -> forward-monitor, not deploy. Tests: 25 pass (skyhook 8 + portfolio 7 + vrp 4 + trend 6). Diary + CLAUDE.md updated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
de72e3ce1f |
feat(skyhook): SKH01-V2-DD — asymmetric %-exits cut standalone DD <30% (2-wave agent research)
Second agent wave (skyhook-improve-v2, 14 DD-reduction families, each adversarially verified by 2 skeptics) beats the prior winner on the only unmet goal (DD<30%). Winner = ASYM_LS -> promoted to engine as SKH01_V2_DD: same signal (ptn_n=45, vola[35,95], vol_lo=0, exit-bars 24/16) but exits switched from ATR to FIXED-PCT ASYMMETRIC — long sl4%/tp10%, short sl2%(tighter)/tp8%. The tight short %-SL caps the per-trade loss that forms the maxDD in vol spikes. Verified (sk.study, independent re-run): standalone maxDD BTC 21.4% / ETH 27.4% (<30%), minFull +0.99, minHold +1.26, causality 0/400 both assets, fee-surviving to 0.40%RT, marginal vs TP01 ADDS (corr 0.09, in-sample edge, robust_oos, multicut, clean-year +0.57), blend 0.75*TP01+0.25*SKH uplift_hold +0.87; blend 50/50 full 1.84/hold 1.59/DD 10.7%. Plateau (not knife-edge); both skeptics holds_up=high, killer=null. Engine: per-direction short exit overrides (exit_mode_short/sl_*_short/tp_*_short), backward-compatible (None -> symmetric, V1/intermediate-winner unchanged). +3 tests (8/8 pass). Lessons: DD is cut by changing the exit MECHANISM (%-SL, L/S asymmetry, ensembles), NOT by entry-only kill-switch / vol-target / cadence. PATTERN_CONF killed as overfit (knife-edge). PCTL_DD unverified (rate-limit) and ENS_PARAM/TPSL_DD recency/hedge-loaded -> forward-monitor. NOT yet wired to live sleeves: re-verify blend@0.25 + causality on execution code before deploy. Includes both waves' research scripts (runs/SKH_* wave 1, runs/SKH2_* wave 2). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
64d98a070d |
feat(skyhook): SKH01 dual-TF regime+breakout engine + honest eval harness
Porting onesto del sistema ES Skyhook su BTC/ETH certificati: - src/strategies/skyhook.py: 690m(segnale)+230m(exec) da 5m; BuzVola/BuzVolume Chande 0-100 (ancore demo verificate); Donchian breakout HTF; regime gate; composer; entries asimmetrici (uscitalong/short + stop/profit ATR) per backtest_signals. - scripts/research/skyhook/skyhooklib.py: study (FULL/HOLD/fee-sweep/per-anno BTCÐ), causality guard (0 mismatch), marginal-vs-TP01. Baseline: BTC FULL Sh +0.91/+581%, ETH +0.64/+255%, fee-surviving, ma HOLD-OUT debole -> da migliorare. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |