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:
@@ -8,7 +8,6 @@ from typing import Any
|
||||
|
||||
from fastapi import HTTPException
|
||||
|
||||
from cerbero_mcp.common import indicators as ind
|
||||
from cerbero_mcp.common import microstructure as micro
|
||||
from cerbero_mcp.common import options as opt
|
||||
from cerbero_mcp.common.candles import validate_candles
|
||||
@@ -1602,37 +1601,6 @@ class DeribitClient:
|
||||
"testnet": self.testnet,
|
||||
}
|
||||
|
||||
async def get_technical_indicators(
|
||||
self,
|
||||
instrument: str,
|
||||
indicators: list[str],
|
||||
start_date: str,
|
||||
end_date: str,
|
||||
resolution: str = "1h",
|
||||
) -> dict:
|
||||
historical = await self.get_historical(instrument, start_date, end_date, resolution)
|
||||
candles = historical.get("candles", [])
|
||||
closes = [c["close"] for c in candles]
|
||||
highs = [c["high"] for c in candles]
|
||||
lows = [c["low"] for c in candles]
|
||||
|
||||
result: dict[str, Any] = {}
|
||||
for indicator in indicators:
|
||||
name = indicator.lower()
|
||||
if name == "sma":
|
||||
result["sma"] = ind.sma(closes, 20)
|
||||
elif name == "rsi":
|
||||
result["rsi"] = ind.rsi(closes)
|
||||
elif name == "atr":
|
||||
result["atr"] = ind.atr(highs, lows, closes)
|
||||
elif name == "macd":
|
||||
result["macd"] = ind.macd(closes)
|
||||
elif name == "adx":
|
||||
result["adx"] = ind.adx(highs, lows, closes)
|
||||
else:
|
||||
result[name] = None
|
||||
return result
|
||||
|
||||
# ── Write tools ──────────────────────────────────────────────
|
||||
|
||||
async def place_order(
|
||||
|
||||
Reference in New Issue
Block a user