feat(strategy): abbandono gating settimanale — entry daily 24/7
Crypto opera 24/7: la cadenza settimanale lunedì-only era un retaggio TradFi senza giustificazione. La nuova cadenza è giornaliera (cron 0 14 * * *), con i gate quantitativi a decidere se entrare o saltare. Cambiamenti principali: * runtime/orchestrator.py — _CRON_ENTRY 0 14 * * * (era MON) * runtime/auto_pause.py — pause_until(days=) (era weeks=); minimo clamp 1 giorno (era 1 settimana) * core/backtest.py — MondayPick→DailyPick, monday_picks→daily_picks (1 pick per calendar-day all'ora target); Sharpe annualization su ~120 trade/anno (era 52) * config/schema.py — default cron daily; max_concurrent_positions 1→5; AutoPauseConfig.pause_weeks→pause_days, default 14 * runtime/option_chain_snapshot_cycle.py + orchestrator — cron */15 per accumulo continuo dataset di backtest empirico Strategy yamls (config_version 1.3.0 → 1.4.0, hash rigenerati): * strategy.yaml — max_concurrent 1→5, cap_aggregate coerente * strategy.aggressiva.yaml — max_concurrent 2→8, cap_aggregate 3200→6400, max_contracts_per_trade invariato a 16 * strategy.conservativa.yaml — max_concurrent 1→3 * tutti — pause_weeks→pause_days: 14 GUI (pages/7_📚_Strategia.py): * slider Trade/anno: range 20-200 (era 8-30), default 110, help riallineato sulla math 365 candidature × pass-rate 30-40% * card profili: versione letta dinamicamente da config_version invece che hard-coded "v1.2.0" * warning "entrambi perdono soldi" ora valuta i P/L effettivi (cons['annual_pl'], aggr['annual_pl']) invece del win_rate grezzo; aggiunto stato intermedio quando solo conservativo è in perdita Tests (450/450 passati): * test_auto_pause: pause_days, clamp ≥1 giorno * test_backtest: rinomina + ridisegno daily picks (assert su calendar-day dedupe e hour filter) * test_sizing_engine: other_open_positions=5 per cap default * test_config_loader: version 1.4.0 Docs (README + 9 file in docs/) — tutti i riferimenti weekly/lunedì allineati a daily/24-7, volume option_chain ricalcolato per cron */15 (~1.1 MB/giorno, ~400 MB/anno). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+1
-1
@@ -36,7 +36,7 @@ per imparare, ma **non sta nel loop di esecuzione**.
|
||||
### Cosa fa Cerbero Bite
|
||||
|
||||
1. Legge dati di mercato dagli MCP (Deribit, Hyperliquid, sentiment, macro).
|
||||
2. Valuta condizioni di entrata su finestra temporale fissa (settimanale).
|
||||
2. Valuta condizioni di entrata su finestra temporale fissa (giornaliera, 14:00 UTC; crypto è 24/7).
|
||||
3. Calcola la struttura ottimale dello spread secondo le regole.
|
||||
4. Verifica liquidità, cap di rischio, calendar macro.
|
||||
5. Calcola sizing in contratti.
|
||||
|
||||
@@ -19,10 +19,12 @@ Sorgente teorica: `Cerbero_Office/NewStrategy/strategia-credit-spread-eth.md`
|
||||
|
||||
## 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.
|
||||
Il rule engine valuta l'apertura di un nuovo trade **una volta al
|
||||
giorno**, alle **14:00 UTC** (orario UE pomeridiano stabile, fuori
|
||||
dai picchi di funding statunitensi). Crypto è 24/7: non c'è un "giorno
|
||||
buono" intrinseco, sono i gate quantitativi a decidere se entrare o
|
||||
saltare. Se il giorno è festività italiana e `skip_holidays_country`
|
||||
è attivo, l'engine attende il giorno successivo.
|
||||
|
||||
Una nuova posizione viene aperta **solo se tutte** le seguenti condizioni
|
||||
sono vere:
|
||||
@@ -70,7 +72,7 @@ Razionale: il selling vol nudo è strutturalmente neutro a win-rate
|
||||
per il razionale completo.
|
||||
|
||||
Se anche **una sola** condizione fallisce → **no entry**, log con motivo,
|
||||
ritento la settimana successiva.
|
||||
ritento il giorno successivo.
|
||||
|
||||
## 3. Selezione struttura
|
||||
|
||||
@@ -256,13 +258,13 @@ 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).
|
||||
> `pause_days` giorni (skip-day 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.
|
||||
disabilitato; profilo aggressivo: lookback 5 trade, soglia 15%, 14
|
||||
giorni di pausa.
|
||||
|
||||
## 8. Esecuzione di apertura
|
||||
|
||||
@@ -296,7 +298,7 @@ settimane di pausa.
|
||||
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 opera fuori dalla finestra delle 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.
|
||||
|
||||
@@ -122,7 +122,7 @@ Cerbero_Bite/
|
||||
│ │ ├── lockfile.py # fcntl.flock single-instance
|
||||
│ │ ├── alert_manager.py # severity routing
|
||||
│ │ ├── health_check.py # ping + 3-strikes kill switch
|
||||
│ │ ├── entry_cycle.py # weekly entry auto-execute
|
||||
│ │ ├── entry_cycle.py # daily entry auto-execute (crypto 24/7)
|
||||
│ │ ├── monitor_cycle.py # 12h exit auto-execute
|
||||
│ │ └── recovery.py # state reconcile al boot
|
||||
│ ├── state/ # persistenza
|
||||
|
||||
+10
-7
@@ -220,11 +220,12 @@ NULL = engine attivo.
|
||||
|
||||
### `option_chain_snapshots`
|
||||
|
||||
Snapshot della catena opzioni Deribit prelevata settimanalmente
|
||||
(cron `55 13 * * MON`, 5 minuti prima del trigger entry). 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 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`.
|
||||
|
||||
```sql
|
||||
CREATE TABLE option_chain_snapshots (
|
||||
@@ -259,8 +260,10 @@ sugli strike candidati al picker.
|
||||
con prezzi reali invece di Black-Scholes), la calibrazione empirica
|
||||
dello skew premium, la validazione ex-post dello strike picker.
|
||||
|
||||
Volume atteso: ~50 strike × 3 scadenze × 1 snapshot/settimana ×
|
||||
17 colonne ≈ 12 KB/settimana, ~600 KB/anno.
|
||||
Volume atteso (cron `*/15 * * * *`, ~96 snapshot/giorno):
|
||||
~50 strike × 3 scadenze × 96 snap/giorno × 17 colonne ≈ ~1.1 MB/giorno,
|
||||
~400 MB/anno. Considerare politiche di retention (archive trimestrale
|
||||
in parquet) se il bot gira a lungo.
|
||||
|
||||
## Log file
|
||||
|
||||
|
||||
@@ -27,9 +27,11 @@ L'avvio è progettato per essere **safe**: se qualcosa non torna, il
|
||||
sistema si rifiuta di operare. Mai partire con uno stato dubbio o un
|
||||
ambiente diverso da quello atteso.
|
||||
|
||||
## Flusso 2 — Settimanale (entry)
|
||||
## Flusso 2 — Daily (entry)
|
||||
|
||||
Trigger: cron `0 14 * * MON` (lunedì 14:00 UTC).
|
||||
Trigger: cron `0 14 * * *` (ogni giorno 14:00 UTC). Crypto è 24/7:
|
||||
la cadenza di candidatura non è gateata sulla settimana — sono i gate
|
||||
quantitativi a decidere se entrare o saltare il giorno.
|
||||
|
||||
```
|
||||
START
|
||||
@@ -219,7 +221,7 @@ proposed
|
||||
|
||||
| Cron | Trigger | Frequenza |
|
||||
|---|---|---|
|
||||
| `0 14 * * MON` | Entry evaluation | Settimanale |
|
||||
| `0 14 * * *` | Entry evaluation | Giornaliera |
|
||||
| `0 2,14 * * *` | Position monitoring | 2× giorno |
|
||||
| `0 12 1 * *` | Kelly recalibration | Mensile |
|
||||
| `*/5 * * * *` | Health check | 5 min |
|
||||
@@ -237,7 +239,7 @@ Il bot riconosce due interruttori indipendenti, letti da
|
||||
| Variabile d'ambiente | Default | Cosa abilita |
|
||||
|---|---|---|
|
||||
| `CERBERO_BITE_ENABLE_DATA_ANALYSIS` | `true` | Job `market_snapshot` ogni 15 min: raccolta dati MCP, scrittura tabella `market_snapshots`, calibrazione soglie. |
|
||||
| `CERBERO_BITE_ENABLE_STRATEGY` | `false` | Job `entry` (lunedì 14:00 UTC) e `monitor` (2× giorno): valutazione regole §2-§9 di `01-strategy-rules.md` e proposta/esecuzione ordini. |
|
||||
| `CERBERO_BITE_ENABLE_STRATEGY` | `false` | Job `entry` (daily 14:00 UTC) e `monitor` (2× giorno): valutazione regole §2-§9 di `01-strategy-rules.md` e proposta/esecuzione ordini. |
|
||||
|
||||
I job di infrastruttura (`health`, `backup`, `manual_actions`) sono
|
||||
**sempre attivi**, indipendentemente dai flag, perché tengono in vita il
|
||||
|
||||
@@ -54,7 +54,7 @@ cerbero-bite kill-switch disarm --reason "<motivo>" \
|
||||
L'operazione è transazionale: SQLite `system_state.kill_switch = 0` +
|
||||
una linea `KILL_SWITCH_DISARMED` nella audit chain con il motivo. Il
|
||||
disarm non riavvia automaticamente lo scheduler; è il prossimo tick
|
||||
naturale (entry settimanale o monitor 12h) a far ripartire la
|
||||
naturale (entry giornaliero o monitor 12h) a far ripartire la
|
||||
decisione.
|
||||
|
||||
## Cap di rischio (oltre alle regole di strategia)
|
||||
|
||||
@@ -157,9 +157,9 @@ chain:
|
||||
|
||||
| Test | Scenario |
|
||||
|---|---|
|
||||
| `test_weekly_open_happy_path` | Tutto OK → proposta inviata |
|
||||
| `test_weekly_open_no_strike_available` | Chain vuota nel range delta |
|
||||
| `test_weekly_open_macro_blocks` | FOMC entro 5 giorni |
|
||||
| `test_daily_open_happy_path` | Tutto OK → proposta inviata |
|
||||
| `test_daily_open_no_strike_available` | Chain vuota nel range delta |
|
||||
| `test_daily_open_macro_blocks` | FOMC entro 5 giorni |
|
||||
| `test_monitor_profit_take` | Mark = 50% credito → close_profit |
|
||||
| `test_monitor_vol_stop` | DVOL +12 → close_vol |
|
||||
| `test_recovery_after_crash_open_position` | Crash mid-fill, restart, riconcilia |
|
||||
@@ -175,8 +175,8 @@ checked-in.
|
||||
|
||||
```
|
||||
tests/golden/
|
||||
├── 2026-04-27_weekly_open_bull_put.yaml # input snapshot
|
||||
├── 2026-04-27_weekly_open_bull_put.golden # output atteso
|
||||
├── 2026-04-27_daily_open_bull_put.yaml # input snapshot
|
||||
├── 2026-04-27_daily_open_bull_put.golden # output atteso
|
||||
└── runner.py
|
||||
```
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ Tasks:
|
||||
4. `runtime/alert_manager.py` — escalation policy
|
||||
|
||||
Test integration su scenari completi (vedi `08-testing-validation.md`):
|
||||
- weekly open happy path
|
||||
- daily open happy path
|
||||
- monitor profit take
|
||||
- monitor vol stop
|
||||
- recovery dopo crash
|
||||
@@ -206,7 +206,7 @@ Setup:
|
||||
|
||||
Metriche da raccogliere:
|
||||
|
||||
- Numero proposte settimanali emesse
|
||||
- Numero proposte giornaliere emesse
|
||||
- Quante passano i filtri
|
||||
- Win rate, avg P&L paper
|
||||
- Discrepanze tra mid stimato e fill reale (slippage)
|
||||
|
||||
@@ -24,8 +24,8 @@ asset:
|
||||
# === ENTRY ===
|
||||
|
||||
entry:
|
||||
# finestra di valutazione settimanale
|
||||
cron: "0 14 * * MON" # lunedì 14:00 UTC
|
||||
# finestra di valutazione giornaliera (crypto 24/7)
|
||||
cron: "0 14 * * *" # ogni giorno 14:00 UTC
|
||||
skip_holidays_country: "IT"
|
||||
|
||||
# filtri di accesso (vedi 01-strategy-rules.md §2)
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
## TL;DR
|
||||
|
||||
Cerbero Bite vende **credit spread settimanali su ETH/Deribit** quando
|
||||
Cerbero Bite vende **credit spread su ETH/Deribit (DTE 14-21, valutati ogni giorno)** quando
|
||||
la volatilità implicita è **abbastanza alta da pagare bene**, il
|
||||
mercato non è in **stress di liquidazione**, non ci sono **eventi macro
|
||||
forti** in finestra, e il bias direzionale è **chiaro** (bull o bear).
|
||||
@@ -22,8 +22,9 @@ strategia.
|
||||
Ogni 15 minuti raccoglie 1 riga per asset (ETH e BTC) nella tabella
|
||||
`market_snapshots`. Quei dati alimentano tre obiettivi distinti:
|
||||
|
||||
1. **Decisione live** — l'entry ciclo del lunedì 14:00 UTC legge i
|
||||
campi più freschi per dire "go/no-go".
|
||||
1. **Decisione live** — l'entry ciclo daily alle 14:00 UTC legge i
|
||||
campi più freschi per dire "go/no-go" (crypto è 24/7: la cadenza
|
||||
non è gateata sulla settimana, decidono i gate quantitativi).
|
||||
2. **Monitoring continuo** — il decision loop di gestione attiva
|
||||
confronta la situazione con quella all'apertura.
|
||||
3. **Calibrazione** — la pagina `📐 Calibrazione` usa la distribuzione
|
||||
@@ -197,7 +198,7 @@ Quanto segue è la versione "leggibile" delle regole §2-§9 di
|
||||
`01-strategy-rules.md`. Ogni passo cita i campi di
|
||||
`market_snapshots` che lo alimentano.
|
||||
|
||||
### Fase 1 — Trigger (lunedì 14:00 UTC, festività italiane escluse)
|
||||
### Fase 1 — Trigger (daily 14:00 UTC, festività italiane escluse se `skip_holidays_country` è on)
|
||||
|
||||
```
|
||||
SE NESSUNA posizione aperta
|
||||
@@ -211,7 +212,7 @@ SE NESSUNA posizione aperta
|
||||
ALLORA
|
||||
procedi alla Fase 2
|
||||
ALTRIMENTI
|
||||
no entry, log motivo, ritento la settimana successiva
|
||||
no entry, log motivo, ritento il giorno successivo
|
||||
```
|
||||
|
||||
### Fase 2 — Bias e struttura
|
||||
@@ -363,8 +364,8 @@ capitale **non aumenta** i contratti per trade.
|
||||
|
||||
### Frequenza realistica di entry
|
||||
|
||||
La regola si valuta una volta a settimana, ma la maggioranza dei
|
||||
lunedì viene saltata per:
|
||||
La regola si valuta **una volta al giorno** (crypto è 24/7), ma la
|
||||
maggioranza dei giorni viene saltata per:
|
||||
|
||||
| Motivo di skip | Frequenza tipica |
|
||||
|---|---|
|
||||
@@ -372,11 +373,12 @@ lunedì viene saltata per:
|
||||
| Bias non chiaro (trend × funding discordi o entrambi neutri senza IC) | 25–35% |
|
||||
| Macro entro DTE | 10–20% |
|
||||
| Funding o liquidation risk fuori soglia | 5–15% |
|
||||
| Capitale o sizing insufficiente | 0–5% |
|
||||
| Capitale, sizing insufficiente o concurrency cap raggiunto | 5–15% |
|
||||
|
||||
**Risultato netto: 30–50% delle settimane finisce in entry effettiva
|
||||
⇒ 15–25 trade / anno** (52 lunedì × 30–50%). Le altre settimane il
|
||||
bot sta fermo. È il design.
|
||||
**Risultato netto: ~30–40% dei giorni finisce in entry effettiva
|
||||
⇒ 110–145 trade / anno** (365 candidature × pass-rate, capped da
|
||||
`max_concurrent_positions`). I restanti giorni il bot sta fermo:
|
||||
è il design — la disciplina è la strategia.
|
||||
|
||||
### Win-rate atteso (short delta 0.12 + profit-take 50%)
|
||||
|
||||
@@ -450,11 +452,11 @@ In modalità data-only (oggi) il P/L atteso è **0** — l'engine
|
||||
2. **Validare** i filtri quant osservando ex-post quanti tick
|
||||
sarebbero stati filtrati (vedi pagina `📐 Calibrazione`, colonna
|
||||
"% bloccato dalla soglia").
|
||||
3. **Misurare** la quota effettiva di lunedì che superano i filtri
|
||||
3. **Misurare** la quota effettiva di giorni che superano i filtri
|
||||
nel proprio regime, prima di committare capitale.
|
||||
|
||||
> Suggerimento: 4 settimane di dati = 4 lunedì × probabilità entry =
|
||||
> 1–2 candidate entry effettive. **Aspettare almeno 8 settimane**
|
||||
> Suggerimento: 30 giorni di dati = 30 candidature × probabilità entry
|
||||
> ≈ 9–12 candidate entry effettive. **Aspettare almeno 60 giorni**
|
||||
> prima di tarare le soglie dà uno storico con dispersione
|
||||
> sufficiente per decisioni non-rumorose.
|
||||
|
||||
@@ -560,8 +562,8 @@ step di calibrazione, vedi §4-quinquies in roadmap).
|
||||
|
||||
- **Conservativa / golden config**: `enabled=false, min=0`. Tutti i
|
||||
setup passano questo gate, anche con IV-RV negativa. Motivo: nei
|
||||
primi 8 turni di lunedì non si hanno abbastanza tick per stabilire
|
||||
che soglia ha senso nel proprio regime. Lasciamo la pagina
|
||||
primi 60 giorni non si hanno abbastanza tick per stabilire che
|
||||
soglia ha senso nel proprio regime. Lasciamo la pagina
|
||||
`📐 Calibrazione` mostrare la distribuzione e poi alziamo
|
||||
manualmente.
|
||||
- **Aggressiva**: `enabled=true, min=3`. Il profilo aggressivo già di
|
||||
@@ -599,7 +601,8 @@ questa logica: muovi da 0.72 a 0.78 e vedi l'APR scattare.
|
||||
|
||||
In aggiunta a `market_snapshots` (cron `*/15`), il bot raccoglie
|
||||
ora una seconda fonte di dati: la **catena opzioni Deribit completa**
|
||||
ogni lunedì alle 13:55 UTC (5 minuti prima del trigger entry).
|
||||
ogni 15 minuti (cron `*/15`, allineato a `market_snapshots` — crypto
|
||||
è 24/7, l'accumulo dataset deve essere continuo).
|
||||
|
||||
Tabella `option_chain_snapshots` — vedi `05-data-model.md` per lo
|
||||
schema. Cosa registra per ogni strumento entro la finestra
|
||||
@@ -628,7 +631,7 @@ schema. Cosa registra per ogni strumento entro la finestra
|
||||
|
||||
- `cerbero-bite option-chain trigger` — esegue UNA volta il
|
||||
collector senza aspettare il cron. Utile per test e per popolare
|
||||
prima del primo lunedì utile.
|
||||
prima del primo tick utile.
|
||||
- `cerbero-bite option-chain analyze [--bias bull_put|bear_call]` —
|
||||
legge l'ultimo snapshot, simula il selector di strike con la
|
||||
strategy passata e stampa: short/long strike, delta, width,
|
||||
@@ -643,9 +646,9 @@ Tre euristiche operative sui campi raccolti:
|
||||
1. **Premio "ricco":** `iv_minus_rv` consistentemente > 5 punti per
|
||||
N giorni → il regime sta pagando bene la vendita di vol. Sono i
|
||||
periodi in cui la strategia ha edge maggiore.
|
||||
2. **Premio "magro":** `dvol < 35` per più giorni → la finestra del
|
||||
lunedì viene saltata. Non è un fallimento: è la disciplina che
|
||||
funziona.
|
||||
2. **Premio "magro":** `dvol < 35` per più giorni → la finestra
|
||||
giornaliera viene saltata. Non è un fallimento: è la disciplina
|
||||
che funziona.
|
||||
3. **Stress imminente:** `liquidation_*_risk = high` o spike di
|
||||
`oi_delta_pct_4h` (> 5% in valore assoluto) + funding ai limiti
|
||||
→ atteso vol stop / time stop attivi nei prossimi cicli, anche
|
||||
|
||||
Reference in New Issue
Block a user