From c05478015dfd26fb256960dd2e4432812ba5a1c6 Mon Sep 17 00:00:00 2001 From: dekun Date: Thu, 30 Jul 2026 15:03:26 +0800 Subject: [PATCH] Read risk_loss_pct exit base and option lev from strategy settings. Co-authored-by: Cursor --- backend/app/api/fleet.py | 33 ++++++++++++++++++++------ control/frontend/src/pages/Monitor.tsx | 32 ++++++++++++++++++------- 2 files changed, 49 insertions(+), 16 deletions(-) diff --git a/backend/app/api/fleet.py b/backend/app/api/fleet.py index feab568..b801233 100644 --- a/backend/app/api/fleet.py +++ b/backend/app/api/fleet.py @@ -199,6 +199,23 @@ async def fleet_status(_tok: Annotated[str, Depends(require_fleet_token)]) -> di "upl": pos.get("option_upl"), } ) + + # 风控展示字段以引擎 state 为准;缺省时回落 settings 表(避免旧进程漏字段) + db = get_db() + + def _sf(key: str, default: float) -> float: + try: + return float(db.get_setting(key, str(default)) or default) + except Exception: + return float(default) + + def _pick(key: str, default: float | None = None): + if key in st and st.get(key) is not None: + return st.get(key) + if default is None: + return None + return _sf(key, default) + return { "ok": True, "mode": settings.mode, @@ -223,19 +240,21 @@ async def fleet_status(_tok: Annotated[str, Depends(require_fleet_token)]) -> di "exit_mode": st.get("exit_mode"), "exit_target_usdt": st.get("exit_target_usdt"), "net_profit_target": st.get("net_profit_target"), - "premium_exit_multiple": st.get("premium_exit_multiple"), - "leverage": st.get("leverage"), - "min_option_leverage": st.get("min_option_leverage"), + "premium_exit_multiple": _pick("premium_exit_multiple"), + "leverage": _pick("leverage", float(settings.leverage)), + "min_option_leverage": _pick( + "min_option_leverage", float(settings.min_option_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"), - "risk_loss_pct": st.get("risk_loss_pct"), - "risk_perp_unit": st.get("risk_perp_unit"), - "risk_option_unit": st.get("risk_option_unit"), - "risk_exit_unit": st.get("risk_exit_unit"), + "risk_loss_pct": _pick("risk_loss_pct", 1.0), + "risk_perp_unit": _pick("risk_perp_unit", 1.0), + "risk_option_unit": _pick("risk_option_unit", 2.0), + "risk_exit_unit": _pick("risk_exit_unit", 15.0), }, "position": { "status": pos.get("status") or ("open" if pos.get("has_position") else "flat"), diff --git a/control/frontend/src/pages/Monitor.tsx b/control/frontend/src/pages/Monitor.tsx index 3421365..3280fc7 100644 --- a/control/frontend/src/pages/Monitor.tsx +++ b/control/frontend/src/pages/Monitor.tsx @@ -80,19 +80,33 @@ function riskLines(strat: Record): RiskLines { const exitMode = String(strat.exit_mode || "fixed_usdt"); let exit: string; if (riskBased) { - exit = `基数${unitLabel(strat.risk_exit_unit ?? 15)}`; + // 必须读策略机 risk_exit_unit,禁止写死 15 + exit = + strat.risk_exit_unit != null && Number.isFinite(Number(strat.risk_exit_unit)) + ? `基数${unitLabel(strat.risk_exit_unit)}` + : "基数—"; } else if (exitMode === "premium_multiple") { - exit = `权利金×${fmt(strat.premium_exit_multiple ?? 1, 2)}`; + exit = + strat.premium_exit_multiple != null + ? `权利金×${fmt(strat.premium_exit_multiple, 2)}` + : "权利金×—"; } else { - exit = `固定 ${fmt(strat.net_profit_target ?? strat.exit_target_usdt, 2)}U`; + const t = strat.net_profit_target ?? strat.exit_target_usdt; + exit = + t != null && Number.isFinite(Number(t)) + ? `固定 ${fmt(t, 2)}U` + : "固定 —"; } - const lossN = Number(strat.risk_loss_pct); - const lossPct = - riskBased && Number.isFinite(lossN) + // 以损定仓必显风险比例(risk_loss_pct);手动隐藏 + let lossPct: string | null = null; + if (riskBased) { + const lossN = Number(strat.risk_loss_pct); + lossPct = Number.isFinite(lossN) ? `${fmt(lossN, lossN % 1 === 0 ? 0 : 2)}%` - : null; + : "—"; + } const openRatio = riskBased - ? `${unitLabel(strat.risk_perp_unit ?? 1)}:${unitLabel(strat.risk_option_unit ?? 2)}` + ? `${unitLabel(strat.risk_perp_unit)}:${unitLabel(strat.risk_option_unit)}` : null; return { riskBased, @@ -114,7 +128,7 @@ function RiskParamsBox({ strat }: { strat: Record }) {
定仓
{r.sizing}
- {r.lossPct ? ( + {r.lossPct != null ? (
风险比例
{r.lossPct}