This commit is contained in:
2026-09-05 23:36:25 +08:00
parent 2f93fe2ecb
commit b38ff12f2a
3 changed files with 112 additions and 22 deletions

View File

@@ -1,22 +1,27 @@
# Trend 当前工作树重新审计
审计日期2026-09-05。以当前磁盘文件(包含未提交的手动修改)为准,不继承旧报告的问题状态。仅审计 Trend 及直接依赖;不修改策略代码,不连接交易接口。
审计日期2026-09-05。审计基线:`2f93fe2`,本轮读取时工作树干净。以当前磁盘文件为准,仅审计 Trend 及直接依赖;不修改策略代码,不连接交易接口。
## 结论
当前仍有 4 项高风险、3 项中风险问题。不建议仅凭语法检查通过直接运行实盘。本报告只保留当前存在的问题与待确认行为,问题编号保留以便引用
当前发现 **P00 项P14 项P23 项**。本报告只保留当前存在的问题与待确认行为,不保留已修复问题清单。不建议仅凭语法检查通过直接运行实盘
- **P0紧急**:无需特定边界条件即可造成全面故障或迫切严重损害,需要立即处理。本轮未发现符合此定义的问题。
- **P1优先修复**:在明确场景下影响资金约束、订单权限或交易决策,建议实盘前处理。
- **P2常规修复**:异常场景下影响局部执行或可靠性,需要安排修复。
工作树中 `strategy/trend/state.py` 已删除,`Runtime` 也已移除 `state` 字段;`docs/arch/state.py` 是归档,不是当前运行模块。因此此前围绕 `merged_order()` 的结论不作为当前策略结论。
## H5止盈委托刚受理就清理峰值未成交持仓失去回撤基准
## P1-1清仓后没有清理峰值新持仓会继承旧回撤基准
- 位置:`positions.py:136``libs/grid_take_profit.py``clear(self, position_key)`
- 证据:`orders.place()` 返回成功后立即执行 `runtime.profit_tracker.clear(key)`,没有等待成交或持仓消失
- 影响:卖单未成交、部分成交或随后被超时撤销时,剩余持仓的旧峰值已丢失;下轮会从较低盈利重新建立基准,原回撤信号可能不再触发
- 验证:真实网格跟踪器记录 12% 峰值10% 时模拟提交成功;同一持仓下一次 9.5% 观察返回 `ARMED` 而不是沿用旧峰值的 `RETREAT`。没有真实交易
- 建议:仅在后续快照确认持仓消失时清理;撤单或部分成交继续保留剩余持仓的峰值,成本变化时另行明确重置规则
- 位置:`positions.py:105``:182``boot.py:122` 起的快照处理;`libs/grid_take_profit.py:71`
- 证据:峰值键只有账户和证券代码;当前 Trend 没有调用 `clear()`没有在持仓消失时清理对应键
- 触发:同一进程内清仓后重新买入同一证券
- 影响:新持仓达到最低收益门槛后,可能按上一笔持仓的高峰立即触发止盈,而不是建立自己的峰值;补仓改变成本时也未明确重置基准
- 验证:真实网格组件以同一键记录 12% 峰值,再输入新持仓的 9% 盈利,返回 `RETREAT`;代码中没有清仓清理步骤隔离两次持仓
- 建议:根据后续快照确认持仓消失后清理;撤单或部分成交继续保留峰值,成本变化另行明确重置规则。
## H2自动撤单未限定为本策略订单
## P1-2自动撤单未限定为本策略订单
- 位置:`order.py:60``:68``:78``boot.py:57``sdk/portfolio.py:9`
- 证据:将组合接口的订单列表直接传入 `refresh()`,只检查状态与时间,没有检查本地订单号前缀、策略归属或排除名单。
@@ -24,7 +29,7 @@
- 影响:启动及每轮刷新都可能撤销非 Trend 订单,包括排除证券的订单。
- 建议:账户级活动订单可用于防重,但主动撤单必须单独限定所有权。若业务确实授权管理整个账户,需明确记录该权限。
## H3大盘过滤实际始终放行
## P1-3大盘过滤实际始终放行
- 位置:`py-client/libs/market.py``market_allow_open()``boot.py:151``positions.py:67`
- 证据:真实状态比较被注释,函数直接 `return True`
@@ -32,7 +37,7 @@
- 建议:恢复真实状态判断,或以明确、可见的配置表示主动关闭过滤。
- 验证:将本地测试状态设为 `DOWN`,仍返回 `True`;未请求网络。
## H4买入没有统一资金预算最小整手还可能突破单笔额度
## P1-4买入没有统一资金预算最小整手还可能突破单笔额度
- 位置:`boot.py:146``:176``open.py:51``positions.py:160``libs/calc.py:10`
- 证据:开仓只依据本轮起始资金比例决定是否启动,不逐单扣减预算;补仓线程独立使用相同快照资金。`calc_buy_volume()``max(1, ...)` 强制至少买一手。
@@ -40,14 +45,14 @@
- 示例:价格 100 元、单笔额度 5,000 元,计算出 100 股,即 10,000 元。
- 建议:开仓和补仓共享本轮可预留预算;不足一手返回零;预留考虑手续费和行情变化,保留最小现金要求。
## M2:撤单异常会中断整轮刷新和交易管理
## P2-1:撤单异常会中断整轮刷新和交易管理
- 位置:`order.py:78``:86``boot.py:122` 起的快照处理。
- 证据:撤单在遍历中直接调用,未逐单隔离;`busy_keys``data` 在全部遍历结束后才赋值。
- 影响:某笔撤单失败即退出 `refresh()`,快照不更新;常规轮次返回而跳过全部交易管理,初始化阶段则退出启动(客户端会关闭)。持续失败的订单可能持续阻断后续轮次。
- 建议:撤单逐项记录异常,同时发布完整活动订单快照;撤单失败的订单继续作为在途订单防重。
## M3:信号前置处理没有逐项异常隔离
## P2-2:信号前置处理没有逐项异常隔离
- 位置:`open.py:16``:55`
- 证据:异常捕获仅包围 `do_open()`;配置、价格、数量计算、观察器调用不在逐候选保护边界中。
@@ -55,12 +60,12 @@
- 影响:该候选之后的所有开仓信号本轮不再处理;工作线程最外层只能记录整个任务失败。
- 建议:把一个候选的完整处理放入同一异常边界,记录证券与信号键后继续;保持必要校验即可。
## M4:补仓请求结果不确定时未保留资金预算
## P2-3:补仓请求结果不确定时未保留资金预算
- 位置:`positions.py:175``:75``order.py:119` 起的异常处理。
- 证据:`place()` 对请求超时等异常返回 `False`,保留证券方向缓存,但 `handle_loss()` 返回的 `reserved_cash` 默认为零。
- 触发:券商已受理补仓但响应丢失,本轮继续处理后续证券。
- 影响:方向缓存只能防同证券重复下单,不能阻止其他证券重复使用这笔可能已消耗的资金。该问题即使只启用持仓管理、不开新仓也存在,与 H4 的跨线程预算问题不同。
- 影响:方向缓存只能防同证券重复下单,不能阻止其他证券重复使用这笔可能已消耗的资金。该问题即使只启用持仓管理、不开新仓也存在,与 P1-4 的跨线程预算问题不同。
- 验证:模拟 `place()` 返回 `False`,补仓结果 `reserved_cash == 0.0`
- 建议:区分明确未提交与结果不确定;不确定时保留本轮预计金额,或停止本轮后续买入并刷新资金。
@@ -77,8 +82,8 @@
- 开仓与持仓管理都检查排除名单;未知信号配置有独立日志后跳过。
- `place()` 捕获 API、HTTP 请求和解码类异常;持仓管理有逐证券异常边界。
- 启动生命周期有 `finally`,等待线程池后关闭客户端。
- 当前 7 个 Trend 源文件全部重新通过 AST 语法检查。本轮使用真实网格组件和模拟下单,验证成功提交后的峰值清理及下一轮重新激活行为
- 资金预算、大盘过滤、撤单和信号异常边界本轮已重新读取;预算超额及失败补仓零预算预留的实现与此前最小测试对应代码一致。
- 当前 7 个 Trend 源文件全部重新通过 AST 语法检查。本轮真实网格组件的最小测试验证同一键沿用旧峰值;重新执行资金数量计算、大盘状态判断,分别得到 10,000 元买入金额和 DOWN 状态仍放行
- 资金预算、大盘过滤、撤单和信号异常边界本轮已重新读取;失败补仓零预算预留的实现与此前最小测试对应代码一致。
- 未执行真实下单、撤单、完整 SDK 联调或券商回报测试;语法通过不代表策略可运行。归档文件和历史审计测试统计不计入当前验证。
优先顺序:先处理撤单权限、市场过滤、资金预算及止盈峰值生命周期,再完善异常边界。