7.3 KiB
IPO、Trend、ZT 策略审计
复审日期:2026-09-12。基线:7a7049ce44965d27c42f08ede1818d16495d8232 加本次读取的工作区代码,包含手工修改及未提交文件。
范围:三个策略及直接相关的委托簿、状态存储、SDK、服务端成交映射、网格和快照模块。本次只更新报告,不修改策略、测试或生产数据,不连接交易账户。
仅保留复审后仍需处理的问题。已修复及用户已标记忽略的条目、历史复现和过时统计已移除;编号沿用原报告。部分修复的问题仅描述尚未解决的策略范围。
结论
待处理:P0 0 项、P1 2 项、P2 2 项。 IPO 本次未确认新的待处理问题。
| 编号 | 级别 | 范围 | 问题 |
|---|---|---|---|
| P1-07 | P1 | ZT | 按委托编号去重,分笔成交可能漏记 |
| P1-08 | P1 | Trend | 超时撤单仍覆盖手工单及其他非 IPO 策略订单 |
| P2-01 | P2 | Trend | 止盈峰值跨仓位沿用 |
| P2-07 | P2 | 共用模块测试 | 旧 OrderBook 构造调用导致回归测试错误 |
P0 表示已确认的紧急严重风险;P1 表示主要交易控制或记账问题;P2 表示特定条件下的可靠性和回归验证问题。本次未确认 P0。
P1
P1-07:ZT 按委托编号去重,分笔成交可能漏记
位置: state.py 第 55、146–156、362–389 行;服务端成交映射 第 371–387 行;ZT 启动 第 49–51 行。
证据: 服务端将 m_strOrderSysID 映射为 order_sys_id,成交表以该字段建立唯一索引。ZT 增量路径插入第一条后将编号加入 existing,其余同编号记录不再插入。不同 ref、时间和数量不参与身份识别。启动时两次成交查询也按此编号转成字典比较,会折叠同委托的多条记录。
本轮复现: 临时数据库中,同一委托编号、不同 ref 的 40 股和 60 股买入成交,对应账户快照为 100 股。sync_account() 仅记入 40 股并隔离该证券;重新加载数据库并再次同步,仍为 40 股,未恢复。
影响与边界: 逐笔回报可能漏记后续成交;累计回报也无法通过当前只追加逻辑更新已存数量。库存、金额及成本可能不完整,证券持续暂停交易。复现证明代码无法处理上述输入,不代表已确认目标柜台采用哪一种回报契约。
修改建议: 先核验实际回报是逐笔还是累计,以及唯一身份字段。逐笔回报透传真实成交编号并据此去重;累计回报按增量差额更新。启动稳定性比较也需保留完整回报。不要未经核验拼接时间、价格或 ref 作为唯一键;修改存储键时同时明确已有数据的处理方式。
验收: 同委托分笔成交累计为 100 股;重复查询和重启不重复记账;累计回报按已确认契约处理;初始化比较不因同编号覆盖而遗漏变化。
P1-08:Trend 超时撤单仍覆盖手工单及其他策略订单
位置: Trend boot.py 第 40、119 行;OrderBook.refresh() 第 61、77–88 行。
证据: Trend 启动及每轮运行均传入完整账户委托,未指定 cancel_prefix,默认值为 None。所有满足超时及可撤状态的非 IPO-* 委托都会进入撤单路径,包括空备注手工单和 zt-* 订单。
本轮复现: 四笔超时、状态 50 的模拟订单分别使用 TREN-BUY-*、zt-base-*、IPO-* 和空备注。按 Trend 当前调用方式刷新,Trend、ZT 和手工订单触发撤单,IPO 未触发;四笔均保留缓存。
影响与边界: 运行 Trend 可能干扰人工或其他策略希望继续等待的委托。本项仅保留 Trend 范围;当前 IPO 排除有效,不再沿用旧报告的 IPO 误撤结论。Mock 只能证明撤单调用,不能证明柜台受理。
修改建议: 若 Trend 只管理自己的订单,应明确归属后限制自动撤单,同时保留全账户在途防重。Trend 开仓使用信号前缀、持仓管理使用 TREN-*,不能简单改为单一 trend- 前缀。如果全账户非 IPO 撤单是预期行为,应明确记录这一范围后再决定是否关闭本项。
验收: Trend 自有超时订单能撤,手工单和其他策略订单不被 Trend 自动撤销;全部活动委托继续参与防重。
P2
P2-01:Trend 止盈峰值跨仓位沿用
位置: Trend positions.py 第 120–121、198–199 行;Trend boot.py 第 60、113–119 行;网格跟踪器 第 44–74 行。
证据: Trend 使用普通 GridTrailingTracker,键仅包含账户及证券。清仓、重新建仓和补仓成本变化时,没有清理旧峰值;每轮快照更新也未同步网格生命周期。
本轮复现: 使用真实 manage_positions()、真实 tracker 和模拟委托簿,依次输入成本 10 元、价格 12 元的持仓,价格 11.9 元的同一持仓,空持仓,再输入成本 10 元、价格 11 元的新持仓。各步新增卖出调用次数为 0、1、0、1。新仓位第一次观察仍沿用旧峰值触发卖出。
影响: 重新建仓或成本基准变化后,当前收益率可能被当成旧仓位的回撤,提前触发止盈。本项仅保留 Trend 范围。
修改建议: 根据已确认的清仓、重新建仓及成本变化同步止盈基准。不要仅在提交成功时清理,避免撤单或部分成交丢失有效峰值。
验收: 新仓位首次观察只建立峰值;同一仓位正常回撤仍触发卖出;未成交提交、撤单及同一成本下部分卖出不误清理。
P2-07:OrderBook 旧构造调用导致回归测试错误
位置: test_deal_model.py 第 71 行;OrderBook 构造函数 第 35–38 行。
本轮复现: 测试调用 ActiveOrders('trend'),字符串被当成 lock_timeout_sec,在 max(1, lock_timeout_sec) 处抛出 TypeError。完整测试 86 项中 85 项通过、1 项错误、0 项断言失败。
影响与边界: 回归套件无法全绿。实际 Trend/ZT 入口已使用无参构造,本项不意味着策略必然启动失败。
修改建议: 将测试改为当前构造接口;撤单范围通过 refresh() 参数和调用方约定验证,不为旧测试重新引入已删除的构造参数。
验收: 该测试通过,并保持默认刷新、ZT 范围过滤、IPO 排除和在途防重断言有效。
本轮验证及边界
- 完整执行
unittest发现的 86 项测试:85 通过、1 项错误,详情见 P2-07。其中 IPO 专项 15 项、ZT 相关 26 项全部通过。 - 额外执行真实状态同步、委托刷新和 Trend 持仓管理路径,分别复现 P1-07、P1-08、P2-01,结果已写入对应条目。
- 验证使用模拟客户端及临时 SQLite 数据库,未发送真实委托、撤单或采集请求,未修改生产数据库和锁文件。
- 成交唯一身份、逐笔/累计语义及柜台实际受理结果仍需目标环境确认,未将未核验事实写成确定结论。
- 不新增旧 IPO 编号兼容要求,不恢复已忽略事项,不将已修复内容作为待办重复列出。