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

10 KiB
Raw Blame History

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)

# 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)

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

# 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

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

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

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.