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:
@@ -15,7 +15,9 @@ testnet venga instradato (deribit `get_ticker BTC-PERPETUAL`).
|
||||
Verifica end-to-end contro Deribit/Hyperliquid (endpoint pubblici):
|
||||
- `get_instruments exchange=deribit` → `fees` e `history_start` popolati live
|
||||
- `get_instruments` fan-out → contribuiscono sia deribit sia hyperliquid
|
||||
- `get_historical` deribit + hyperliquid → candele non vuote, schema uniforme
|
||||
- `get_historical` singolo (deribit, hyperliquid) → candele non vuote
|
||||
- `get_historical` consenso (senza `exchange`) → `sources_used` multipli + `div_pct`
|
||||
- `get_indicators` singolo + consenso → indicatori calcolati
|
||||
- `get_historical exchange=bybit` → `422` (rifiutato a livello schema)
|
||||
|
||||
Variabili di ambiente:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
# Smoke test interfaccia comune /mcp contro un server vivo + upstream reali.
|
||||
# get_instruments e get_historical di Deribit/Hyperliquid sono pubblici, ma il
|
||||
# bearer (testnet o mainnet) e X-Bot-Tag sono comunque richiesti dall'auth.
|
||||
# get_instruments/get_historical/get_indicators di Deribit/Hyperliquid sono
|
||||
# pubblici, ma bearer (testnet o mainnet) e X-Bot-Tag sono comunque richiesti.
|
||||
set -euo pipefail
|
||||
|
||||
PORT="${PORT:-9000}"
|
||||
@@ -40,19 +40,31 @@ post() {
|
||||
|
||||
echo "==> get_instruments exchange=deribit (fees + history_start live)"
|
||||
post "/mcp/tools/get_instruments" '{"exchange":"deribit","currency":"BTC","kind":"future"}' 200 \
|
||||
"assert d['instruments'], 'no instruments'; i=d['instruments'][0]; assert i['exchange']=='deribit'; assert 'fees' in i and 'history_start' in i; print(' ', i['symbol'], i['fees'], i['history_start'])"
|
||||
"assert d['instruments']; i=d['instruments'][0]; assert i['exchange']=='deribit'; assert 'fees' in i and 'history_start' in i; print(' ', i['symbol'], i['fees'], i['history_start'])"
|
||||
|
||||
echo "==> get_instruments fan-out (deribit + hyperliquid)"
|
||||
post "/mcp/tools/get_instruments" '{}' 200 \
|
||||
"exs={i['exchange'] for i in d['instruments']}; assert {'deribit','hyperliquid'} <= exs, exs; print(' venues:', sorted(exs), '| failed:', d['failed_sources'])"
|
||||
"exs={i['exchange'] for i in d['instruments']}; assert {'deribit','hyperliquid'} <= exs, exs; print(' venues:', sorted(exs))"
|
||||
|
||||
echo "==> get_historical deribit BTC-PERPETUAL 1h"
|
||||
echo "==> get_historical SINGLE deribit BTC-PERPETUAL 1h"
|
||||
post "/mcp/tools/get_historical" "{\"exchange\":\"deribit\",\"instrument\":\"BTC-PERPETUAL\",\"interval\":\"1h\",\"start_date\":\"${start}\",\"end_date\":\"${end}\"}" 200 \
|
||||
"assert d['exchange']=='deribit'; assert d['candles'], 'no candles'; c=d['candles'][0]; assert {'timestamp','open','high','low','close','volume'} <= set(c); print(' candles:', len(d['candles']))"
|
||||
"assert d['exchange']=='deribit'; assert d['candles']; c=d['candles'][0]; assert {'timestamp','open','high','low','close','volume'} <= set(c); print(' candles:', len(d['candles']))"
|
||||
|
||||
echo "==> get_historical hyperliquid BTC 1h"
|
||||
echo "==> get_historical SINGLE hyperliquid BTC 1h"
|
||||
post "/mcp/tools/get_historical" "{\"exchange\":\"hyperliquid\",\"instrument\":\"BTC\",\"interval\":\"1h\",\"start_date\":\"${start}\",\"end_date\":\"${end}\"}" 200 \
|
||||
"assert d['exchange']=='hyperliquid'; assert d['candles'], 'no candles'; print(' candles:', len(d['candles']))"
|
||||
"assert d['exchange']=='hyperliquid'; assert d['candles']; print(' candles:', len(d['candles']))"
|
||||
|
||||
echo "==> get_historical CONSENSUS (no exchange) BTC 1h"
|
||||
post "/mcp/tools/get_historical" "{\"instrument\":\"BTC\",\"interval\":\"1h\",\"start_date\":\"${start}\",\"end_date\":\"${end}\"}" 200 \
|
||||
"assert d['exchange'] is None; assert {'deribit','hyperliquid'} <= set(d['sources_used']), d['sources_used']; assert 'div_pct' in d['candles'][0]; print(' sources:', d['sources_used'], '| candles:', len(d['candles']))"
|
||||
|
||||
echo "==> get_indicators SINGLE deribit BTC-PERPETUAL"
|
||||
post "/mcp/tools/get_indicators" "{\"exchange\":\"deribit\",\"instrument\":\"BTC-PERPETUAL\",\"indicators\":[\"rsi\",\"atr\",\"macd\"],\"interval\":\"1h\",\"start_date\":\"${start}\",\"end_date\":\"${end}\"}" 200 \
|
||||
"assert set(d['indicators']) == {'rsi','atr','macd'}; print(' rsi:', d['indicators']['rsi'], '| candles_used:', d['candles_used'])"
|
||||
|
||||
echo "==> get_indicators CONSENSUS BTC"
|
||||
post "/mcp/tools/get_indicators" "{\"instrument\":\"BTC\",\"indicators\":\"rsi,atr\",\"interval\":\"1h\",\"start_date\":\"${start}\",\"end_date\":\"${end}\"}" 200 \
|
||||
"assert d['exchange'] is None; assert 'rsi' in d['indicators']; print(' sources:', d['sources_used'])"
|
||||
|
||||
echo "==> get_historical exchange non supportato → 422"
|
||||
post "/mcp/tools/get_historical" "{\"exchange\":\"bybit\",\"instrument\":\"BTCUSDT\",\"interval\":\"1h\",\"start_date\":\"${start}\",\"end_date\":\"${end}\"}" 422
|
||||
|
||||
Reference in New Issue
Block a user