Files
Cerbero-Bite/docs/01-strategy-rules.md
T
root dabcc8d15b docs: aggiornamento Phase 5 — IV-RV gate, F+D+A, backtest, option chain
- 01-strategy-rules.md:
  * §2.8 (filtri quant: dealer gamma + liquidation risk)
  * §2.9 (IV richness gate, opt-in, default disabled)
  * §3.2 — variante delta_by_dvol step-function
  * §7-bis.1 (vol-collapse harvest D)
  * §7-bis.2 (graduated profit-take C — scaffolding)
  * §7-bis.3 (auto-pause su drawdown F)

- 05-data-model.md:
  * `system_state.auto_pause_until / _reason` (migration 0004)
  * Nuova tabella `option_chain_snapshots` (migration 0005)
  * Tabella migrations completa (1→5)

- 13-strategia-spiegata.md:
  * §4-quinquies — catena opzioni storica (Phase 5):
    cosa raccoglie, cosa sblocca, CLI `option-chain
    trigger|analyze`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 21:29:00 +00:00

311 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 01 — Regole della strategia (Cerberus Bite)
Le regole qui formalizzate sono la versione **canonica e immutabile** che
il rule engine deve applicare. Modifiche richiedono una review esplicita
con Adriano (e una nuova versione di questo documento).
Sorgente teorica: `Cerbero_Office/NewStrategy/strategia-credit-spread-eth.md`
+ analisi Monte Carlo + cap operativi Cerbero v4.
## 1. Universo e strumenti
| Parametro | Valore |
|---|---|
| Sottostante | ETH/USD |
| Exchange | Deribit |
| Tipo opzioni | Europee, cash-settled, USDC-margined |
| Strutture ammesse | Bull Put Spread, Bear Call Spread, (Iron Condor solo in regime laterale, vedere §6) |
| Strutture vietate | Naked options, calendar spread, ratio spread, condor sbilanciati |
## 2. Trigger di apertura (entry)
Il rule engine valuta l'apertura di un nuovo trade **una sola volta al
giorno**, alle **14:00 UTC** del lunedì (orario UE pomeridiano stabile,
fuori dai picchi di funding statunitensi). Se il lunedì è festività
italiana, l'engine ignora la regola e attende il lunedì successivo.
Una nuova posizione viene aperta **solo se tutte** le seguenti condizioni
sono vere:
1. **Nessuna posizione Cerberus Bite già aperta.**
2. **Capitale corrente ≥ 720 USD.** Sotto questa soglia il sizing in
contratti non può raggiungere 1 unità Deribit.
3. **DVOL corrente ≥ 35.** Sotto 35 il premio è troppo magro per
mantenere il rapporto fees/credit accettabile.
4. **DVOL corrente ≤ 90.** Sopra 90 si è in regime di stress, no entry.
5. **Nessun evento macro** (FOMC, CPI USA, NFP, ECB, Powell speech)
nei prossimi DTE giorni dall'apertura.
6. **Funding rate ETH-PERP** in valore assoluto annualizzato ≤ 80%
(filtra regimi di liquidazioni a cascata imminenti).
7. **Holdings ETH** in `cerbero-portfolio` non superiori al 30% del
patrimonio totale (correlazione direzionale già alta).
8. **Liquidità degli strike candidati** entro le soglie del §3.
### 2.8 Filtri quant (introdotti in Phase 4)
Due gate aggiuntivi che leggono i campi del `market_snapshot`:
- **Dealer net gamma > 0** (default: `dealer_gamma_min: 0`). Long-gamma
regime = dealer hedge che sopprime la vol → ideale per vendere
credit spread. Short-gamma = vol-amplifying flow, statisticamente
perdente. Disattivabile via `dealer_gamma_filter_enabled: false`.
- **Liquidation risk ≠ high** (default: `liquidation_filter_enabled:
true`). Salta entry quando il modulo sentiment flagga uno squeeze
imminente su long o short side.
### 2.9 IV richness gate (introdotto in Phase 5, opt-in)
Filtro a maggior impatto sul win-rate. **Disabilitato** di default
nella golden config — abilitato esplicitamente nel profilo
`strategy.aggressiva.yaml`:
- `iv_minus_rv_filter_enabled: true|false` — master switch.
- `iv_minus_rv_min: <pt vol>` — soglia: l'entry passa solo se la
IV implicita 30g supera la realized vol 30g di almeno tot punti.
Default 0; valori sensati 3-5 dopo calibrazione sui dati raccolti.
Razionale: il selling vol nudo è strutturalmente neutro a win-rate
70-72%. L'edge della strategia esiste solo quando il premio è
"ricco" — IV30 > RV30 + N. Vedere `13-strategia-spiegata.md §4-quater`
per il razionale completo.
Se anche **una sola** condizione fallisce → **no entry**, log con motivo,
ritento la settimana successiva.
## 3. Selezione struttura
### 3.1 Bias direzionale
Il bias è dedotto deterministicamente da due indicatori, mai in modo
discrezionale:
| Indicatore | Calcolo | Soglia bull | Soglia bear |
|---|---|---|---|
| Trend ETH 30g | (ETH_now / ETH_30g_ago - 1) × 100 | ≥ +5% | ≤ -5% |
| Funding cross-exchange | mediana funding annualizzato 4 maggiori exchange | ≥ +20% | ≤ -20% |
Risultato:
- Entrambi bull → **Bull Put Spread**.
- Entrambi bear → **Bear Call Spread**.
- Discordanti → **no entry** (mercato indeciso, edge incerto).
- Entrambi in range neutro `(-5%, +5%)` E DVOL ≥ 55 E ADX(14) < 20 →
**Iron Condor stretto** ammesso (vedi §6).
- Tutti gli altri casi neutri → **no entry**.
### 3.2 Strike short
Si seleziona lo strike short più vicino a delta target, in valore
assoluto.
| Parametro | Valore |
|---|---|
| Delta short target | 0.12 |
| Tolleranza delta | [0.10, 0.15] |
| Distanza minima OTM | 15% (anche se delta è dentro tolleranza) |
| Distanza massima OTM | 25% |
**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
bassa il bot prende delta più alto (più premio), a DVOL alta sceglie
delta più basso (più safety distance). Lista vuota = comportamento
classico col delta target sopra. Esempio bande nel profilo
`strategy.aggressiva.yaml`:
| 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 |
Se nessuno strike disponibile rientra in entrambe le tolleranze → no entry.
### 3.3 Strike long (protezione)
Si seleziona lo strike a distanza fissa dallo short:
| Parametro | Valore |
|---|---|
| Larghezza spread (in % di spot) | 4% |
| Larghezza minima accettabile | 3% |
| Larghezza massima accettabile | 5% |
Se non esiste lo strike esatto a 4%, si prende il più vicino entro
[3%, 5%]; altrimenti no entry.
### 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.
## 4. Liquidità (filtro hard pre-entry)
Per ciascuno strumento delle due gambe, **tutte** le condizioni:
| Misura | Soglia |
|---|---|
| Open interest | ≥ 100 contratti |
| Volume 24h sullo strumento | ≥ 20 contratti |
| Spread bid-ask | ≤ 15% del mid (≤ 10% per ATM, irrilevante qui) |
| Profondità book ai primi 3 livelli | ≥ 5 contratti aggregati |
Calcoliamo inoltre uno **slippage stimato** moltiplicando la larghezza
del bid-ask di entrambe le gambe per la size proposta. Se lo slippage
totale > 8% del credito atteso → no entry.
## 5. Sizing
### 5.1 Calcolo numero contratti
```
risk_target_usd = capitale_corrente * 0.13 # Quarter Kelly
risk_target_usd = min(risk_target_usd, 200_eur_in_usd) # cap Cerbero
n_contracts = floor(risk_target_usd / max_loss_per_contract)
n_contracts = min(n_contracts, 4) # cap aggregato implicito
```
`max_loss_per_contract` = larghezza spread × multiplier ETH (1 ETH).
### 5.2 Vincolo aggregato
Se `n_contracts × max_loss_per_contract + engagement_aperto_totale > 1.000_eur` →
riduci `n_contracts` finché il vincolo è rispettato. Se risulta < 1 → no entry.
### 5.3 Volatilità di volatilità
Sizing dinamico per regime DVOL:
| DVOL corrente | Aggiustamento `n_contracts` |
|---|---|
| < 45 | × 1.0 (base) |
| 4560 | × 0.85 |
| 6080 | × 0.65 |
| > 80 | (no entry, vedi §2) |
Arrotondamento sempre per difetto a intero, minimo 1.
## 6. Iron Condor (ammesso solo in regime laterale)
Se le condizioni del §3.1 attivano IC, struttura:
- Bull Put Spread alle stesse regole §3.2/§3.3
- Bear Call Spread speculare (delta 0.12, 4% width)
- Sizing: `n_contracts` calcolato come sopra ma **dimezzato** per gamba
(rischio totale = somma max loss dei due lati, ma su ETH i due lati
non possono essere entrambi violati, quindi rischio effettivo = max
loss del lato peggiore + credito del lato vincente)
- Profit take: 25% del credito totale (più aggressivo)
- Tutto il resto delle regole §7-§9 si applica per lato.
## 7. Gestione attiva (decision loop ogni 12 ore)
Per ogni posizione aperta, il rule engine valuta in ordine:
1. **Profit take** — se mark price del combo ≤ 50% del credito incassato,
`decision = CLOSE_PROFIT`.
2. **Stop loss stretto** — se mark price del combo ≥ 250% del credito
(perdita = 1.5× credito), `decision = CLOSE_STOP`.
3. **Vol stop** — se DVOL corrente ≥ DVOL all'entry + 10,
`decision = CLOSE_VOL`.
4. **Time stop** — se `(scadenza - oggi) ≤ 7 giorni`,
`decision = CLOSE_TIME` (a meno che non siamo già al 50% di profit:
in quel caso teniamo per regola 1 in arrivo).
5. **Strike testato** — se `|delta_short_corrente| ≥ 0.30`,
`decision = CLOSE_DELTA`. Su ETH non si difende, si esce.
6. **Movimento esplosivo** — se `|return_4h_ETH| ≥ 5%` direzione avversa,
`decision = CLOSE_AVERSE` (azione conservativa, può essere finalizzata
alla prossima fenestra).
7. Altrimenti `decision = HOLD`.
L'ordine è importante: il primo trigger soddisfatto vince.
## 7-bis. Estensioni opzionali (Phase 5)
Tre miglioramenti opt-in al decision loop. Tutti **disabled** di
default nella golden config; il profilo `strategy.aggressiva.yaml`
li abilita.
### 7-bis.1 Vol-collapse harvest (D)
Inserito tra il profit-take §7.1 e lo stop-loss §7.2:
> Se `vol_harvest_dvol_decrease > 0`, siamo in profit
> (`debit < credit`) E `DVOL_now ≤ DVOL_entry vol_harvest_dvol_decrease`,
> `decision = CLOSE_VOL_HARVEST`.
Razionale: edge IV-RV già catturato, vol attesa rientrata, non c'è
motivo di tenere fino al profit-take. Default disabilitato (`0`);
profilo aggressivo: `15` punti vol.
### 7-bis.2 Profit-take graduale (C — scaffolding)
Schema in place per chiusure parziali; pipeline runtime di
chiusura partial-close NON ancora wirata. Default vuoto. Quando
popolato, ogni livello `{mark_at_pct_credit, close_pct_of_initial_contracts}`
emette un'azione `CLOSE_PROFIT_PARTIAL` advisory che il runtime
attualmente ignora. Il completamento richiede refactor del position
model (contracts_open vs contracts_initial) — PR dedicato.
### 7-bis.3 Auto-pause su drawdown (F)
Circuit breaker sopra il kill-switch tecnico. Valutato all'inizio di
ogni entry-cycle:
> Se `auto_pause.enabled` e P/L cumulato delle ultime
> `lookback_trades` posizioni chiuse < `max_drawdown_pct ×
> capitale_corrente`, l'engine si auto-mette in pausa per
> `pause_weeks` settimane (skip-week mode).
Difende dai regime change non rilevati dai filtri quant. La pausa
si annulla automaticamente alla scadenza, oppure manualmente con
`UPDATE system_state SET auto_pause_until = NULL`. Default
disabilitato; profilo aggressivo: lookback 5 trade, soglia 15%, 2
settimane di pausa.
## 8. Esecuzione di apertura
1. Engine costruisce **combo order Deribit** (un solo ordine atomico
con due gambe). Mai due ordini separati.
2. Limit price = mid-price calcolato dall'engine.
3. Ordine inviato come limit GTC con time-in-force che scade alle
16:00 UTC dello stesso giorno.
4. Se non riempito entro 30 min, engine alza limit di 1 tick verso
ask combinato fino a un massimo di 3 step (poi cancella e log
"no fill").
5. Riempimento → engine persiste lo stato (vedi `05-data-model.md`)
includendo: spot ETH, DVOL, strike, scadenza, credit incassato,
timestamp.
## 9. Esecuzione di chiusura
1. Stessa logica di combo, in direzione inversa.
2. Limit di partenza al mid-price.
3. Se non riempito entro 30 min: alza limit fino a 3 step verso il
bid combinato. Su trigger `CLOSE_STOP` o `CLOSE_VOL` o `CLOSE_DELTA`
l'engine può accettare slippage maggiore (fino a 5 step) perché
l'urgenza prevale sul prezzo.
4. Riempimento → posizione marcata `CLOSED`, P&L calcolato e loggato,
record archiviato per Kelly recalibration mensile.
## 10. Cosa NON fa il rule engine — esplicito
- Non rolla mai una posizione (regola §7.5: si esce e basta).
- Non aggiunge gambe a una posizione esistente (no conversione in IC
durante un trade aperto).
- Non aggiusta strike o size dopo l'apertura.
- Non apre nuovi trade per "compensare" perdite recenti.
- Non opera fuori dalla finestra del lunedì 14:00 UTC, eccetto chiusure.
- Non deroga ai cap nemmeno per "opportunità eccezionali".
- Non si aggiorna automaticamente: nuovo set di regole = nuovo deploy
con review esplicita.
## 11. Riepilogo soglie (parametri di config)
Tutti i numeri sopra sono **parametrizzati** in `strategy.yaml` (vedi
`10-config-spec.md`). Modificarli è una decisione di Adriano con
giustificazione scritta nel commit message. La regola di default
fissata da questo documento è la **golden config** che il sistema parte
con al primo deploy.