Files
PythagorasGoal/docs/diary/2026-09-02b-debito-7-cadenza-docstring.md
Adriano Dal Pastro 1279ea605a revisione 02/09, seconda tornata: il classificatore dei movimenti era cieco ~23 ore al giorno
Il feed 1h certificato si ferma alle 00:00: per le letture successive `asof` dava la stessa
barra a t0 e t1, mercato "fermo" = 0, e qualunque calo >=10% del giorno sarebbe stato un
"movimento" scorporato come prelievo (giornale dal 25/08, report da oggi). Con feed assente
tutto era "ambiguo" e il report stampava e1/e0-1 sotto l'etichetta TWR.

- journal.movimenti_capitale: stato "mercato non misurabile" (feed fermo/assente/barra
  mancante) => ambiguo con la ragione; leva_tetto = min(frac x n x scala, LEVA_LORDA_MAX) (P1).
- journal.rendimento_twr: salto non classificabile => twr E trading None con motivo.
- journal.pnl_giorno CHIAMA rendimento_twr (prima rifaceva cum - certi: "entrambi la chiamano"
  era falso); la pagina stampa il TWR; analista qualifica il cumulato "di cui versati".
- trades_db --report: la classe di ogni salto con la sua misura (mercato max a leva piena).
- book_execute docstring: banda dello stop -33,5%/-26,5% (era invertita), "non costa ordini"
  -> micro-ordini di ri-taglia (22/48, C2), latenza <=1h solo con feed fresca, conteggi di
  r0823 al posto di "raddoppia" (2 contro 1 e' rotolante vs pavimento sulla riga 4h; la
  peggiore misurata e' 24h).
- test_book_cadenza: LTF_MIN importato da skyhook; tutte le righe attive della crontab (una
  sola); tre stati dello skip (col progetto ma senza cron_book => ROSSO); slot di release
  testato con venue_probe (il :07 come controllo positivo); parser regolare, passo > 0.
- r0823_sl_anchor: guardia sul :47 (era sul vecchio :07), prosa al passato; cron_chain.sh idem.
- CLAUDE.md: §5.7 frase invertita corretta, §5.14 limite vero (non l'artefatto della fixture),
  §2 ora della LETTURA (13:47Z), nuovo debito §5.15 (USDE fuori dal bound di mercato).
- diari: tempi "scritto" corretti coi commit; sezione "Seconda tornata".

Test +11 (858 verdi).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XDJsH3iDSaBns3ccpPBwiu
2026-09-02 15:33:13 +00:00

6.0 KiB
Raw Permalink Blame History

2026-09-02 — Debito 7: il docstring diceva 230 minuti, il cron gira ogni ora

Scritto il 2026-09-02 fra le 14:36Z e le 14:38Z (commit 861cc7f, 14:38:53Z; la prima stesura diceva «alle 14:45Z» senza averlo letto — corretto in revisione). Cadenza misurata dal log (r0823_sl_anchor.py: 1.443 giri in 1.442 ore) e dalla crontab installata, letta dal test.

Il difetto

fonte cosa diceva dal
scripts/live/book_execute.py, docstring «va lanciato ogni ~230 minuti» 20/06
scripts/cron_book.sh, intestazione cadenza ORARIA, 47 * * * * 25/08 (prima :07, sempre orario)
crontab della VPS 47 * * * * 25/08

Era il docstring a sbagliare. E non era una svista innocua: sulla riga 4h (la più vicina ai 230 minuti) BTC raddoppia gli scatti del disaster-SL rotolante (2 contro 1; a 24h ETH arriva a 5, con 2 in 30 giorni). Il rischio era un lettore diligente che "allineasse" il cron al docstring.

La riparazione

  1. Docstring riscritto: CADENZA: ORARIA, la riga di crontab citata, la ragione (giro idempotente → girare più fitto della griglia non costa ordini; latenza ≤1h sugli ingressi/uscite software di SKH01; ri-ancoraggio orario del rotolante) e il divieto esplicito, con la data.
  2. tests/test_book_cadenza.py, 10 test. P1: non ridichiara «60 minuti», deriva le tre fonti e le confronta fra loro:
    • il docstring non contiene più «ogni ~230» e dichiara ORARIA;
    • la riga di crontab citata nel docstring è quella dichiarata in cron_book.sh;
    • la riga dichiarata è oraria (parser a 5 campi, solo casi regolari, rifiuta il resto), sotto i 230 della griglia e lontana dai 240 della riga peggiore, e fuori dal minuto :00;
    • la crontab installata (crontab -l) coincide con la dichiarata. Dove la crontab non è leggibile il test è saltato, non verde (P5). Sulla VPS oggi gira e passa.

Numeri

test nuovi 10, tutti verdi; suite dei moduli che toccano book_execute: 231 verdi
cadenza dichiarata / installata 60 min / 60 min
griglia SKH01 230 min (la riga da non usare)
riga peggiore misurata 240 min (BTC 2 scatti contro 1)

Cosa NON ho fatto

  • Non ho toccato il cron né cron_book.sh: la configurazione che gira era quella giusta.
  • Non ho aggiunto un sorvegliante a runtime sulla cadenza (contare i giri per ora nel log): il giornale già stampa «giri mancanti» ogni giorno, e il test copre la deriva di configurazione.

Revisione del codice, prima tornata (15:15Z, commit 835e0c8) — due cose trovate, tutte riparate

trovato vero? riparazione
il docstring nuovo diceva «il disaster-SL rotolante si ri-ancora ogni ora»: falso. ensure_disaster_sl lascia il bracket com'è finché lo stop voluto è entro il 5% da quello piazzato e la taglia entro il 10%; il giro orario controlla, ri-ancora oltre la tolleranza (mark +5,263% / 4,762%). I «BTC 0 / ETH 1» di r0823 sono misurati con questa isteresi sì, verificato in execution.py:233-235. Propagato anche a CLAUDE.md §5.7 e memoria 40 riscritto in tutti e tre i posti: «controllato ogni ora, ri-ancorato solo oltre la tolleranza; lo stop siede fra 26,3% e 33,3% dal mark corrente». Frase sbagliata su un meccanismo di sicurezza vivo: era la segnalazione più importante
la guardia del test cercava due letterali («ogni ~230»): «ogni quattro ore» sarebbe passato la guardia estrae ogni prescrizione «ogni/every N unità» e pretende 60 minuti; controllo positivo (M15) su cinque frasi. Limite dichiarato (P13): una prosa che prescrive senza «ogni» passa

Seconda tornata (15:30Z)

trovato vero? riparazione
la frase nuova di CLAUDE.md §5.7 era invertita («chi lo avesse corretto nel verso del cron»): correggere il docstring verso il cron e' proprio la riparazione; il pericolo e' correggere il CRON verso il docstring si' riscritta nel verso giusto
la banda dello stop era sbagliata: con isteresi 5% sullo stop (0,70·mark) lo stop siede a 0,6650,735 × mark, cioe' 33,5% / 26,5%, non 26,3/33,3 si' corretta in docstring, CLAUDE.md, memoria
«BTC raddoppia gli scatti» leggeva male r0823: il «2 contro 1» e' rotolante contro pavimento dentro la riga 4h; a 1h il rotolante ne fa 0, e la riga peggiore misurata e' 24h (ETH 5) si' (la revisione ha eseguito r0823.simula) riscritto ovunque coi conteggi; nel test RIGA_4H_MIN, non «peggiore»; LTF_MIN importato da skyhook (P1)
«girare piu' fitto non costa ordini» era falso: 22 dei 48 ordini live sono ri-taglie Δ ≤$10 a segnale invariato; il deadband e' in valuta assoluta (C2)
«latenza ≤1h» senza condizione: vale solo con la feed 5m fresca; fresh_5m ripiega in silenzio sul giornaliero e skh_feed_max_age_min allerta e basta si' condizione scritta
_cron_installato leggeva la prima riga: una seconda riga attiva sotto (17 * * * *, dentro lo slot di release) era invisibile si' (simulato) si contano tutte le righe attive, e devono essere una
lo skip collassava tre stati: crontab illeggibile, leggibile senza il progetto, leggibile col progetto ma senza cron_book.sh attivo (= libro non schedulato) si' tre stati: SALTATO, SALTATO, ROSSO
solo il vincolo 1 del :47 era testato (minuto ≠ 00); il vincolo 2 (fuori dallo slot di release del martedi') no si' test con venue_probe.in_release_window, il :07 come controllo positivo
_cron_dichiarato accettava solo N * * * * e falliva come «assente» su */30; cadenza_minuti accettava */45, 0 */5, */0 si' regex a 5 campi qualunque, regolarita' e passo > 0 imposti, parametrizzati
r0823_sl_anchor.py si rifiutava di girare nella finestra del vecchio :07 e stampava a runtime che il docstring «prescrive ~230 min»; cron_chain.sh giustificava il :25 «fuori dal :07» si' guardia sul :47, prosa al passato, commento aggiornato