某个策略在 10:00 提交了一笔限价单。10:03 信号发生变化。回测在 10:04 悄悄替换了订单,随后在 10:05 记入一笔成交。模拟交易中,原订单可能仍在交易场所挂着。如果它在替换订单也生效时成交,策略就会有两笔订单,而持仓模型却假装只有一笔。
未成交订单需要自己的状态和时钟。回测应记录每笔订单的提交时间、可撤销时间、撤单是否已送达交易场所,以及成交与撤单竞速时会发生什么。以下 3 种常见捷径会抹掉这些事实。
错误 1:把新信号当成立即撤单
许多回测会在每根 bar 上重新计算目标持仓,然后用最新信号想要的订单覆盖挂单。这样一来,策略刚改变主意,订单就立刻消失了。真实交易场所并非如此运作。撤单请求需要时间,交易场所处理之前,订单可能已经成交。
设想一笔买入限价单:100 股,价格 $50.00。10:03 信号走弱,策略于是发送撤单请求。10:03:00.080,订单成交了 60 股;10:03:00.110,撤单得到确认。剩余 40 股被撤销,但持仓中此时已有 60 股。若按 bar 运行的回测在 10:03 删除订单,可能会报告零持仓。若回测假设撤单立即生效,却仍记录之后的成交,就凭空捏造了方向相反的风险敞口。
明确追踪订单生命周期:已提交、已确认、部分成交、撤单待确认、已撤销或已全部成交。保留撤单确认前发生的成交。对于较粗粒度的 bar 模拟,如果两个事件可能发生在同一根 bar 内,就选定一条保守的先后顺序规则,并说明清楚。
错误 2:让挂单永不过期
即使信号没有明确的退出规则,根据 10:00 信号定价的限价单也可能变得过时。盘口会变化,波动率会改变,市场对该工具的估值也可能漂移。然而,如果模拟器让订单一直有效直到成交,它最终可能在几个月后才成交,却把这笔成交归功于早已失效的交易逻辑。
设定与策略匹配的订单有效期策略。1-minute 信号可以设为 30 秒后到期;每日调仓则可以让订单保留到收盘。这些是策略选择,没有放之四海皆准的默认值。如果策略每根 bar 都重新定价,就应模拟撤单和替换的流程,而不是让订单瞬间跳到新价格。
| 订单策略 | 常见用途 | 回测问题 |
|---|---|---|
| 立即成交或取消 | 获取可用流动性,然后停止 | 提交订单时,有多少数量可能成交? |
| 短时有效 | 执行窗口较短的快速信号 | 价格回到该水平时,订单是否仍然有效? |
| 有效至交易时段结束 | 缓慢调仓或意图参与收盘竞价 | 交易场所是否真的支持这样的有效期? |
错误 3:把每次触价都算作成交
如果一根蜡烛图的最低价触及买入限价单,订单未必就成交了。队列中可能有排在它前面的订单,该价格上的成交量可能很少,也可能只是价格打印瞬间出现,而且发生在订单到达之前。过时的订单模型往往会把这 3 种错误全都混在一起:让订单存续过久,假设它排在队列首位,再在价格触及时直接记入全部成交。
至少要避免订单到达前发生的成交,并将模拟成交量限制在该限价上合理的实际成交量范围内。对于依赖队列位置的策略,应使用逐笔成交和订单簿数据,或采用有意保守的队列模型。基于触价的成交假设仍可用于粗略筛选,但应标明这是偏乐观的近似,并与更严苛的假设进行比较。
一个实用的审查办法:记录每笔订单的创建时间、有效时段、撤单请求和确认时间、成交时间、已成交数量及剩余数量。然后,选取信号反转前后的几笔交易进行回放。如果无法解释订单成交时为何仍然有效,就需要改进回测的成交统计。
模拟你打算进行模拟交易的订单
订单状态连接了策略意图与实际风险敞口。持仓应随成交变化,而不是随信号目标或撤单请求变化。替换订单应留下可审计的记录,部分成交也应延续到下一次决策中。这会让回测更繁琐,但也让模拟交易对比变得有意义:两个系统在执行上的差异,都能找到明确的原因。
订单模型存在不确定性时,应在结果中保留这种不确定性。测试有效期较短和较长的订单,调整撤单延迟,并展示表现对乐观队列假设的依赖程度。策略本身可能没有问题;但它看似存在的优势,也可能只是来自一笔真实系统早在几小时前就会撤销的订单所带来的收益。
← 全部文章


