Add weekend open skip, expiry force-close, and Chinese trade labels.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -44,6 +44,7 @@ const PHASE_ZH: Record<string, string> = {
|
||||
stopped: "已停开",
|
||||
outside_window: "窗外",
|
||||
liquidity_wait: "流动性等待",
|
||||
weekend_skip: "周末跳过",
|
||||
};
|
||||
|
||||
export default function PlanPage() {
|
||||
@@ -123,7 +124,7 @@ export default function PlanPage() {
|
||||
<div>
|
||||
<h2 style={{ marginTop: 0 }}>自动对冲计划</h2>
|
||||
<p style={{ color: "var(--muted)", marginTop: -8 }}>
|
||||
SIM 本地撮合 · 期权只买 · 剩余时长选到期 · 净盈利达标全平
|
||||
SIM 本地撮合 · 期权只买 · 净盈利达标或到期全平
|
||||
</p>
|
||||
{err ? <div className="err">{err}</div> : null}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ export default function SettingsPage() {
|
||||
const [netTarget, setNetTarget] = useState(15);
|
||||
const [premMult, setPremMult] = useState(1);
|
||||
const [rest, setRest] = useState(300);
|
||||
const [skipWeekends, setSkipWeekends] = useState(true);
|
||||
const [leverage, setLeverage] = useState(3);
|
||||
const [minHours, setMinHours] = useState(12);
|
||||
const [minOptLev, setMinOptLev] = useState(100);
|
||||
@@ -43,6 +44,7 @@ export default function SettingsPage() {
|
||||
setNetTarget(s.net_profit_target ?? 15);
|
||||
setPremMult(s.premium_exit_multiple ?? 1);
|
||||
setRest(s.rest_seconds);
|
||||
setSkipWeekends(s.skip_weekends !== false);
|
||||
setLeverage(s.leverage ?? 3);
|
||||
setMinHours(s.min_option_hours ?? 12);
|
||||
setMinOptLev(s.min_option_leverage ?? 100);
|
||||
@@ -97,6 +99,7 @@ export default function SettingsPage() {
|
||||
net_profit_target: netTarget,
|
||||
premium_exit_multiple: premMult,
|
||||
rest_seconds: rest,
|
||||
skip_weekends: skipWeekends,
|
||||
leverage,
|
||||
min_option_hours: minHours,
|
||||
min_option_leverage: minOptLev,
|
||||
@@ -134,7 +137,7 @@ export default function SettingsPage() {
|
||||
{tab === "strategy" ? (
|
||||
<div className="card settings-card">
|
||||
<p className="settings-lead">
|
||||
无开仓时间窗;期权按剩余时长选到期 → 平值 → 校验杠杆;出场可选固定金额或权利金倍数。
|
||||
无开仓时间窗;可选周六日跳过开仓;期权按剩余时长选到期 → 平值 → 校验杠杆;出场可选固定金额或权利金倍数。
|
||||
</p>
|
||||
{stratOk ? <div className="settings-ok">{stratOk}</div> : null}
|
||||
{err && tab === "strategy" ? <div className="err">{err}</div> : null}
|
||||
@@ -282,6 +285,18 @@ export default function SettingsPage() {
|
||||
onChange={(e) => setRest(Number(e.target.value))}
|
||||
/>
|
||||
</div>
|
||||
<div className="field">
|
||||
<label htmlFor="skipWe">周六日跳过开仓(上海时区)</label>
|
||||
<select
|
||||
id="skipWe"
|
||||
className="mono"
|
||||
value={skipWeekends ? "1" : "0"}
|
||||
onChange={(e) => setSkipWeekends(e.target.value === "1")}
|
||||
>
|
||||
<option value="1">开启(推荐)</option>
|
||||
<option value="0">关闭</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className="field">
|
||||
<label htmlFor="fee">手续费率</label>
|
||||
<input
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { apiFetch } from "../api/client";
|
||||
import { closeReasonZh } from "../labels";
|
||||
|
||||
type Summary = {
|
||||
groups: number;
|
||||
@@ -22,6 +23,10 @@ export default function StatsPage() {
|
||||
.catch((e) => setErr(e instanceof Error ? e.message : String(e)));
|
||||
}, []);
|
||||
|
||||
const reasonEntries = s
|
||||
? Object.entries(s.close_reasons).sort((a, b) => b[1] - a[1])
|
||||
: [];
|
||||
|
||||
return (
|
||||
<div className="card">
|
||||
<h2 style={{ marginTop: 0 }}>统计</h2>
|
||||
@@ -46,9 +51,17 @@ export default function StatsPage() {
|
||||
{s.total_fees.toFixed(2)} / {s.total_slip.toFixed(2)}
|
||||
</span>
|
||||
</div>
|
||||
<div className="kv">
|
||||
<div className="kv" style={{ alignItems: "flex-start" }}>
|
||||
<span>平仓原因</span>
|
||||
<span className="mono">{JSON.stringify(s.close_reasons)}</span>
|
||||
<span className="mono" style={{ textAlign: "right" }}>
|
||||
{reasonEntries.length === 0
|
||||
? "—"
|
||||
: reasonEntries.map(([k, n]) => (
|
||||
<div key={k}>
|
||||
{closeReasonZh(k)} × {n}
|
||||
</div>
|
||||
))}
|
||||
</span>
|
||||
</div>
|
||||
<h3>按组盈亏</h3>
|
||||
{s.equity_curve.map((x) => (
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { apiFetch } from "../api/client";
|
||||
import {
|
||||
closeReasonZh,
|
||||
fillDescZh,
|
||||
positionSidesZh,
|
||||
statusZh,
|
||||
} from "../labels";
|
||||
|
||||
type Group = {
|
||||
group_id: string;
|
||||
@@ -62,10 +68,12 @@ export default function TradesPage() {
|
||||
onClick={() => openGroup(g.group_id)}
|
||||
>
|
||||
<span className="mono">
|
||||
{g.group_id} · {g.status} · {g.perp_side}/{g.option_side}
|
||||
{g.group_id} · {statusZh(g.status)} ·{" "}
|
||||
{positionSidesZh(g.perp_side, g.option_side)}
|
||||
</span>
|
||||
<span className="mono">
|
||||
PnL {Number(g.realized_pnl || 0).toFixed(2)} · {g.close_reason || "—"}
|
||||
盈亏 {Number(g.realized_pnl || 0).toFixed(2)} ·{" "}
|
||||
{closeReasonZh(g.close_reason)}
|
||||
</span>
|
||||
</div>
|
||||
))
|
||||
@@ -77,10 +85,11 @@ export default function TradesPage() {
|
||||
{fills.map((f) => (
|
||||
<div key={f.id} className="kv">
|
||||
<span className="mono">
|
||||
{f.leg} {f.action} {f.side}
|
||||
{fillDescZh(f.leg, f.action, f.side)}
|
||||
</span>
|
||||
<span className="mono">
|
||||
px {f.fill_px.toFixed(4)} · qty {f.qty_eth} · fee {f.fee.toFixed(4)}
|
||||
价 {f.fill_px.toFixed(4)} · 数量 {f.qty_eth} · 手续费{" "}
|
||||
{f.fee.toFixed(4)}
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
|
||||
Reference in New Issue
Block a user