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:
root
2026-05-03 16:21:16 +00:00
parent dabcc8d15b
commit 6ff021fbf4
26 changed files with 216 additions and 181 deletions
+24 -21
View File
@@ -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) | 2535% |
| Macro entro DTE | 1020% |
| Funding o liquidation risk fuori soglia | 515% |
| Capitale o sizing insufficiente | 05% |
| Capitale, sizing insufficiente o concurrency cap raggiunto | 515% |
**Risultato netto: 3050% delle settimane finisce in entry effettiva
⇒ 1525 trade / anno** (52 lunedì × 3050%). Le altre settimane il
bot sta fermo. È il design.
**Risultato netto: ~3040% dei giorni finisce in entry effettiva
⇒ 110145 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 =
> 12 candidate entry effettive. **Aspettare almeno 8 settimane**
> Suggerimento: 30 giorni di dati = 30 candidature × probabilità entry
> ≈ 912 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