Add Binance SIM market adapter and exchange switch in settings.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,11 +1,18 @@
|
||||
"""币安交易所适配器占位:后期接入,接口与 OKX 对齐。"""
|
||||
"""币安交易所适配器:USDT 永续 + 欧洲期权公共行情(SIM 只读)。"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from typing import Any, Sequence
|
||||
|
||||
from ...config import Settings, get_settings
|
||||
from ..book_cache import BookCache
|
||||
from ..types import BookLevel, MarketSnapshot, OptionPair, Quote
|
||||
from .parse import safe_float
|
||||
from .rest import BinanceRestClient
|
||||
from .ws import BinancePublicWs
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class BinanceExchange:
|
||||
@@ -13,50 +20,105 @@ class BinanceExchange:
|
||||
|
||||
def __init__(self, settings: Settings | None = None) -> None:
|
||||
self.settings = settings or get_settings()
|
||||
self.cache = BookCache()
|
||||
proxy = (
|
||||
self.settings.binance_http_proxy
|
||||
or self.settings.okx_http_proxy
|
||||
or None
|
||||
)
|
||||
self.rest = BinanceRestClient(
|
||||
fapi_base=self.settings.binance_fapi_base,
|
||||
eapi_base=self.settings.binance_eapi_base,
|
||||
proxy=proxy,
|
||||
)
|
||||
self.ws = BinancePublicWs(
|
||||
futures_ws_base=self.settings.binance_futures_ws,
|
||||
options_ws_base=self.settings.binance_options_ws,
|
||||
cache=self.cache,
|
||||
proxy=proxy,
|
||||
)
|
||||
self._started = False
|
||||
self._ct_cache: dict[str, float] = {}
|
||||
|
||||
async def start(self) -> None:
|
||||
raise NotImplementedError("币安交易所模块尚未接入,请配置 EXCHANGE=okx")
|
||||
if self._started:
|
||||
return
|
||||
self._started = True
|
||||
await self.ws.start()
|
||||
logger.info("Binance exchange started")
|
||||
|
||||
async def stop(self) -> None:
|
||||
return
|
||||
self._started = False
|
||||
await self.ws.stop()
|
||||
self.rest.close()
|
||||
logger.info("Binance exchange stopped")
|
||||
|
||||
def list_option_contracts(self, family: str) -> list[dict[str, Any]]:
|
||||
raise NotImplementedError("BinanceExchange.list_option_contracts")
|
||||
contracts = self.rest.list_option_contracts(family)
|
||||
for c in contracts:
|
||||
if c.get("ct_mult"):
|
||||
self._ct_cache[str(c["inst_id"])] = float(c["ct_mult"])
|
||||
return contracts
|
||||
|
||||
def fetch_index(self, index_id: str) -> float | None:
|
||||
raise NotImplementedError("BinanceExchange.fetch_index")
|
||||
return self.rest.fetch_index(index_id)
|
||||
|
||||
def fetch_mark(self, inst_id: str) -> float | None:
|
||||
raise NotImplementedError("BinanceExchange.fetch_mark")
|
||||
return self.rest.fetch_mark(inst_id)
|
||||
|
||||
def fetch_book(
|
||||
self, inst_id: str, depth: int = 5
|
||||
) -> tuple[list[BookLevel], list[BookLevel], int | None]:
|
||||
raise NotImplementedError("BinanceExchange.fetch_book")
|
||||
return self.rest.fetch_books(inst_id, sz=depth)
|
||||
|
||||
def get_ct_mult(self, option_inst_id: str, family: str, default: float) -> float:
|
||||
return float(default)
|
||||
if option_inst_id in self._ct_cache:
|
||||
return self._ct_cache[option_inst_id]
|
||||
# 币安 ETH 期权 unit 常见为 1
|
||||
return float(default if default > 0 else 1.0)
|
||||
|
||||
def set_pair(self, pair: OptionPair | None) -> None:
|
||||
raise NotImplementedError("BinanceExchange.set_pair")
|
||||
self.cache.set_pair(pair)
|
||||
|
||||
def warm_and_subscribe(self, inst_ids: Sequence[str]) -> None:
|
||||
raise NotImplementedError("BinanceExchange.warm_and_subscribe")
|
||||
ids = [i for i in inst_ids if i]
|
||||
for inst in ids:
|
||||
try:
|
||||
bids, asks, ts = self.rest.fetch_books(inst, sz=5)
|
||||
self.cache.upsert_book(inst, bids=bids, asks=asks, ts_ms=ts)
|
||||
except Exception as e:
|
||||
logger.warning("binance warm book %s failed: %s", inst, e)
|
||||
try:
|
||||
mp = self.rest.fetch_mark(inst)
|
||||
if mp:
|
||||
self.cache.set_mark_px(inst, mp)
|
||||
except Exception:
|
||||
pass
|
||||
# 指数
|
||||
try:
|
||||
idx = self.rest.fetch_index(self.settings.index_inst_id)
|
||||
if idx:
|
||||
self.cache.set_index_px(idx)
|
||||
except Exception as e:
|
||||
logger.warning("binance index failed: %s", e)
|
||||
keep = set(ids)
|
||||
self.cache.drop_except(keep)
|
||||
self.ws.set_instruments(ids)
|
||||
|
||||
async def resubscribe(self, inst_ids: Sequence[str]) -> None:
|
||||
raise NotImplementedError("BinanceExchange.resubscribe")
|
||||
await self.ws.resubscribe([i for i in inst_ids if i])
|
||||
|
||||
def quote(self, inst_id: str) -> Quote | None:
|
||||
return None
|
||||
return self.cache.get(inst_id)
|
||||
|
||||
def snapshot(self, perp_inst_id: str) -> MarketSnapshot:
|
||||
raise NotImplementedError("BinanceExchange.snapshot")
|
||||
return self.cache.snapshot(perp_inst_id)
|
||||
|
||||
def snapshot_dict(self, perp_inst_id: str) -> dict[str, Any]:
|
||||
raise NotImplementedError("BinanceExchange.snapshot_dict")
|
||||
return self.snapshot(perp_inst_id).to_dict()
|
||||
|
||||
def set_index_px(self, px: float | None) -> None:
|
||||
return
|
||||
self.cache.set_index_px(px)
|
||||
|
||||
def set_mark_px(self, inst_id: str, mark_px: float | None) -> None:
|
||||
return
|
||||
self.cache.set_mark_px(inst_id, mark_px)
|
||||
|
||||
Reference in New Issue
Block a user