Gate option closes behind 2x recycle sustained for 2 minutes.

Require bid-side recoverable premium at least 2x cost continuously before target auto-close or depth close can fire.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-07-15 21:13:43 +08:00
parent c025c06fac
commit c2a0cea3f4
7 changed files with 387 additions and 38 deletions
+37
View File
@@ -11,6 +11,7 @@ from jinja2 import ChoiceLoader, FileSystemLoader
from lib.options.options_db import init_options_tables
from lib.options.options_monitor_lib import options_monitor_loop
from lib.options.options_close_gate_lib import clear_close_gate, update_close_gate
from lib.options.options_pricing_lib import (
calc_order_size,
close_ref_prices,
@@ -731,6 +732,7 @@ def register_options_routes(app: Flask, cfg: dict[str, Any]) -> None:
usable0, stub_only0, stub_reason0 = filter_bids_for_close(
book0.get("bids") or [], mark_px=mark_px, intrinsic_px=intrinsic_px
)
paid = _open_premium_paid(cfg, inst_id)
if stub_only0 or not usable0:
bid_chk = None
if book0.get("bids"):
@@ -738,6 +740,7 @@ def register_options_routes(app: Flask, cfg: dict[str, Any]) -> None:
bid_chk = bid_chk or _safe_float(bid)
stub, stub_reason = is_stub_bid_px(bid_chk, mark_px=mark_px, intrinsic_px=intrinsic_px)
if stub or stub_only0:
update_close_gate(inst_id, recycle_usdc=None, premium_paid=paid)
return jsonify(
{
"ok": False,
@@ -746,6 +749,39 @@ def register_options_routes(app: Flask, cfg: dict[str, Any]) -> None:
"auto_close_blocked": True,
}
)
preview_gate = estimate_close_by_bids(
book0.get("bids") or [],
close_sheets,
ct_mult=ct_mult,
premium_paid=paid,
mark_px=mark_px,
intrinsic_px=intrinsic_px,
)
if preview_gate.get("bid_invalid"):
update_close_gate(inst_id, recycle_usdc=None, premium_paid=paid)
return jsonify(
{
"ok": False,
"msg": preview_gate.get("bid_invalid_reason") or "暂无有效买盘,禁止按买盘自动平仓",
"stopped_reason": "stub_bid",
"auto_close_blocked": True,
}
)
gate = update_close_gate(
inst_id,
recycle_usdc=_safe_float(preview_gate.get("total_received")),
premium_paid=paid,
)
if not gate.get("ready"):
return jsonify(
{
"ok": False,
"msg": gate.get("msg") or "平仓门控未就绪(需可回收≥2×权利金并持续2分钟)",
"stopped_reason": "close_gate",
"auto_close_blocked": True,
"close_gate": gate,
}
)
remaining = close_sheets
submitted_sheets = 0
filled_or_reduced_sheets = 0
@@ -826,6 +862,7 @@ def register_options_routes(app: Flask, cfg: dict[str, Any]) -> None:
bid = (total_received / (submitted_sheets * ct_mult)) if submitted_sheets > 0 and ct_mult > 0 else 0
prem_recv = round(total_received, 4)
fully_submitted = submitted_sheets >= close_sheets and stopped_reason is None
clear_close_gate(inst_id)
conn = cfg["get_db"]()
try:
init_options_tables(conn)