37d1565a1e
Decisione dell'operatore 10/09 («riportarla a quota in autonomia»). Verificato da revisione fable (10 segnalazioni, 9 applicate; loop numerico su usde_convert.piano: nessuna sequenza vendita→acquisto). - quarto stato ECCEDENTE: slack > cuscino_riacquisto_frac (0,40) x cuscino => acquisto di USDE fino allo stesso bersaglio della vendita, q* = 1 - 0,30 x (1 + cuscino_margine_frac 0,20) = 0,64. Isteresi [0 ; 0,40] x cuscino con bersaglio unico 0,20: per oscillare servono +-8,6% di equity USDC (~$380); un bonifico alza lo slack di 0,7 x importo e sopra ~9% dell'equity ricompra da solo. - le tre frazioni (preavviso/margine/riacquisto) in config/live.json sezione usde, lette da usde.bande_cuscino() che verifica l'ordine; quota_target 0,70 TOLTO (slack zero per costruzione). - notifier.notify: html.escape su titolo e valori — la prima allerta vera (13:53Z) era andata persa per un '<' nudo; allerta_errore registrato nel record (P3). - da ECCEDENTE un fallimento si ritenta ogni 24h (non 4 Telegram/giorno per sempre); bande fuori ordine => BLIND con motivo, non un traceback ingoiato dal cron. - CLAUDE.md §1/§4/§5.17, config _nota_usde/_nota_cuscino, diario. 0,64 e' una DERIVAZIONE dell'autore, non la quota decisa il 30/08 (0,70): dichiarato, da confermare. - test: 1070 (+8 netti). Fixes #7 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016kqvff47UBGeYfj1QeN4zE
210 lines
14 KiB
Markdown
210 lines
14 KiB
Markdown
# 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 `<` |
|
||
| 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.
|