Keep unflat legs on 当前持仓 after plan end.
Closed plans with open legs stay visible and closable so residual positions are not orphaned from the UI. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -85,15 +85,28 @@ def _parse_opened_ms(opened_at: Any) -> Optional[int]:
|
||||
return None
|
||||
|
||||
|
||||
def build_live_hedge_cards(cfg: dict[str, Any], conn: Any) -> list[dict[str, Any]]:
|
||||
"""进行中的永期计划 → 期权/永续腿实时卡 + 扣费组合净利."""
|
||||
from lib.hedge_plan.hedge_plan_db import attach_legs_to_plans, list_plans
|
||||
def _pick_leg(
|
||||
legs: list[dict[str, Any]], roles: tuple[str, ...], *, prefer_open: bool = True
|
||||
) -> Optional[dict[str, Any]]:
|
||||
matched = [x for x in legs if str(x.get("leg_role") or "") in roles]
|
||||
if not matched:
|
||||
return None
|
||||
if prefer_open:
|
||||
open_ones = [x for x in matched if str(x.get("status") or "").lower() == "open"]
|
||||
if open_ones:
|
||||
return open_ones[0]
|
||||
return matched[0]
|
||||
|
||||
rows: list[dict[str, Any]] = []
|
||||
for status in ("opening", "active", "partial"):
|
||||
rows.extend(list_plans(conn, status=status, limit=40))
|
||||
rows = [r for r in rows if str(r.get("plan_type") or "") == "perp_options"]
|
||||
rows.sort(key=lambda row: int(row.get("id") or 0), reverse=True)
|
||||
|
||||
def _has_open_leg(legs: list[dict[str, Any]]) -> bool:
|
||||
return any(str(x.get("status") or "").lower() == "open" for x in legs)
|
||||
|
||||
|
||||
def build_live_hedge_cards(cfg: dict[str, Any], conn: Any) -> list[dict[str, Any]]:
|
||||
"""当前持仓:未平完的永期仓(含计划已结束但腿仍 open)."""
|
||||
from lib.hedge_plan.hedge_plan_db import attach_legs_to_plans, list_plans_for_live_positions
|
||||
|
||||
rows = list_plans_for_live_positions(conn, plan_type="perp_options", limit=40)
|
||||
if not rows:
|
||||
return []
|
||||
plans = attach_legs_to_plans(conn, rows)
|
||||
@@ -121,10 +134,22 @@ def build_live_hedge_cards(cfg: dict[str, Any], conn: Any) -> list[dict[str, Any
|
||||
|
||||
for plan in plans:
|
||||
legs = plan.get("legs") or []
|
||||
opt_leg = next((x for x in legs if str(x.get("leg_role") or "") in ("option_hedge", "option_a")), None)
|
||||
perp_leg = next((x for x in legs if str(x.get("leg_role") or "") == "perp"), None)
|
||||
plan_st = str(plan.get("status") or "").lower()
|
||||
# 已结束计划:仅当仍有未平腿才进当前持仓
|
||||
if plan_st == "closed" and not _has_open_leg(legs):
|
||||
continue
|
||||
opt_leg = _pick_leg(legs, ("option_hedge", "option_a"))
|
||||
perp_leg = _pick_leg(legs, ("perp",))
|
||||
if not opt_leg and not perp_leg:
|
||||
continue
|
||||
# 已结束:只展示仍 open 的腿;若该腿已平则置空
|
||||
if plan_st == "closed":
|
||||
if opt_leg and str(opt_leg.get("status") or "").lower() != "open":
|
||||
opt_leg = None
|
||||
if perp_leg and str(perp_leg.get("status") or "").lower() != "open":
|
||||
perp_leg = None
|
||||
if not opt_leg and not perp_leg:
|
||||
continue
|
||||
|
||||
view = str(plan.get("direction") or "long").lower()
|
||||
uly = str(plan.get("underlying") or "ETH").upper()
|
||||
@@ -218,6 +243,7 @@ def build_live_hedge_cards(cfg: dict[str, Any], conn: Any) -> list[dict[str, Any
|
||||
{
|
||||
"plan_id": plan.get("id"),
|
||||
"status": plan.get("status"),
|
||||
"unflat": plan_st == "closed",
|
||||
"underlying": uly,
|
||||
"direction": view,
|
||||
"opened_at": opened_at,
|
||||
|
||||
Reference in New Issue
Block a user