chore(V2): mypy clean — fix radice V2 nuovo + suppress mirato V1 legacy
- settings.py: lambda factory + type:ignore[call-arg] per env-loaded models
- routers/*.py (6 file): cast esplicito Environment / Client per request.state
- __main__.py: cast Literal env in builder, type:ignore Settings()
- server.py: type:ignore[method-assign] su app.openapi
- deribit/tools.py: assert su validator-normalized fields, list return type
- deribit/client.py: type:ignore mirato no-any-return / has-type, rinomina types→types_list
- hyperliquid/{client,tools}.py: assert su validator-normalized fields, var-annotated
- alpaca/client.py: type:ignore mirato per SDK quirks (assignment, no-any-return, arg-type, union-attr)
- {macro,sentiment}/fetchers.py: type:ignore mirato no-any-return / operator / union-attr
Mypy: 68 → 0 errors. Test: 259 passing. Ruff: clean.
This commit is contained in:
@@ -10,6 +10,7 @@ Boot:
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from contextlib import asynccontextmanager
|
from contextlib import asynccontextmanager
|
||||||
|
from typing import Literal, cast
|
||||||
|
|
||||||
import uvicorn
|
import uvicorn
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
@@ -40,7 +41,9 @@ def _make_app(settings: Settings) -> FastAPI:
|
|||||||
app.state.settings = settings
|
app.state.settings = settings
|
||||||
|
|
||||||
async def builder(exchange: str, env: str):
|
async def builder(exchange: str, env: str):
|
||||||
return await build_client(settings, exchange, env)
|
return await build_client(
|
||||||
|
settings, exchange, cast(Literal["testnet", "mainnet"], env)
|
||||||
|
)
|
||||||
|
|
||||||
app.state.registry = ClientRegistry(builder=builder)
|
app.state.registry = ClientRegistry(builder=builder)
|
||||||
|
|
||||||
@@ -65,7 +68,7 @@ def _make_app(settings: Settings) -> FastAPI:
|
|||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
configure_root_logging()
|
configure_root_logging()
|
||||||
settings = Settings()
|
settings = Settings() # type: ignore[call-arg]
|
||||||
app = _make_app(settings)
|
app = _make_app(settings)
|
||||||
uvicorn.run(
|
uvicorn.run(
|
||||||
app,
|
app,
|
||||||
|
|||||||
@@ -130,14 +130,14 @@ class AlpacaClient:
|
|||||||
|
|
||||||
async def get_account(self) -> dict:
|
async def get_account(self) -> dict:
|
||||||
acc = await self._run(self._trading.get_account)
|
acc = await self._run(self._trading.get_account)
|
||||||
return _serialize(acc)
|
return _serialize(acc) # type: ignore[no-any-return]
|
||||||
|
|
||||||
async def get_positions(self) -> list[dict]:
|
async def get_positions(self) -> list[dict]:
|
||||||
pos = await self._run(self._trading.get_all_positions)
|
pos = await self._run(self._trading.get_all_positions)
|
||||||
return [_serialize(p) for p in pos]
|
return [_serialize(p) for p in pos]
|
||||||
|
|
||||||
async def get_activities(self, limit: int = 50) -> list[dict]:
|
async def get_activities(self, limit: int = 50) -> list[dict]:
|
||||||
acts = await self._run(self._trading.get_account_activities)
|
acts = await self._run(self._trading.get_account_activities) # type: ignore[union-attr]
|
||||||
data = [_serialize(a) for a in acts]
|
data = [_serialize(a) for a in acts]
|
||||||
return data[:limit]
|
return data[:limit]
|
||||||
|
|
||||||
@@ -148,7 +148,7 @@ class AlpacaClient:
|
|||||||
) -> list[dict]:
|
) -> list[dict]:
|
||||||
req = GetAssetsRequest(
|
req = GetAssetsRequest(
|
||||||
asset_class=_asset_class_enum(asset_class),
|
asset_class=_asset_class_enum(asset_class),
|
||||||
status=status,
|
status=status, # type: ignore[arg-type]
|
||||||
)
|
)
|
||||||
assets = await self._run(self._trading.get_all_assets, req)
|
assets = await self._run(self._trading.get_all_assets, req)
|
||||||
return [_serialize(a) for a in assets[:500]]
|
return [_serialize(a) for a in assets[:500]]
|
||||||
@@ -175,10 +175,10 @@ class AlpacaClient:
|
|||||||
"timestamp": _serialize(getattr(trade, "timestamp", None)),
|
"timestamp": _serialize(getattr(trade, "timestamp", None)),
|
||||||
}
|
}
|
||||||
if ac == "crypto":
|
if ac == "crypto":
|
||||||
req = CryptoLatestTradeRequest(symbol_or_symbols=symbol)
|
req = CryptoLatestTradeRequest(symbol_or_symbols=symbol) # type: ignore[assignment]
|
||||||
data = await self._run(self._crypto.get_crypto_latest_trade, req)
|
data = await self._run(self._crypto.get_crypto_latest_trade, req)
|
||||||
trade = data.get(symbol)
|
trade = data.get(symbol)
|
||||||
q_req = CryptoLatestQuoteRequest(symbol_or_symbols=symbol)
|
q_req = CryptoLatestQuoteRequest(symbol_or_symbols=symbol) # type: ignore[assignment]
|
||||||
qdata = await self._run(self._crypto.get_crypto_latest_quote, q_req)
|
qdata = await self._run(self._crypto.get_crypto_latest_quote, q_req)
|
||||||
quote = qdata.get(symbol)
|
quote = qdata.get(symbol)
|
||||||
return {
|
return {
|
||||||
@@ -190,7 +190,7 @@ class AlpacaClient:
|
|||||||
"timestamp": _serialize(getattr(trade, "timestamp", None)),
|
"timestamp": _serialize(getattr(trade, "timestamp", None)),
|
||||||
}
|
}
|
||||||
if ac == "options":
|
if ac == "options":
|
||||||
req = OptionLatestQuoteRequest(symbol_or_symbols=symbol)
|
req = OptionLatestQuoteRequest(symbol_or_symbols=symbol) # type: ignore[assignment]
|
||||||
data = await self._run(self._option.get_option_latest_quote, req)
|
data = await self._run(self._option.get_option_latest_quote, req)
|
||||||
quote = data.get(symbol)
|
quote = data.get(symbol)
|
||||||
return {
|
return {
|
||||||
@@ -224,13 +224,13 @@ class AlpacaClient:
|
|||||||
)
|
)
|
||||||
data = await self._run(self._stock.get_stock_bars, req)
|
data = await self._run(self._stock.get_stock_bars, req)
|
||||||
elif ac == "crypto":
|
elif ac == "crypto":
|
||||||
req = CryptoBarsRequest(
|
req = CryptoBarsRequest( # type: ignore[assignment]
|
||||||
symbol_or_symbols=symbol, timeframe=tf,
|
symbol_or_symbols=symbol, timeframe=tf,
|
||||||
start=start_dt, end=end_dt, limit=limit,
|
start=start_dt, end=end_dt, limit=limit,
|
||||||
)
|
)
|
||||||
data = await self._run(self._crypto.get_crypto_bars, req)
|
data = await self._run(self._crypto.get_crypto_bars, req)
|
||||||
elif ac == "options":
|
elif ac == "options":
|
||||||
req = OptionBarsRequest(
|
req = OptionBarsRequest( # type: ignore[assignment]
|
||||||
symbol_or_symbols=symbol, timeframe=tf,
|
symbol_or_symbols=symbol, timeframe=tf,
|
||||||
start=start_dt, end=end_dt, limit=limit,
|
start=start_dt, end=end_dt, limit=limit,
|
||||||
)
|
)
|
||||||
@@ -255,7 +255,7 @@ class AlpacaClient:
|
|||||||
async def get_snapshot(self, symbol: str) -> dict:
|
async def get_snapshot(self, symbol: str) -> dict:
|
||||||
req = StockSnapshotRequest(symbol_or_symbols=symbol)
|
req = StockSnapshotRequest(symbol_or_symbols=symbol)
|
||||||
data = await self._run(self._stock.get_stock_snapshot, req)
|
data = await self._run(self._stock.get_stock_snapshot, req)
|
||||||
return _serialize(data.get(symbol))
|
return _serialize(data.get(symbol)) # type: ignore[no-any-return]
|
||||||
|
|
||||||
async def get_option_chain(
|
async def get_option_chain(
|
||||||
self,
|
self,
|
||||||
@@ -301,23 +301,23 @@ class AlpacaClient:
|
|||||||
"time_in_force": tif_enum,
|
"time_in_force": tif_enum,
|
||||||
}
|
}
|
||||||
if qty is not None:
|
if qty is not None:
|
||||||
common["qty"] = qty
|
common["qty"] = qty # type: ignore[assignment]
|
||||||
if notional is not None:
|
if notional is not None:
|
||||||
common["notional"] = notional
|
common["notional"] = notional # type: ignore[assignment]
|
||||||
if ot == "market":
|
if ot == "market":
|
||||||
req = MarketOrderRequest(**common)
|
req = MarketOrderRequest(**common)
|
||||||
elif ot == "limit":
|
elif ot == "limit":
|
||||||
if limit_price is None:
|
if limit_price is None:
|
||||||
raise ValueError("limit_price required for limit order")
|
raise ValueError("limit_price required for limit order")
|
||||||
req = LimitOrderRequest(**common, limit_price=limit_price)
|
req = LimitOrderRequest(**common, limit_price=limit_price) # type: ignore[assignment]
|
||||||
elif ot == "stop":
|
elif ot == "stop":
|
||||||
if stop_price is None:
|
if stop_price is None:
|
||||||
raise ValueError("stop_price required for stop order")
|
raise ValueError("stop_price required for stop order")
|
||||||
req = StopOrderRequest(**common, stop_price=stop_price)
|
req = StopOrderRequest(**common, stop_price=stop_price) # type: ignore[assignment]
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"unsupported order_type: {order_type}")
|
raise ValueError(f"unsupported order_type: {order_type}")
|
||||||
order = await self._run(self._trading.submit_order, req)
|
order = await self._run(self._trading.submit_order, req)
|
||||||
return _serialize(order)
|
return _serialize(order) # type: ignore[no-any-return]
|
||||||
|
|
||||||
async def amend_order(
|
async def amend_order(
|
||||||
self,
|
self,
|
||||||
@@ -338,7 +338,7 @@ class AlpacaClient:
|
|||||||
kwargs["time_in_force"] = TimeInForce(tif.lower())
|
kwargs["time_in_force"] = TimeInForce(tif.lower())
|
||||||
req = ReplaceOrderRequest(**kwargs)
|
req = ReplaceOrderRequest(**kwargs)
|
||||||
order = await self._run(self._trading.replace_order_by_id, order_id, req)
|
order = await self._run(self._trading.replace_order_by_id, order_id, req)
|
||||||
return _serialize(order)
|
return _serialize(order) # type: ignore[no-any-return]
|
||||||
|
|
||||||
async def cancel_order(self, order_id: str) -> dict:
|
async def cancel_order(self, order_id: str) -> dict:
|
||||||
await self._run(self._trading.cancel_order_by_id, order_id)
|
await self._run(self._trading.cancel_order_by_id, order_id)
|
||||||
@@ -364,7 +364,7 @@ class AlpacaClient:
|
|||||||
order = await self._run(
|
order = await self._run(
|
||||||
self._trading.close_position, symbol, close_options=req
|
self._trading.close_position, symbol, close_options=req
|
||||||
)
|
)
|
||||||
return _serialize(order)
|
return _serialize(order) # type: ignore[no-any-return]
|
||||||
|
|
||||||
async def close_all_positions(self, cancel_orders: bool = True) -> list[dict]:
|
async def close_all_positions(self, cancel_orders: bool = True) -> list[dict]:
|
||||||
resp = await self._run(
|
resp = await self._run(
|
||||||
@@ -376,7 +376,7 @@ class AlpacaClient:
|
|||||||
|
|
||||||
async def get_clock(self) -> dict:
|
async def get_clock(self) -> dict:
|
||||||
clock = await self._run(self._trading.get_clock)
|
clock = await self._run(self._trading.get_clock)
|
||||||
return _serialize(clock)
|
return _serialize(clock) # type: ignore[no-any-return]
|
||||||
|
|
||||||
async def get_calendar(
|
async def get_calendar(
|
||||||
self, start: str | None = None, end: str | None = None
|
self, start: str | None = None, end: str | None = None
|
||||||
|
|||||||
@@ -87,10 +87,10 @@ class DeribitClient:
|
|||||||
resp = await http.get(url, params=request_params, headers=headers)
|
resp = await http.get(url, params=request_params, headers=headers)
|
||||||
data = resp.json()
|
data = resp.json()
|
||||||
if "result" in data:
|
if "result" in data:
|
||||||
return data
|
return data # type: ignore[no-any-return]
|
||||||
return {"result": None, "error": error_msg}
|
return {"result": None, "error": error_msg}
|
||||||
|
|
||||||
return data
|
return data # type: ignore[no-any-return]
|
||||||
|
|
||||||
# ── Read tools ───────────────────────────────────────────────
|
# ── Read tools ───────────────────────────────────────────────
|
||||||
|
|
||||||
@@ -190,9 +190,9 @@ class DeribitClient:
|
|||||||
self._request("public/get_book_summary_by_currency", summary_params),
|
self._request("public/get_book_summary_by_currency", summary_params),
|
||||||
return_exceptions=True,
|
return_exceptions=True,
|
||||||
)
|
)
|
||||||
raw = instruments_raw if isinstance(instruments_raw, dict) else {}
|
raw = instruments_raw if isinstance(instruments_raw, dict) else {} # type: ignore[has-type]
|
||||||
summary_items = (
|
summary_items = (
|
||||||
summary_raw.get("result") if isinstance(summary_raw, dict) else None
|
summary_raw.get("result") if isinstance(summary_raw, dict) else None # type: ignore[has-type]
|
||||||
) or []
|
) or []
|
||||||
oi_by_name: dict[str, float] = {}
|
oi_by_name: dict[str, float] = {}
|
||||||
for s in summary_items:
|
for s in summary_items:
|
||||||
@@ -1200,8 +1200,8 @@ class DeribitClient:
|
|||||||
if len({l["expiry"] for l in legs}) == 2 and len(strikes) == 1:
|
if len({l["expiry"] for l in legs}) == 2 and len(strikes) == 1:
|
||||||
return "calendar spread"
|
return "calendar spread"
|
||||||
if n == 4:
|
if n == 4:
|
||||||
types = [l["type"] for l in legs]
|
types_list = [l["type"] for l in legs]
|
||||||
if types.count("P") == 2 and types.count("C") == 2:
|
if types_list.count("P") == 2 and types_list.count("C") == 2:
|
||||||
return "iron condor"
|
return "iron condor"
|
||||||
return "custom"
|
return "custom"
|
||||||
|
|
||||||
@@ -1484,7 +1484,7 @@ class DeribitClient:
|
|||||||
if not values_sorted:
|
if not values_sorted:
|
||||||
return None
|
return None
|
||||||
idx = int(round((len(values_sorted) - 1) * p))
|
idx = int(round((len(values_sorted) - 1) * p))
|
||||||
return values_sorted[idx]
|
return values_sorted[idx] # type: ignore[no-any-return]
|
||||||
|
|
||||||
mean = sum(values) / len(values) if values else None
|
mean = sum(values) / len(values) if values else None
|
||||||
return {
|
return {
|
||||||
@@ -1567,7 +1567,7 @@ class DeribitClient:
|
|||||||
r = raw.get("result")
|
r = raw.get("result")
|
||||||
if r is None:
|
if r is None:
|
||||||
return {"error": raw.get("error", "unknown"), "state": "error"}
|
return {"error": raw.get("error", "unknown"), "state": "error"}
|
||||||
return r
|
return r # type: ignore[no-any-return]
|
||||||
|
|
||||||
async def place_combo_order(
|
async def place_combo_order(
|
||||||
self,
|
self,
|
||||||
|
|||||||
@@ -296,10 +296,12 @@ async def environment_info(
|
|||||||
|
|
||||||
|
|
||||||
async def get_ticker(client: DeribitClient, params: GetTickerReq) -> dict:
|
async def get_ticker(client: DeribitClient, params: GetTickerReq) -> dict:
|
||||||
|
assert params.instrument_name is not None # validator garantisce non-None
|
||||||
return await client.get_ticker(params.instrument_name)
|
return await client.get_ticker(params.instrument_name)
|
||||||
|
|
||||||
|
|
||||||
async def get_ticker_batch(client: DeribitClient, params: GetTickerBatchReq) -> dict:
|
async def get_ticker_batch(client: DeribitClient, params: GetTickerBatchReq) -> dict:
|
||||||
|
assert params.instrument_names is not None # validator garantisce non-None
|
||||||
return await client.get_ticker_batch(params.instrument_names)
|
return await client.get_ticker_batch(params.instrument_names)
|
||||||
|
|
||||||
|
|
||||||
@@ -327,7 +329,7 @@ async def get_orderbook_imbalance(
|
|||||||
return await client.get_orderbook_imbalance(params.instrument_name, params.depth)
|
return await client.get_orderbook_imbalance(params.instrument_name, params.depth)
|
||||||
|
|
||||||
|
|
||||||
async def get_positions(client: DeribitClient, params: GetPositionsReq) -> dict:
|
async def get_positions(client: DeribitClient, params: GetPositionsReq) -> list:
|
||||||
return await client.get_positions(params.currency)
|
return await client.get_positions(params.currency)
|
||||||
|
|
||||||
|
|
||||||
@@ -337,7 +339,7 @@ async def get_account_summary(
|
|||||||
return await client.get_account_summary(params.currency)
|
return await client.get_account_summary(params.currency)
|
||||||
|
|
||||||
|
|
||||||
async def get_trade_history(client: DeribitClient, params: GetTradeHistoryReq) -> dict:
|
async def get_trade_history(client: DeribitClient, params: GetTradeHistoryReq) -> list:
|
||||||
return await client.get_trade_history(params.limit, params.instrument_name)
|
return await client.get_trade_history(params.limit, params.instrument_name)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -317,7 +317,7 @@ class HyperliquidClient:
|
|||||||
)
|
)
|
||||||
if resp.status_code == 200:
|
if resp.status_code == 200:
|
||||||
res = resp.json().get("result") or {}
|
res = resp.json().get("result") or {}
|
||||||
first = next(iter(res.values()), {})
|
first: dict = next(iter(res.values()), {})
|
||||||
price = (first.get("c") or [None])[0]
|
price = (first.get("c") or [None])[0]
|
||||||
spot_price = float(price) if price else None
|
spot_price = float(price) if price else None
|
||||||
spot_source = "kraken"
|
spot_source = "kraken"
|
||||||
@@ -466,8 +466,10 @@ class HyperliquidClient:
|
|||||||
mark = ticker.get("mark_price", 0)
|
mark = ticker.get("mark_price", 0)
|
||||||
price = round(mark * 1.03, 1) if is_buy else round(mark * 0.97, 1)
|
price = round(mark * 1.03, 1) if is_buy else round(mark * 0.97, 1)
|
||||||
elif type in ("stop_market", "stop_loss"):
|
elif type in ("stop_market", "stop_loss"):
|
||||||
|
assert price is not None
|
||||||
ot = {"trigger": {"triggerPx": float(price), "isMarket": True, "tpsl": "sl"}}
|
ot = {"trigger": {"triggerPx": float(price), "isMarket": True, "tpsl": "sl"}}
|
||||||
elif type == "take_profit":
|
elif type == "take_profit":
|
||||||
|
assert price is not None
|
||||||
ot = {"trigger": {"triggerPx": float(price), "isMarket": True, "tpsl": "tp"}}
|
ot = {"trigger": {"triggerPx": float(price), "isMarket": True, "tpsl": "tp"}}
|
||||||
else:
|
else:
|
||||||
ot = {"limit": {"tif": "Gtc"}}
|
ot = {"limit": {"tif": "Gtc"}}
|
||||||
|
|||||||
@@ -247,6 +247,9 @@ async def get_trade_history(
|
|||||||
async def get_historical(
|
async def get_historical(
|
||||||
client: HyperliquidClient, params: GetHistoricalReq
|
client: HyperliquidClient, params: GetHistoricalReq
|
||||||
) -> dict:
|
) -> dict:
|
||||||
|
assert params.instrument is not None # validator garantisce non-None
|
||||||
|
assert params.start_date is not None # validator garantisce non-None
|
||||||
|
assert params.end_date is not None # validator garantisce non-None
|
||||||
return await client.get_historical(
|
return await client.get_historical(
|
||||||
params.instrument, params.start_date, params.end_date, params.resolution
|
params.instrument, params.start_date, params.end_date, params.resolution
|
||||||
)
|
)
|
||||||
@@ -273,6 +276,9 @@ async def basis_spot_perp(
|
|||||||
async def get_indicators(
|
async def get_indicators(
|
||||||
client: HyperliquidClient, params: GetIndicatorsReq
|
client: HyperliquidClient, params: GetIndicatorsReq
|
||||||
) -> dict:
|
) -> dict:
|
||||||
|
assert params.instrument is not None # validator garantisce non-None
|
||||||
|
assert params.start_date is not None # validator garantisce non-None
|
||||||
|
assert params.end_date is not None # validator garantisce non-None
|
||||||
return await client.get_indicators(
|
return await client.get_indicators(
|
||||||
params.instrument,
|
params.instrument,
|
||||||
params.indicators,
|
params.indicators,
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ async def fetch_asset_price(ticker: str) -> dict[str, Any]:
|
|||||||
now = time.monotonic()
|
now = time.monotonic()
|
||||||
cached = _ASSET_CACHE.get(key)
|
cached = _ASSET_CACHE.get(key)
|
||||||
if cached and (now - cached["ts"]) < _ASSET_CACHE_TTL:
|
if cached and (now - cached["ts"]) < _ASSET_CACHE_TTL:
|
||||||
return cached["data"]
|
return cached["data"] # type: ignore[no-any-return]
|
||||||
|
|
||||||
mapping = ASSET_TICKER_MAP.get(key)
|
mapping = ASSET_TICKER_MAP.get(key)
|
||||||
if not mapping:
|
if not mapping:
|
||||||
@@ -137,7 +137,7 @@ async def fetch_treasury_yields() -> dict[str, Any]:
|
|||||||
|
|
||||||
now = time.monotonic()
|
now = time.monotonic()
|
||||||
if _TREASURY_CACHE["data"] and (now - _TREASURY_CACHE["ts"]) < _TREASURY_TTL:
|
if _TREASURY_CACHE["data"] and (now - _TREASURY_CACHE["ts"]) < _TREASURY_TTL:
|
||||||
return _TREASURY_CACHE["data"]
|
return _TREASURY_CACHE["data"] # type: ignore[no-any-return]
|
||||||
|
|
||||||
symbols = [
|
symbols = [
|
||||||
("us2y", "^UST2YR"),
|
("us2y", "^UST2YR"),
|
||||||
@@ -155,7 +155,7 @@ async def fetch_treasury_yields() -> dict[str, Any]:
|
|||||||
|
|
||||||
spread = None
|
spread = None
|
||||||
if yields.get("us10y") is not None and yields.get("us2y") is not None:
|
if yields.get("us10y") is not None and yields.get("us2y") is not None:
|
||||||
spread = round(yields["us10y"] - yields["us2y"], 3)
|
spread = round(yields["us10y"] - yields["us2y"], 3) # type: ignore[operator]
|
||||||
shape = "unknown"
|
shape = "unknown"
|
||||||
if spread is not None:
|
if spread is not None:
|
||||||
if spread > 0.25:
|
if spread > 0.25:
|
||||||
@@ -586,7 +586,7 @@ async def fetch_market_overview() -> dict[str, Any]:
|
|||||||
|
|
||||||
now = time.monotonic()
|
now = time.monotonic()
|
||||||
if _MARKET_CACHE["data"] is not None and (now - _MARKET_CACHE["ts"]) < _MARKET_CACHE_TTL:
|
if _MARKET_CACHE["data"] is not None and (now - _MARKET_CACHE["ts"]) < _MARKET_CACHE_TTL:
|
||||||
return _MARKET_CACHE["data"]
|
return _MARKET_CACHE["data"] # type: ignore[no-any-return]
|
||||||
|
|
||||||
async with async_client(timeout=10.0) as client:
|
async with async_client(timeout=10.0) as client:
|
||||||
global_data: dict[str, Any] = {}
|
global_data: dict[str, Any] = {}
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ async def fetch_crypto_news(api_key: str = "", limit: int = 20) -> dict[str, Any
|
|||||||
providers_failed.append(name)
|
providers_failed.append(name)
|
||||||
continue
|
continue
|
||||||
providers_ok.append(name)
|
providers_ok.append(name)
|
||||||
for item in res:
|
for item in res: # type: ignore[union-attr]
|
||||||
if "provider" not in item:
|
if "provider" not in item:
|
||||||
item["provider"] = name
|
item["provider"] = name
|
||||||
all_items.append(item)
|
all_items.append(item)
|
||||||
@@ -643,7 +643,7 @@ async def fetch_oi_history(asset: str = "BTC", period: str = "5m", limit: int =
|
|||||||
past = next((p for p in reversed(points) if p["timestamp"] <= cutoff_ts), None)
|
past = next((p for p in reversed(points) if p["timestamp"] <= cutoff_ts), None)
|
||||||
if past is None or past["oi"] == 0:
|
if past is None or past["oi"] == 0:
|
||||||
return None
|
return None
|
||||||
return round(100.0 * (current["oi"] - past["oi"]) / past["oi"], 3)
|
return round(100.0 * (current["oi"] - past["oi"]) / past["oi"], 3) # type: ignore[no-any-return]
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"asset": asset,
|
"asset": asset,
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ dal middleware in `cerbero_mcp.auth`; qui leggiamo solo `request.state.environme
|
|||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import Literal
|
from typing import Literal, cast
|
||||||
|
|
||||||
from fastapi import APIRouter, Depends, Request
|
from fastapi import APIRouter, Depends, Request
|
||||||
|
|
||||||
@@ -18,14 +18,14 @@ Environment = Literal["testnet", "mainnet"]
|
|||||||
|
|
||||||
|
|
||||||
def get_environment(request: Request) -> Environment:
|
def get_environment(request: Request) -> Environment:
|
||||||
return request.state.environment
|
return cast(Environment, request.state.environment)
|
||||||
|
|
||||||
|
|
||||||
async def get_alpaca_client(
|
async def get_alpaca_client(
|
||||||
request: Request, env: Environment = Depends(get_environment)
|
request: Request, env: Environment = Depends(get_environment)
|
||||||
) -> AlpacaClient:
|
) -> AlpacaClient:
|
||||||
registry: ClientRegistry = request.app.state.registry
|
registry: ClientRegistry = request.app.state.registry
|
||||||
return await registry.get("alpaca", env)
|
return cast(AlpacaClient, await registry.get("alpaca", env))
|
||||||
|
|
||||||
|
|
||||||
def _build_creds(request: Request) -> dict:
|
def _build_creds(request: Request) -> dict:
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ dal middleware in `cerbero_mcp.auth`; qui leggiamo solo `request.state.environme
|
|||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import Literal
|
from typing import Literal, cast
|
||||||
|
|
||||||
from fastapi import APIRouter, Depends, Request
|
from fastapi import APIRouter, Depends, Request
|
||||||
|
|
||||||
@@ -18,14 +18,14 @@ Environment = Literal["testnet", "mainnet"]
|
|||||||
|
|
||||||
|
|
||||||
def get_environment(request: Request) -> Environment:
|
def get_environment(request: Request) -> Environment:
|
||||||
return request.state.environment
|
return cast(Environment, request.state.environment)
|
||||||
|
|
||||||
|
|
||||||
async def get_bybit_client(
|
async def get_bybit_client(
|
||||||
request: Request, env: Environment = Depends(get_environment)
|
request: Request, env: Environment = Depends(get_environment)
|
||||||
) -> BybitClient:
|
) -> BybitClient:
|
||||||
registry: ClientRegistry = request.app.state.registry
|
registry: ClientRegistry = request.app.state.registry
|
||||||
return await registry.get("bybit", env)
|
return cast(BybitClient, await registry.get("bybit", env))
|
||||||
|
|
||||||
|
|
||||||
def _build_creds(request: Request) -> dict:
|
def _build_creds(request: Request) -> dict:
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ dal middleware in `cerbero_mcp.auth`; qui leggiamo solo `request.state.environme
|
|||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import Literal
|
from typing import Literal, cast
|
||||||
|
|
||||||
from fastapi import APIRouter, Depends, Request
|
from fastapi import APIRouter, Depends, Request
|
||||||
|
|
||||||
@@ -18,14 +18,14 @@ Environment = Literal["testnet", "mainnet"]
|
|||||||
|
|
||||||
|
|
||||||
def get_environment(request: Request) -> Environment:
|
def get_environment(request: Request) -> Environment:
|
||||||
return request.state.environment
|
return cast(Environment, request.state.environment)
|
||||||
|
|
||||||
|
|
||||||
async def get_deribit_client(
|
async def get_deribit_client(
|
||||||
request: Request, env: Environment = Depends(get_environment)
|
request: Request, env: Environment = Depends(get_environment)
|
||||||
) -> DeribitClient:
|
) -> DeribitClient:
|
||||||
registry: ClientRegistry = request.app.state.registry
|
registry: ClientRegistry = request.app.state.registry
|
||||||
return await registry.get("deribit", env)
|
return cast(DeribitClient, await registry.get("deribit", env))
|
||||||
|
|
||||||
|
|
||||||
def _build_creds(request: Request) -> dict:
|
def _build_creds(request: Request) -> dict:
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ dal middleware in `cerbero_mcp.auth`; qui leggiamo solo `request.state.environme
|
|||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import Literal
|
from typing import Literal, cast
|
||||||
|
|
||||||
from fastapi import APIRouter, Depends, Request
|
from fastapi import APIRouter, Depends, Request
|
||||||
|
|
||||||
@@ -18,14 +18,14 @@ Environment = Literal["testnet", "mainnet"]
|
|||||||
|
|
||||||
|
|
||||||
def get_environment(request: Request) -> Environment:
|
def get_environment(request: Request) -> Environment:
|
||||||
return request.state.environment
|
return cast(Environment, request.state.environment)
|
||||||
|
|
||||||
|
|
||||||
async def get_hyperliquid_client(
|
async def get_hyperliquid_client(
|
||||||
request: Request, env: Environment = Depends(get_environment)
|
request: Request, env: Environment = Depends(get_environment)
|
||||||
) -> HyperliquidClient:
|
) -> HyperliquidClient:
|
||||||
registry: ClientRegistry = request.app.state.registry
|
registry: ClientRegistry = request.app.state.registry
|
||||||
return await registry.get("hyperliquid", env)
|
return cast(HyperliquidClient, await registry.get("hyperliquid", env))
|
||||||
|
|
||||||
|
|
||||||
def _build_creds(request: Request) -> dict:
|
def _build_creds(request: Request) -> dict:
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ Tutti i tool sono READ — niente write, niente leverage_cap.
|
|||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import Literal
|
from typing import Literal, cast
|
||||||
|
|
||||||
from fastapi import APIRouter, Depends, Request
|
from fastapi import APIRouter, Depends, Request
|
||||||
|
|
||||||
@@ -18,14 +18,14 @@ Environment = Literal["testnet", "mainnet"]
|
|||||||
|
|
||||||
|
|
||||||
def get_environment(request: Request) -> Environment:
|
def get_environment(request: Request) -> Environment:
|
||||||
return request.state.environment
|
return cast(Environment, request.state.environment)
|
||||||
|
|
||||||
|
|
||||||
async def get_macro_client(
|
async def get_macro_client(
|
||||||
request: Request, env: Environment = Depends(get_environment)
|
request: Request, env: Environment = Depends(get_environment)
|
||||||
) -> MacroClient:
|
) -> MacroClient:
|
||||||
registry: ClientRegistry = request.app.state.registry
|
registry: ClientRegistry = request.app.state.registry
|
||||||
return await registry.get("macro", env)
|
return cast(MacroClient, await registry.get("macro", env))
|
||||||
|
|
||||||
|
|
||||||
def make_router() -> APIRouter:
|
def make_router() -> APIRouter:
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ niente write, niente leverage_cap.
|
|||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import Literal
|
from typing import Literal, cast
|
||||||
|
|
||||||
from fastapi import APIRouter, Depends, Request
|
from fastapi import APIRouter, Depends, Request
|
||||||
|
|
||||||
@@ -19,14 +19,14 @@ Environment = Literal["testnet", "mainnet"]
|
|||||||
|
|
||||||
|
|
||||||
def get_environment(request: Request) -> Environment:
|
def get_environment(request: Request) -> Environment:
|
||||||
return request.state.environment
|
return cast(Environment, request.state.environment)
|
||||||
|
|
||||||
|
|
||||||
async def get_sentiment_client(
|
async def get_sentiment_client(
|
||||||
request: Request, env: Environment = Depends(get_environment)
|
request: Request, env: Environment = Depends(get_environment)
|
||||||
) -> SentimentClient:
|
) -> SentimentClient:
|
||||||
registry: ClientRegistry = request.app.state.registry
|
registry: ClientRegistry = request.app.state.registry
|
||||||
return await registry.get("sentiment", env)
|
return cast(SentimentClient, await registry.get("sentiment", env))
|
||||||
|
|
||||||
|
|
||||||
def make_router() -> APIRouter:
|
def make_router() -> APIRouter:
|
||||||
|
|||||||
@@ -201,5 +201,5 @@ def build_app(
|
|||||||
app.openapi_schema = schema
|
app.openapi_schema = schema
|
||||||
return schema
|
return schema
|
||||||
|
|
||||||
app.openapi = _custom_openapi
|
app.openapi = _custom_openapi # type: ignore[method-assign]
|
||||||
return app
|
return app
|
||||||
|
|||||||
@@ -99,9 +99,9 @@ class Settings(_Sub):
|
|||||||
testnet_token: SecretStr
|
testnet_token: SecretStr
|
||||||
mainnet_token: SecretStr
|
mainnet_token: SecretStr
|
||||||
|
|
||||||
deribit: DeribitSettings = Field(default_factory=DeribitSettings)
|
deribit: DeribitSettings = Field(default_factory=lambda: DeribitSettings()) # type: ignore[call-arg]
|
||||||
bybit: BybitSettings = Field(default_factory=BybitSettings)
|
bybit: BybitSettings = Field(default_factory=lambda: BybitSettings()) # type: ignore[call-arg]
|
||||||
hyperliquid: HyperliquidSettings = Field(default_factory=HyperliquidSettings)
|
hyperliquid: HyperliquidSettings = Field(default_factory=lambda: HyperliquidSettings()) # type: ignore[call-arg]
|
||||||
alpaca: AlpacaSettings = Field(default_factory=AlpacaSettings)
|
alpaca: AlpacaSettings = Field(default_factory=lambda: AlpacaSettings()) # type: ignore[call-arg]
|
||||||
macro: MacroSettings = Field(default_factory=MacroSettings)
|
macro: MacroSettings = Field(default_factory=lambda: MacroSettings()) # type: ignore[call-arg]
|
||||||
sentiment: SentimentSettings = Field(default_factory=SentimentSettings)
|
sentiment: SentimentSettings = Field(default_factory=lambda: SentimentSettings()) # type: ignore[call-arg]
|
||||||
|
|||||||
Reference in New Issue
Block a user