refactor(V2): get_historical & get_indicators are common-only on /mcp

Consolidate the cross-cutting data tools onto the unified interface and
remove their per-exchange duplicates.

- /mcp/tools/get_historical: single call, `exchange` now optional. Set →
  that venue's candles (native symbol); omitted → cross-exchange consensus
  (canonical symbol, median OHLC + div_pct). Folds in the former
  /mcp-cross consensus, whose router is deleted.
- /mcp/tools/get_indicators: new common tool computing sma/rsi/atr/macd/adx
  over the single-or-consensus series. Computation centralized in
  common/indicators.py::compute_indicators (was duplicated per exchange).
- Remove get_historical from /mcp-deribit and /mcp-hyperliquid; remove
  get_technical_indicators (deribit) and get_indicators (hyperliquid),
  including the now-dead client methods, Req schemas and tool wrappers.
  The client get_historical METHODS stay (used by the unified dispatch).

Tests: rewrite cross tests into test_unified (instruments, historical
single + consensus + failures, indicators single + consensus); drop the
old CrossClient test; tighten app-boot surface assertions (/mcp owns the
data tools; no /mcp-cross, no per-exchange historical/indicators).

Docs: API_REFERENCE / README / CLAUDE updated; smoke run_unified.sh now
covers consensus + indicators.

324 passed, ruff clean. Verified live against Deribit/Hyperliquid.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Adriano
2026-05-29 10:51:21 +00:00
parent 2272d5520b
commit 6faf21369d
20 changed files with 505 additions and 708 deletions
+30 -30
View File
@@ -13,8 +13,9 @@ sul token bearer fornito dal client.
read-only (Macro, Sentiment). Bybit e Alpaca sono stati ritirati dalla
superficie API in V2 (codice archiviato in `old/`)
- **Interfaccia comune `/mcp`** trasversale agli exchange: `get_instruments`
con schema uniforme (ogni elemento porta `exchange`, `fees`,
`history_start`) e `get_historical` per-exchange selezionabile
(schema uniforme con `exchange`/`fees`/`history_start`), `get_historical` e
`get_indicators` — singolo exchange o consenso multi-exchange. Storico e
indicatori vivono **solo** qui, non più per-exchange
- **Switch testnet/mainnet per-request** tramite header
`Authorization: Bearer <TOKEN>`: lo stesso container serve entrambi gli
ambienti senza riavvii
@@ -23,9 +24,9 @@ sul token bearer fornito dal client.
override-abili tramite variabili dedicate (`DERIBIT_URL_*`,
`HYPERLIQUID_URL_*`, `IBKR_URL_*`)
- **Documentazione interattiva** OpenAPI/Swagger esposta a `/apidocs`
- **Endpoint cross-exchange a consenso** (`/mcp-cross/tools/get_historical`):
fan-out agli exchange che supportano (symbol, asset_class) e consensus
per-bar (mediana OHLC + `div_pct` + `sources`)
- **Consenso multi-exchange** integrato in `/mcp/tools/get_historical`: ometti
`exchange` per il fan-out e il merge per-bar (mediana OHLC + `div_pct` +
`sources`)
- **Qualità verificata**: 323 test (unit + integration + smoke), mypy
pulito, ruff pulito
@@ -92,13 +93,13 @@ non è richiesto sugli endpoint pubblici (`/health`, `/apidocs`,
| `GET /apidocs` | Swagger UI (no auth) |
| `GET /openapi.json` | Schema OpenAPI 3.1 (no auth) |
| `POST /mcp/tools/get_instruments` | Lista strumenti uniforme cross-exchange (deribit, hyperliquid) |
| `POST /mcp/tools/get_historical` | Storico di un singolo exchange selezionabile |
| `POST /mcp/tools/get_historical` | Storico comune: singolo exchange o consenso multi-exchange |
| `POST /mcp/tools/get_indicators` | Indicatori tecnici sulla stessa serie (single o consenso) |
| `POST /mcp-deribit/tools/{tool}` | Tool exchange Deribit |
| `POST /mcp-hyperliquid/tools/{tool}` | Tool exchange Hyperliquid |
| `POST /mcp-ibkr/tools/{tool}` | Tool exchange Interactive Brokers |
| `POST /mcp-macro/tools/{tool}` | Tool macro/market data |
| `POST /mcp-sentiment/tools/{tool}` | Tool sentiment/news |
| `POST /mcp-cross/tools/get_historical` | Storico aggregato cross-exchange con consensus + divergenza |
| `GET /admin/audit` | Query dell'audit log JSONL (bearer richiesto, no X-Bot-Tag) |
## Observability
@@ -177,14 +178,14 @@ Tecnici (`sma`, `rsi`, `macd`, `atr`, `adx`), volatilità (`vol_cone`,
### Deribit
DVOL, GEX, P/C ratio, skew_25d, term_structure, iv_rank, realized_vol,
indicatori tecnici, find_by_delta, calculate_spread_payoff,
get_dealer_gamma_profile, get_vanna_charm, get_oi_weighted_skew,
get_smile_asymmetry, get_atm_vs_wings_vol, get_orderbook_imbalance,
place_combo_order.
find_by_delta, calculate_spread_payoff, get_dealer_gamma_profile,
get_vanna_charm, get_oi_weighted_skew, get_smile_asymmetry,
get_atm_vs_wings_vol, get_orderbook_imbalance, run_backtest, place_combo_order.
(Storico/indicatori → `/mcp`.)
### Hyperliquid
Account summary, positions, orderbook, historical, indicators, funding
rate, basis spot/perp, place_order, set_stop_loss, set_take_profit.
Account summary, positions, orderbook, funding rate, basis spot/perp,
place_order, set_stop_loss, set_take_profit. (Storico/indicatori → `/mcp`.)
### IBKR (Interactive Brokers)
Account, positions, activities, ticker, bars, snapshot, option chain,
@@ -204,24 +205,23 @@ OI history, get_funding_arb_spread, get_liquidation_heatmap,
get_cointegration_pairs.
### Unified (`/mcp`) — interfaccia comune
`get_instruments` ritorna una lista strumenti **uniforme**: ogni elemento
porta in sé `exchange`, `fees` (maker/taker, popolati live da Deribit, `null`
dove l'exchange non li espone per-strumento), `history_start` (data inizio
storico, live da Deribit), oltre a `type`, `tick_size` e un blocco `native`
lossless. Con `exchange` opzionale filtra una singola sorgente; se omesso fa
fan-out su tutti gli exchange integrati. `get_historical` è generalizzato a
`{exchange, instrument, interval, start_date, end_date}` e ritorna le candele
del **singolo exchange scelto**. Exchange supportati: `deribit`, `hyperliquid`
(IBKR non ancora integrato — usa `/mcp-ibkr`).
Espone gli **unici** tool dati trasversali (storico e indicatori vivono solo
qui, non per-exchange). Exchange supportati: `deribit`, `hyperliquid` (IBKR non
ancora integrato — usa `/mcp-ibkr`).
### Cross (storico a consenso)
`get_historical` aggrega le candele dello stesso simbolo da tutti gli
exchange che lo supportano e ritorna una serie consensus: la chiusura è
la mediana, `sources` è il numero di exchange che hanno contribuito al
bar e `div_pct = (max-min)/median` segnala il disaccordo tra fonti — un
quality gate per i bot. Crypto: BTC/ETH via Hyperliquid + Deribit, SOL via
Hyperliquid. In caso di fallimento parziale ritorna i dati disponibili più
`failed_sources`; se *tutti* gli upstream falliscono → HTTP 502 retryable.
- **`get_instruments`** — lista strumenti **uniforme**: ogni elemento porta in
sé `exchange`, `fees` (maker/taker, live da Deribit, `null` dove l'exchange
non li espone), `history_start` (data inizio storico, live da Deribit),
`type`, `tick_size` e un blocco `native` lossless. `exchange` opzionale →
filtra una sorgente; se omesso fan-out su tutti.
- **`get_historical`** — `{exchange?, instrument, interval, start_date,
end_date}`. Con `exchange` ritorna il **singolo** exchange; **omettendolo**
fa il **consenso** multi-exchange (mediana OHLC, `sources`,
`div_pct=(max-min)/median` come quality gate) usando il simbolo canonico
(BTC/ETH via Hyperliquid+Deribit, SOL via Hyperliquid). Fallimento parziale →
`failed_sources`; tutti gli upstream giù → HTTP 502 retryable.
- **`get_indicators`** — stessa selezione sorgente; calcola sma/rsi/atr/macd/adx
sulle candele risultanti.
## Deploy su VPS con Traefik