Show strategy rules in fold; larger nav; notify only when cannot open.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-07-29 18:12:26 +08:00
parent a5945f0837
commit 71b5fcae79
6 changed files with 76 additions and 12 deletions
+4
View File
@@ -93,6 +93,8 @@ class StrategyEngine:
max_atm_off = self.ledger.get_setting_float( max_atm_off = self.ledger.get_setting_float(
"max_atm_open_offset", s.max_atm_open_offset "max_atm_open_offset", s.max_atm_open_offset
) )
perp_qty = self.ledger.get_setting_float("perp_qty_eth", s.perp_qty_eth)
opt_qty = self.ledger.get_setting_float("option_qty_eth", s.option_qty_eth)
rest_until = row["rest_until_ms"] rest_until = row["rest_until_ms"]
rest_left = 0 rest_left = 0
if rest_until: if rest_until:
@@ -128,6 +130,8 @@ class StrategyEngine:
"premium_exit_multiple": prem_mult, "premium_exit_multiple": prem_mult,
"exit_target_usdt": exit_amt, "exit_target_usdt": exit_amt,
"leverage": leverage, "leverage": leverage,
"perp_qty_eth": perp_qty,
"option_qty_eth": opt_qty,
"min_option_hours": min_hours, "min_option_hours": min_hours,
"min_option_leverage": min_opt_lev, "min_option_leverage": min_opt_lev,
"atm_open_offset_enabled": atm_off_on, "atm_open_offset_enabled": atm_off_on,
+6 -3
View File
@@ -171,13 +171,16 @@ def assess_open_capacity(db: Database | None = None) -> dict[str, Any]:
def maybe_notify_funds_short(cap: dict[str, Any] | None = None) -> None: def maybe_notify_funds_short(cap: dict[str, Any] | None = None) -> None:
"""交易账户资金不足时企业微信推送:不足期间只推一次""" """仅在「不能开」时推送一次;能开绝不通知"""
global _notified_while_short global _notified_while_short
cap = cap or assess_open_capacity() cap = cap or assess_open_capacity()
short = cap.get("perp_can_open") is False or cap.get("option_can_open") is False # 能开 / 未知:不通知;资金恢复则重置,便于下次不足再提醒一次
if not short: if cap.get("funds_ok") is True:
_notified_while_short = False _notified_while_short = False
return return
cannot = cap.get("perp_can_open") is False or cap.get("option_can_open") is False
if not cannot:
return
if _notified_while_short: if _notified_while_short:
return return
_notified_while_short = True _notified_while_short = True
+10
View File
@@ -5,6 +5,16 @@
--- ---
## 2026-07-29 — 规则说明展示策略数值;导航加大;不可开才通知
### 变更
1. 能开不通知;不能开才企业微信提醒一次(恢复后再次不足才再推)。
2. 导航字号加大;规则说明正文字号缩小。
3. 规则说明按当前策略设置展示开仓/平仓/节奏参数。
---
## 2026-07-29 — 可开判定只看交易账户;不足只通知一次;去重标题 ## 2026-07-29 — 可开判定只看交易账户;不足只通知一次;去重标题
### 变更 ### 变更
+2
View File
@@ -228,6 +228,8 @@ export type PlanState = {
premium_exit_multiple: number; premium_exit_multiple: number;
exit_target_usdt: number; exit_target_usdt: number;
leverage: number; leverage: number;
perp_qty_eth?: number;
option_qty_eth?: number;
min_option_hours: number; min_option_hours: number;
min_option_leverage: number; min_option_leverage: number;
atm_open_offset_enabled?: boolean; atm_open_offset_enabled?: boolean;
+28 -3
View File
@@ -149,6 +149,13 @@ export default function PlanPage() {
? `权利金×${fmt(plan?.premium_exit_multiple ?? 1, 2)}` ? `权利金×${fmt(plan?.premium_exit_multiple ?? 1, 2)}`
: `固定 ${fmt(plan?.net_profit_target ?? 15)} U`; : `固定 ${fmt(plan?.net_profit_target ?? 15)} U`;
const phaseLabel = PHASE_ZH[plan?.phase || ""] || plan?.phase || "—"; const phaseLabel = PHASE_ZH[plan?.phase || ""] || plan?.phase || "—";
const atmRule = plan?.atm_open_offset_enabled
? `ATM偏差≤${fmt(plan?.max_atm_open_offset ?? 3, 0)}`
: "ATM偏差关";
const exitDetail =
exitMode === "premium_multiple"
? `净盈利≥初始权利金×${fmt(plan?.premium_exit_multiple ?? 1, 2)}`
: `净盈利≥${fmt(plan?.net_profit_target ?? 15)} U`;
const expiryMs = const expiryMs =
pos?.expiry_ms ?? expiryMsFromYmd(pos?.expiry_ymd) ?? null; pos?.expiry_ms ?? expiryMsFromYmd(pos?.expiry_ymd) ?? null;
const countdown = const countdown =
@@ -213,10 +220,28 @@ export default function PlanPage() {
<div className="plan-rules-fold"> <div className="plan-rules-fold">
<details> <details>
<summary></summary> <summary></summary>
<p className="meta plan-rules-body"> <div className="plan-rules-body">
{String(plan?.exchange || "okx").toUpperCase()} · ETH-USDT-SWAP · <p>
(/) · <span className="plan-rules-k"></span>
{String(plan?.exchange || "okx").toUpperCase()} · ETH-USDT-SWAP
</p> </p>
<p>
<span className="plan-rules-k"></span>
{fmt(plan?.perp_qty_eth ?? 1, 2)} ETH / {fmt(plan?.leverage, 0)}x
· {fmt(plan?.option_qty_eth ?? 2, 2)} ETH ·
{fmt(plan?.min_option_hours, 0)}h ·
{fmt(plan?.min_option_leverage, 0)}x · {atmRule}
{plan?.skip_weekends ? " · 周末跳过开仓" : ""}
</p>
<p>
<span className="plan-rules-k"></span>
{exitDetail}
</p>
<p>
<span className="plan-rules-k"></span>
{plan?.rest_seconds ?? "—"}s ·
</p>
</div>
</details> </details>
</div> </div>
+25 -5
View File
@@ -149,13 +149,14 @@ input {
} }
.top-nav a { .top-nav a {
padding: 6px 10px; padding: 8px 14px;
border: 1px solid var(--line); border: 1px solid var(--line);
border-radius: 8px; border-radius: 8px;
background: var(--bg-elev); background: var(--bg-elev);
color: var(--muted); color: var(--muted);
text-decoration: none; text-decoration: none;
font-size: 13px; font-size: 15px;
font-weight: 600;
white-space: nowrap; white-space: nowrap;
} }
@@ -307,7 +308,7 @@ input {
.plan-rules-fold summary { .plan-rules-fold summary {
cursor: pointer; cursor: pointer;
color: var(--muted); color: var(--muted);
font-size: 13px; font-size: 12px;
user-select: none; user-select: none;
} }
@@ -317,7 +318,26 @@ input {
.plan-rules-body { .plan-rules-body {
margin: 8px 0 0; margin: 8px 0 0;
line-height: 1.45; font-size: 11px;
line-height: 1.5;
color: var(--muted);
}
.plan-rules-body p {
margin: 0 0 4px;
}
.plan-rules-body p:last-child {
margin-bottom: 0;
}
.plan-rules-k {
display: inline-block;
min-width: 2.2em;
margin-right: 6px;
color: var(--text);
font-weight: 600;
opacity: 0.85;
} }
.open-cap-row { .open-cap-row {
@@ -485,7 +505,7 @@ input {
min-height: 48px; min-height: 48px;
text-decoration: none; text-decoration: none;
color: var(--muted); color: var(--muted);
font-size: 13px; font-size: 14px;
font-weight: 600; font-weight: 600;
border-radius: 8px; border-radius: 8px;
} }