Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016kqvff47UBGeYfj1QeN4zE
15 KiB
I cinque punti della revisione del 09/09 — decisi e fatti
Data: 2026-09-10 (sessione 12:08Z → 13:10Z; i timestamp qui dentro sono letti, non ricordati)
Origine: la prima revisione settimanale (docs/revisioni/2026-09-09.md, revisore fable) e il
giornale del 09/09. Ogni punto e' stato spiegato all'operatore con pro e contro e deciso da lui
(§3-style: decisioni con l'informazione completa). Issue sul Gitea di casa #2-#6, chiuse con la
soluzione scritta (regola globale del 10/09).
Le decisioni, in una tabella
| # | punto | decisione dell'operatore | issue |
|---|---|---|---|
| 1 | usde_watch contava 400 USDE come reward (07/09) |
ripara ora + issue | #2 bug |
| 2 | cuscino USDC senza sorvegliante (§5.17) | equity USDC, riconverte da solo | #3 sviluppo |
| 3 | versamento 04/09 solo rilevato; piano €5.000 «in attesa» | e' l'INTERO versamento previsto: dichiarato, piano chiuso | #6 sviluppo |
| 4 | SCALA-01 A2: da quando contano i 180 giorni | dal 01/09 (sorvegliante attivo) → gate non prima del 2027-02-28 | #5 bug |
| 5 | PREVDAY-01 «senza data» | tieni 21/06/2027, cabla kill e veto, correggi §4 | #4 bug |
Sul punto 5 la domanda giusta e' stata «ricorda dove dobbiamo arrivare (50 €/g)»: PREVDAY de-luckato al 15% vale +0,10 di Sharpe sul libro e la somma di tutti i lead dell'ondata di agosto vale +0,036 €/giorno. Verso i 50 €/g il candidato vale centesimi in qualunque esito del gate: non si spende una sessione di ricerca per anticipare (a)+(b), e non si butta l'unica gamba short scorrelata oltre a SKH01 per risparmiare un cron. Costo scelto: mezza giornata, una volta.
Punto 1 — il lettore dei trade spot aveva DUE limiti, non uno
Il primo era noto dalla revisione: trade_history(limit=50) con 54 ordini. Il secondo l'ho
trovato sondando il gateway per ripararlo: get_user_trades_by_instrument chiamato senza
historical restituisce solo le ultime ~24 ore — il fill BTC dell'08/09 06:47Z e' invisibile
alle 12:55Z del 10/09, quello del 09/09 21:47Z si vede. Il cron gira ogni 24h alle 12:35: sta
dentro la finestra per pochi secondi. Un giro saltato avrebbe reso invisibili i trade fra 48h e
24h fa, e il delta sarebbe stato attribuito al reward esattamente come il 07/09, con un
meccanismo diverso.
Ora trade_copertura() dichiara non leggibile (somma None, e analizza non attribuisce:
P12) in entrambi i casi — lista lunga quanto il limite (troncata) o ultima lettura oltre 24h+5min —
e il record porta trades_motivo (P4: il perche'). TRADE_LIMIT = 1000 e' il count massimo di
Deribit. Controllo positivo nei test: 54 ordini si sommano tutti.
La riga del 07/09 in data/live/usde_watch.jsonl e' corretta in loco con campo correzione
(originale conservato dentro, copia del file in usde_watch.jsonl.pre_fix_20260910): 54 ordini
= 8 + 30 + 16 dal registro usde_convert.jsonl, 2.434 USDE, reward 0,080934. Il tasso non
cambia — la riga era gia' esclusa per con_trade — e rendimento() oggi da' 3,94% su 14
finestre, 12 pagate.
Punto 2 — cuscino_watch: la grandezza che nessuno guardava
Il cuscino richiesto e' 2 × 0,5 × 0,30 × equity_tot = 30% dell'equity, derivato da
config e book.WEIGHT. La formula e' passata da usde_convert.py a src/live/usde.py, e
usde_convert la importa da li': due lettori, una formula (P1 — cinque occorrenze nel
progetto di sorveglianti puntati su un bersaglio ridichiarato).
| stato | criterio | azione |
|---|---|---|
| OK | slack ≥ 10% del cuscino | niente |
| PREAVVISO | 0 ≤ slack < 10% | ⚠️ alla transizione |
| SCOPERTO | slack < 0 | 🚨 + usde_convert --quota 0,64 --esegui (cuscino + 20% di margine, alzato dal 10% in revisione) |
| BLIND | conto non leggibile | ⚠️ alla transizione |
Guardie della riconversione: execution_enabled del libro (un solo interruttore), niente vendita
sotto depeg_warn (li' decide l'operatore, e l'allarme lo dice), un tentativo ogni 6h, le guardie
proprie di usde_convert (banda di prezzo, book leggibile, tetto HARD) ereditate lanciando lo
script vero (P15). Il marcatore «gia' detto» e' l'esito di notify: un invio fallito non consuma
la transizione (lezione del debito §5.2). Cron :53 = dopo il giro del book (:47), fuori dal
minuto tondo. monitor_health lo sorveglia (max 3h).
📌 Primo giro a secco (13:00Z): gia' PREAVVISO. USDC equity $1.361,23 contro $1.335,26 richiesti: slack +$25,97. Il 09/09 il revisore aveva stimato +$41/+$59; la marcatura del libro dal picco del 06/09 ne aveva consumati altri 15-30 senza che nessuno lo vedesse. E' il caso d'uso del sorvegliante, arrivato prima del sorvegliante.
Punto 3 — il versamento del 04/09, dal balance e non dall'equity
Il salto di equity 13:47→14:47Z diceva +$2.410,14 col mercato dell'ora dentro. Il balance
USDC di balance_watch (cambia solo per P&L realizzato, fee, funding e movimenti) dice
1.417,73455581 → 3.832,41432481 = +$2.414,68, nessun fill nella finestra, funding su $541
di nozionale ~$0,01. Dichiarato con banda $0,05. Il report ora lo mostra come dichiarato e
il TWR passa a +6,66% (era +7,22% stamattina, +7,83% il 06/09): la coda −0,63% dal 04/09 e'
marcatura delle due long, trading da arming +$13,82.
L'operatore ha detto che era l'intero versamento previsto: la voce «in attesa di importo e data» di §1 e' chiusa. Resta la lezione di §2: per sei giorni il movimento e' stato solo rilevato, la regola diceva il giorno stesso.
Punto 4 — SCALA-01: la data era il punto 5 della SPEC scambiato per il gate
«Non prima del 2026-10-01» erano i 30 giorni di sorvegliante del punto 5 (§7 della SPEC); A2
chiede ≥180 giorni col criterio passato ogni giorno, e il criterio lo misura solo
scale_watch, attivo dal 01/09. Le tre letture possibili, con pro e contro, sono nel diario di
sessione; l'operatore ha scelto dal 01/09 → 2027-02-28. Contare dall'arming avrebbe dato
un criterio ricostruito a posteriori, che non prova nulla sul sorvegliante; ridurre A2 a 30 giorni
avrebbe allentato un gate senza un costo d'attesa che lo giustifichi (il gradino 1,25x vale meno
di €100/mese di versamento).
Riconciliata anche la data d'arming: 20/06 = TP01 da solo (commit 4650aa7), 23/06 = il
BOOK (commit db738bc, prima lettura di equity 23/06 22:00Z). CLAUDE.md §0 diceva solo la
prima, config/live.json e il TWR usano la seconda: erano due eventi, non un errore.
Punto 5 — PREVDAY-01 aveva la data; non l'aveva la tabella
RESULTS-0822 §54: decisione 2027-06-21, kill, veto. La tabella §4 diceva «scritto 23/08 ·
10 condizioni», e il revisore ha letto quella. Ora la riga ha data, kill, veto e stato (5/7:
(a) e (b) sono strutturali, nessun forward le cambia).
Cablato in paper_prevday.py (prima esisteva solo nel testo, a differenza di paper_dvolspread):
| misura | valore al 10/09 |
|---|---|
| Sharpe forward giornaliero (lente del kill; l'oraria +1,19 non si cita, §54) | +0,95 su 81 giorni, 81 attivi |
| kill (< −0,50 su ≥180 g attivi) | NON MATURO, leggibile dal ~18/12/2026 |
| barre ricostruibili dal feed di oggi | 1.942/1.943 (99,9%); l'unica divergente e' il 26/08 00:00, il giorno del fix di advance() |
| veto | ok |
⚠️ Errore mio, catturato prima di committare: la prima stesura del veto leggeva «divergenze
non crescenti» come tasso_recente > tasso_totale, e con UNA barra divergente negli ultimi 30
giorni (0,03/g contro 0,01/g) dichiarava VETO. Una guardia piu' stretta del contratto produce
allarmi che si impara a ignorare (P14): ora la crescita richiede ≥5 barre recenti E tasso
doppio, dichiarato nel codice e provato nel test con i numeri della serie vera.
La ricostruzione al 99,9% contro il 95,6% di §54: la misura del 23/08 era stata fatta prima
del fix di advance() del 26/08 (le 67 barre divergenti erano «all'ora del cron», cioe' barre
parziali); oggi il feed rivisto e la serie coincidono tranne quella barra.
Cose trovate per strada
- Due timestamp «di comodo» scritti a mano (13:05Z e 13:07Z) invece dell'ora letta (12:57:43Z e
13:04:09Z): corretti subito. E' esattamente la regola globale «la data si LEGGE» — vale anche per
chi la scrive nel campo
correzione. issue --jsonva prima del sottocomando; il percorso nella regola globale era/opt/docker/AI-OSinvece di/opt/AI-OS(corretto la mattina, nel test dello strumento).
Verifica
uv run pytest: 1060 passati (erano 1031). Nuovi: test_cuscino_watch.py (14),
test_paper_prevday_gate.py (8), +5 in test_usde_watch.py. Revisione del diff affidata a
fable (agente fresco): esito e correzioni applicate in coda a questo diario.
Revisione fable (13:10-13:18Z): 15 segnalazioni, 4 medie — tutte verificate, 12 applicate
| # | segnalazione | verifica | esito |
|---|---|---|---|
| 1 | puo_riconvertire contava anche i NON tentativi (tentata=False): un giro --secco o un prezzo illeggibile bloccava la riconversione vera per 6h |
riprodotta | filtro su tentata + test |
| 2 | il tetto del venue in usde_convert.piano bloccava anche la vendita: con venue_cap_frac rimesso in config la riconversione automatica sarebbe stata morta |
riprodotta (side=sell, ok=False) |
vale solo in acquisto |
| 3 | MARGINE_RIPRISTINO 10% == PREAVVISO_FRAC 10%: dopo ogni 🚨 un ⚠️ per costruzione (P14) |
riprodotta col floor di 1 USDE | margine 20% → quota 0,64, test |
| 4 | --secco scriveva nel registro vivo (veicolo del punto 1, e maschera un cron fermo) |
riprodotta (riga 13:00:15Z) | non scrive; riga tolta |
| 5 | due bersagli di quota: quota_target 0,70 in config contro 0,64 del ripristino; il ripristino e' un ratchet verso il basso |
letto | dichiarato in CLAUDE.md §5.17 e nel docstring: decisione dell'operatore (N9) |
| 7 | buco di ≤5 min dentro la tolleranza della finestra 24h | letto | dichiarato (D5) + fonte Deribit documentata |
| 8 | giorni_attivi legge posizioni REAL, il kill e' MODELED |
letto | dichiarato nel docstring (81/81 oggi) |
| 10 | il test del cron leggeva un commento nello .sh, non la crontab |
letto | legge crontab -l come test_book_cadenza |
| 11 | prevday_target patchato senza monkeypatch |
letto | monkeypatch |
| 13 | «QUATTRO movimenti» in §2: sono TRE, in quattro tratti | letto | corretto |
| 14 | «5/7» contro «8/10» di §54: base diversa non dichiarata | letto | dichiarata |
| 6, 9, 12, 15 | verifiche che reggono (sys.executable, cwd, piano() in SCOPERTO, ricostruzione ≡ advance) |
— | — |
Non applicato: il lock fra cron e conversione a mano (DUBBIO 2) — dichiarato come limite nel docstring. Il DUBBIO 1 (ratchet) e' la domanda aperta per l'operatore.
Coda (13:55Z →): il riacquisto automatico — issue #7
Alla domanda aperta (ratchet verso il basso) l'operatore ha risposto «crea una strategia per
riportarla a quota in autonomia». La risposta ingenua — ricomprare fino a quota_target 0,70 —
e' sbagliata per costruzione: a 0,70 lo slack e' zero, la prima ora in perdita vende, il
riacquisto ricompra, e cosi' via a 6 bps al giro. Serve isteresi con un bersaglio unico:
| slack / cuscino | stato | azione |
|---|---|---|
| < 0 | SCOPERTO | 🚨 vende USDE → 0,20 |
| 0 – 0,10 | PREAVVISO | ⚠️ |
| 0,10 – 0,40 | OK | — |
| > 0,40 | ECCEDENTE | 📌 compra USDE → 0,20 |
Bersaglio 0,20 ⇒ quota 0,64. Per oscillare lo slack deve muoversi di ±0,20×cuscino = ±6%
dell'equity, cioe' ±8,6% di equity USDC (~$380) perche' slack = 0,7·USDC − 0,3·USDE (la prima
stesura diceva ±6%/$270: corretta in revisione): a leva 0,26x sono ~33% di mercato. Un bonifico alza lo slack di
0,7×importo: sopra 9% dell'equity ($380) il riacquisto scatta da solo — la regola di §1
«dopo un bonifico si rilancia usde_convert» non dipende piu' da qualcuno che se ne ricordi.
Le tre frazioni vivono in config/live.json (usde.bande_cuscino verifica 0 < preavviso <
margine < riacquisto), quota_target 0,70 e' stato tolto. Soglie dichiarate, non ottimizzate
(M8): il costo di un giro e' ~$0,2, la frequenza attesa qualche giro al mese nei tratti mossi.
📌 Trovato al primo giro vero del cron (13:53Z): l'allerta PREAVVISO non e' partita. Il token
era valido (getMe ok); il testo conteneva «(< 10% del cuscino)» e Telegram in parse_mode=HTML
rifiuta un < nudo. Testi riscritti senza <, allerta_errore registrato nel record (P3),
test che legge il sorgente delle notify. Un sorvegliante nuovo che non riesce a parlare al
primo giro e' il caso di P2: si valida sul segnale E sul trasporto.
Stato al giro a secco delle 14:0xZ: quota 69,3%, slack +$30 = PREAVVISO. Il piano a 0,64 e' valido (SELL 237 USDE, slack dopo +$267): il sorvegliante lo esegue alla prima ora sotto zero; allinearlo subito e' una riga a mano.
Seconda revisione fable (14:04Z): 10 segnalazioni, 1 ALTA, 3 MEDIE — applicate 9
| # | segnalazione | esito |
|---|---|---|
| 1 ALTA | il < arrivava ancora a Telegram dal campo motivo («(< 6h)») dentro l'allerta 🚨: il 🚨 piu' importante perso fino a 4h |
escape nel sink notifier.notify (html.escape su titolo e valori; nessuno dei 45 chiamanti passa tag: grep) + motivi senza < |
| 2 MEDIA | il test sul sorgente era parziale (codice morto, cieco ai valori interpolati) | sostituito: cattura la POST e verifica < |
| 3 MEDIA | ECCEDENTE con guasto persistente = «acquisto FALLITA» ogni 6h per sempre | da ECCEDENTE dopo un fallimento si riprova ogni 24h; da SCOPERTO resta 6h |
| 4 MEDIA | bande fuori ordine ⇒ traceback ingoiato dal cron, nessun record, «fermo» invece di «rotto» | giudica ⇒ BLIND con motivo; record e allerta scritti |
| 5-7 | CLAUDE.md §1 diceva ancora «nessuno sorveglia»; §5.17 «tre stati»; _nota_usde con quota_target |
corretti |
| 8 | «±6% di equity USDC» sbagliato di 0,7: slack = 0,7·USDC − 0,3·USDE ⇒ ±8,6% (~$380) | corretto in 4 posti |
| 9 | TOLL ridichiarato nel test |
importato da usde_convert |
| 10 | esempi --quota 0.70 nel docstring di usde_convert |
0,64 |
Verifiche numeriche del revisore (loop su piano() con passo 1 USDE, TOLL, min order): bonifico
+$2.000 → 11 acquisti → OK, slack +$387; perdita −$50 → 3 vendite → OK, +$264; conto tutto USDC →
20 acquisti → OK. Nessuna sequenza vendita→acquisto→vendita. Non applicato: min(q*, cap) con
il tetto del venue (dubbio 3: un conto al tetto resta ECCEDENTE e ora allerta una volta al giorno).
Dubbio 4, che vale una riga in §5.17: 0,64 e' una derivazione dell'autore, non la quota decisa
dall'operatore il 30/08 (0,70); ~$10/anno di resa di differenza; da confermare.
Allineamento eseguito (14:16:38Z, ordine dell'operatore «allinea subito a 0.64, esegui»)
usde_convert --quota 0.64 --esegui: SELL 100 + 100 + 38 USDE a 1,0000 medio (limite 0,9995,
fill al book), quota 69,4% → 64,02%, conto USDC $1.602,79 + USDE 2.851,95 = $4.454,74.
Slack dopo +$266 su $1.336 di cuscino: cuscino_watch --secco dice OK (era PREAVVISO a
+$29). Costo: ~$0,1 di spread, fee zero. Registro in data/live/usde_convert.jsonl.