From c9bc654d3a328fa7b0c2b5006d8e67f603566649 Mon Sep 17 00:00:00 2001 From: claude_dev Date: Fri, 14 Aug 2026 19:45:09 +0800 Subject: [PATCH] =?UTF-8?q?fix(paper):=20=E5=AE=9E=E8=B5=B0/=E5=BD=B1?= =?UTF-8?q?=E5=AD=90=E9=9A=90=E8=97=8F=E8=B5=B7=E6=AD=A2=E6=97=A5=E6=9C=9F?= =?UTF-8?q?(=E7=94=A8=E6=88=B7=E6=8C=87=E6=AD=A3:=E5=BC=80=E6=94=BE?= =?UTF-8?q?=E8=B4=A6=E6=88=B7=E5=8C=BA=E9=97=B4=E6=97=A0=E6=84=8F=E4=B9=89?= =?UTF-8?q?):=20=E5=89=8D=E7=AB=AF=E4=BB=85=E5=9B=9E=E6=94=BE=E6=98=BE?= =?UTF-8?q?=E7=A4=BA=E6=97=A5=E6=9C=9F,=E5=8D=A1=E7=89=87=E6=A0=87?= =?UTF-8?q?=E9=A2=98=E8=B5=84=E9=87=91=E4=B8=8E=E5=8C=BA=E9=97=B4=E2=86=92?= =?UTF-8?q?=E8=B5=84=E9=87=91+=E8=AF=B4=E6=98=8E=E6=96=87=E6=A1=88;=20?= =?UTF-8?q?=E5=90=8E=E7=AB=AF=E9=9D=9E=E5=9B=9E=E6=94=BE=E5=BC=BA=E5=88=B6?= =?UTF-8?q?start=3D=E5=88=9B=E5=BB=BA=E5=BD=93=E5=A4=A9end=E7=A9=BA(?= =?UTF-8?q?=E7=BB=84=E5=90=88=E6=97=A5=E7=BB=88=E9=87=8D=E6=94=BE=E4=BE=9D?= =?UTF-8?q?=E8=B5=96start=5Fdate=E7=A9=BA=E5=80=BC=E4=BC=9A=E5=B4=A9);=20?= =?UTF-8?q?=E5=8C=BA=E9=97=B4=E6=96=AD=E8=A8=80=E8=BF=9B=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=20[nas]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/views/paper/New.vue | 26 +++++++++++++++++++------- sanguo_api/routes_paper.py | 7 +++++++ tests/api/test_paper_routes.py | 6 ++++++ 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/frontend/src/views/paper/New.vue b/frontend/src/views/paper/New.vue index 44cfadb..044332a 100644 --- a/frontend/src/views/paper/New.vue +++ b/frontend/src/views/paper/New.vue @@ -153,6 +153,11 @@ async function onSubmit(): Promise { } // 影子模式:engine=shadow(VPS 柜台盘中实时撮合);其余 eod_replay(回放/日终) payload.engine = payload.mode === 'shadow' ? 'shadow' : 'eod_replay' + // 实走/影子是开放账户:起止日期无意义,开始=创建当天,结束留空(回放才需要历史区间) + if (payload.mode !== 'replay') { + payload.start = new Date().toISOString().slice(0, 10) + payload.end = '' + } const aid = await createPaper(payload) ElMessage.success(payload.mode === 'shadow' ? `已创建影子柜台模拟盘 #${aid}(VPS 柜台运行期间盘中实时结算)` @@ -284,18 +289,25 @@ function onSymbols(v: string): void { - + 单位:元 - - - - - - + +
+ {{ form.mode === 'shadow' ? '影子柜台从创建当天开始实时跟踪,无结束日期' : '每日 20:30 从创建当天开始结算,无结束日期' }} +
diff --git a/sanguo_api/routes_paper.py b/sanguo_api/routes_paper.py index 47267c0..1712984 100644 --- a/sanguo_api/routes_paper.py +++ b/sanguo_api/routes_paper.py @@ -70,6 +70,13 @@ def create_paper(req: PaperCreateRequest): db = _db_path["path"] or ":memory:" init_db(db) + # 实走/影子是开放账户:起止日期无意义,开始=创建当天(组合日终重放依赖 start_date, + # 空值会崩),结束留空;仅回放保留用户填的历史区间 + if req.mode in ("live", "shadow"): + from datetime import date + + req.start = date.today().isoformat() + req.end = "" if req.strategy_type == "portfolio": if req.mode not in ("live", "shadow"): raise HTTPException(400, "组合策略模拟盘仅支持实走(live)/影子(shadow)模式;历史回放请用「组合回测」") diff --git a/tests/api/test_paper_routes.py b/tests/api/test_paper_routes.py index 7424d6e..2358be4 100644 --- a/tests/api/test_paper_routes.py +++ b/tests/api/test_paper_routes.py @@ -63,8 +63,14 @@ def test_create_shadow_mode(tmp_path): cta = by_id[r1.json()["account_id"]] assert cta["mode"] == "shadow" assert cta["engine"] == "shadow" + # 实走/影子是开放账户:用户填的区间被忽略,开始=创建当天,结束留空 + from datetime import date + + assert cta["start_date"] == date.today().isoformat() + assert not cta["end_date"] pf = by_id[r2.json()["account_id"]] assert pf["mode"] == "shadow" and pf["engine"] == "shadow" + assert not pf["end_date"] def test_create_portfolio_rejects_replay(tmp_path):