Add delete for closed trade records.

Only closed groups can be removed from local history; equity is unchanged.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-08-07 16:06:36 +08:00
parent ec244c63c6
commit 42e56d940c
5 changed files with 331 additions and 68 deletions
+43
View File
@@ -190,3 +190,46 @@ async def group_detail(
"fills": [_row(x) for x in fills],
"pnl_summary": gr.get("pnl_summary"),
}
@router.delete("/groups/{group_id}")
async def delete_group(
group_id: str, _user: Annotated[str, Depends(require_user)]
) -> dict:
"""删除一条已平仓交易记录(组/成交/残留/相关账本流水)。不回滚权益。"""
db = get_db()
g = db.fetchone("SELECT * FROM groups WHERE group_id=?", (group_id,))
if g is None:
raise HTTPException(status_code=404, detail="group not found")
status = str(g["status"] or "").lower()
if status != "closed":
raise HTTPException(
status_code=409,
detail="只能删除已平仓记录;持仓中或开仓中的组不可删",
)
pos = db.fetchone("SELECT group_id FROM positions WHERE id=1")
if pos and str(pos["group_id"] or "") == group_id:
raise HTTPException(
status_code=409,
detail="当前持仓仍引用该组,不可删除",
)
with db._lock:
db._conn.execute("DELETE FROM fills WHERE group_id=?", (group_id,))
db._conn.execute(
"DELETE FROM residual_options WHERE group_id=?", (group_id,)
)
db._conn.execute(
"DELETE FROM ledger_entries WHERE group_id=?", (group_id,)
)
cur = db._conn.execute(
"DELETE FROM groups WHERE group_id=? AND status='closed'",
(group_id,),
)
if cur.rowcount <= 0:
db._conn.rollback()
raise HTTPException(
status_code=409,
detail="删除失败:组状态已变更",
)
db._conn.commit()
return {"ok": True, "group_id": group_id}
+26 -26
View File
@@ -139,34 +139,34 @@ def assess_open_capacity(
idx, ask_book = _index_and_option_ask()
ask = float(option_ask) if option_ask is not None and float(option_ask) > 0 else ask_book
if hedge == "option_option":
ca = float(call_ask) if call_ask is not None and float(call_ask) > 0 else None
pa = float(put_ask) if put_ask is not None and float(put_ask) > 0 else None
if ca is None or pa is None:
# 回退:用监控对 call/put 卖一
try:
from .session import get_session
if hedge == "option_option":
ca = float(call_ask) if call_ask is not None and float(call_ask) > 0 else None
pa = float(put_ask) if put_ask is not None and float(put_ask) > 0 else None
if ca is None or pa is None:
# 回退:用监控对 call/put 卖一
try:
from .session import get_session
snap = get_session().snapshot()
if ca is None and snap.call and snap.call.ask:
ca = float(snap.call.ask)
if pa is None and snap.put and snap.put.ask:
pa = float(snap.put.ask)
except Exception:
pass
cush = float(
ledger.get_setting_float("oo_budget_cushion", s.oo_budget_cushion)
or s.oo_budget_cushion
)
cush = min(1.0, max(0.5, cush))
if ca is not None and pa is not None and ca > 0 and pa > 0:
# 与定仓一致:按预留后的权利金需求估资金门
premium_need = (ca + pa) * opt_qty * (1.0 + fee_rate) * cush
else:
premium_need = None
margin_need = 0.0
perp_qty = 0.0
snap = get_session().snapshot()
if ca is None and snap.call and snap.call.ask:
ca = float(snap.call.ask)
if pa is None and snap.put and snap.put.ask:
pa = float(snap.put.ask)
except Exception:
pass
cush = float(
ledger.get_setting_float("oo_budget_cushion", s.oo_budget_cushion)
or s.oo_budget_cushion
)
cush = min(1.0, max(0.5, cush))
if ca is not None and pa is not None and ca > 0 and pa > 0:
# 与定仓一致:按预留后的权利金需求估资金门
premium_need = (ca + pa) * opt_qty * (1.0 + fee_rate) * cush
else:
premium_need = None
margin_need = 0.0
perp_qty = 0.0
else:
margin_need = (float(idx) * perp_qty / lev) if idx and idx > 0 else None
premium_need = (
float(ask) * opt_qty * (1.0 + fee_rate) if ask is not None and ask > 0 else None