4. 未成交原因分类

在限价单回测中,最容易犯的错误是把“未成交”当成一个单一事件,用同一个假设去处理。实际上,未成交背后至少有五类完全不同的成因,它们对回测结果的影响方向、修正方式和可信度要求都不一样。如果不在成交判定环节就把原因区分清楚,后续的收益曲线、换手率、滑点统计都会混入系统性偏差。本节的目标是建立一套可落地的未成交原因分类框架,并说明每一类原因在回测引擎中应当如何被识别、记录和修正。

为什么必须分类,而不是统一按“不成交”处理

假设某策略在回测期内发出 1000 笔限价买单,最终 620 笔成交。若把剩余 380 笔一律视为“价格没到”,回测会低估策略的真实成交能力;若一律视为“流动性不足”,又会高估成本。更关键的是,不同原因对应不同的修正手段:价格未触及属于行情路径问题,流动性不足属于容量问题,排队靠后属于撮合优先级问题,涨跌停和交易规则属于市场制度约束问题。只有分类清楚,才能对每一类分别施加合理的成交概率模型,而不是用一个拍脑袋的全局成交率去缩放。

从工程角度看,分类的价值在于把“不可成交”拆成可观测、可参数化、可验证的子问题。回测引擎在每一根 K 线或每一个 tick 上判断限价单能否成交时,应当按固定顺序逐层筛查,先排除制度性约束,再判断价格路径,最后处理撮合细节。这个顺序不能颠倒,否则会出现“价格明明触及却因涨跌停被误判为流动性不足”之类的错误归因。

限价单成交判定与未成交原因分层筛查 按制度约束 → 价格路径 → 撮合细节的顺序逐层判断,避免错误归因 限价单指令 方向 / 价格 / 数量 ① 制度约束筛查 涨跌停 / 停牌 / T+1 最小变动价位 / 交易时段 ② 价格路径判断 最高/最低价是否触及 盘中路径 vs 收盘价 ③ 撮合细节判断 成交量 / 排队位置 盘口深度 / 部分成交 成交 全部或部分成交 A. 涨跌停限制 封板期间无法成交,需按封单量估计 B. 交易规则限制 停牌、T+1、最小价位、非交易时段 C. 价格未触及 区间高低价未达到限价,路径不满足 D. 流动性不足 成交量不足以吸收委托量,容量受限 E. 排队位置靠后 同价位先到先得,未轮到即未成交 记录字段建议: 每笔未成交单写入 reason_code(A/B/C/D/E)、触发时点、当时盘口量、封单量、区间高低价与限价差,便于事后分原因统计成交率与修正效果。

五类原因的识别口径与回测处理

价格未触及是最基础的一类。判定口径是:在委托有效期内,标的的最高价(买单)或最低价(卖单)始终没有达到或穿越限价。这里有一个常见陷阱——用收盘价判断。若某日最低价为 9.95 元,限价买单为 9.96 元,收盘价 10.02 元,用收盘价会误判为未成交,而实际盘中已经触及。正确做法是用区间极值判断,并进一步区分“触及即成交”和“触及后需排队”两种情形。对于日频回测,若最低价严格低于限价,可认为必然成交;若最低价恰好等于限价,则只能认为“可能成交”,需要引入概率或降级为排队判断。

流动性不足关注的是量而非价。即使价格触及,若该价位或该区间的成交量小于委托量,也只能部分成交。回测中常用的处理是设定一个参与率上限,例如假设单笔委托最多吃掉当期成交量的 10%,超出部分不成交或顺延。这个参数必须与标的的日均成交额匹配:大盘股可以设 5%~10%,小盘股应降到 1%~3%。示例性地,若某标的当日成交量为 200 万股,参与率设为 5%,则单笔最多成交 10 万股,委托 30 万股时只有 10 万股成交,剩余 20 万股记为流动性不足导致的未成交。

排队位置靠后是限价单特有的问题。在价格优先、时间优先的撮合规则下,同一价位上先到的委托先成交。回测若假设“价格触及即全部成交”,会系统性高估成交率,尤其在挂单价格等于当日最优价时。工程上可用两种近似:一是对等于最优价的委托施加一个成交概率,概率随该价位累计委托量增大而下降;二是用盘口快照估计前方排队量,只有成交量超过前方量时才轮到本单。前者实现简单,后者更贴近真实但依赖高频数据。

涨跌停限制属于制度性约束,必须在价格判断之前筛查。涨停时买单无法成交、跌停时卖单无法成交,这是硬约束。但要注意“封板”与“触板”的区别:价格触及涨停但未封死时,仍可能有成交机会。回测中可用封单量与成交量的比值来近似:封单量远大于成交量时视为无法成交,封单量较小或盘中打开涨停时按普通撮合处理。跌停同理。若忽略这一层,策略在极端行情下的买入信号会被错误地计为成交,导致回测收益虚高。

交易规则限制覆盖面最广,包括停牌、T+1、最小变动价位、非交易时段等。停牌期间任何委托都不应成交;T+1 意味着当日买入的持仓当日不能卖出,若策略在回测中忽略这一点,会高估日内反转类策略的收益;最小变动价位则影响限价单能否被合法挂出,例如价格精度不符合 tick size 的委托应被拒绝而非成交。这类原因往往在数据层面就能识别,建议在回测前先做一轮规则校验,把不合规的委托直接标记为规则限制未成交,而不是让它们进入撮合环节。

分类落地:记录字段与统计口径

要让分类真正可用,回测引擎应为每笔未成交委托写入结构化记录,至少包含:原因代码(A 涨跌停、B 规则限制、C 价格未触及、D 流动性不足、E 排队靠后)、触发时点、当时盘口量或封单量、区间高低价与限价的差值、以及是否发生部分成交。有了这些字段,就可以按原因分组统计成交率,并检验修正模型是否合理。例如,若 C 类占比过高而 D 类几乎为零,说明参与率参数可能过于宽松;若 A 类在特定月份集中出现,则应检查策略是否在极端行情中过度发单。

分类顺序建议固定为:规则限制 → 涨跌停 → 价格路径 → 流动性 → 排队。前两层是硬约束,后三层是软约束,顺序颠倒会导致同一笔委托被重复归因或错误归因。

最后需要强调,五类原因并非互斥。一笔委托可能同时满足“价格触及但流动性不足且排队靠后”,此时应记录主因并保留次因标记,主因取筛查顺序中第一个未通过的层级。这样统计时既能得到清晰的归因分布,又不会丢失复合情形的信息。分类的目的不是追求标签精确,而是让每一类未成交都能对应到一个可调、可验证的回测假设,从而把限价单回测从“拍一个成交率”推进到“按原因分别建模”的可信水平。