Files
Cerbero-Bite/docs/10-config-spec.md
T
Adriano ce158a92dd feat(mcp+runtime): allineamento a Cerbero MCP V2 e flag operativi
Adegua Cerbero Bite alla nuova versione 2.0.0 del server MCP unificato
(testnet/mainnet routing per token, header X-Bot-Tag obbligatorio) e
introduce due interruttori operativi indipendenti per separare la
raccolta dati dall'esecuzione di strategia.

Auth e collegamento MCP
- Token bearer letto dalla nuova variabile CERBERO_BITE_MCP_TOKEN; il
  valore sceglie l'ambiente upstream (testnet vs mainnet) sul server.
  Rimosso il caricamento da file (`secrets/core.token`,
  CERBERO_BITE_CORE_TOKEN_FILE, Docker secret /run/secrets/core_token).
- Aggiunto header X-Bot-Tag (default `BOT__CERBERO_BITE`, override via
  CERBERO_BITE_MCP_BOT_TAG) su ogni call MCP, con validazione lato client
  (non vuoto, ≤ 64 caratteri).
- Cartella `secrets/` rimossa, `.gitignore` ripulito, Dockerfile e
  docker-compose.yml aggiornati con env passthrough e fail-fast quando
  manca il token.

Modalità operativa (RuntimeFlags)
- Nuovo modulo `config/runtime_flags.py` con `RuntimeFlags(
  data_analysis_enabled, strategy_enabled)` e loader che parserizza
  CERBERO_BITE_ENABLE_DATA_ANALYSIS e CERBERO_BITE_ENABLE_STRATEGY
  (true/false/yes/no/on/off/enabled/disabled, case-insensitive).
- L'orchestratore espone i flag, audita e logga la modalità al boot
  (`engine started: env=… data_analysis=… strategy=…`), e in
  `install_scheduler` esclude i job `entry`/`monitor` quando strategy è
  off e il job `market_snapshot` quando data analysis è off. I job di
  infrastruttura (health, backup, manual_actions) restano sempre attivi.
- Default profile = "solo analisi dati" (data_analysis=true,
  strategy=false), pensato per la finestra di soak post-deploy.

GUI saldi
- `gui/live_data.py::_fetch_deribit_currency` riconosce il campo soft
  `error` nel payload V2 (HTTP 200 con `error` valorizzato dal server
  quando l'auth Deribit fallisce) e lo propaga come `BalanceRow.error`,
  evitando di mostrare un fuorviante equity = 0,00.

CLI
- Sostituita l'opzione `--token-file` con `--token` (stringa) sui comandi
  start/dry-run/ping; il default proviene dall'env. Le chiamate al
  builder dell'orchestrator passano anche `bot_tag` e `flags`.

Documentazione
- `docs/04-mcp-integration.md`: descrizione del nuovo flusso di auth V2
  (token = ambiente, X-Bot-Tag nell'audit) e router unificati.
- `docs/06-operational-flow.md`: nuova sezione "Modalità operativa" con
  i tre profili canonici e tabella di gating per ogni job; aggiunto
  `market_snapshot` al cron summary.
- `docs/10-config-spec.md`: nuova sezione "Variabili d'ambiente"
  tabellare con tutti gli env, comprese le bool dei flag operativi.
- `docs/02-architecture.md`: layout del repo aggiornato (`secrets/`
  rimosso, `runtime_flags.py` aggiunto), descrizione di `config/`
  estesa.

Test
- 5 nuovi test su `_fetch_deribit_currency` (soft-error, payload pulito,
  eccezione, error blank, signature parity).
- 7 nuovi test su `load_runtime_flags` (default, override, parsing
  truthy/falsy, blank fallback, valore invalido).
- 4 nuovi test su `HttpToolClient` (X-Bot-Tag default e custom, blank e
  troppo lungo rifiutati).
- 3 nuovi test integration sull'orchestratore (gating dei job in base
  ai flag).
- Test esistenti su token/CLI ping/orchestrator aggiornati al nuovo
  schema. Suite intera: 404 passed, 1 skipped (sqlite3 CLI assente
  sull'host di sviluppo).

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

338 lines
10 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.
# 10 — Config Spec (`strategy.yaml`)
Tutti i parametri della strategia sono esposti in un file YAML
versionato. Modificare il file = decisione esplicita di Adriano.
Modifiche richiedono nuovo `config_version`, ricalcolo `config_hash`
e commit con motivazione.
## Schema completo (golden default)
```yaml
# strategy.yaml — Cerberus Bite golden config v1.0.0
# Riferimento: docs/01-strategy-rules.md
# NB: hash auto-calcolato dal CLI `cerbero-bite config hash`
config_version: "1.0.0"
config_hash: "0000000000000000000000000000000000000000000000000000000000000000" # placeholder
last_review: "2026-04-26"
last_reviewer: "Adriano"
asset:
symbol: "ETH"
exchange: "deribit"
# === ENTRY ===
entry:
# finestra di valutazione settimanale
cron: "0 14 * * MON" # lunedì 14:00 UTC
skip_holidays_country: "IT"
# filtri di accesso (vedi 01-strategy-rules.md §2)
capital_min_usd: 720
dvol_min: 35
dvol_max: 90
funding_perp_abs_max_annualized: 0.80
eth_holdings_pct_max: 0.30
no_position_concurrent: true # 1 sola posizione alla volta
exclude_macro_severity: ["high"]
exclude_macro_countries: ["US", "EU"]
# bias direzionale (§3.1)
trend_window_days: 30
trend_bull_threshold_pct: 0.05
trend_bear_threshold_pct: -0.05
funding_bull_threshold_annualized: 0.20
funding_bear_threshold_annualized: -0.20
iron_condor_dvol_min: 55
iron_condor_adx_max: 20
iron_condor_trend_neutral_band_pct: 0.05
# === STRUCTURE ===
structure:
dte_target: 18
dte_min: 14
dte_max: 21
short_strike:
delta_target: 0.12
delta_min: 0.10
delta_max: 0.15
distance_otm_pct_min: 0.15
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
credit_to_width_ratio_min: 0.30
# === LIQUIDITY GATE ===
liquidity:
open_interest_min: 100
volume_24h_min: 20
bid_ask_spread_pct_max: 0.15
book_depth_top3_min: 5
slippage_pct_of_credit_max: 0.08
# === SIZING ===
sizing:
kelly_fraction: 0.13 # Quarter Kelly basato su MC
# cap nominali (Cerbero v4 hard prohibitions)
cap_per_trade_eur: 200
cap_aggregate_open_eur: 1000
max_concurrent_positions: 1 # da 2+ solo via override esplicito
# soft cap difensivi (interni a Cerbero Bite)
max_contracts_per_trade: 4
# aggiustamento volatilità
dvol_adjustment:
- {dvol_under: 45, multiplier: 1.00}
- {dvol_under: 60, multiplier: 0.85}
- {dvol_under: 80, multiplier: 0.65}
# >= 80 → no entry (gestito da entry filters)
# === EXIT ===
exit:
# ordine di valutazione vincolante
profit_take_pct_of_credit: 0.50
stop_loss_mark_x_credit: 2.50 # mark = 250% credito → perdita 1.5×
vol_stop_dvol_increase: 10
time_stop_dte_remaining: 7
time_stop_skip_if_close_to_profit_pct: 0.70 # skip se mark ≤ 70% di profit_take
delta_breach_threshold: 0.30
adverse_move_4h_pct: 0.05
monitor_cron: "0 2,14 * * *" # 02 + 14 UTC
user_confirmation_timeout_min: 30
# escalation per urgenza alta
escalate_on_timeout:
- "CLOSE_STOP"
- "CLOSE_VOL"
- "CLOSE_DELTA"
# === EXECUTION ===
execution:
combo_only: true # mai due ordini separati
initial_limit: "mid"
reprice_step_ticks: 1
reprice_max_steps: 3
reprice_max_steps_urgent: 5 # per chiusure urgenti
order_tif: "GTC"
order_expiry_min: 30
ack_timeout_s: 300 # ack Cerbero core
# === MONITORING ===
monitoring:
health_check_interval_s: 300
health_failures_before_kill: 3
health_failures_before_restart: 5
daily_digest_cron: "0 8 * * *"
monthly_report_cron: "0 12 1 * *"
# === STORAGE ===
storage:
sqlite_path: "data/state.sqlite"
log_path: "data/log/"
log_retention_days: 365
backup_path: "data/backups/"
backup_retention_days: 30
# === MCP ===
mcp:
config_file: "~/.config/cerbero-suite/mcp.json"
call_timeout_s: 8
retry_max: 3
retry_base_delay_s: 1
required_versions:
cerbero-deribit: "^2.0.0"
cerbero-hyperliquid: "^1.5.0"
cerbero-memory: "^4.0.0"
cerbero-portfolio: "^1.2.0"
cerbero-macro: "^1.0.0"
cerbero-sentiment: "^1.0.0"
cerbero-telegram: "^1.0.0"
cerbero-brain-bridge: "^1.0.0"
# === TELEGRAM ===
telegram:
parse_mode: "MarkdownV2"
confirmation_timeout_min: 60
exit_confirmation_timeout_min: 30
backup_channel_on_critical: true # canale BotPapà su severity critical
# === KELLY RECALIBRATION ===
kelly_recalibration:
lookback_days: 365
min_sample_low_confidence: 30
min_sample_high_confidence: 100
weight_when_medium_confidence: 0.50
```
## Validazione (`config/schema.py`)
```python
from pydantic import BaseModel, Field, model_validator
from decimal import Decimal
class StrategyConfig(BaseModel):
config_version: str
config_hash: str
last_review: str
last_reviewer: str
asset: AssetConfig
entry: EntryConfig
structure: StructureConfig
liquidity: LiquidityConfig
sizing: SizingConfig
exit: ExitConfig
execution: ExecutionConfig
monitoring: MonitoringConfig
storage: StorageConfig
mcp: McpConfig
telegram: TelegramConfig
kelly_recalibration: KellyConfig
@model_validator(mode="after")
def validate_consistency(self) -> "StrategyConfig":
# short delta range coerente
s = self.structure.short_strike
if not (s.delta_min <= s.delta_target <= s.delta_max):
raise ValueError("delta_target outside [delta_min, delta_max]")
# OTM range coerente
if s.distance_otm_pct_min >= s.distance_otm_pct_max:
raise ValueError("OTM range invalid")
# Kelly range
if not (0 < self.sizing.kelly_fraction < 0.5):
raise ValueError("kelly_fraction out of safe range (0, 0.5)")
# spread width range
sw = self.structure.spread_width
if not (sw.min_pct_of_spot <= sw.target_pct_of_spot <= sw.max_pct_of_spot):
raise ValueError("spread_width target outside min/max")
# exit thresholds sensati
if self.exit.profit_take_pct_of_credit >= 1.0:
raise ValueError("profit_take >= 100% impossible")
if self.exit.stop_loss_mark_x_credit <= 1.0:
raise ValueError("stop_loss multiple <= 1× makes no sense")
return self
```
## Override locale
Se esiste `strategy.local.yaml` (gitignored), i suoi campi sovrascrivono
`strategy.yaml`. Usato per:
- Test in dry-run con cap dimezzati
- Personalizzazioni dello sviluppatore senza inquinare il main
- Override emergenza ("max_concurrent_positions: 0" per congelare entry
senza disabilitare l'engine)
L'override viene loggato all'avvio:
```
2026-04-27T10:00:00Z | OVERRIDE_APPLIED | sizing.cap_per_trade_eur: 200 → 100
```
## Hash integrity
```bash
# Calcolo manuale
cerbero-bite config hash
# Aggiornamento automatico (richiede review prompt)
cerbero-bite config update --reason "Reduce kelly to 0.10 after Apr drawdown"
```
Il comando:
1. Apre il file in editor.
2. All'esci, ricalcola SHA-256 escludendo la riga `config_hash`.
3. Aggiorna `config_hash`, `last_review`, `last_reviewer`.
4. Mostra diff ad Adriano.
5. Firma in audit chain.
Mismatch hash a runtime = kill switch immediato (vedi `07-risk-controls.md`).
## Esempi di modifiche valide
### Riduzione difensiva post-drawdown
```diff
sizing:
- kelly_fraction: 0.13
+ kelly_fraction: 0.10
```
Commit: `chore(config): reduce kelly to 0.10 after April -20% DD`.
### Aggiunta nuovo evento macro escluso
```diff
entry:
exclude_macro_severity: ["high"]
+ exclude_macro_keywords: ["Powell", "Lagarde", "ETF approval"]
```
Commit: `chore(config): exclude ETF-related events from entry window`.
### Disabilitazione temporanea iron condor
```diff
entry:
- iron_condor_dvol_min: 55
+ iron_condor_dvol_min: 999 # de facto disabled
```
Commit: `chore(config): disable IC pending review of vol regime`.
## Cosa NON è in config
Non è permesso parametrizzare:
- L'**ordine** dei trigger di uscita (è una scelta strategica codificata).
- Le **strutture** ammesse (vietato vendita nuda, ecc., scolpito nel codice).
- Le **hard prohibitions** Cerbero v4 (cap 200/1000 EUR sono limiti
superiori, non ulteriormente liberalizzabili).
- Lo **scheduler** per intervalli più stretti (un'ottimizzazione che
non si fa via config).
## Variabili d'ambiente
`strategy.yaml` definisce **cosa** fa il bot quando è acceso. Le
variabili d'ambiente in `.env` definiscono **come** si collega al
mondo esterno e **quali interruttori operativi** sono attivi.
Queste vivono fuori da `strategy.yaml` perché cambiano per ambiente
(testnet vs mainnet, soak vs trading) ma non per regola di strategia.
| Variabile | Tipo | Default | Uso |
|---|---|---|---|
| `CERBERO_BITE_MCP_TOKEN` | string (obbligatoria) | — | Bearer token presentato a Cerbero MCP V2. Il valore decide l'ambiente upstream (testnet o mainnet). Cambia il valore = cambia l'ambiente. |
| `CERBERO_BITE_MCP_BOT_TAG` | string ≤ 64 char | `BOT__CERBERO_BITE` | Header `X-Bot-Tag` registrato nell'audit log del server MCP per ogni write. |
| `CERBERO_BITE_MCP_DERIBIT_URL` | URL | gateway pubblico | Override URL router Deribit. |
| `CERBERO_BITE_MCP_HYPERLIQUID_URL` | URL | gateway pubblico | Override URL router Hyperliquid. |
| `CERBERO_BITE_MCP_MACRO_URL` | URL | gateway pubblico | Override URL router Macro. |
| `CERBERO_BITE_MCP_SENTIMENT_URL` | URL | gateway pubblico | Override URL router Sentiment. |
| `CERBERO_BITE_ENABLE_DATA_ANALYSIS` | bool (`true`/`false`) | `true` | Abilita il job `market_snapshot` (raccolta dati MCP ogni 15 min). |
| `CERBERO_BITE_ENABLE_STRATEGY` | bool (`true`/`false`) | `false` | Abilita i job `entry` e `monitor` (esecuzione regole §2-§9). |
| `CERBERO_BITE_TELEGRAM_BOT_TOKEN` | string | — | Token bot Telegram (notify-only). Senza, il client è in modalità disabled. |
| `CERBERO_BITE_TELEGRAM_CHAT_ID` | string | — | Chat ID destinatario notifiche Telegram. |
I valori bool accettano in input `1`/`0`, `true`/`false`, `yes`/`no`,
`on`/`off`, `enabled`/`disabled` (case-insensitive). Qualunque altro
valore fa fallire il boot con `ValueError`.
Vedi `06-operational-flow.md` §"Modalità operativa" per i profili
canonici di `ENABLE_DATA_ANALYSIS` e `ENABLE_STRATEGY`.