Pin market watch to held option strike while a position is open.
Stop falling back to ATM quotes for unrealized/close PnL after ATM drifts or restart. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -348,9 +348,13 @@ class Matcher:
|
||||
|
||||
option_inst_id = str(pos["option_inst_id"])
|
||||
option_side = str(pos["option_side"])
|
||||
oq = get_exchange().quote(option_inst_id) or (
|
||||
snap.call if option_side == "call" else snap.put
|
||||
)
|
||||
# 严禁回退到 ATM 对:持仓行权价可能已偏离当前 ATM
|
||||
oq = self._quote_held_option(option_inst_id)
|
||||
if oq is None and reason != "expiry":
|
||||
return CloseResult(
|
||||
ok=False,
|
||||
detail=f"持仓期权盘口不可用: {option_inst_id}",
|
||||
)
|
||||
|
||||
ct_mult = self._ct_mult(option_inst_id)
|
||||
need_eth = float(pos["option_qty_eth"] or s.option_qty_eth)
|
||||
@@ -888,6 +892,29 @@ class Matcher:
|
||||
"forced": force,
|
||||
}
|
||||
|
||||
def _quote_held_option(self, option_inst_id: str):
|
||||
"""只取持仓合约盘口;缺失时 REST 补一次,绝不借用 ATM 对。"""
|
||||
if not option_inst_id:
|
||||
return None
|
||||
ex = get_exchange()
|
||||
oq = ex.quote(option_inst_id)
|
||||
if oq is not None and (oq.bid is not None or oq.ask is not None or oq.mark_px is not None):
|
||||
return oq
|
||||
try:
|
||||
bids, asks, ts = ex.fetch_book(option_inst_id, depth=5)
|
||||
cache = getattr(ex, "cache", None)
|
||||
if cache is not None and (bids or asks):
|
||||
cache.upsert_book(option_inst_id, bids=bids, asks=asks, ts_ms=ts)
|
||||
try:
|
||||
mp = ex.fetch_mark(option_inst_id)
|
||||
if mp:
|
||||
cache.set_mark_px(option_inst_id, mp)
|
||||
except Exception:
|
||||
pass
|
||||
return ex.quote(option_inst_id)
|
||||
except Exception:
|
||||
return ex.quote(option_inst_id)
|
||||
|
||||
def unrealized(self) -> dict[str, Any]:
|
||||
pos = self.current_position()
|
||||
if pos.get("status") != "open":
|
||||
@@ -947,9 +974,7 @@ class Matcher:
|
||||
|
||||
option_side = str(pos["option_side"])
|
||||
opt_inst = str(pos.get("option_inst_id") or "")
|
||||
oq = get_exchange().quote(opt_inst) if opt_inst else None
|
||||
if oq is None:
|
||||
oq = snap.call if option_side == "call" else snap.put
|
||||
oq = self._quote_held_option(opt_inst)
|
||||
initial_premium = float(pos["initial_premium"] or 0)
|
||||
option_upl = 0.0
|
||||
est_opt_close_fee = 0.0
|
||||
|
||||
Reference in New Issue
Block a user