Phase 0: project skeleton
- pyproject.toml with uv, deps for runtime + gui + backtest + dev - ruff/mypy strict config, pre-commit hooks for ruff/mypy/pytest - src/cerbero_bite/ layout with empty modules ready for Phase 1+ - structlog JSONL logger with daily rotation - click CLI with placeholder subcommands (status, start, kill-switch, gui, replay, config hash, audit verify) - 6 smoke tests passing, mypy --strict clean, ruff clean Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,225 @@
|
||||
# 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.
|
||||
|
||||
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% |
|
||||
|
||||
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) |
|
||||
| 45–60 | × 0.85 |
|
||||
| 60–80 | × 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.
|
||||
|
||||
## 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.
|
||||
Reference in New Issue
Block a user