From 444b8044155c39bb4359410f4468da4d50d15b7f Mon Sep 17 00:00:00 2001 From: Adriano Dal Pastro Date: Thu, 30 Jul 2026 20:25:08 +0000 Subject: [PATCH] ops(backup): PythagorasGoal nel backup rotativo, solo il dato non ricostruibile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit data/raw/ e' gitignored e /opt/docker/scripts/backup.sh non copriva questo progetto: dopo lo spegnimento di cerbero-bite la catena opzioni esisteva in due copie SULLO STESSO DISCO. Aggiunta do_pythagoras con criterio dichiarato — si salva cio' che non si puo' riscaricare: dentro (28 MB): catena + contesto, data/paper_* e data/chain_collect (serie forward-only che alimentano i gate pre-registrati: non sono ricalcolabili, sono un registro di cosa si sapeva e quando), options_daily, live, venue_watch, fee_watch, config/live.json fuori (~110 MB): quanto si riscarica dai venue (rebuild_history, fetch_dvol, fetch_hyperliquid, fetch_ib_equities) + cache Due guardie provate nei DUE versi: fallisce se la catena e' assente o vuota invece di produrre un archivio che sembra a posto, e verifica che il tar contenga davvero la catena (caso negativo: 0 file prodotti). La radice e' sovrascrivibile via PYG_ROOT solo per poter far scattare la guardia. Verificato che dopo un riavvio la raccolta riprenda da sola: cron enabled + active, nessuna dipendenza da docker o cerbero-mcp; giro provato con env -i (574 chiamate, 0 errori). Finestra scoperta fino al :25 successivo, senza catch-up. /opt/docker/scripts NON e' un repo git: la modifica vive solo su disco, il diario e' l'unico posto in cui e' scritta. Book, pesi, config, strategia INVARIATI. Co-Authored-By: Claude Opus 5 (1M context) --- CLAUDE.md | 14 +++++++++ data/chain_collect/runs.jsonl | 1 + .../2026-07-30-assorbimento-cerbero-bite.md | 31 +++++++++++++++++++ 3 files changed, 46 insertions(+) diff --git a/CLAUDE.md b/CLAUDE.md index 974eed9..1ffda6c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1684,6 +1684,20 @@ df = load_data("BTC", "1h") # OK. load_data("SOL", ...) -> FileNotFoundError ( - **battuta di cuore:** ogni giro scrive `data/chain_collect/runs.jsonl`, sorvegliato da `monitor_health` (cadenza 1h, `max_age_h=3`) — **un collettore fermo non produce niente, e il niente si legge come "nessun dato quel giorno"**. + - **BACKUP (aggiunto 2026-07-30):** `data/raw/` è gitignored → la catena **non è in git**, e il + backup rotativo della VPS non copriva PythagorasGoal. Aggiunta `do_pythagoras` a + `/opt/docker/scripts/backup.sh` (daily 04:00, retention 7/28/185 g): salva **solo il dato non + ricostruibile** — catena + contesto, `data/paper_*` e `data/chain_collect` (serie forward-only + che alimentano i gate pre-registrati: **non sono ricalcolabili**), `data/options_daily`, + `data/live`, `venue_watch`, `fee_watch`, `config/live.json`. ~28 MB. **Esclusi di proposito** + i ~110 MB ricostruibili (`rebuild_history.py`, `fetch_dvol.py`, `fetch_hyperliquid.py`, + `fetch_ib_equities.py`, cache). La funzione **fallisce rumorosamente** se la catena è assente o + vuota, e verifica il tar prodotto (controllo positivo provato in entrambi i versi). + ⚠️ `/opt/docker/scripts` **non è un repo git**: quella modifica vive solo su disco. + - **Dopo un riavvio della VPS la raccolta riprende da sola** (cron di sistema `enabled`+`active`, + nessuna dipendenza da docker o da cerbero-mcp: API pubblica Deribit diretta). Verificato con + `env -i` che il giro funzioni nell'ambiente nudo di cron. Finestra scoperta: fino al `:25` + successivo, **senza recupero** — un'ora persa resta persa (il collettore non fa catch-up). **TRE DIFETTI DI BITE NON REPLICATI** (misurati il 30/07): (a) **una chiamata per strumento** — `get_order_book?depth=3` dà già quote+greche+IV+OI+book+underlying, bite ne faceva due con rischio di disallineamento; (b) **pacing** (token bucket 4/s + backoff) invece della raffica — diff --git a/data/chain_collect/runs.jsonl b/data/chain_collect/runs.jsonl index d513534..e0ccb3b 100644 --- a/data/chain_collect/runs.jsonl +++ b/data/chain_collect/runs.jsonl @@ -1 +1,2 @@ {"ts": 1785442011000, "righe": 570, "ok": 570, "no_quote": 0, "error": 0, "chiamate": 574, "rate_limited": 0} +{"ts": 1785442920000, "righe": 570, "ok": 570, "no_quote": 0, "error": 0, "chiamate": 574, "rate_limited": 0} diff --git a/docs/diary/2026-07-30-assorbimento-cerbero-bite.md b/docs/diary/2026-07-30-assorbimento-cerbero-bite.md index 8661ab5..7eeeb21 100644 --- a/docs/diary/2026-07-30-assorbimento-cerbero-bite.md +++ b/docs/diary/2026-07-30-assorbimento-cerbero-bite.md @@ -89,3 +89,34 @@ al minuto `:00`. - `scripts/research/cblib.py` — `load_chain()` ora unisce archivio + raccolta - `src/live/monitor_health.py` — nuovo spec `collect_chain` - `tests/test_collect_chain.py` (11 casi) + +## Addendum (stessa sera) — spegnimento, backup, ripresa dopo un riavvio + +**Spegnimento.** Prima di fermare i container ho preso uno snapshot **finale** (bite aveva raccolto +fino alle 20:15, oltre il backup delle 19:55) e ho reimportato: archivio a **1.232.212 righe**. +Consegna verificata: ultima riga di bite 20:15:00, prima nostra 20:00:18 → **sovrapposizione, nessun +buco**. `docker compose stop` (non `down -v`: i volumi restano). Effetto misurato: **0 risposte 429** +su cerbero-mcp nei minuti successivi, contro ~650 per ogni giro orario. + +**Backup.** `data/raw/` è gitignored e il backup rotativo della VPS non copriva PythagorasGoal: dopo +lo spegnimento di bite l'archivio esisteva in due copie **sullo stesso disco**. Aggiunta +`do_pythagoras` a `/opt/docker/scripts/backup.sh` con un criterio dichiarato: **si salva ciò che non +si può riscaricare**. Dentro: catena + contesto, `data/paper_*` e `data/chain_collect` (serie +forward-only che alimentano i gate pre-registrati — non ricalcolabili per costruzione), +`options_daily`, `live`, `venue_watch`, `fee_watch`, `config/live.json` → **28 MB**. Fuori: i ~110 MB +che si riscaricano dai venue. + +Due guardie, entrambe provate **nei due versi**: la funzione fallisce se la catena è assente o +vuota (invece di produrre un archivio che sembra a posto), e verifica che il tar prodotto contenga +davvero la catena. Il caso negativo produce **0 file**. Per poterlo provare la radice è +sovrascrivibile via `PYG_ROOT` — *una guardia che non si riesce a far scattare non è distinguibile +da una rotta.* + +⚠️ `/opt/docker/scripts` **non è un repo git**: quella modifica vive solo su disco, e questo diario +è l'unico posto in cui è scritta. + +**Riavvio.** La raccolta riprende da sola: `cron` è `enabled` e `active`, e il collettore non +dipende da docker né da cerbero-mcp (API pubblica Deribit diretta) — il contrario di bite, che era un +container. Verificato girando `cron_chain.sh` con `env -i PATH=/usr/bin:/bin`: 574 chiamate, 0 +errori, dato e battuta di cuore scritti. ⚠️ **Finestra scoperta: fino al `:25` successivo, senza +recupero.** Il collettore non fa catch-up e non potrebbe: le quote passate non sono richiedibili.