From ea04dcd9d1c2af23aa5dcdaa6af9422f96b116d1 Mon Sep 17 00:00:00 2001 From: AdrianoDev Date: Fri, 29 May 2026 15:47:10 +0200 Subject: [PATCH] feat(portfolio): metodi Cerbero v2 (get_historical_v2, get_instruments, get_ticker_batch) Co-Authored-By: Claude Sonnet 4.6 --- pyproject.toml | 1 + src/live/cerbero_client.py | 22 ++++++++++++++++++++++ tests/portfolio/__init__.py | 0 tests/portfolio/test_cerbero_v2.py | 18 ++++++++++++++++++ 4 files changed, 41 insertions(+) create mode 100644 tests/portfolio/__init__.py create mode 100644 tests/portfolio/test_cerbero_v2.py diff --git a/pyproject.toml b/pyproject.toml index b77b758..f37f540 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,3 +27,4 @@ dev = [ [tool.pytest.ini_options] testpaths = ["tests"] asyncio_mode = "auto" +markers = ["network: test che richiede Cerbero MCP (rete+token)"] diff --git a/src/live/cerbero_client.py b/src/live/cerbero_client.py index c7a4a68..91676b2 100644 --- a/src/live/cerbero_client.py +++ b/src/live/cerbero_client.py @@ -49,6 +49,28 @@ class CerberoClient: }) return data.get("candles", []) + def get_historical_v2(self, instrument: str, start_date: str, end_date: str, + interval: str = "1h", exchange: str = "deribit") -> list[dict]: + """Endpoint unificato v2: /mcp/tools/get_historical (exchange deribit|hyperliquid). + Stesso shape candele del legacy: [{timestamp(ms), open, high, low, close, volume}].""" + data = self._post("/mcp/tools/get_historical", { + "exchange": exchange, "instrument": instrument, + "interval": interval, "start_date": start_date, "end_date": end_date, + }) + return data.get("candles", []) + + def get_instruments(self, currency: str, kind: str = "future", + exchange: str = "deribit", limit: int = 100) -> list[dict]: + """Enumera gli strumenti reali (v2). Usato per risolvere il naming senza hardcoding.""" + data = self._post("/mcp/tools/get_instruments", { + "exchange": exchange, "currency": currency, "kind": kind, "limit": limit, + }) + return data.get("instruments", data if isinstance(data, list) else []) + + def get_ticker_batch(self, instruments: list[str]) -> dict: + """Prezzi correnti di N strumenti in una sola chiamata (v2, Deribit).""" + return self._post("/mcp-deribit/tools/get_ticker_batch", {"instruments": instruments}) + # --- Account --- def get_account_summary(self, currency: str = "USDC") -> dict: diff --git a/tests/portfolio/__init__.py b/tests/portfolio/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/portfolio/test_cerbero_v2.py b/tests/portfolio/test_cerbero_v2.py new file mode 100644 index 0000000..0e17941 --- /dev/null +++ b/tests/portfolio/test_cerbero_v2.py @@ -0,0 +1,18 @@ +import pytest +from src.live.cerbero_client import CerberoClient + + +@pytest.mark.network +def test_get_historical_v2_shape(): + cli = CerberoClient() + candles = cli.get_historical_v2("BTC-PERPETUAL", "2026-05-25", "2026-05-27", "1h") + assert len(candles) > 0 + c0 = candles[0] + assert {"timestamp", "open", "high", "low", "close", "volume"} <= set(c0) + + +@pytest.mark.network +def test_get_instruments_returns_list(): + cli = CerberoClient() + inst = cli.get_instruments("ETH", "future") + assert isinstance(inst, list) and len(inst) > 0