fix bug
This commit is contained in:
19
docs/ipo-submission-state.md
Normal file
19
docs/ipo-submission-state.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# IPO 提交与结果核对
|
||||
|
||||
当前实现使用文件记录,不增加数据库或后台任务。
|
||||
|
||||
- 路径:`qmt_data_dir/ipo/<账户 SHA-256>/<YYYYMMDD>/<证券>/<尝试序号>.json`。
|
||||
- 提交前用独占创建方式写入并落盘 `pending`;占位失败不提交。
|
||||
- HTTP 正常返回仍保留 `pending`,不代表最终申购成功。
|
||||
- 下次 IPO 任务先查询账户委托。查不到、状态未知、仍在处理或已有部分成交时,不重发。
|
||||
- 同一本地订单编号查到状态 56 后记录 `confirmed`,后续保持防重。
|
||||
- 同一编号查到状态 57 且成交量为 0,才记录 `rejected` 并原子占位下一次尝试。旧尝试的废单不能授权新尝试再次重发。
|
||||
- 不同账户、日期使用不同记录。每次尝试都有写入记录且传给 QMT 的本地订单编号。
|
||||
|
||||
状态码依据:[迅投官方委托核对示例](https://dict.thinktrader.net/innerApi/code_examples.html)。撤单、部撤等情况未自动视为可以再次申购。
|
||||
|
||||
旧版只有证券名的 `.lock` 文件不再作为新账户的申购记录,避免跨账户锁冲突;首次运行通过当天同证券买入委托防重。升级应在当前账户委托可查询的条件下进行,旧锁本身无法证明归属账户或最终结果。
|
||||
|
||||
损坏或无法读取的记录不会触发重新提交;记录写入失败也不会提交。若长期查不到回报,需要先人工核对柜台结果,不能直接删除待确认记录后重跑。
|
||||
|
||||
接口响应必须是列表,合法空列表表示无候选;非列表响应记录错误。候选要求完整代码及对应交易所、有限正价格、正整数数量。当前参与板块范围保持不变。
|
||||
86
docs/strategy-audit-2026-09-12.md
Normal file
86
docs/strategy-audit-2026-09-12.md
Normal file
@@ -0,0 +1,86 @@
|
||||
# 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](../py-client/libs/state.py) 第 55、146–156、362–389 行;[服务端成交映射](../api/qmt_rest_new.py) 第 371–387 行;[ZT 启动](../py-client/strategy/zt/boot.py) 第 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](../py-client/strategy/trend/boot.py) 第 40、119 行;[OrderBook.refresh()](../py-client/libs/order.py) 第 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](../py-client/strategy/trend/positions.py) 第 120–121、198–199 行;[Trend boot.py](../py-client/strategy/trend/boot.py) 第 60、113–119 行;[网格跟踪器](../py-client/libs/grid_take_profit.py) 第 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](../py-client/tests/test_deal_model.py) 第 71 行;[OrderBook 构造函数](../py-client/libs/order.py) 第 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 编号兼容要求,不恢复已忽略事项,不将已修复内容作为待办重复列出。
|
||||
Reference in New Issue
Block a user