From 1bb7f9b0bae4208feaee59532a0ea06c68ec5049 Mon Sep 17 00:00:00 2001 From: dekun Date: Thu, 20 Aug 2026 16:05:10 +0800 Subject: [PATCH] =?UTF-8?q?=E6=A8=A1=E6=8B=9F=E7=9B=98=E4=B9=B0=E5=B8=81?= =?UTF-8?q?=E6=94=B9=E7=94=A8=E5=85=AC=E5=BC=80=E8=A1=8C=E6=83=85=EF=BC=8C?= =?UTF-8?q?=E9=81=BF=E5=85=8D=E6=97=A0=E6=95=88=20OKX=20Key=20=E5=AF=BC?= =?UTF-8?q?=E8=87=B4=2050111=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Cursor --- lib/sim/broker_lib.py | 13 +++++++++++++ lib/sim/hooks.py | 27 +++++++++++++-------------- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/lib/sim/broker_lib.py b/lib/sim/broker_lib.py index d0e4523..0614127 100644 --- a/lib/sim/broker_lib.py +++ b/lib/sim/broker_lib.py @@ -15,6 +15,19 @@ def _now() -> str: def _ticker_bid_ask(exchange: Any, symbol: str) -> tuple[float, float]: + """取买卖一.优先 public ticker,避免私钥无效时 ccxt 带坏 Key 导致 50111.""" + inst = symbol.replace("/", "-") if symbol and "/" in symbol else (symbol or "") + if inst and exchange is not None and hasattr(exchange, "public_get_market_ticker"): + try: + rows = (exchange.public_get_market_ticker({"instId": inst}) or {}).get("data") or [] + if rows: + t = rows[0] + bid = t.get("bidPx") or t.get("last") or t.get("lastPx") + ask = t.get("askPx") or t.get("last") or t.get("lastPx") + if bid is not None and ask is not None and float(bid) > 0 and float(ask) > 0: + return float(bid), float(ask) + except Exception: + pass t = exchange.fetch_ticker(symbol) last = t.get("last") bid = t.get("bid") diff --git a/lib/sim/hooks.py b/lib/sim/hooks.py index 66e1cbe..62ff676 100644 --- a/lib/sim/hooks.py +++ b/lib/sim/hooks.py @@ -277,11 +277,9 @@ def _patch_okx_options_lib(app_module: Any) -> None: try: if _GET_DB is not None and is_sim_mode(_GET_DB): # 对齐实盘: 交易账户 + USDC/USDT 公开买卖一(含手续费滑点) - pub = ex + pub = _sim_public_exchange(ex) if pub is None and _APP_MODULE is not None: - pub = getattr(_APP_MODULE, "exchange", None) or getattr( - _APP_MODULE, "exchange_options", None - ) + pub = getattr(_APP_MODULE, "exchange_options", None) if pub is None: return {"ok": False, "msg": "sim: 无公开行情 exchange"} result = broker().convert_usdt_usdc( @@ -370,6 +368,15 @@ def _patch_okx_options_lib(app_module: Any) -> None: _patch_spot_bridge_lib() +def _sim_public_exchange(ex: Any = None) -> Any: + """模拟盘行情优先用无密钥/公开实例,避免 options 私钥 50111 污染 public 请求.""" + if _APP_MODULE is not None: + pub = getattr(_APP_MODULE, "exchange", None) + if pub is not None: + return pub + return ex + + def _patch_spot_bridge_lib() -> None: """币本位现货桥:模拟盘走本地 USDT↔ETH/BTC,勿打实盘 private_post_trade_order.""" import lib.options.options_spot_bridge_lib as bridge_lib @@ -396,11 +403,7 @@ def _patch_spot_bridge_lib() -> None: def spot_market_buy_coin_with_usdt(ex, *, underlying: str, usdt_amount: float): try: if _GET_DB is not None and is_sim_mode(_GET_DB): - pub = ex - if pub is None and _APP_MODULE is not None: - pub = getattr(_APP_MODULE, "exchange", None) or getattr( - _APP_MODULE, "exchange_options", None - ) + pub = _sim_public_exchange(ex) if pub is None: return {"ok": False, "msg": "sim: 无公开行情 exchange"} result = broker().convert_usdt_coin( @@ -448,11 +451,7 @@ def _patch_spot_bridge_lib() -> None: sell_sz = max(0.0, sell_sz * 0.999) if sell_sz <= 0: return {"ok": False, "msg": f"{coin} 可卖数量过小"} - pub = ex - if pub is None and _APP_MODULE is not None: - pub = getattr(_APP_MODULE, "exchange", None) or getattr( - _APP_MODULE, "exchange_options", None - ) + pub = _sim_public_exchange(ex) if pub is None: return {"ok": False, "msg": "sim: 无公开行情 exchange"} result = broker().convert_usdt_coin(