Files
PythagorasGoal/docs/diary/2026-09-10-cinque-punti-revisione.md
T

15 KiB
Raw Blame History

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 --json va prima del sottocomando; il percorso nella regola globale era /opt/docker/AI-OS invece 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 &lt;
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.