Add control residual options table with liquidity-only manual close.
Fleet status exposes enriched residuals; manual close skips the premium recovery gate while auto mid-close remains unchanged. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1250,21 +1250,26 @@ class OkxLiveExecutor(Matcher):
|
||||
}
|
||||
return row
|
||||
|
||||
def try_close_one_residual(self, row: dict) -> dict | None:
|
||||
"""LIVE:权利金达标后按最新买一 IOC 限价卖出归档期权(不扫市价)。"""
|
||||
def try_close_one_residual(
|
||||
self, row: dict, *, skip_premium_ratio: bool = False
|
||||
) -> dict | None:
|
||||
"""LIVE:流动性通过后按最新买一 IOC 限价卖;自动路径另要求权利金比例。"""
|
||||
err = self._guard_live()
|
||||
if err:
|
||||
logger.warning("residual premium close blocked: %s", err)
|
||||
logger.warning("residual close blocked: %s", err)
|
||||
return None
|
||||
synced = self._sync_residual_contracts_with_exchange(row)
|
||||
if synced is None:
|
||||
return None
|
||||
row = synced
|
||||
skip, close_bid, _oq = self._evaluate_residual_premium_close(row)
|
||||
require_ratio = not skip_premium_ratio
|
||||
skip, close_bid, _oq = self._evaluate_residual_premium_close(
|
||||
row, require_premium_ratio=require_ratio
|
||||
)
|
||||
if skip or close_bid is None:
|
||||
if skip:
|
||||
logger.debug(
|
||||
"residual premium close skip %s: %s",
|
||||
"residual close skip %s: %s",
|
||||
row.get("group_id"),
|
||||
skip,
|
||||
)
|
||||
@@ -1277,17 +1282,19 @@ class OkxLiveExecutor(Matcher):
|
||||
opt_contracts = float(contracts_for_eth(opt_qty, ct) or 0)
|
||||
if opt_contracts <= 0:
|
||||
logger.warning(
|
||||
"residual premium close skip %s: bad contracts", row.get("group_id")
|
||||
"residual close skip %s: bad contracts", row.get("group_id")
|
||||
)
|
||||
return None
|
||||
oq2 = self._quote_held_option(option_inst_id)
|
||||
if oq2 is None or oq2.bid is None:
|
||||
return None
|
||||
bid_px = float(oq2.bid)
|
||||
skip2 = self._residual_bid_gate(row, bid=bid_px, oq=oq2)
|
||||
skip2 = self._residual_bid_gate(
|
||||
row, bid=bid_px, oq=oq2, require_premium_ratio=require_ratio
|
||||
)
|
||||
if skip2:
|
||||
logger.debug(
|
||||
"residual premium close recheck skip %s: %s",
|
||||
"residual close recheck skip %s: %s",
|
||||
row.get("group_id"),
|
||||
skip2,
|
||||
)
|
||||
@@ -1304,7 +1311,7 @@ class OkxLiveExecutor(Matcher):
|
||||
)
|
||||
except Exception as e:
|
||||
logger.warning(
|
||||
"residual premium close bid-ioc sell failed %s: %s",
|
||||
"residual close bid-ioc sell failed %s: %s",
|
||||
row.get("group_id"),
|
||||
e,
|
||||
)
|
||||
@@ -1321,6 +1328,7 @@ class OkxLiveExecutor(Matcher):
|
||||
remaining = max(0.0, opt_contracts - filled_c)
|
||||
fill_eth = eth_from_contracts(filled_c, self._ct_mult(option_inst_id))
|
||||
now_ms = int(time.time() * 1000)
|
||||
tag = "manual" if skip_premium_ratio else "mid"
|
||||
return self._book_residual_market_close(
|
||||
row,
|
||||
fill_px=of_px,
|
||||
@@ -1328,11 +1336,15 @@ class OkxLiveExecutor(Matcher):
|
||||
notional=of_px * fill_eth,
|
||||
slip=0.0,
|
||||
now_ms=now_ms,
|
||||
note=f"LIVE residual mid-close at bid IOC px={bid_px}",
|
||||
note=f"LIVE residual {tag}-close at bid IOC px={bid_px}",
|
||||
exec_mode="LIVE",
|
||||
filled_contracts=filled_c,
|
||||
remaining_contracts=remaining,
|
||||
close_reason="residual_premium_close",
|
||||
close_reason=(
|
||||
"residual_manual_close"
|
||||
if skip_premium_ratio
|
||||
else "residual_premium_close"
|
||||
),
|
||||
)
|
||||
|
||||
def _try_exchange_flatten_residual(
|
||||
|
||||
Reference in New Issue
Block a user