Fix strategy-logic P0s from audit: monitor false-flat, fill-confirmed open/close, mode gates.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-07-30 09:56:18 +08:00
parent fa7ff739a0
commit 4b4dca9e3c
15 changed files with 820 additions and 167 deletions
+139 -18
View File
@@ -480,8 +480,44 @@ def register_options_routes(app: Flask, cfg: dict[str, Any]) -> None:
"budget_full_usdc": budget if mode == "budget_full" else None,
}
)
except Exception:
pass
except Exception as e:
return jsonify(
{
"ok": False,
"can_open": False,
"msg": f"交易模式校验失败: {e}",
}
)
try:
from lib.hedge_plan.hedge_options_exclusive_lib import block_standalone_option_open_msg
conn_q = cfg["get_db"]()
try:
excl = block_standalone_option_open_msg(conn_q)
finally:
conn_q.close()
if excl:
return jsonify(
{
**q,
"ok": True,
"can_open": False,
"msg": excl,
"quote_per_unit": ask,
"premium_per_sheet": None,
"sizing": {
"ok": False,
"msg": excl,
"sheets": 0,
"eth_amount": 0.0,
"total_premium": 0.0,
},
"available_usdc": available_usdc,
"budget_full_usdc": budget if mode == "budget_full" else None,
}
)
except Exception as e:
return jsonify({"ok": False, "can_open": False, "msg": f"互斥校验失败: {e}"})
can_open, block_msg = option_buy_liquidity_ok(ask, ask_sz)
if not can_open:
# 合约可报价,但不可开仓:返回参考标记价供展示
@@ -598,8 +634,8 @@ def register_options_routes(app: Flask, cfg: dict[str, Any]) -> None:
mode_block = block_standalone_open_by_mode_msg()
if mode_block:
return jsonify({"ok": False, "msg": mode_block, "can_open": False})
except Exception:
pass
except Exception as e:
return jsonify({"ok": False, "msg": f"交易模式校验失败: {e}", "can_open": False})
try:
from lib.hedge_plan.hedge_options_exclusive_lib import block_standalone_option_open_msg
@@ -610,8 +646,8 @@ def register_options_routes(app: Flask, cfg: dict[str, Any]) -> None:
conn_gate.close()
if block_msg:
return jsonify({"ok": False, "msg": block_msg})
except Exception:
pass
except Exception as e:
return jsonify({"ok": False, "msg": f"互斥校验失败: {e}"})
data = request.get_json(silent=True) or {}
inst_id = (data.get("inst_id") or "").strip()
mode = (data.get("mode") or "budget_full").strip()
@@ -690,16 +726,14 @@ def register_options_routes(app: Flask, cfg: dict[str, Any]) -> None:
if capped is None:
return jsonify({"ok": False, "msg": cap_msg or "卖一深度不足,无法买入"})
if capped < sheets:
sizing = calc_order_size(
quote_per_unit=float(ask),
ct_mult=ct_mult,
min_sz=min_sz,
sheets=capped,
budget_cap=budget_cap if mode in ("budget_full", "sheets", "eth_amount") else None,
return jsonify(
{
"ok": False,
"msg": f"卖一深度仅 {int(capped)} 张,不足请求 {int(sheets)} 张,拒绝缩量成交",
"requested_sheets": int(sheets),
"ask_sz": ask_sz,
}
)
if not sizing.get("ok"):
return jsonify({"ok": False, "msg": sizing.get("msg") or "张数计算失败", "sizing": sizing})
sheets = int(sizing["sheets"])
tick_sz = q.get("tick_sz")
order = cfg["place_option_limit_order"](
ex,
@@ -709,9 +743,56 @@ def register_options_routes(app: Flask, cfg: dict[str, Any]) -> None:
price=float(ask),
td_mode=td_mode_for_option_buy(cfg["td_mode"]),
tick_sz=tick_sz,
ord_type="ioc",
)
if not order.get("ok"):
return jsonify(order)
ord_id = str((order.get("data") or {}).get("ordId") or "").strip()
if not ord_id:
return jsonify({"ok": False, "msg": "下单成功但未返回订单号", "order": order})
from lib.exchange.okx_options_lib import wait_option_order_full_fill
try:
fill_timeout = max(2.0, float(os.getenv("OKX_OPTIONS_OPEN_FILL_TIMEOUT_SEC") or "12"))
except (TypeError, ValueError):
fill_timeout = 12.0
fill = wait_option_order_full_fill(
ex,
inst_id=inst_id,
ord_id=ord_id,
need_sheets=int(sheets),
timeout_sec=fill_timeout,
cancel_on_timeout=True,
)
if not fill.get("ok"):
filled_n = int(fill.get("filled_sheets") or 0)
orphan_close = None
if filled_n > 0:
try:
from lib.options.options_close_exec_lib import close_option_by_bid1
orphan_close = close_option_by_bid1(
cfg, ex, inst_id, sheets=filled_n, require_recycle_gate=False
)
except Exception as e:
orphan_close = {"ok": False, "msg": str(e)}
return jsonify(
{
"ok": False,
"msg": fill.get("msg") or "未完全成交,开仓失败",
"filled_sheets": filled_n,
"orphan_close": orphan_close,
"fill": fill,
"order": order,
}
)
fill_px = float(fill.get("avg_px") or ask)
filled_n = int(fill.get("filled_sheets") or sheets)
sheets = filled_n
sizing = dict(sizing)
sizing["sheets"] = sheets
sizing["eth_amount"] = round(sheets * ct_mult, 8)
sizing["total_premium"] = round(fill_px * sheets * ct_mult, 4)
conn = cfg["get_db"]()
trade_id = None
target_mon = None
@@ -739,10 +820,10 @@ def register_options_routes(app: Flask, cfg: dict[str, Any]) -> None:
str(q.get("exp_time") or ""),
sheets,
sizing["eth_amount"],
float(ask),
fill_px,
sizing["total_premium"],
signal_note,
(order.get("data") or {}).get("ordId"),
ord_id,
),
)
trade_id = int(cur.lastrowid)
@@ -778,7 +859,7 @@ def register_options_routes(app: Flask, cfg: dict[str, Any]) -> None:
opt_type=open_opt_type,
sheets=sheets,
premium_paid=sizing.get("total_premium"),
open_quote=float(ask) if ask is not None else None,
open_quote=fill_px,
target_index=target_index,
signal_note=signal_note,
)
@@ -937,6 +1018,26 @@ def register_options_routes(app: Flask, cfg: dict[str, Any]) -> None:
inst_id = (data.get("inst_id") or "").strip()
if not inst_id:
return jsonify({"ok": False, "msg": "缺少 inst_id"})
try:
from lib.hedge_plan.hedge_plan_db import (
active_hedge_option_inst_ids,
init_hedge_plan_tables,
)
conn_h = cfg["get_db"]()
try:
init_hedge_plan_tables(conn_h)
if inst_id in active_hedge_option_inst_ids(conn_h):
return jsonify(
{
"ok": False,
"msg": "该合约属于进行中的对冲计划,请在对冲计划中管理,禁止在期权页设置目标",
}
)
finally:
conn_h.close()
except Exception as e:
return jsonify({"ok": False, "msg": f"对冲托管校验失败: {e}"})
try:
target_index = float(data.get("target_index"))
except (TypeError, ValueError):
@@ -1013,6 +1114,26 @@ def register_options_routes(app: Flask, cfg: dict[str, Any]) -> None:
inst_id = (data.get("inst_id") or "").strip()
if not inst_id:
return jsonify({"ok": False, "msg": "缺少 inst_id"})
try:
from lib.hedge_plan.hedge_plan_db import (
active_hedge_option_inst_ids,
init_hedge_plan_tables,
)
conn_h = cfg["get_db"]()
try:
init_hedge_plan_tables(conn_h)
if inst_id in active_hedge_option_inst_ids(conn_h):
return jsonify(
{
"ok": False,
"msg": "该合约属于进行中的对冲计划,请在对冲计划中管理,禁止在期权页平仓",
}
)
finally:
conn_h.close()
except Exception as e:
return jsonify({"ok": False, "msg": f"对冲托管校验失败: {e}"})
if data.get("market"):
return jsonify({"ok": False, "msg": "已禁用市价平仓,仅支持买一限价"})
sheets = data.get("sheets")