Improve control monitor cards: green when running, detail modal with positions.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-07-30 11:07:54 +08:00
parent 08fe06d074
commit a317822f7a
3 changed files with 377 additions and 7 deletions
+63 -1
View File
@@ -167,6 +167,38 @@ async def fleet_status(_tok: Annotated[str, Depends(require_fleet_token)]) -> di
st = get_engine().state()
except Exception:
st = {}
pos = st.get("position") if isinstance(st.get("position"), dict) else {}
legs: list[dict] = []
if pos.get("has_position") or str(pos.get("status") or "") in (
"open",
"half_open",
"option_closed_perp_pending",
"opening",
):
if pos.get("perp_side") or pos.get("perp_inst_id"):
legs.append(
{
"kind": "perp",
"side": pos.get("perp_side"),
"inst_id": pos.get("perp_inst_id"),
"qty": pos.get("perp_qty_eth"),
"avg_px": pos.get("perp_entry_px"),
"mark_px": pos.get("perp_mark_px"),
"upl": pos.get("perp_upl"),
}
)
if pos.get("option_side") or pos.get("option_inst_id"):
legs.append(
{
"kind": "option",
"side": pos.get("option_side"),
"inst_id": pos.get("option_inst_id"),
"qty": pos.get("option_qty_eth"),
"avg_px": pos.get("option_entry_px"),
"mark_px": pos.get("option_mark_px"),
"upl": pos.get("option_upl"),
}
)
return {
"ok": True,
"mode": settings.mode,
@@ -175,13 +207,43 @@ async def fleet_status(_tok: Annotated[str, Depends(require_fleet_token)]) -> di
"sim": settings.is_sim,
"market_connected": bool(snap.connected) if snap else False,
"pair": snap.pair.to_dict() if snap and snap.pair else None,
"index_px": (
pos.get("index_px")
if pos.get("index_px") is not None
else (getattr(snap, "index_px", None) if snap else None)
),
"updated_at_ms": snap.updated_at_ms if snap else None,
"strategy": {
"running": st.get("running"),
"phase": st.get("phase"),
"rounds_done": st.get("rounds_done"),
"last_error": st.get("last_error"),
"group_id": st.get("group_id"),
"group_id": pos.get("group_id"),
"rest_left_sec": st.get("rest_left_sec"),
"exit_mode": st.get("exit_mode"),
"exit_target_usdt": st.get("exit_target_usdt"),
"net_profit_target": st.get("net_profit_target"),
"leverage": st.get("leverage"),
"perp_margin_mode": st.get("perp_margin_mode"),
"perp_qty_eth": st.get("perp_qty_eth"),
"option_qty_eth": st.get("option_qty_eth"),
"sizing_mode": st.get("sizing_mode"),
"risk_last_k": st.get("risk_last_k"),
"risk_sizing_locked": st.get("risk_sizing_locked"),
},
"position": {
"status": pos.get("status") or ("open" if pos.get("has_position") else "flat"),
"has_position": bool(pos.get("has_position")),
"group_id": pos.get("group_id"),
"open_at_ms": pos.get("open_at_ms"),
"initial_premium": pos.get("initial_premium"),
"exit_target_usdt": pos.get("exit_target_usdt"),
"net_pnl": pos.get("net_pnl"),
"perp_upl": pos.get("perp_upl"),
"option_upl": pos.get("option_upl"),
"strike": pos.get("strike"),
"expiry_ymd": pos.get("expiry_ymd"),
"legs": legs,
},
"update": {
"running": bool(_update_state.get("running")),