Fix Binance boot using OKX symbols after restart.
Startup ignored DB exchange choice and kept OKX ATM ids under a Binance health label, so option bid/ask stayed empty. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -55,19 +55,25 @@ class BinanceRestClient:
|
||||
return self._exchange_info
|
||||
|
||||
def fetch_option_instruments(self, underlying: str) -> list[dict[str, Any]]:
|
||||
"""underlying 如 ETH / ETHUSDT。"""
|
||||
"""underlying 如 ETH / ETHUSDT。误传 OKX family(ETH-USD_UM)时映射到 ETHUSDT。"""
|
||||
info = self.fetch_option_exchange_info()
|
||||
rows = info.get("optionSymbols") or info.get("symbols") or []
|
||||
want = (underlying or "ETHUSDT").strip().upper()
|
||||
eth_mode = want in ("ETH", "ETHUSDT") or want.startswith("ETH")
|
||||
# 兼容误用 OKX 期权族名
|
||||
if "USD_UM" in want or want in ("ETH-USD", "ETH-USDT", "ETHUSD"):
|
||||
want = "ETHUSDT"
|
||||
eth_mode = want in ("ETH", "ETHUSDT") or (
|
||||
want.startswith("ETH") and "-" not in want
|
||||
)
|
||||
out: list[dict[str, Any]] = []
|
||||
for row in rows:
|
||||
if not isinstance(row, dict):
|
||||
continue
|
||||
u = str(row.get("underlying") or row.get("underlyingAsset") or "").upper()
|
||||
sym = str(row.get("symbol") or "").upper()
|
||||
# 只收币安格式 ETH-YYMMDD-STRIKE-C/P,避免脏符号进缓存
|
||||
if eth_mode:
|
||||
if sym.startswith("ETH-") or u.startswith("ETH"):
|
||||
if sym.startswith("ETH-") and u.startswith("ETH"):
|
||||
out.append(row)
|
||||
continue
|
||||
base = want.replace("USDT", "") if want.endswith("USDT") else want
|
||||
|
||||
+5
-1
@@ -30,9 +30,13 @@ def resolve_frontend_dist() -> Path:
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
settings = get_settings()
|
||||
db = Database()
|
||||
set_db(db)
|
||||
# 必须在 set_db 之后读 DB 覆盖,否则会按 .env 默认 okx 起会话,
|
||||
# 而 health 显示 DB 里的 binance → 合约号/盘口错乱(期权一直 -/-)
|
||||
from .exchange.runtime import load_runtime_settings
|
||||
|
||||
settings = load_runtime_settings()
|
||||
engine = StrategyEngine()
|
||||
set_engine(engine)
|
||||
engine.ensure_loop()
|
||||
|
||||
@@ -330,10 +330,14 @@ set_gateway = set_session
|
||||
|
||||
|
||||
def bootstrap_session(settings: Settings | None = None) -> StrategySession:
|
||||
"""main 启动:创建交易所 + 策略会话。"""
|
||||
"""main 启动:创建交易所 + 策略会话。始终以 DB 覆盖后的 runtime 为准。"""
|
||||
from ..exchange.runtime import load_runtime_settings
|
||||
|
||||
s = settings or load_runtime_settings()
|
||||
# 忽略裸 get_settings():重启后必须跟 DB 里选的交易所一致
|
||||
try:
|
||||
s = load_runtime_settings()
|
||||
except Exception:
|
||||
s = settings or get_settings()
|
||||
ex = build_exchange(s)
|
||||
set_exchange(ex)
|
||||
sess = StrategySession(s, ex)
|
||||
|
||||
@@ -57,3 +57,35 @@ def test_normalize_exchange() -> None:
|
||||
assert normalize_exchange_name("BN") == "binance"
|
||||
assert normalize_exchange_name("okx") == "okx"
|
||||
assert normalize_exchange_name(None) == "okx"
|
||||
|
||||
|
||||
def test_binance_maps_okx_family_name() -> None:
|
||||
"""误传 OKX family 时不应按 startswith(ETH) 乱匹配,应映射到 ETHUSDT。"""
|
||||
from app.exchange.binance.rest import BinanceRestClient
|
||||
|
||||
cli = BinanceRestClient.__new__(BinanceRestClient)
|
||||
cli._exchange_info = {
|
||||
"optionSymbols": [
|
||||
{
|
||||
"symbol": "ETH-260726-1860-C",
|
||||
"underlying": "ETHUSDT",
|
||||
"status": "TRADING",
|
||||
"strikePrice": "1860",
|
||||
"side": "CALL",
|
||||
"expiryDate": 1785052800000,
|
||||
"unit": "1",
|
||||
},
|
||||
{
|
||||
"symbol": "BTC-260726-100000-C",
|
||||
"underlying": "BTCUSDT",
|
||||
"status": "TRADING",
|
||||
"strikePrice": "100000",
|
||||
"side": "CALL",
|
||||
"expiryDate": 1785052800000,
|
||||
"unit": "1",
|
||||
},
|
||||
]
|
||||
}
|
||||
rows = BinanceRestClient.fetch_option_instruments(cli, "ETH-USD_UM")
|
||||
assert len(rows) == 1
|
||||
assert rows[0]["symbol"] == "ETH-260726-1860-C"
|
||||
|
||||
Reference in New Issue
Block a user