9a74052dc5
Espone private/get_open_orders_by_currency sul router Deribit (pattern gia' presente per Hyperliquid/IBKR). Serve al reconciler resting di PythagorasGoal: TP/DSL attesi dai libri vs ordini realmente in book (caso MR02_BTC 2026-06-12: TP resting fillato di notte + disaster-SL sparito, scoperti solo al close sim). NB: per i trigger untriggered interrogare anche type='trigger_all' e fare merge per order_id. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
369 lines
14 KiB
Markdown
369 lines
14 KiB
Markdown
# Cerbero MCP — API Reference (V2.0.0)
|
|
|
|
Documento di riferimento completo per tutti gli endpoint HTTP e i tool MCP
|
|
esposti dal container `cerbero-mcp`. Generato dall'analisi diretta dei
|
|
router FastAPI in `src/cerbero_mcp/routers/`.
|
|
|
|
> **Nota V2** — Bybit e Alpaca sono stati ritirati dalla superficie API
|
|
> (codice archiviato in `old/`). Gli exchange di trading attivi sono
|
|
> **Deribit**, **Hyperliquid** e **IBKR**; **Macro** e **Sentiment** restano
|
|
> data-provider read-only.
|
|
|
|
---
|
|
|
|
## 1. Autenticazione
|
|
|
|
Tutte le chiamate ai namespace `/mcp*` richiedono:
|
|
|
|
| Header | Valore | Note |
|
|
|---|---|---|
|
|
| `Authorization` | `Bearer <TOKEN>` | `TESTNET_TOKEN` → upstream testnet · `MAINNET_TOKEN` → upstream live · token sconosciuto → `401` |
|
|
| `X-Bot-Tag` | stringa ≤ 64 char | identifica il bot chiamante, loggato nell'audit · mancante → `400` |
|
|
|
|
Gli endpoint pubblici (`/health`, `/apidocs`, `/openapi.json`) non
|
|
richiedono auth. L'endpoint `/admin/audit` richiede bearer ma **non**
|
|
richiede `X-Bot-Tag`.
|
|
|
|
---
|
|
|
|
## 2. Endpoint pubblici
|
|
|
|
| Path | Metodo | Descrizione |
|
|
|---|---|---|
|
|
| `/health` | GET | Liveness — sempre `200` finché il processo è vivo |
|
|
| `/health/ready` | GET | Readiness — itera i client registry, status `ready` / `degraded` / `not_ready`. Forza `503` se `READY_FAILS_ON_DEGRADED=true` |
|
|
| `/apidocs` | GET | Swagger UI interattiva |
|
|
| `/openapi.json` | GET | Schema OpenAPI 3.1 |
|
|
|
|
---
|
|
|
|
## 3. Endpoint admin
|
|
|
|
| Path | Metodo | Descrizione |
|
|
|---|---|---|
|
|
| `/admin/audit` | GET | Query del JSONL `AUDIT_LOG_FILE`. Filtri: `from`, `to`, `actor`, `exchange`, `action`, `bot_tag`, `limit` (default 1000, max 10000) |
|
|
| `/admin/ibkr/rotate-keys/confirm?env=` | POST | Swap atomico chiavi IBKR con auto-rollback su validazione fallita |
|
|
|
|
---
|
|
|
|
## 4. Namespace MCP — panoramica
|
|
|
|
| Namespace | Tool | Tipo | Note |
|
|
|---|---|---|---|
|
|
| `/mcp/tools/*` | 3 | **interfaccia comune** | `get_instruments` + `get_historical` + `get_indicators` (single exchange o consensus) |
|
|
| `/mcp-deribit/tools/*` | 31 | exchange (options-first) | DVOL, GEX, dealer gamma, spread payoff |
|
|
| `/mcp-hyperliquid/tools/*` | 15 | exchange (perp DEX) | L1 signing, leverage cap |
|
|
| `/mcp-ibkr/tools/*` | 24 | exchange (multi-asset broker) | OAuth 1.0a, streaming WS, bracket/OCO/OTO |
|
|
| `/mcp-macro/tools/*` | 11 | data provider (read-only) | yields, FRED, COT |
|
|
| `/mcp-sentiment/tools/*` | 9 | data provider (read-only) | news, social, funding cross-exchange |
|
|
|
|
`get_instruments`, `get_historical` e `get_indicators` vivono **solo**
|
|
sull'interfaccia comune `/mcp` (non più per-exchange). I restanti tool
|
|
per-exchange (ticker, ordini, analytics options, …) restano sui rispettivi
|
|
router `/mcp-{exchange}`.
|
|
|
|
---
|
|
|
|
## 5. `/mcp/tools/*` — interfaccia comune (raccomandata)
|
|
|
|
Interfaccia unica trasversale agli exchange integrati: il **campo `exchange`
|
|
è dentro ogni risultato**, non nel path. Exchange supportati: `deribit`,
|
|
`hyperliquid`.
|
|
|
|
### `get_instruments` — schema strumenti uniforme
|
|
|
|
Request body:
|
|
|
|
| Campo | Tipo | Default | Note |
|
|
|---|---|---|---|
|
|
| `exchange` | `"deribit"\|"hyperliquid"` \| null | `null` | se omesso → fan-out su tutti gli exchange integrati |
|
|
| `currency` | str | `"BTC"` | filtro Deribit |
|
|
| `kind` | str \| null | `"future"` | filtro Deribit (`future`/`option`/`spot`) |
|
|
| `expiry_from` / `expiry_to` | str \| null | `null` | filtro Deribit (data scadenza) |
|
|
| `strike_min` / `strike_max` | float \| null | `null` | filtro Deribit (opzioni) |
|
|
| `min_open_interest` | float \| null | `null` | filtro Deribit |
|
|
| `offset` / `limit` | int | `0` / `100` | paginazione Deribit |
|
|
|
|
I filtri/paginazione si applicano a **Deribit**; gli exchange che elencano
|
|
tutto (es. Hyperliquid `get_markets`) li ignorano. Ogni elemento di
|
|
`instruments[]` ha **schema uniforme**:
|
|
|
|
```json
|
|
{
|
|
"exchange": "deribit",
|
|
"symbol": "BTC-PERPETUAL",
|
|
"asset_class": "crypto",
|
|
"type": "perpetual", // perpetual | future | option | spot
|
|
"fees": {"maker": 0.0, "taker": 0.0005}, // null se l'exchange non lo espone
|
|
"history_start": "2018-08-13", // data inizio storico, null se ignota
|
|
"tick_size": 0.5,
|
|
"native": { /* campi specifici dell'exchange, lossless */ }
|
|
}
|
|
```
|
|
|
|
Risposta: `{ "instruments": [...], "failed_sources": [{exchange, error}],
|
|
"meta": { "deribit": {total, offset, limit, has_more} } }`. Il blocco `meta`
|
|
riporta la paginazione per-sorgente quando disponibile (oggi: Deribit).
|
|
|
|
> **Copertura `fees` / `history_start`** — popolati live dall'upstream dove
|
|
> disponibili. Oggi: **Deribit** li espone (commissioni maker/taker +
|
|
> `creation_timestamp` → `history_start`); **Hyperliquid** ha fee a livello
|
|
> account e nessuna data di listing per-strumento → entrambi `null`.
|
|
|
|
### `get_historical` — unica chiamata storica comune
|
|
|
|
`get_historical` esiste **solo qui** (non più per-exchange). Request body:
|
|
|
|
| Campo | Tipo | Default | Note |
|
|
|---|---|---|---|
|
|
| `exchange` | `"deribit"\|"hyperliquid"` \| null | `null` | set → singolo exchange · omesso → **consenso** multi-exchange |
|
|
| `instrument` | str | — | simbolo *nativo* (modalità singola) o *canonico* `BTC/ETH/SOL` (consenso) |
|
|
| `interval` | str | `"1h"` | `1m`/`5m`/`15m`/`1h`/`4h`/`1d` |
|
|
| `start_date` | str | — | `YYYY-MM-DD` o ISO datetime (UTC) |
|
|
| `end_date` | str | — | idem |
|
|
| `asset_class` | str | `"crypto"` | routing del consenso (solo se `exchange` omesso) |
|
|
|
|
- **Singolo** (`exchange` valorizzato) → `{ exchange, instrument, interval, candles, sources_used:[exchange] }`.
|
|
- **Consenso** (`exchange` omesso) → fan-out agli exchange che supportano il
|
|
simbolo + merge per-bar: `{ exchange:null, instrument, asset_class, interval,
|
|
candles, sources_used, failed_sources }`. Ogni bar consenso porta `sources`
|
|
(n. exchange) e `div_pct = (max-min)/median` come quality gate. Se *tutti*
|
|
gli upstream falliscono → `502` retryable.
|
|
|
|
Tutte le candele usano la chiave uniforme
|
|
`candles: [{timestamp(ms), open, high, low, close, volume}]`.
|
|
|
|
> **Semantica `start_date`/`end_date`** (UTC). Date nude `YYYY-MM-DD`:
|
|
> `start_date` = `00:00:00`, `end_date` = `23:59:59.999` dello stesso giorno
|
|
> (giorno intero incluso → `end_date=oggi` dà l'intraday fino all'ultima candela
|
|
> chiusa). Timestamp con orario (`2026-05-28T14:00:00`) sono onorati così come
|
|
> sono (naive = UTC). Range ampi su Deribit sono paginati internamente (no cap
|
|
> ~5000), così `start_date` è sempre rispettato.
|
|
|
|
### `get_indicators` — indicatori sulla stessa serie
|
|
|
|
Stessa selezione sorgente di `get_historical` (single o consensus); calcola
|
|
indicatori tecnici sulle candele risultanti. Request body: i campi di
|
|
`get_historical` più `indicators` (lista o stringa CSV, es. `["rsi","atr"]` o
|
|
`"rsi,atr,macd"`; default `["rsi","atr","macd","adx"]`). Supportati:
|
|
`sma`, `rsi`, `atr`, `macd`, `adx` (nomi ignoti → `null`).
|
|
|
|
Risposta: `{ exchange, instrument, interval, indicators:{...}, candles_used,
|
|
sources_used }` (+ `failed_sources` in modalità consenso).
|
|
|
|
---
|
|
|
|
## 6. `/mcp-deribit/tools/*`
|
|
|
|
### Info
|
|
- `is_testnet` — flag ambiente corrente
|
|
- `environment_info` — stringa diagnostica completa
|
|
|
|
### Market data
|
|
- `get_ticker`, `get_ticker_batch`
|
|
- `get_orderbook`, `get_orderbook_imbalance`
|
|
- `get_trade_history`
|
|
|
|
> Lista strumenti, storico OHLCV e indicatori tecnici NON sono più qui: usa
|
|
> `/mcp/tools/get_instruments`, `/mcp/tools/get_historical` e
|
|
> `/mcp/tools/get_indicators` (sezione 5) con `exchange="deribit"`.
|
|
|
|
### Account
|
|
- `get_positions`
|
|
- `get_account_summary`
|
|
- `get_open_orders` — ordini aperti (`currency`, `kind?`, `type` default `all`;
|
|
per i trigger non scattati interrogare anche `type="trigger_all"` e fare
|
|
merge per `order_id`)
|
|
|
|
### Options analytics
|
|
- `get_dvol`, `get_dvol_history`
|
|
- `get_gex`, `get_dealer_gamma_profile`
|
|
- `get_vanna_charm`
|
|
- `get_oi_weighted_skew`, `get_smile_asymmetry`, `get_atm_vs_wings_vol`
|
|
- `get_pc_ratio`, `get_skew_25d`, `get_term_structure`
|
|
- `get_iv_rank`, `get_realized_vol`
|
|
- `find_by_delta`, `calculate_spread_payoff`
|
|
|
|
### Technicals
|
|
- `run_backtest`
|
|
|
|
### Write (richiede leverage cap)
|
|
- `place_order`, `place_combo_order`
|
|
- `cancel_order`
|
|
- `set_stop_loss`, `set_take_profit`
|
|
- `close_position`
|
|
|
|
---
|
|
|
|
## 7. `/mcp-hyperliquid/tools/*`
|
|
|
|
### Info
|
|
- `environment_info`
|
|
|
|
### Market data
|
|
- `get_markets`, `get_ticker`, `get_orderbook`
|
|
- `get_trade_history`
|
|
- `get_funding_rate`, `basis_spot_perp`
|
|
|
|
> Storico e indicatori: usa `/mcp/tools/get_historical` e
|
|
> `/mcp/tools/get_indicators` (sezione 5) con `exchange="hyperliquid"`.
|
|
|
|
### Account
|
|
- `get_positions`, `get_account_summary`, `get_open_orders`
|
|
|
|
### Write (L1 signing + leverage cap)
|
|
- `place_order`, `cancel_order`
|
|
- `set_stop_loss`, `set_take_profit`
|
|
- `close_position`
|
|
|
|
---
|
|
|
|
## 8. `/mcp-ibkr/tools/*`
|
|
|
|
Auth via OAuth 1.0a Self-Service con minting di session token
|
|
unattended. Setup one-time per ambiente (paper + live) — vedi sezione
|
|
"IBKR Setup" del README.
|
|
|
|
> IBKR non è ancora integrato nell'interfaccia comune `/mcp` (il suo endpoint
|
|
> bars usa un `period` relativo invece di `(start, end)`); usare il router
|
|
> dedicato `/mcp-ibkr`.
|
|
|
|
### Info / clock
|
|
- `environment_info`, `get_clock`
|
|
|
|
### Account
|
|
- `get_account`, `get_positions`
|
|
- `get_open_orders`, `get_activities`
|
|
|
|
### Market data
|
|
- `get_ticker`, `get_bars`, `get_snapshot`
|
|
- `get_option_chain`, `search_contracts`
|
|
|
|
### Streaming (WebSocket singleton)
|
|
- `get_tick`, `get_depth`
|
|
- `subscribe_tick`, `unsubscribe`
|
|
|
|
### Write
|
|
- `place_order`, `amend_order`
|
|
- `cancel_order`, `cancel_all_orders`
|
|
- `close_position`, `close_all_positions`
|
|
|
|
### Complex orders
|
|
- `place_bracket_order` — entry + TP + SL atomico
|
|
- `place_oco_order` — One-Cancels-Other (OCA group)
|
|
- `place_oto_order` — One-Triggers-Other (parent → child)
|
|
|
|
---
|
|
|
|
## 9. `/mcp-macro/tools/*` (read-only)
|
|
|
|
| Tool | Sorgente |
|
|
|---|---|
|
|
| `get_economic_indicators` | FRED + Yahoo |
|
|
| `get_macro_calendar` | Finnhub + impact heuristic |
|
|
| `get_market_overview` | mix Yahoo + Deribit DVOL |
|
|
| `get_asset_price` | Yahoo Finance |
|
|
| `get_treasury_yields` | US Treasury XML |
|
|
| `get_equity_futures` | Yahoo |
|
|
| `get_yield_curve_slope` | derivato da treasury yields |
|
|
| `get_breakeven_inflation` | FRED (T10YIE / T5YIE) |
|
|
| `get_cot_tff` | CFTC TFF report |
|
|
| `get_cot_disaggregated` | CFTC disaggregated report |
|
|
| `get_cot_extreme_positioning` | percentili COT (gate ±5%) |
|
|
|
|
---
|
|
|
|
## 10. `/mcp-sentiment/tools/*` (read-only)
|
|
|
|
| Tool | Fonte |
|
|
|---|---|
|
|
| `get_crypto_news` | CryptoPanic + CoinDesk + CryptoCompare + Messari (deduped) |
|
|
| `get_world_news` | aggregato generalista |
|
|
| `get_social_sentiment` | LunarCrush + Fear&Greed Index |
|
|
| `get_funding_rates` | per-asset multi-exchange |
|
|
| `get_cross_exchange_funding` | snapshot multi-asset multi-venue |
|
|
| `get_funding_arb_spread` | spread arbitraggio funding |
|
|
| `get_oi_history` | open interest serie storica |
|
|
| `get_liquidation_heatmap` | heatmap liquidazioni |
|
|
| `get_cointegration_pairs` | screening coppie cointegrate |
|
|
|
|
> Le fonti di funding/OI includono endpoint pubblici multi-venue (Binance,
|
|
> Bybit, OKX, Hyperliquid): qui Bybit è una **sorgente dati pubblica**, non il
|
|
> client di trading ritirato.
|
|
|
|
---
|
|
|
|
## 11. Observability
|
|
|
|
### Request log (`mcp.request`)
|
|
Una riga JSON per richiesta con: `request_id`, `method`, `path`,
|
|
`status_code`, `duration_ms`, `actor`, `bot_tag`, `exchange`, `tool`,
|
|
`client_ip`, `user_agent`.
|
|
|
|
### Audit log (`mcp.audit`)
|
|
Persistito su `AUDIT_LOG_FILE` (JSONL) per le operazioni write.
|
|
Rotazione configurabile via `AUDIT_LOG_BACKUP_DAYS`.
|
|
|
|
### Correlation
|
|
Lo stesso `request_id` appare in `mcp.request`, `mcp.audit` e
|
|
nell'envelope di errore restituito al client.
|
|
|
|
### `data_timestamp`
|
|
Ogni risposta JSON sotto `/tools/*` riceve dal middleware un campo
|
|
`data_timestamp` (ISO UTC) al top level — oltre all'header `X-Data-Timestamp`.
|
|
|
|
---
|
|
|
|
## 12. Esempio chiamata
|
|
|
|
```bash
|
|
# Singolo exchange: storico Deribit
|
|
curl -X POST http://localhost:9000/mcp/tools/get_historical \
|
|
-H "Authorization: Bearer $MAINNET_TOKEN" \
|
|
-H "X-Bot-Tag: scanner-alpha-prod" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"exchange":"deribit","instrument":"BTC-PERPETUAL","interval":"1h","start_date":"2026-05-01","end_date":"2026-05-29"}'
|
|
|
|
# Consenso multi-exchange: ometti "exchange", usa il simbolo canonico
|
|
curl -X POST http://localhost:9000/mcp/tools/get_historical \
|
|
-H "Authorization: Bearer $MAINNET_TOKEN" -H "X-Bot-Tag: scanner-alpha-prod" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"instrument":"BTC","interval":"1h","start_date":"2026-05-01","end_date":"2026-05-29"}'
|
|
```
|
|
|
|
Per lo schema completo dei body di richiesta e risposta:
|
|
<http://localhost:9000/apidocs>.
|
|
|
|
---
|
|
|
|
## 13. Discovery strumenti & schemi candele
|
|
|
|
Schemi verificati sulle risposte live. `get_historical` ritorna la chiave
|
|
uniforme `candles: [{timestamp(ms), open, high, low, close, volume}]`.
|
|
|
|
### Tool dati comuni (`/mcp`)
|
|
| Tool | Request body | Risposta (campi principali) |
|
|
|---|---|---|
|
|
| `get_instruments` | `{exchange?, currency:"BTC", kind:"future", expiry_from?, expiry_to?, strike_min?, strike_max?, min_open_interest?, offset:0, limit:100}` | `instruments[]` uniforme: `exchange`, `symbol`, `asset_class`, `type`, `fees`, `history_start`, `tick_size`, `native` · `failed_sources[]` · `meta:{deribit:{total,offset,limit,has_more}}` |
|
|
| `get_historical` | `{exchange?, instrument, interval, start_date, end_date, asset_class?}` | single: `{exchange, instrument, interval, candles, sources_used}` · consensus (no `exchange`): `+ div_pct`/`sources` per bar, `failed_sources` |
|
|
| `get_indicators` | come `get_historical` + `indicators:["rsi","atr",…]` | `{exchange, instrument, interval, indicators:{…}, candles_used, sources_used}` |
|
|
|
|
Sorgenti normalizzate dentro `get_instruments`: Deribit espone `name`,
|
|
`expiry`, `option_type`, `tick_size`, `min_trade_amount`, `maker_commission`,
|
|
`taker_commission`, `creation_timestamp` (→ `fees`/`history_start`); Hyperliquid
|
|
`get_markets` espone `{asset, mark_price, funding_rate, open_interest,
|
|
volume_24h, max_leverage}`. Ogni risposta `/tools/*` riceve inoltre
|
|
`data_timestamp` dal middleware.
|
|
|
|
### Convenzione simboli Deribit
|
|
- **BTC/ETH** → perpetui *inverse*: `BTC-PERPETUAL`, `ETH-PERPETUAL`
|
|
- **Altcoin** → perpetui *lineari USDC*: `<COIN>_USDC-PERPETUAL` (es. `SOL_USDC-PERPETUAL`), storia da ~2022
|
|
- Esistono anche `BTC_USDC-PERPETUAL` / `ETH_USDC-PERPETUAL` (varianti lineari)
|
|
- ⚠️ `LTC-PERPETUAL` / `ADA-PERPETUAL` (inverse) **non esistono** (0 candele); `SOL-PERPETUAL` è elencato ma è un contratto vuoto/stale (prezzo ~9.6 vs SOL reale ~82) → usare `SOL_USDC-PERPETUAL`
|
|
|
|
### Nota testnet
|
|
Con `TESTNET_TOKEN` le risposte includono `"testnet": true` (ticker,
|
|
get_instruments, …) e i prezzi possono divergere dal mainnet. Su testnet
|
|
alcuni feed sono inaffidabili: validare la congruenza cross-exchange prima di
|
|
usare i dati per backtest/trading.
|