Files
Cerbero-Bite/docs/04-mcp-integration.md
T
Adriano f4faef6fd1 Phase 4 hardening: dealer-gamma + liquidation-heatmap entry filters
Integra due nuovi filtri dal pacchetto quant indicators rilasciato in
Cerbero_mcp (commit a13e3fe). 335 test pass, mypy strict pulito,
ruff clean.

Filtri (§2.8 — nuovo):
- dealer-gamma: blocca entry quando total_net_dealer_gamma <
  dealer_gamma_min (default 0). Long-gamma regime favorisce credit
  spread (vol-suppressing dealer flow); short-gamma flow lo amplifica
  ed è da evitare.
- liquidation-heatmap: blocca entry quando il segnale euristico di
  cerbero-sentiment riporta long o short squeeze risk = "high"
  (cluster di liquidations imminenti entro 24h).

Entrambi sono best-effort: se il tool MCP fallisce o restituisce
dati anomali l'entry_cycle popola EntryContext con None e
validate_entry salta il gate per non bloccare entry su problemi
infrastrutturali.

Wrapper:
- DeribitClient.dealer_gamma_profile_eth → DealerGammaSnapshot.
- SentimentClient.liquidation_heatmap → LiquidationHeatmap con
  property has_high_squeeze_risk.

Schema:
- EntryConfig.dealer_gamma_min, dealer_gamma_filter_enabled,
  liquidation_filter_enabled.
- EntryContext.dealer_net_gamma, liquidation_squeeze_risk_high
  opzionali.
- strategy.yaml: nuovi campi documentati con commento + hash
  ricalcolato (4c2be4c5...).

Documentazione:
- docs/04-mcp-integration.md riscritto al modello attuale (HTTP
  REST, no mcp SDK, no memory/brain-bridge, place_combo_order
  documentato, environment_info al boot).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 07:26:33 +02:00

159 lines
7.7 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.
# 04 — MCP Integration
Cerbero Bite consuma sei servizi MCP HTTP della suite (`Cerbero_mcp`).
Non utilizza l'SDK Python `mcp`: ogni server espone gli endpoint REST
`POST <base_url>/tools/<tool_name>` con autenticazione Bearer, e Cerbero
Bite vi si collega tramite `httpx.AsyncClient` long-lived
(`clients/_base.py`).
## Configurazione di connessione
Le URL sono risolte da `cerbero_bite.config.mcp_endpoints.load_endpoints`,
con default che corrispondono al DNS della rete Docker
`cerbero-suite` (`http://mcp-deribit:9011`, `http://mcp-macro:9013`,
ecc.). Ogni servizio può essere sovrascritto da una variabile
d'ambiente dedicata, utile in sviluppo:
| Servizio | Variabile d'ambiente | Default Docker DNS |
|---|---|---|
| Deribit | `CERBERO_BITE_MCP_DERIBIT_URL` | `http://mcp-deribit:9011` |
| Hyperliquid | `CERBERO_BITE_MCP_HYPERLIQUID_URL` | `http://mcp-hyperliquid:9012` |
| Macro | `CERBERO_BITE_MCP_MACRO_URL` | `http://mcp-macro:9013` |
| Sentiment | `CERBERO_BITE_MCP_SENTIMENT_URL` | `http://mcp-sentiment:9014` |
| Telegram | `CERBERO_BITE_MCP_TELEGRAM_URL` | `http://mcp-telegram:9017` |
| Portfolio | `CERBERO_BITE_MCP_PORTFOLIO_URL` | `http://mcp-portfolio:9018` |
Il bearer token per le chiamate è il token con capability `core` letto
da `secrets/core.token` (path configurabile via
`CERBERO_BITE_CORE_TOKEN_FILE`, default `/run/secrets/core_token` nel
container). Non è loggato.
```python
# clients/_base.py — sintesi
class HttpToolClient:
service: str # "deribit", "macro", ...
base_url: str # "http://mcp-deribit:9011"
token: str # bearer
timeout_s: float = 8.0
retry_max: int = 3 # esponenziale 1s/5s/30s
client: httpx.AsyncClient | None # condiviso dal RuntimeContext
async def call(self, tool: str, body: dict | None = None) -> Any: ...
```
Ogni wrapper concreto compone un `HttpToolClient` e ritorna i record
Pydantic consumati direttamente dagli algoritmi `core/`.
## Server MCP usati
### `cerbero-deribit`
Sorgente di tutti i dati di mercato sulle opzioni e canale di
esecuzione: Cerbero Bite invia gli ordini combo direttamente al broker
attraverso questo MCP, senza intermediazioni.
| Tool | Uso | Frequenza |
|---|---|---|
| `environment_info` | Verifica al boot: testnet/mainnet, base_url, max_leverage | Boot + ogni ciclo health |
| `get_ticker(instrument_name)` | Spot proxy via `ETH-PERPETUAL.mark_price`, mid/bid/ask + greche per le leg | Ogni ciclo entry + monitor |
| `get_ticker_batch(instrument_names)` | Quotes in batch per la chain candidata (max 20) | Solo entry |
| `get_dvol(currency="ETH", start_date, end_date)` | Latest DVOL per filtro §2.3 e bias §3.1 | Ogni ciclo entry + monitor |
| `get_instruments(currency, kind="option", expiry_from, expiry_to, min_open_interest)` | Lista strike per il DTE window | Solo entry |
| `get_orderbook(instrument_name, depth=3)` | `book_depth_top3` per liquidity gate | Solo entry |
| `get_historical(instrument, start_date, end_date, resolution)` | Spot 30g fa per bias direzionale + bootstrap return_4h | Entry + monitor (fallback) |
| `get_technical_indicators(instrument, indicators=["adx"], ...)` | ADX(14) per il filtro Iron Condor §3.1 | Solo entry |
| `get_account_summary(currency="USDC")` | Equity Deribit, margin libero (informativo) | Boot + monitor |
| `get_positions(currency="USDC")` | Riconciliazione stato dopo crash | Boot |
| `place_combo_order(legs, side, amount, type, price, label)` | **Esecuzione**: combo atomico via `private/create_combo` + `private/buy/sell` sul combo creato | Entry + monitor (close) |
| `cancel_order(order_id)` | Repricing e annullamenti | Solo monitor |
Note operative:
- Tutti i prezzi e le greche sono restituiti come `float` dal server e
convertiti in `Decimal` ad alta precisione nel wrapper, mai usati
come `float` nel motore decisionale.
- Se la chain risponde con `mark_iv` palesemente fuori range
(es. 7% o 300%) o tutti i `bid == 0` la chiamata viene segnalata come
`McpDataAnomalyError`; l'orchestrator emette un alert e salta il
ciclo.
- L'invio di `place_combo_order` è atomico: la creazione del combo e
l'ordine eseguito sul combo viaggiano in sequenza ma all'interno di
un'unica chiamata MCP, senza esposizione a leg risk.
### `cerbero-hyperliquid`
| Tool | Uso |
|---|---|
| `get_funding_rate(instrument="ETH")` | Funding rate ETH-PERP (annualizzato × 8760) per il filtro entry §2.6 |
### `cerbero-sentiment`
| Tool | Uso |
|---|---|
| `get_cross_exchange_funding(assets=["ETH"])` | Mediana funding annualizzato (Binance/Bybit/OKX 1095, Hyperliquid 8760) per bias direzionale §3.1 |
Le news qualitative non vengono consumate dal decision loop:
Cerbero Bite è deterministico e non interpreta testi liberi.
### `cerbero-macro`
| Tool | Uso |
|---|---|
| `get_macro_calendar(days, country_filter, importance_min)` | Filtro entry §2.5: zero eventi `high` in `country_filter` (default `["US","EU"]`) entro la finestra DTE |
### `cerbero-portfolio`
| Tool | Uso |
|---|---|
| `get_total_portfolio_value(currency="EUR")` | Capitale di base per il sizing engine, dopo conversione in USD |
| `get_holdings()` | Aggregazione manuale di `current_value_eur` per i ticker che contengono `"ETH"`, usata dal filtro §2.7 (`eth_holdings_pct_max`) |
### `cerbero-telegram`
Cerbero Bite usa Telegram in modalità **notify-only**: nessuna conferma
manuale, nessun callback. L'engine apre e chiude le posizioni
automaticamente quando le regole sono soddisfatte; Telegram viene
informato post-fact.
| Tool | Uso |
|---|---|
| `notify(message, priority, tag)` | Alert MEDIUM o messaggi informativi |
| `notify_position_opened(instrument, side, size, strategy, greeks, expected_pnl)` | Notifica di entry placed |
| `notify_position_closed(instrument, realized_pnl, reason)` | Notifica di exit filled |
| `notify_alert(source, message, priority)` | Alert HIGH (kill switch) |
| `notify_system_error(message, component, priority)` | Alert CRITICAL |
## Errori e degradation
| Server fuori uso | Comportamento |
|---|---|
| `cerbero-deribit` | **Hard fail**: senza dati di mercato e canale di esecuzione il ciclo viene saltato; in monitor le posizioni esistenti restano nello stato corrente, alert HIGH e kill switch |
| `cerbero-hyperliquid` | Skip del filtro funding §2.6 con warning; il ciclo prosegue se le altre condizioni sono soddisfatte |
| `cerbero-sentiment` | Bias §3.1 cade su `no_entry` per default (senza funding cross il bias non può fissare la direzione) |
| `cerbero-macro` | Hard fail per il filtro §2.5; senza calendar non si apre |
| `cerbero-portfolio` | Skip dei filtri §2.7 con warning; il sizing usa l'ultimo capitale noto da SQLite |
| `cerbero-telegram` | Skip notifiche post-fact; il ciclo decisionale non viene bloccato (l'engine non aspetta risposte) |
I trigger HIGH e CRITICAL armano il kill switch e propagano un alert
in audit chain.
## Verifica ambiente al boot
All'avvio l'orchestrator (`runtime/orchestrator.boot`) chiama
`cerbero-deribit.environment_info` e confronta il campo `environment`
con `strategy.execution.environment`. Un `mismatch` (per esempio engine
configurato per `testnet` ma server agganciato a `mainnet`) produce un
alert CRITICAL e arma il kill switch prima che qualsiasi ciclo
trading parta. La stessa verifica viene ripetuta dal probe periodico
(ogni 5 minuti) di `runtime/health_check.HealthCheck`.
## Versioning
I server MCP non espongono attualmente un endpoint `get_version()`
formale; il check di compatibilità si limita a `environment_info` per
Deribit e a un round-trip lightweight sui tool read-only degli altri
servizi nel job di health check. Quando i server pubblicheranno il
versionamento esplicito, l'orchestrator confronterà al boot le
versioni con la tabella `EXPECTED_MCP_VERSIONS` e armerà il kill
switch su mismatch.