diff --git a/DEVLOG.md b/DEVLOG.md index 9f6ef9f..79985a9 100644 --- a/DEVLOG.md +++ b/DEVLOG.md @@ -1873,3 +1873,8 @@ docs/交接_2026-09-20.md(新)、docs/dev_preview/mock_preview.py 与 sample 先备份后写入,批号 HIST_c036a684cab040387321396e。134 笔成交恢复 61 个真实批次并将 33 个重复或 RECON 批次归零留痕;24 条父指令进度、活跃网格余量同步恢复。122 行修改与 123 条审计在同一事务提交,独立读回原值比较通过;重复执行返回 already_applied 且审计数量不变。三票恢复为 700/1900/1400 股,成本 44.109/55.060/23.704,毛盈亏 -6762.70/-1684.25/16.86。对账 diffs=[]、severity=OK,健康及通道正常。完整证据与不可还原边界见三项差异排查文档及四仓交接。 真实超目标成交 1300 股保留事实,七条误判完成指令暂停剩余执行;未改原始成交、游标和历史报表。费用、历史峰值、旧轮次原批次及全组合历史绩效未伪造恢复。自然新成交与次日首晨版尚待真实事件判收。automation-2 已更新结果并保留 10-16 07:25,不增加五日观察。 + + +## 2026-10-15 · 指令执行均价的有效期补齐 + +历史修复后发现原成交路径只累加 exec_qty,未维护 exec_avg_price。新增成交时清空已过期均价,固定修复时点的准确金额继续保存在 progress 与审计。没有成交金额输入时保持未知,避免静默沿用旧值。变更 pms_repo.add_instruction_exec;内存数据库验证执行量增加、均价失效、固定证据保持。batch40 共 22 例,全量 44 批本地隔离禁网通过;候选镜像和部署验收另记。 diff --git a/app/repo/pms_repo.py b/app/repo/pms_repo.py index be597a7..64781c8 100644 --- a/app/repo/pms_repo.py +++ b/app/repo/pms_repo.py @@ -469,7 +469,10 @@ def update_instruction(instruction_id: str, *, status=None, exec_qty=None, exec_ def add_instruction_exec(instruction_id: str, qty: int) -> int: - return execute("UPDATE pms_instruction SET exec_qty = exec_qty + :q, updated_at = :ts " + # 本入口没有成交金额,不能维护均价。新增成交后使旧均价失效,避免历史修复的 + # 固定时点均价冒充当前全量均价;原修复金额仍在 progress 与操作审计中可查。 + return execute("UPDATE pms_instruction SET exec_avg_price = NULL, " + "exec_qty = exec_qty + :q, updated_at = :ts " "WHERE instruction_id = :iid", {"q": int(qty), "iid": instruction_id, "ts": _NOW()}) diff --git a/docs/复盘决定台账.md b/docs/复盘决定台账.md index 501611a..9e74069 100644 --- a/docs/复盘决定台账.md +++ b/docs/复盘决定台账.md @@ -285,3 +285,6 @@ **预期。** 数量、金额、批次盈亏和指令执行量可逐笔核验。任何漏笔、歧义、并发变化、中断不产生半套账;已有终态指令不因修账续单。手续费、历史峰值和原历史绩效不假装已还原。方案、排序、仓位及明日启用门槛不变。 **复核日期。** 2026-10-15 写回前后按备份核验;2026-10-16 晨版核验继续检查自然回放。21 个新回归和全部 44 批隔离离线测试通过。部署与生产判收另记 DEVLOG。 + + +**台账 020 均价有效期补充(2026-10-15)。** 原 add_instruction_exec 只收到增量数量,不知道成交金额。历史修复填入的均价在未来新成交后会过期,故增量数量写入时一并将 exec_avg_price 置空。准确的修复时点金额继续保留在 progress.historical_repair 与行级审计;不把旧均价冒充新的全量成交均价。增加内存数据库行为测试,batch40 共 22 例,全量 44 批离线通过。 diff --git a/scripts/run_tests.py b/scripts/run_tests.py index 0dec6d9..d44f540 100644 --- a/scripts/run_tests.py +++ b/scripts/run_tests.py @@ -5,7 +5,7 @@ 运行: docker compose run --rm pms-web python scripts/run_tests.py 包含 (例数按 2026-10-12 隔离回归实跑校正): - test_batch40_units.py 逐笔历史修复、进度暂停、并发与事务回滚 (21 例) + test_batch40_units.py 逐笔历史修复、进度暂停、并发与事务回滚与均价失效 (22 例) test_batch39_units.py 成交双来源归属、迟到、部分成交与失败守成 (12 例) test_batch38_units.py 每日计划顺序、版本核验、重新确认、并发采纳、历史保留 (15 例) test_core_units.py 仓位规划器 / 安全垫与成本账 (14 例) diff --git a/scripts/test_batch40_units.py b/scripts/test_batch40_units.py index cdbef73..cd39a9b 100644 --- a/scripts/test_batch40_units.py +++ b/scripts/test_batch40_units.py @@ -83,6 +83,16 @@ class CoreTests(unittest.TestCase): b=fixture();b['tables']['pms_instruction'][0]['qty']=50 s=self.plan(b)['summaries'][0]['instructions'][0] self.assertEqual((s['exec_qty'],s['overfill_qty']),(100,50)) + def test_new_fill_invalidates_fixed_historical_average(self): + import sqlite3 + from app.repo import pms_repo + with sqlite3.connect(':memory:') as db: + db.execute('CREATE TABLE pms_instruction (instruction_id TEXT, exec_qty INTEGER, exec_avg_price REAL, updated_at TEXT, progress_json TEXT)') + db.execute("INSERT INTO pms_instruction VALUES ('P',100,10,'old','fixed evidence')") + with patch.object(pms_repo,'execute',side_effect=lambda sql,params:db.execute(sql,params).rowcount): + pms_repo.add_instruction_exec('P',100) + row=db.execute('SELECT exec_qty,exec_avg_price,progress_json FROM pms_instruction').fetchone() + self.assertEqual(row,(200,None,'fixed evidence')) def test_money_precision_does_not_multiply_rounded_average(self): lots=[dict(qty=1,closed_qty=3,open_price='10.000',close_avg_price='10.003',realized_pnl='0.01')] self.assertEqual(net_lot_cost(lots),D('9.99'))