1. 课程导入与规则回测全景

在真实交易中,限价单挂出后并不总能立刻成交。价格可能长时间在挂单价之外徘徊,订单被动“躺”在盘口里,既占用资金,又错过行情。于是很多交易者会设定一条规则:限价单挂出后若超过某个时间仍未成交,就撤单并按新的参考价重新挂价。这条规则听起来简单,但它到底能不能改善成交率、会不会抬高成本、在震荡市和趋势市里表现是否一致,仅凭盘感无法回答。本课程要做的,就是把这条规则放进历史数据中,用回测的方式量化它的收益与代价。

先厘清四个核心概念。限价单是指定价格、只在该价格或更优价格成交的委托,买单挂价不高于市价、卖单挂价不低于市价,它保证价格但不保证成交。超时是订单从挂出到当前时刻的存活时长超过预设阈值,例如 30 秒、5 分钟或 1 个交易日,阈值本身是规则参数。改价规则规定超时后如何动作:撤单后按什么价格重挂、重挂几次、每次是否调整价差、达到最大改价次数后是否转为市价单或直接放弃。回测则是用历史行情逐笔重放订单生命周期,统计成交、成本与收益,从而评估规则优劣。

学习目标可以归纳为三层:第一层是看懂——能说清限价单、超时、改价、回测各自的定义与相互关系;第二层是算清——能根据行情与规则推演单笔订单的挂价、撤单、重挂与最终成交结果;第三层是判清——能用成交率、平均成交价偏差、改价次数、机会成本等指标判断规则是否值得使用。

理解这条规则,关键是看清一张订单在时间轴上的状态流转。下图把限价单从提交到终结的完整生命周期画了出来,其中“超时判断”是整条链路的分叉点:未超时则继续等待,超时则进入改价分支,而改价分支又受最大改价次数约束,最终收敛到成交、放弃或转市价三种终态。

限价单生命周期与超时改价回测框架 历史行情数据 盘口 / 逐笔成交 / 时间戳 规则参数 超时阈值 / 最大改价次数 / 价差 订单初始条件 方向 / 数量 / 初始挂价 订单挂出(限价单存活) 记录挂出时刻 t₀ 与挂价 p₀ 是否已成交? 按盘口可成交性判定 成交终态 记录成交价与等待时长 存活时长 ≥ 超时阈值? t − t₀ 与阈值比较 未超时:继续等待 改价次数 < 上限? 计数 n 与 N_max 比较 撤单并按新价重挂 n = n + 1,更新 t₀、p₀ 放弃 / 转市价(终态) 回测统计输出: 成交率 · 平均成交价偏差 · 平均改价次数 · 超时占比 · 机会成本

这张图揭示了回测实现的两个要点。其一,订单状态必须逐笔推进:每来一条行情,都要判断当前挂单能否成交;不能成交再看存活时长是否越过阈值;越过阈值再检查改价次数是否还有余量。其二,所有分支都要有明确终态,否则回测会在某些行情下“卡住”订单,导致统计失真。实际编码时,通常用一个订单对象维护 方向、数量、挂价、挂出时刻、改价次数 五个字段,主循环按时间戳顺序消费行情,遇到状态变化就更新字段并记录事件日志。

为了让规则可计算,需要把“改价”写成明确的公式。设初始挂价为 p₀,第 n 次改价后的挂价为 pₙ,参考价为当前盘口最优价 m(买方向取卖一价,卖方向取买一价),价差参数为 δ,则一种常见设定是:

买单:pₙ = min(m, p₀) − δ × n
卖单:pₙ = max(m, p₀) + δ × n
约束:n ≤ N_max,且 pₙ 不得越过涨跌停价

这里 δ 是“每次改价让出多少价格优势”,n 越大让价越多,成交概率上升但成交价变差。N_max 则限制让价总幅度,防止订单在单边行情中无限追价。回测时把 δ 与 N_max 作为可扫描参数,就能得到一张“成交率—平均成交价偏差”的权衡表,而不是凭感觉拍一个阈值。

回测中必须区分“规则造成的成本”和“行情本身的结果”。例如订单最终没成交,可能是改价不够激进,也可能是行情根本没回到可成交区间。前者是规则可优化的部分,后者属于机会成本,应单独统计,不能混在一起评价规则好坏。

举个教学示例(以下数值为合理假设,用于说明计算过程,非实测结果)。假设某标的买一价 10.00、卖一价 10.02,我们挂买单于 10.00,超时阈值 60 秒,δ = 0.01,N_max = 3。挂出后 60 秒内卖一价始终在 10.02 以上,订单未成交,触发第一次改价:参考价 m = 10.02,p₁ = min(10.02, 10.00) − 0.01 = 9.99。若再等 60 秒仍未成交,第二次改价 p₂ = min(m, 10.00) − 0.02,依此类推。回测统计时,这笔订单的“成交价偏差”就是最终成交价与初始挂价之差,“改价次数”记录实际发生的 n,“等待时长”累计各段存活时间。把这些单笔记录汇总,就得到规则层面的成交率与成本分布。