Fix LIVE open/close double-book and security audit findings.
Prevent expiry dual-close from re-booking option cash, abandon ledger rejection, margin-mode mismatch, and manual close races; harden fill wait and refuse default AUTH_SECRET on LIVE. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+32
-25
@@ -103,16 +103,20 @@ async def sim_open_group(
|
||||
db.fetchall("SELECT group_id FROM groups WHERE group_id LIKE ?", (f"G-{wkey}-%",))
|
||||
)
|
||||
gid = next_group_id(count)
|
||||
r = ex.open_group(
|
||||
group_id=gid,
|
||||
bias=bias,
|
||||
option_side=option_side,
|
||||
perp_side=perp_side,
|
||||
option_inst_id=option_inst,
|
||||
entry_index_px=float(pick.underlying_px),
|
||||
strike=pick.pair.strike,
|
||||
expiry_ymd=pick.pair.expiry_ymd,
|
||||
)
|
||||
engine = get_engine()
|
||||
async with engine._lock:
|
||||
if ex.has_open_position():
|
||||
raise HTTPException(status_code=409, detail="有未平仓,禁止开下一组")
|
||||
r = ex.open_group(
|
||||
group_id=gid,
|
||||
bias=bias,
|
||||
option_side=option_side,
|
||||
perp_side=perp_side,
|
||||
option_inst_id=option_inst,
|
||||
entry_index_px=float(pick.underlying_px),
|
||||
strike=pick.pair.strike,
|
||||
expiry_ymd=pick.pair.expiry_ymd,
|
||||
)
|
||||
if not r.ok:
|
||||
raise HTTPException(status_code=400, detail=r.detail)
|
||||
try:
|
||||
@@ -151,22 +155,25 @@ async def sim_close_group(_user: Annotated[str, Depends(require_user)]) -> dict:
|
||||
)
|
||||
from ..strategy import get_engine
|
||||
|
||||
r = get_executor().close_group(reason="manual")
|
||||
if not r.ok and not r.liquidity_wait:
|
||||
raise HTTPException(status_code=400, detail=r.detail)
|
||||
if r.ok:
|
||||
# 与自动/紧急全平一致:成功全平后进入组间休息
|
||||
get_engine().enter_rest_after_close()
|
||||
try:
|
||||
from ..notify import wecom
|
||||
engine = get_engine()
|
||||
# 与策略引擎共用锁,避免与自动平仓/开仓竞态
|
||||
async with engine._lock:
|
||||
r = get_executor().close_group(reason="manual")
|
||||
if not r.ok and not r.liquidity_wait:
|
||||
raise HTTPException(status_code=400, detail=r.detail)
|
||||
if r.ok:
|
||||
# 与自动/紧急全平一致:成功全平后进入组间休息
|
||||
engine.enter_rest_after_close()
|
||||
try:
|
||||
from ..notify import wecom
|
||||
|
||||
wecom.notify_close(
|
||||
reason="manual",
|
||||
detail=r.detail,
|
||||
data=r.data or {},
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
wecom.notify_close(
|
||||
reason="manual",
|
||||
detail=r.detail,
|
||||
data=r.data or {},
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
return {
|
||||
"ok": r.ok,
|
||||
"liquidity_wait": r.liquidity_wait,
|
||||
|
||||
Reference in New Issue
Block a user