回测吃单只要处理价格;回测挂单要处理一个不可观测的东西:你排在第几个。 同一个价位上有几百股,谁先成交取决于队列 —— 而队列在历史数据里看不到。 于是这一步几乎全靠假设,而假设的方向决定了结论的正负号。
你在 0.61 挂 100 股。这个价位上已经有 800 股。现在有人卖出 500 股 ——
| 如果你排在 | 成交 | 回测会说 |
|---|---|---|
| 最前面 | 100 股全成 | 赚到价差 |
| 中间 | 部分成交 | 一半一半 |
| 最后面 | 一股没成 | 什么都没发生 |
三种情况在历史数据里长得完全一样:你只看到「0.61 价位成交了 500 股」。 所以回测框架必须替你做一个假设,而大多数框架的默认假设是乐观的。
我们用的规则只有两条,都是往对自己不利的方向取:
| 规则 | 意思 | 为什么保守 |
|---|---|---|
| 挂单时点的显示量全部排我们前面 | 下单那一刻这个价位有 800 股,就当 800 股都在我们前面 | 实际可能有人在我们之后撤单,让我们提前 |
| 前方撤单不让位 | 别人撤了单,我们的位置不往前挪 | 实际撤单确实会让位 |
这两条合起来的效果是:我们会少吃到「良性成交」,多吃到「毒性成交」。
为什么?因为良性成交(对手只是要平仓)通常量小,吃不穿队列就轮不到我们; 而毒性成交(对手知道消息)往往量大、扫穿整个价位,排最后也会被吃到。
因为两种错误的代价完全不对称:
| 假设方向 | 如果错了 | 代价 |
|---|---|---|
| 乐观 | 回测正、实盘负 | 上线之后用真钱发现 |
| 保守 | 回测负、实盘可能正 | 错过一个机会 |
错过机会的代价是有限的,用真钱发现假边的代价没有上限。 所以在所有说不准的地方,都往对自己不利的方向取 —— 这不是悲观主义,是不对称风险管理。
保守假设本身不解决问题,它只是把问题变成已知的。真正重要的是第二步:
我们的做法是每条结论后面必须跟一句「这个数是下界还是上界」。 举个真实例子 —— 同一件事的两个数:
| 来源 | 结果 | 方向 |
|---|---|---|
| 保守队列的全额模拟 | −3¢/股 | 悲观下界 |
| 熟练玩家的实测 | +0.1¢/股 | 乐观上界 |
于是结论不是一个数,而是一个区间:−3¢ 到 +0.1¢。 接下来要问的问题就变得非常具体:有没有证据表明我们能拿到正的那一端?
那次的答案是没有,所以那条线没有上。如果只有一个中间数字, 这个问题根本问不出来 —— 你会以为自己知道答案。
挂单回测里有一类数据特别容易被悄悄丢掉:你想挂但没成交的单。
如果框架把它们直接从样本里删掉,剩下的就只有成交了的那些 —— 而成交与否恰恰不是随机的。这等于用结果来筛样本,得到的统计必然偏乐观。
| 要单独上报 | 为什么 |
|---|---|
| 未成交率 | 它本身就是策略性质的一部分,不是噪声 |
| 部分成交的比例 | 「挂 100 成 30」和「挂 100 成 100」是两种策略 |
| 被撤单的量 | 撤掉的单也占用过资金和排队时间 |
| 问自己 | 不合格的答案 |
|---|---|
| 队列假设是什么? | 「框架默认的」——那你不知道方向 |
| 撤单让不让位? | 不知道 = 大概率让位 = 乐观 |
| 没成交的单去哪了? | 「被过滤掉了」——样本已被污染 |
| 这个数是上界还是下界? | 答不上就不能拿来做决定 |
| 有证据说我们能拿到好的那一端吗? | 「应该可以吧」 |
挂单回测里最重要的数字不在数据里,在假设里。 所以正确的产出不是一个收益率,是一个带方向标签的区间 —— 以及一句诚实的话:我有没有证据能拿到好的那一端。