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:
dekun
2026-07-25 12:13:19 +08:00
parent d701d30c04
commit 586469482e
4 changed files with 52 additions and 6 deletions
+9 -3
View File
@@ -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 familyETH-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
View File
@@ -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()
+6 -2
View File
@@ -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)
+32
View File
@@ -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"