From cfc1d42c09a70765ef22f4d8c1560851949b04b8 Mon Sep 17 00:00:00 2001 From: dekun Date: Wed, 15 Jul 2026 15:37:55 +0800 Subject: [PATCH] Fall back to mark price when option target close has no bid depth. Keeps auto limit-close workable on thin books instead of stalling after the index target is hit. Co-authored-by: Cursor --- lib/options/options_target_lib.py | 34 +++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/lib/options/options_target_lib.py b/lib/options/options_target_lib.py index e53a808..19ac10d 100644 --- a/lib/options/options_target_lib.py +++ b/lib/options/options_target_lib.py @@ -273,8 +273,13 @@ def close_option_by_bid_depth( preview = estimate_close_by_bids(book.get("bids") or [], remaining, ct_mult=ct_mult) levels = preview.get("levels") or [] if not levels: - stopped_reason = "no_bid_depth" - break + # 无买盘时回退:报价买一 → 标记价 → 再查一次 quote + q2 = cfg["quote_option_contract"](ex, inst_id) + fallback_px = _safe_float(q2.get("bid")) or _safe_float(q2.get("mark_px")) or _safe_float(q.get("bid")) or _safe_float(q.get("mark_px")) + if fallback_px is None or fallback_px <= 0: + stopped_reason = "no_bid_depth" + break + levels = [{"sheets": remaining, "px": fallback_px, "fallback": True}] level = levels[0] level_sheets = int(level.get("sheets") or 0) level_px = float(level.get("px") or 0) @@ -319,6 +324,31 @@ def close_option_by_bid_depth( remaining = max(0, close_sheets - filled_or_reduced_sheets) if not orders: + # 最后兜底:允许市价平仓时用市价 + if cfg.get("allow_market_close"): + mkt = cfg["place_option_market_order"]( + ex, + inst_id=inst_id, + side="sell", + sheets=close_sheets, + td_mode=td_mode, + reduce_only=True, + pos_side=pos_side, + ) + if mkt.get("ok"): + oid = str((mkt.get("data") or {}).get("ordId") or "") + return { + "ok": True, + "mode": "market", + "orders": [{"order": mkt, "sheets": close_sheets}], + "submitted_sheets": close_sheets, + "filled_or_reduced_sheets": close_sheets, + "remaining_sheets": 0, + "premium_received": None, + "close_ord_id": oid or None, + "fully_closed": True, + } + return {"ok": False, "msg": mkt.get("msg") or "市价平仓失败", "stopped_reason": stopped_reason} return {"ok": False, "msg": "暂无可用买盘深度,无法限价平仓", "stopped_reason": stopped_reason} avg_bid = (total_received / (submitted_sheets * ct_mult)) if submitted_sheets > 0 and ct_mult > 0 else 0