Enhance dashboard with contract symbols and risk control overview.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-29 21:40:53 +08:00
parent 28c54b1a3f
commit b460c6c4e5
4 changed files with 272 additions and 8 deletions
+86 -2
View File
@@ -16,6 +16,83 @@ def _direction_label(direction: str) -> str:
return "做多" if (direction or "").strip().lower() == "long" else "做空"
def _symbol_fields(ths_code: str) -> dict[str, Any]:
from symbols import position_symbol_meta
sym = (ths_code or "").strip()
meta = position_symbol_meta(sym)
return {
"symbol_code": sym,
"symbol_name": meta.get("name") or sym,
"symbol_exchange": meta.get("exchange") or "",
"symbol_is_main": bool(meta.get("is_main")),
}
def build_risk_overview(
conn,
get_setting: Callable[[str, str], str],
*,
equity: Optional[float] = None,
margin_used: Optional[float] = None,
) -> dict[str, Any]:
from risk.account_risk_lib import (
ensure_account_risk_schema,
get_risk_status,
manual_close_daily_limit,
max_active_positions,
risk_control_enabled,
cooling_hours_manual,
cooling_hours_manual_journal,
trading_day_label,
trading_day_reset_hour,
)
from trading_context import (
get_fixed_amount,
get_fixed_lots,
get_max_margin_pct,
get_roll_max_margin_pct,
get_risk_percent,
get_sizing_mode,
)
ensure_account_risk_schema(conn)
risk = dict(get_risk_status(conn) or {})
row = conn.execute("SELECT * FROM account_risk_state WHERE id=1").fetchone()
td = trading_day_label()
stored_td = str(row["trading_day"] or "") if row else ""
manual_count = int(row["manual_close_count"] or 0) if row and stored_td == td else 0
margin_pct_used: Optional[float] = None
if equity and equity > 0 and margin_used is not None and margin_used >= 0:
margin_pct_used = round(float(margin_used) / float(equity) * 100, 2)
max_margin = get_max_margin_pct(get_setting)
sizing = get_sizing_mode(get_setting)
sizing_label = "固定金额" if sizing == "amount" else "固定手数"
return {
"enabled": risk_control_enabled(),
"status": risk,
"manual_close_count_today": manual_count,
"margin_pct_used": margin_pct_used,
"limits": {
"max_active_positions": max_active_positions(),
"manual_close_daily_limit": manual_close_daily_limit(),
"cooling_hours_manual": cooling_hours_manual(),
"cooling_hours_manual_journal": cooling_hours_manual_journal(),
"trading_day_reset_hour": trading_day_reset_hour(),
"max_margin_pct": max_margin,
"roll_max_margin_pct": get_roll_max_margin_pct(get_setting),
"risk_percent": get_risk_percent(get_setting),
"sizing_mode": sizing,
"sizing_label": sizing_label,
"fixed_lots": get_fixed_lots(get_setting),
"fixed_amount": get_fixed_amount(get_setting),
},
}
def build_dashboard_payload(
*,
get_db: Callable,
@@ -94,6 +171,7 @@ def build_dashboard_payload(
"id": r["id"],
"symbol": sym,
"symbol_name": r["symbol_name"] or sym,
**_symbol_fields(sym),
"monitor_type": mtype,
"direction": r["direction"] or "",
"direction_label": _direction_label(r["direction"] or "long")
@@ -121,10 +199,12 @@ def build_dashboard_payload(
).fetchall()
closes: list[dict[str, Any]] = []
for r in close_rows:
sym_code = r["symbol"] or ""
closes.append({
"id": r["id"],
"symbol": r["symbol_name"] or r["symbol"],
"symbol_code": r["symbol"],
"symbol": r["symbol_name"] or sym_code,
"symbol_code": sym_code,
**_symbol_fields(sym_code),
"direction": r["direction"] or "long",
"direction_label": _direction_label(r["direction"] or "long"),
"lots": float(r["lots"] or 0),
@@ -139,6 +219,9 @@ def build_dashboard_payload(
})
now_iso = datetime.now(_TZ).strftime("%Y-%m-%d %H:%M:%S")
risk = build_risk_overview(
conn, get_setting, equity=equity, margin_used=margin_used,
)
return {
"ok": True,
"updated_at": now_iso,
@@ -150,6 +233,7 @@ def build_dashboard_payload(
"available": available,
"capital_fallback": round(capital, 2),
},
"risk": risk,
"keys": keys,
"closes": closes,
}