From 9c19afc8d4c7256537c589e069fdfacbf0a5e7a9 Mon Sep 17 00:00:00 2001 From: dekun Date: Wed, 12 Aug 2026 16:08:16 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E6=9C=9F=E6=9D=83=E5=BC=80?= =?UTF-8?q?=E4=BB=93=2051008=20=E6=96=87=E6=A1=88=EF=BC=9A=E4=B8=8D?= =?UTF-8?q?=E5=86=8D=E8=AF=AF=E6=8A=A5=E8=B5=84=E9=87=91=E8=B4=A6=E6=88=B7?= =?UTF-8?q?=20USDT=EF=BC=8C=E6=8C=89=20USDC/USDT=20=E5=8C=BA=E5=88=86?= =?UTF-8?q?=E6=8F=90=E7=A4=BA=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Cursor --- lib/exchange/okx_options_lib.py | 55 +++++++++++++++++++-------------- tests/test_okx_spot_swap.py | 17 +++++++++- 2 files changed, 48 insertions(+), 24 deletions(-) diff --git a/lib/exchange/okx_options_lib.py b/lib/exchange/okx_options_lib.py index c709c71..094b298 100644 --- a/lib/exchange/okx_options_lib.py +++ b/lib/exchange/okx_options_lib.py @@ -19,32 +19,11 @@ from lib.options.options_pricing_lib import ( ) _OKX_OPTION_ERR_ZH: dict[str, str] = { - "51008": "资金账户 USDT 可用余额不足", + "51008": "可用余额或保证金不足(期权买入请确认交易账户 USDC 足够)", "51018": "期权账户不能持有净空头头寸", "51019": "期权买入须使用逐仓模式(全仓模式下不能持有多头净头寸)", } -_OPTIONS_BALANCE_CACHE: dict[str, Any] = {"updated_at": 0.0, "data": None} - -# public/instruments 全族缓存:合约列表变化慢,限频时用旧数据保活 -_OPTION_INSTRUMENTS_CACHE: dict[str, dict[str, Any]] = {} -_OPTION_INSTRUMENTS_CACHE_LOCK = threading.Lock() -_OPTION_INSTRUMENTS_CACHE_TTL = 90.0 -_OPTION_INSTRUMENTS_STALE_MAX = 600.0 - - -def invalidate_options_balance_cache() -> None: - _OPTIONS_BALANCE_CACHE["updated_at"] = 0.0 - _OPTIONS_BALANCE_CACHE["data"] = None - - -def invalidate_option_instruments_cache(inst_family: str | None = None) -> None: - with _OPTION_INSTRUMENTS_CACHE_LOCK: - if inst_family: - _OPTION_INSTRUMENTS_CACHE.pop(str(inst_family), None) - else: - _OPTION_INSTRUMENTS_CACHE.clear() - def _okx_trade_error_message(exc: BaseException | None = None, resp: Any = None) -> str: row: dict[str, Any] | None = None @@ -65,10 +44,18 @@ def _okx_trade_error_message(exc: BaseException | None = None, resp: Any = None) pass if row: code = str(row.get("sCode") or "") + msg = str(row.get("sMsg") or "").strip() + low = msg.lower() + if code == "51008": + # 勿写死「资金账户 USDT」:期权开仓常因交易户 USDC 不足 + if "usdc" in low: + return "交易账户 USDC 可用余额不足" + if "usdt" in low: + return "USDT 可用余额不足(期权请先兑成 USDC 并划入交易账户)" + return _OKX_OPTION_ERR_ZH["51008"] zh = _OKX_OPTION_ERR_ZH.get(code) if zh: return zh - msg = str(row.get("sMsg") or "").strip() if msg: return msg if exc is not None: @@ -79,6 +66,28 @@ def _okx_trade_error_message(exc: BaseException | None = None, resp: Any = None) return "下单失败" +_OPTIONS_BALANCE_CACHE: dict[str, Any] = {"updated_at": 0.0, "data": None} + +# public/instruments 全族缓存:合约列表变化慢,限频时用旧数据保活 +_OPTION_INSTRUMENTS_CACHE: dict[str, dict[str, Any]] = {} +_OPTION_INSTRUMENTS_CACHE_LOCK = threading.Lock() +_OPTION_INSTRUMENTS_CACHE_TTL = 90.0 +_OPTION_INSTRUMENTS_STALE_MAX = 600.0 + + +def invalidate_options_balance_cache() -> None: + _OPTIONS_BALANCE_CACHE["updated_at"] = 0.0 + _OPTIONS_BALANCE_CACHE["data"] = None + + +def invalidate_option_instruments_cache(inst_family: str | None = None) -> None: + with _OPTION_INSTRUMENTS_CACHE_LOCK: + if inst_family: + _OPTION_INSTRUMENTS_CACHE.pop(str(inst_family), None) + else: + _OPTION_INSTRUMENTS_CACHE.clear() + + def td_mode_for_option_buy(configured: str | None = None) -> str: """OKX 买入期权(多头)必须使用逐仓.""" mode = (configured or "isolated").strip().lower() diff --git a/tests/test_okx_spot_swap.py b/tests/test_okx_spot_swap.py index 9de2608..eb2eaf7 100644 --- a/tests/test_okx_spot_swap.py +++ b/tests/test_okx_spot_swap.py @@ -37,9 +37,24 @@ class TestOkxSpotSwap(unittest.TestCase): ) result = spot_market_swap_usdt_usdc(ex, direction="usdt_to_usdc", amount=20) self.assertFalse(result["ok"]) - self.assertEqual(result["msg"], "资金账户 USDT 可用余额不足") + self.assertEqual(result["msg"], "USDT 可用余额不足(期权请先兑成 USDC 并划入交易账户)") self.assertNotIn("{", result["msg"]) + def test_insufficient_usdc_message(self): + from lib.exchange.okx_options_lib import _okx_trade_error_message + + msg = _okx_trade_error_message( + resp={ + "data": [ + { + "sCode": "51008", + "sMsg": "Order failed. Insufficient USDC balance in account.", + } + ] + } + ) + self.assertEqual(msg, "交易账户 USDC 可用余额不足") + if __name__ == "__main__": unittest.main()