From 8a1fb823dc8da478b500a61945cea146c0cb6097 Mon Sep 17 00:00:00 2001 From: Adriano Dal Pastro Date: Tue, 9 Jun 2026 08:31:59 +0000 Subject: [PATCH] docs: profilo B, collettore research, colonna source, backup giornaliero MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allinea la documentazione alle modifiche di v1.7.0. - 01-strategy-rules: §3.2 delta short 0.18 (banda 0.12-0.22, OTM>=10%) con la motivazione dell'analisi (credit/width ~6% irraggiungibile a delta basso); delta_by_dvol aggressiva ritarata; §3.3 width fino a 6% (griglia strike 100pt); §3.4 credit/width min 30% -> 8%. - 05-data-model: option_chain_snapshots alimentata da due collettori (live/research) via colonna source; CREATE TABLE + indice aggiornati; book_depth_top3 popolato sulle righe research; migrazioni 6 e 7 in tabella; backup orario -> giornaliero con nota storica. - 10-config-spec: valori structure profilo B + nuovo blocco research_collector. - 06-operational-flow: cron summary con i due collettori opzioni. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/01-strategy-rules.md | 38 ++++++++++++++++++++---------- docs/05-data-model.md | 47 +++++++++++++++++++++++++++---------- docs/06-operational-flow.md | 2 ++ docs/10-config-spec.md | 36 +++++++++++++++++++++++----- 4 files changed, 93 insertions(+), 30 deletions(-) diff --git a/docs/01-strategy-rules.md b/docs/01-strategy-rules.md index ecbf390..ec193aa 100644 --- a/docs/01-strategy-rules.md +++ b/docs/01-strategy-rules.md @@ -100,13 +100,20 @@ Risultato: Si seleziona lo strike short più vicino a delta target, in valore assoluto. -| Parametro | Valore | +| Parametro | Valore (profilo B, v1.7.0) | |---|---| -| Delta short target | 0.12 | -| Tolleranza delta | [0.10, 0.15] | -| Distanza minima OTM | 15% (anche se delta è dentro tolleranza) | +| Delta short target | 0.18 | +| Tolleranza delta | [0.12, 0.22] | +| Distanza minima OTM | 10% (anche se delta è dentro tolleranza) | | Distanza massima OTM | 25% | +> **Perché delta 0.18 e non 0.12.** A delta 0.10-0.15 il miglior +> `credit/width` fisicamente ottenibile su ETH (analisi 3.689 snapshot, +> 1mag-8giu '26) è ~6%, sotto il minimo richiesto: 0 spread fattibili. +> Per uno spread verticale `credit/width ≲ delta_short`, quindi l'unica +> leva che produce credito vendibile è vendere più vicino. Trade-off: +> la prob. di assegnazione sale da ~12% a ~18-22%. + **Variante dinamica per regime DVOL (Phase 5, opt-in).** Il campo `short_strike.delta_by_dvol` (lista step-function) sostituisce il delta target singolo con bande ordinate per `dvol_under`: a DVOL @@ -117,9 +124,9 @@ classico col delta target sopra. Esempio bande nel profilo | dvol_under | delta_target | delta_min | delta_max | |---|---|---|---| -| 50 | 0.15 | 0.13 | 0.17 | -| 70 | 0.12 | 0.10 | 0.15 | -| 90 | 0.10 | 0.08 | 0.12 | +| 50 | 0.22 | 0.18 | 0.25 | +| 70 | 0.18 | 0.12 | 0.22 | +| 90 | 0.15 | 0.10 | 0.18 | Se nessuno strike disponibile rientra in entrambe le tolleranze → no entry. @@ -131,16 +138,23 @@ Si seleziona lo strike a distanza fissa dallo short: |---|---| | Larghezza spread (in % di spot) | 4% | | Larghezza minima accettabile | 3% | -| Larghezza massima accettabile | 5% | +| Larghezza massima accettabile | 6% | Se non esiste lo strike esatto a 4%, si prende il più vicino entro -[3%, 5%]; altrimenti no entry. +[3%, 6%]; altrimenti no entry. La banda arriva a 6% perché la griglia +strike ETH sotto i $1500 è a 100pt (~6% a spot <$2k): con cap 5% +nessuna gamba long rientrava in banda. ### 3.4 Rapporto credito/larghezza -Il credito netto incassato (mid-price del combo) deve essere ≥ **30%** -della larghezza dello spread. Sotto questa soglia il rapporto -rischio/rendimento è inferiore al minimo accettabile. → no entry. +Il credito netto incassato (mid-price del combo) deve essere ≥ **8%** +della larghezza dello spread (profilo B). → altrimenti no entry. + +> Era **30%**, ma è fisicamente irraggiungibile con delta short ≤0.22 +> in questo mercato: il miglior `credit/width` misurato su ETH è ~6% +> (anche vendendo a delta 0.30 non si superava il 20%). La soglia 8% è +> allineata al realizzabile a delta ~0.18 e mantiene un floor sul +> rapporto rischio/rendimento. ## 4. Liquidità (filtro hard pre-entry) diff --git a/docs/05-data-model.md b/docs/05-data-model.md index bcdb27c..37986b0 100644 --- a/docs/05-data-model.md +++ b/docs/05-data-model.md @@ -229,12 +229,23 @@ NULL = engine attivo. ### `option_chain_snapshots` -Snapshot della catena opzioni Deribit prelevata in continuo -(cron `*/15 * * * *`, allineato a `market_snapshots`). Crypto è -24/7: l'accumulo dataset deve essere continuo, non gateato sulla -settimana. Ogni tick contiene un quote per strumento entro la -finestra `[dte_min, dte_max]` di config; tutti i quote prelevati -nello stesso tick condividono ``timestamp``. Migration `0005`. +Snapshot della catena opzioni Deribit. La tabella è alimentata da +**due collettori distinti**, separati dalla colonna `source`: + +* `source='live'` — collettore operativo (cron `*/15 * * * *`, + allineato a `market_snapshots`). Ogni tick contiene un quote per + strumento entro la finestra `[dte_min, dte_max]` di config (1 + scadenza, ~13-15 strike); `book_depth_top3` NULL. +* `source='research'` — collettore full-chain (§13-bis, cron orario, + opt-in via `research_collector.enabled`). Cattura tutte le scadenze + ≤`expiry_max_days` ed entrambe le ali, con `book_depth_top3` + popolato. Trasforma il dataset da "skew/premi medi" a backtest + opzioni vero (per-trade e standing put). + +Crypto è 24/7: l'accumulo dataset deve essere continuo, non gateato +sulla settimana. Tutti i quote prelevati nello stesso tick +condividono ``timestamp``. Migration `0005` (tabella), `0007` +(colonna `source`). ```sql CREATE TABLE option_chain_snapshots ( @@ -255,15 +266,19 @@ CREATE TABLE option_chain_snapshots ( open_interest INTEGER, volume_24h INTEGER, book_depth_top3 INTEGER, + source TEXT NOT NULL DEFAULT 'live', PRIMARY KEY (timestamp, instrument_name) ) WITHOUT ROWID; ``` Indici: `(asset, timestamp DESC)` per listing recenti, `(asset, -expiry)` per query per scadenza specifica. ``book_depth_top3`` è -NULL by design — il collector non chiama l'order book per ogni -strike per non saturare l'API; lo legge il liquidity gate live solo -sugli strike candidati al picker. +expiry)` per query per scadenza specifica, `(asset, source, +timestamp DESC)` per separare live/research nelle query di backtest. +``book_depth_top3`` è NULL sulle righe `live` (il collector operativo +non chiama l'order book per ogni strike, per non saturare l'API; lo +legge il liquidity gate live solo sugli strike candidati al picker) +ed è **popolato sulle righe `research`** (1 call orderbook/strumento, +concorrenza limitata) per modellare lo slippage reale. **Sblocca**: il backtest non-stilizzato (modulo `core/backtest.py` con prezzi reali invece di Black-Scholes), la calibrazione empirica @@ -363,12 +378,20 @@ idempotente, forward-only: | 3 | `0003_market_snapshots.sql` | tabella `market_snapshots` | | 4 | `0004_auto_pause.sql` | `system_state.auto_pause_until / _reason` | | 5 | `0005_option_chain_snapshots.sql` | tabella `option_chain_snapshots` | +| 6 | `0006_dvol_history_multi_asset.sql` | `dvol_history` multi-asset | +| 7 | `0007_option_chain_source.sql` | colonna `source` (live/research) + indice | ## Backup -Backup orari di `state.sqlite` in +Backup **giornalieri** di `state.sqlite` in `data/backups/state-YYYYMMDD-HH.sqlite`, ritenuti per 30 giorni. Operazione idempotente con SQLite `VACUUM INTO`. Lo job è registrato -nello scheduler dell'orchestrator (`backup_cron = "0 * * * *"`); è +nello scheduler dell'orchestrator (`backup_cron = "0 0 * * *"`); è disponibile anche come CLI `python scripts/backup.py` per backup ad-hoc. + +> Nota storica: il cron era orario (`0 * * * *`) e accumulava ~16 GB +> di snapshot full per ~98 MB di dato unico (la stessa catena opzioni +> ricopiata ~24×/giorno). Portato a giornaliero per ridurre il +> footprint di ~24× a parità di retention — rilevante prima di +> accendere il collettore research, che 2-4× la crescita del DB. diff --git a/docs/06-operational-flow.md b/docs/06-operational-flow.md index bf588d8..7364b6c 100644 --- a/docs/06-operational-flow.md +++ b/docs/06-operational-flow.md @@ -234,6 +234,8 @@ proposed | `0 12 1 * *` | Kelly recalibration | Mensile | | `*/5 * * * *` | Health check | 5 min | | `*/15 * * * *` | Market snapshot (calibrazione soglie) | 15 min | +| `*/15 * * * *` | Option chain snapshot (live, finestra DTE strategia) | 15 min | +| `0 * * * *` | Option chain research (full-chain + book_depth, opt-in) | Orario | | `0 0 * * *` | Backup SQLite + rotation log | Giornaliero | | `0 8 * * *` | Daily digest Telegram | Giornaliero | diff --git a/docs/10-config-spec.md b/docs/10-config-spec.md index 3c841a1..b626a7a 100644 --- a/docs/10-config-spec.md +++ b/docs/10-config-spec.md @@ -55,19 +55,43 @@ structure: dte_min: 14 dte_max: 21 + # Profilo B (v1.7.0). L'analisi su 3.689 snapshot (1mag-8giu '26) ha + # mostrato che a delta 0.10-0.15 il miglior credit/width fisicamente + # ottenibile è ~6%, quindi il vecchio credit_to_width_ratio_min=0.30 + # era irraggiungibile (0 spread fattibili). La sola leva efficace è + # vendere più vicino → delta alzato a ~0.18. short_strike: - delta_target: 0.12 - delta_min: 0.10 - delta_max: 0.15 - distance_otm_pct_min: 0.15 + delta_target: 0.18 + delta_min: 0.12 + delta_max: 0.22 + distance_otm_pct_min: 0.10 distance_otm_pct_max: 0.25 spread_width: target_pct_of_spot: 0.04 min_pct_of_spot: 0.03 - max_pct_of_spot: 0.05 + # 0.06: la griglia strike ETH sotto i $1500 è a 100pt (~6% a spot + # <$2k); con cap 0.05 nessuna gamba long rientrava in banda. + max_pct_of_spot: 0.06 - credit_to_width_ratio_min: 0.30 + credit_to_width_ratio_min: 0.08 # era 0.30 (irraggiungibile a delta ≤0.22) + +# === RESEARCH COLLECTOR (§13-bis) === + +# Collettore opzioni full-chain, indipendente dal live. Cattura tutte +# le scadenze ≤ expiry_max_days ed entrambe le ali, popolando +# book_depth_top3 (1 call orderbook/strumento) → backtest opzioni +# per-trade e standing. Disabilitato di default: costo API non +# trascurabile. Scrive righe con source='research'. +research_collector: + enabled: false + cron: "0 * * * *" # orario, indipendente dal */15 del live + expiry_max_days: 95 # 1g..3mesi + moneyness_band_pct: null # null = catena completa (entrambe le ali) + open_interest_min: 100 + fetch_book_depth: true + book_depth_concurrency: 8 # concorrenza max delle call orderbook + assets: ["ETH", "BTC"] # === LIQUIDITY GATE ===