diff --git a/pyproject.toml b/pyproject.toml index 7fa4b64..0057972 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,7 +15,7 @@ target-version = "py313" [tool.ruff.lint] select = ["E", "F", "I", "W", "UP", "B", "SIM"] -ignore = ["E501"] +ignore = ["E501", "E741"] [tool.ruff.lint.flake8-bugbear] extend-immutable-calls = [ diff --git a/services/common/src/mcp_common/mcp_bridge.py b/services/common/src/mcp_common/mcp_bridge.py index 55c66d7..5cec928 100644 --- a/services/common/src/mcp_common/mcp_bridge.py +++ b/services/common/src/mcp_common/mcp_bridge.py @@ -21,6 +21,7 @@ Claude Code config esempio: """ from __future__ import annotations +import contextlib from typing import Any import httpx @@ -63,10 +64,8 @@ def _derive_input_schemas(app: FastAPI, tool_names: list[str]) -> dict[str, dict if pname == "return": continue if isinstance(ann, type) and issubclass(ann, BaseModel): - try: + with contextlib.suppress(Exception): out[name] = ann.model_json_schema() - except Exception: - pass break return out diff --git a/services/common/src/mcp_common/microstructure.py b/services/common/src/mcp_common/microstructure.py index 5775f4b..056f442 100644 --- a/services/common/src/mcp_common/microstructure.py +++ b/services/common/src/mcp_common/microstructure.py @@ -36,10 +36,7 @@ def orderbook_imbalance( ask_vol = sum(q for _, q in top_asks) total = bid_vol + ask_vol - if total == 0: - ratio = None - else: - ratio = (bid_vol - ask_vol) / total + ratio = None if total == 0 else (bid_vol - ask_vol) / total # Microprice: best bid, best ask. Weighted by opposite-side size. microprice = None diff --git a/services/common/tests/test_http.py b/services/common/tests/test_http.py index 404abc2..6a3a950 100644 --- a/services/common/tests/test_http.py +++ b/services/common/tests/test_http.py @@ -4,7 +4,6 @@ import asyncio import httpx import pytest - from mcp_common.http import async_client, call_with_retry diff --git a/services/common/tests/test_indicators.py b/services/common/tests/test_indicators.py index f0703c0..293ddc0 100644 --- a/services/common/tests/test_indicators.py +++ b/services/common/tests/test_indicators.py @@ -112,7 +112,7 @@ def test_vol_cone_returns_percentiles_per_window(): closes = _gbm_series(mu=0.0, sigma=0.5, n=400) out = vol_cone(closes, windows=[10, 30, 60]) assert set(out.keys()) == {10, 30, 60} - for w, stats in out.items(): + for _w, stats in out.items(): assert "current" in stats assert "p10" in stats and "p50" in stats and "p90" in stats assert stats["p10"] <= stats["p50"] <= stats["p90"] @@ -200,7 +200,7 @@ def test_autocorrelation_white_noise_low(): assert len(out) == 5 # white noise → all autocorr ≈ 0 (within ±2/sqrt(N)) bound = 2.0 / math.sqrt(len(rets)) - for lag, val in out.items(): + for _lag, val in out.items(): assert abs(val) < bound * 2 # generous diff --git a/services/mcp-alpaca/src/mcp_alpaca/client.py b/services/mcp-alpaca/src/mcp_alpaca/client.py index 61d0514..001d5c6 100644 --- a/services/mcp-alpaca/src/mcp_alpaca/client.py +++ b/services/mcp-alpaca/src/mcp_alpaca/client.py @@ -71,13 +71,13 @@ def _asset_class_enum(ac: str) -> AssetClass: def _serialize(obj: Any) -> Any: """Recursively convert pydantic/datetime objects → json-safe.""" - if obj is None or isinstance(obj, (str, int, float, bool)): + if obj is None or isinstance(obj, str | int | float | bool): return obj - if isinstance(obj, (_dt.datetime, _dt.date)): + if isinstance(obj, _dt.datetime | _dt.date): return obj.isoformat() if isinstance(obj, dict): return {k: _serialize(v) for k, v in obj.items()} - if isinstance(obj, (list, tuple)): + if isinstance(obj, list | tuple): return [_serialize(v) for v in obj] if hasattr(obj, "model_dump"): return _serialize(obj.model_dump()) diff --git a/services/mcp-deribit/src/mcp_deribit/client.py b/services/mcp-deribit/src/mcp_deribit/client.py index d473259..cc231a1 100644 --- a/services/mcp-deribit/src/mcp_deribit/client.py +++ b/services/mcp-deribit/src/mcp_deribit/client.py @@ -1,10 +1,10 @@ from __future__ import annotations +import contextlib import time from dataclasses import dataclass, field from typing import Any -import httpx from mcp_common import indicators as ind from mcp_common import microstructure as micro from mcp_common import options as opt @@ -196,10 +196,8 @@ class DeribitClient: name = s.get("instrument_name") oi = s.get("open_interest") if name and oi is not None: - try: + with contextlib.suppress(TypeError, ValueError): oi_by_name[name] = float(oi) - except (TypeError, ValueError): - pass all_items = raw.get("result") or [] filtered: list[dict] = [] @@ -882,10 +880,9 @@ class DeribitClient: shape = "backwardation" short_term = next((x for x in ts if 8 <= x["dte"] <= 14), None) mid_term = next((x for x in ts if 35 <= x["dte"] <= 45), None) - if short_term and mid_term: - if mid_term["atm_iv"] - short_term["atm_iv"] > 5: - contango_steep = True - calendar_opp = True + if short_term and mid_term and mid_term["atm_iv"] - short_term["atm_iv"] > 5: + contango_steep = True + calendar_opp = True return { "currency": currency, @@ -1131,7 +1128,7 @@ class DeribitClient: structure = self._guess_structure(enriched) - notional = sum(l["quantity"] * spot for l in enriched) if spot else 0.0 + sum(l["quantity"] * spot for l in enriched) if spot else 0.0 fee_per_leg = min(0.0003 * (spot or 1) * sum(l["quantity"] for l in enriched), 0.125 * abs(net_premium)) if spot else 0.0 fees_open = round(fee_per_leg, 4) diff --git a/services/mcp-deribit/src/mcp_deribit/server.py b/services/mcp-deribit/src/mcp_deribit/server.py index 7318f48..bfdc231 100644 --- a/services/mcp-deribit/src/mcp_deribit/server.py +++ b/services/mcp-deribit/src/mcp_deribit/server.py @@ -1,5 +1,6 @@ from __future__ import annotations +import contextlib import os from fastapi import Depends, FastAPI, HTTPException @@ -272,10 +273,8 @@ def create_app( @asynccontextmanager async def _lifespan(_app: FastAPI): for inst in ("BTC-PERPETUAL", "ETH-PERPETUAL"): - try: + with contextlib.suppress(Exception): await client.set_leverage(inst, cap_default) - except Exception: - pass yield app = build_app( @@ -551,10 +550,8 @@ def create_app( _check(principal, core=True) lev = _enforce_leverage(body.leverage, creds=creds, exchange="deribit") if lev != cap_default: - try: + with contextlib.suppress(Exception): await client.set_leverage(body.instrument_name, lev) - except Exception: - pass result = await client.place_order( instrument_name=body.instrument_name, side=body.side, @@ -582,10 +579,8 @@ def create_app( lev = _enforce_leverage(body.leverage, creds=creds, exchange="deribit") if lev != cap_default: for leg in body.legs: - try: + with contextlib.suppress(Exception): await client.set_leverage(leg.instrument_name, lev) - except Exception: - pass result = await client.place_combo_order( legs=[leg.model_dump() for leg in body.legs], side=body.side, diff --git a/services/mcp-hyperliquid/src/mcp_hyperliquid/client.py b/services/mcp-hyperliquid/src/mcp_hyperliquid/client.py index df7e287..662c911 100644 --- a/services/mcp-hyperliquid/src/mcp_hyperliquid/client.py +++ b/services/mcp-hyperliquid/src/mcp_hyperliquid/client.py @@ -6,7 +6,6 @@ import asyncio import datetime as _dt from typing import Any -import httpx from mcp_common import indicators as ind from mcp_common.http import async_client diff --git a/services/mcp-macro/src/mcp_macro/fetchers.py b/services/mcp-macro/src/mcp_macro/fetchers.py index 838210e..448d877 100644 --- a/services/mcp-macro/src/mcp_macro/fetchers.py +++ b/services/mcp-macro/src/mcp_macro/fetchers.py @@ -5,6 +5,7 @@ from typing import Any import httpx from mcp_common.http import async_client + from mcp_macro.cot import classify_extreme, compute_percentile, parse_disagg_row, parse_tff_row from mcp_macro.cot_contracts import ( ALL_DISAGG_SYMBOLS, diff --git a/services/mcp-macro/tests/test_cot.py b/services/mcp-macro/tests/test_cot.py index 0151718..1544e77 100644 --- a/services/mcp-macro/tests/test_cot.py +++ b/services/mcp-macro/tests/test_cot.py @@ -1,6 +1,11 @@ from __future__ import annotations -from mcp_macro.cot import classify_extreme, compute_percentile +from mcp_macro.cot import ( + classify_extreme, + compute_percentile, + parse_disagg_row, + parse_tff_row, +) def test_compute_percentile_basic(): @@ -44,9 +49,6 @@ def test_classify_extreme_none_input(): assert classify_extreme(None) == "neutral" -from mcp_macro.cot import parse_disagg_row, parse_tff_row - - # Payload Socrata reale (subset campi rilevanti, valori arbitrari per test) TFF_SOCRATA_ROW = { "report_date_as_yyyy_mm_dd": "2026-04-22T00:00:00.000", diff --git a/services/mcp-macro/tests/test_fetchers.py b/services/mcp-macro/tests/test_fetchers.py index a891506..f3e96f0 100644 --- a/services/mcp-macro/tests/test_fetchers.py +++ b/services/mcp-macro/tests/test_fetchers.py @@ -366,6 +366,7 @@ async def test_fetch_cot_disagg_unknown_symbol(): async def test_fetch_cot_extreme_positioning_flags_outliers(monkeypatch): """Mock fetch_cot_tff e fetch_cot_disagg per simulare history e ultimo punto.""" from unittest.mock import AsyncMock + from mcp_macro import fetchers as f # Simula una serie ES dove ultimo lev_funds_net è in basso (extreme_short) diff --git a/services/mcp-macro/tests/test_server_acl.py b/services/mcp-macro/tests/test_server_acl.py index fa24cbc..91bebd7 100644 --- a/services/mcp-macro/tests/test_server_acl.py +++ b/services/mcp-macro/tests/test_server_acl.py @@ -127,7 +127,6 @@ def test_get_market_overview_no_auth_401(http): assert r.status_code == 401 -from unittest.mock import AsyncMock, patch def test_get_cot_tff_core_ok(http): diff --git a/services/mcp-sentiment/src/mcp_sentiment/fetchers.py b/services/mcp-sentiment/src/mcp_sentiment/fetchers.py index f996dac..7fc907f 100644 --- a/services/mcp-sentiment/src/mcp_sentiment/fetchers.py +++ b/services/mcp-sentiment/src/mcp_sentiment/fetchers.py @@ -5,7 +5,6 @@ import re import xml.etree.ElementTree as ET from typing import Any -import httpx from mcp_common.http import async_client CRYPTOPANIC_URL = "https://cryptopanic.com/api/v1/posts/" diff --git a/services/mcp-sentiment/src/mcp_sentiment/server.py b/services/mcp-sentiment/src/mcp_sentiment/server.py index 68bac9b..65f05b4 100644 --- a/services/mcp-sentiment/src/mcp_sentiment/server.py +++ b/services/mcp-sentiment/src/mcp_sentiment/server.py @@ -9,8 +9,6 @@ from mcp_common.mcp_bridge import mount_mcp_endpoint from mcp_common.server import build_app from pydantic import BaseModel -logger = logging.getLogger(__name__) - from mcp_sentiment.fetchers import ( fetch_cointegration_pairs, fetch_cross_exchange_funding, @@ -23,6 +21,8 @@ from mcp_sentiment.fetchers import ( fetch_world_news, ) +logger = logging.getLogger(__name__) + # --- Body models --- class GetCryptoNewsReq(BaseModel):