币本位盈亏双显ETH/U(按指数换算);平仓卖币改为卖光交易户可用余额
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -115,6 +115,24 @@ def build_options_hub_snapshot(cfg: dict[str, Any]) -> dict[str, Any]:
|
||||
)
|
||||
p["margin_mode_label"] = "币本位" if row_mode == "coin" else "USDC"
|
||||
|
||||
underly = (os.getenv("OKX_OPTIONS_DEFAULT_UNDERLY") or "ETH").strip().upper() or "ETH"
|
||||
options_index_px = None
|
||||
try:
|
||||
from lib.exchange.okx_options_lib import fetch_index_price
|
||||
|
||||
options_index_px = fetch_index_price(ex, underly)
|
||||
except Exception:
|
||||
options_index_px = None
|
||||
if options_index_px is None:
|
||||
for p in positions:
|
||||
try:
|
||||
px = float(p.get("idx_px") or p.get("idxPx") or 0)
|
||||
except (TypeError, ValueError):
|
||||
px = 0
|
||||
if px > 0:
|
||||
options_index_px = px
|
||||
break
|
||||
|
||||
coin_budget = None
|
||||
bridge_status = None
|
||||
open_bridges = []
|
||||
@@ -157,7 +175,8 @@ def build_options_hub_snapshot(cfg: dict[str, Any]) -> dict[str, Any]:
|
||||
"max_active_positions": options_max_active_positions(),
|
||||
"options_margin_mode": margin_mode,
|
||||
"options_margin_mode_label": "币本位" if margin_mode == "coin" else "USDC",
|
||||
"options_underly": (os.getenv("OKX_OPTIONS_DEFAULT_UNDERLY") or "ETH").strip().upper() or "ETH",
|
||||
"options_underly": underly,
|
||||
"options_index_px": options_index_px,
|
||||
"coin_budget": coin_budget,
|
||||
"bridge_status": bridge_status,
|
||||
"open_bridges": open_bridges,
|
||||
|
||||
@@ -221,26 +221,32 @@ def spot_market_sell_coin_to_usdt(
|
||||
underlying: str,
|
||||
coin_amount: float | None = None,
|
||||
) -> dict[str, Any]:
|
||||
"""交易账户:市价卖出标的币换 USDT.coin_amount 空则尽量卖光可用."""
|
||||
"""交易账户:市价卖出标的币换 USDT.
|
||||
|
||||
默认/推荐:coin_amount 为空 → 卖光交易账户全部可用币(全部卖出).
|
||||
传入 coin_amount 时仍不超过可用余额,且尽量按可用全额卖出(不故意留粉尘).
|
||||
"""
|
||||
ccy = (underlying or "ETH").upper()
|
||||
amt = coin_amount
|
||||
if amt is None or float(amt) <= 0:
|
||||
avail = fetch_trading_coin_available(ex, ccy)
|
||||
if avail is None or float(avail) <= 0:
|
||||
return {"ok": False, "msg": f"交易账户无可用 {ccy}"}
|
||||
amt = float(avail)
|
||||
if float(amt) <= 0:
|
||||
avail = fetch_trading_coin_available(ex, ccy)
|
||||
if avail is None or float(avail) <= 0:
|
||||
return {"ok": False, "msg": f"交易账户无可用 {ccy}"}
|
||||
avail_f = float(avail)
|
||||
# 全部卖出:以可用余额为准;若传入数量则不超过可用(开仓失败回滚用)
|
||||
if coin_amount is None or float(coin_amount) <= 0:
|
||||
sell_sz = avail_f
|
||||
else:
|
||||
sell_sz = min(float(coin_amount), avail_f)
|
||||
if sell_sz <= 0:
|
||||
return {"ok": False, "msg": f"{ccy} 数量须大于 0"}
|
||||
# 留一点粉尘避免精度拒单
|
||||
sell_sz = float(amt)
|
||||
if sell_sz > 1e-8:
|
||||
sell_sz = max(0.0, sell_sz * 0.999)
|
||||
inst_id = spot_quote_inst_id(ccy)
|
||||
try:
|
||||
# 现货卖出数量精度:截到 8 位
|
||||
# 现货卖出:向下截到 8 位,避免超过可用被拒;不再 *0.999 故意留残
|
||||
sz = f"{sell_sz:.8f}".rstrip("0").rstrip(".")
|
||||
if not sz or float(sz) <= 0:
|
||||
return {"ok": False, "msg": f"{ccy} 可卖数量过小"}
|
||||
# 二次钳制:格式化后仍不得超过可用
|
||||
if float(sz) > avail_f:
|
||||
sz = f"{avail_f:.8f}".rstrip("0").rstrip(".")
|
||||
body = {
|
||||
"instId": inst_id,
|
||||
"tdMode": "cash",
|
||||
@@ -328,13 +334,8 @@ def sell_residual_after_option_flat(
|
||||
if not underlying or str(b.get("underlying") or "").upper() == underlying.upper():
|
||||
target = b
|
||||
break
|
||||
coin_amt = None
|
||||
if target is not None:
|
||||
try:
|
||||
coin_amt = float(target.get("coin_bought") or 0) or None
|
||||
except (TypeError, ValueError):
|
||||
coin_amt = None
|
||||
sell = spot_market_sell_coin_to_usdt(ex, underlying=underlying, coin_amount=coin_amt)
|
||||
# 平仓后全部卖出交易账户可用标的币(含权利金盈亏留下的币),不按 bridge 记账量限卖
|
||||
sell = spot_market_sell_coin_to_usdt(ex, underlying=underlying, coin_amount=None)
|
||||
if target is None:
|
||||
if not sell.get("ok"):
|
||||
msg = str(sell.get("msg") or "")
|
||||
|
||||
Reference in New Issue
Block a user