模拟盘对齐币本位:钱包支持 ETH/BTC,现货桥与期权权利金走本地撮合。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-08-20 15:16:51 +08:00
parent c8688a11ae
commit 6f721d1e6d
6 changed files with 836 additions and 516 deletions
+144 -8
View File
@@ -192,10 +192,10 @@ def _patch_okx_options_lib(app_module: Any) -> None:
if _GET_DB is not None and is_sim_mode(_GET_DB):
w = broker().balances_header()
return (
round(float(w["trading_usdc"]), 2),
round(float(w["funding_usdc"]), 2),
round(float(w["funding_usdt"]), 2),
round(float(w["trading_usdt"]), 2),
round(float(w.get("trading_usdc") or 0), 2),
round(float(w.get("funding_usdc") or 0), 2),
round(float(w.get("funding_usdt") or 0), 2),
round(float(w.get("trading_usdt") or 0), 2),
)
except Exception:
pass
@@ -207,20 +207,32 @@ def _patch_okx_options_lib(app_module: Any) -> None:
try:
if _GET_DB is not None and is_sim_mode(_GET_DB):
w = broker().balances_header()
fu = float(w["funding_usdt"])
fc = float(w["funding_usdc"])
tu = float(w["trading_usdt"])
tc = float(w["trading_usdc"])
fu = float(w.get("funding_usdt") or 0)
fc = float(w.get("funding_usdc") or 0)
tu = float(w.get("trading_usdt") or 0)
tc = float(w.get("trading_usdc") or 0)
fe = float(w.get("funding_eth") or 0)
te = float(w.get("trading_eth") or 0)
fb = float(w.get("funding_btc") or 0)
tb = float(w.get("trading_btc") or 0)
return {
"scope": "main",
"funding_usdt": fu,
"funding_usdc": fc,
"trading_usdt": tu,
"trading_usdc": tc,
"funding_eth": fe,
"trading_eth": te,
"funding_btc": fb,
"trading_btc": tb,
"funding_usdt_avail": fu,
"funding_usdc_avail": fc,
"trading_usdt_avail": tu,
"trading_usdc_avail": tc,
"funding_eth_avail": fe,
"trading_eth_avail": te,
"funding_btc_avail": fb,
"trading_btc_avail": tb,
}
except Exception:
pass
@@ -355,6 +367,130 @@ def _patch_okx_options_lib(app_module: Any) -> None:
opt_lib.fetch_option_positions = fetch_option_positions
opt_lib._sim_hooks_applied = True
_patch_spot_bridge_lib()
def _patch_spot_bridge_lib() -> None:
"""币本位现货桥:模拟盘走本地 USDT↔ETH/BTC,勿打实盘 private_post_trade_order."""
import lib.options.options_spot_bridge_lib as bridge_lib
if getattr(bridge_lib, "_sim_hooks_applied", False):
return
_orig_buy = bridge_lib.spot_market_buy_coin_with_usdt
_orig_sell = bridge_lib.spot_market_sell_coin_to_usdt
_orig_avail = bridge_lib.fetch_trading_coin_available
def fetch_trading_coin_available(ex, ccy: str):
try:
if _GET_DB is not None and is_sim_mode(_GET_DB):
ccy_u = (ccy or "").strip().upper()
if ccy_u not in ("ETH", "BTC"):
return None
w = broker().balances_header()
return float(w.get(f"trading_{ccy_u.lower()}") or 0)
except Exception:
pass
return _orig_avail(ex, ccy)
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
)
if pub is None:
return {"ok": False, "msg": "sim: 无公开行情 exchange"}
result = broker().convert_usdt_coin(
pub,
underlying=underlying,
direction="usdt_to_coin",
amount=float(usdt_amount),
account="trading",
)
if not result.get("ok"):
return {
"ok": False,
"msg": result.get("detail") or result.get("msg") or "买币失败",
}
try:
from lib.instance.instance_live_push_lib import notify_instance_balance_changed
notify_instance_balance_changed()
except Exception:
pass
return {
"ok": True,
"inst_id": result.get("inst_id") or "",
"ord_id": f"sim-spot-buy-{result.get('fill_px') or 0}",
"sim": True,
"coin_bought": result.get("coin_bought"),
"data": {"sCode": "0", "sMsg": "sim filled"},
**{k: result[k] for k in ("fill_px", "usdt_spent", "underlying") if k in result},
}
except Exception as e:
return {"ok": False, "msg": str(e)}
return _orig_buy(ex, underlying=underlying, usdt_amount=usdt_amount)
def spot_market_sell_coin_to_usdt(ex, *, underlying: str, coin_amount: float | None = None):
try:
if _GET_DB is not None and is_sim_mode(_GET_DB):
coin = (underlying or "ETH").strip().upper() or "ETH"
amt = coin_amount
if amt is None or float(amt) <= 0:
amt = fetch_trading_coin_available(ex, coin)
if amt is None or float(amt) <= 0:
return {"ok": False, "msg": f"交易账户无可用 {coin}"}
sell_sz = float(amt)
if sell_sz > 1e-8:
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
)
if pub is None:
return {"ok": False, "msg": "sim: 无公开行情 exchange"}
result = broker().convert_usdt_coin(
pub,
underlying=coin,
direction="coin_to_usdt",
amount=float(sell_sz),
account="trading",
)
if not result.get("ok"):
return {
"ok": False,
"msg": result.get("detail") or result.get("msg") or "卖币失败",
}
try:
from lib.instance.instance_live_push_lib import notify_instance_balance_changed
notify_instance_balance_changed()
except Exception:
pass
return {
"ok": True,
"inst_id": result.get("inst_id") or "",
"ord_id": f"sim-spot-sell-{result.get('fill_px') or 0}",
"coin_sold": float(sell_sz),
"sim": True,
"usdt_recovered": result.get("usdt_recovered"),
"data": {"sCode": "0", "sMsg": "sim filled"},
}
except Exception as e:
return {"ok": False, "msg": str(e)}
return _orig_sell(ex, underlying=underlying, coin_amount=coin_amount)
bridge_lib.fetch_trading_coin_available = fetch_trading_coin_available
bridge_lib.spot_market_buy_coin_with_usdt = spot_market_buy_coin_with_usdt
bridge_lib.spot_market_sell_coin_to_usdt = spot_market_sell_coin_to_usdt
bridge_lib._sim_hooks_applied = True
def wrap_option_place_fns(get_db: Callable, live_place_limit, live_place_market):
"""返回按模式分流的 place_option_limit/market."""