技术博客

涨跌停与临停的系统处理:规则引擎在撮合环路里的位置

第 36 / 141 篇 · 2025-06-29 · secfin · 交易规则涨跌停规则引擎

涨跌停看起来是交易规则里最简单的一条:价格不能超过前收盘的 ±10%。但把它写进系统,会发现细节多得不像话:10% 之后怎么对齐到最小变动价位?ST 股为什么是 5%?注册制新股上市前五天不设涨跌幅,那笼子价怎么算?盘中临停触发后已排队的委托怎么办?这篇把这条规则从业务语言编译成系统语言的全过程过一遍。

涨跌停价的精确计算

先给公式。主板非 ST 股票,涨跌停价由前收盘价决定:

$$ P_{\text{limit}} = \text{TickAlign}\big(P_{\text{prev}} \times (1 \pm r)\big), \quad r = 10\% \ (\text{ST 股}\ 5\%) $$

TickAlign 是取整到最小变动价位,方向有讲究:涨停价向下取(11.05 不能超,取 11.00),跌停价向上取,保证价格绝不越界。一个常被忽视的点:前收盘价除权除息后要调整(公司行动篇讲过),所以涨跌停价的依赖链是"公司行动 → 调整前收盘 → 重算涨跌停价 → 刷新校验参数",任何一环延迟都会造成系统内两个模块用的限价不一致。

取整还有个数学上的副作用:有效涨跌幅不是精确的 10%。前收 10.00 元、tick 0.01 元,涨停 11.00,恰 10%;前收 10.03 元,$10.03 \times 1.1 = 11.033$,向下取整 11.03,实际涨幅只有 9.97%。tick 越大、股价越低,偏差越明显。规则引擎里存"涨跌停价"这个绝对值,不存"10%"这个比例——比例只是生成工具,绝对值才是运行时真理。

集合竞价阶段的参考价不同:9:25 之前用前收盘,9:25 之后(深市 14:57~15:00 收盘集合竞价)用集合竞价产生的价格,价格笼子随之实时变化。同一个校验函数要能切换基准,这是"规则引擎"和"一堆 if-else"的分水岭。

校验点放哪:报单入口 vs 撮合环路

限价校验有两个候选位置,各管一段:

  • 报单入口校验:委托价格超出涨跌停,直接拒单,理由码精确到"买入超涨停/卖出破跌停"。挡掉的是客户错误和恶意报单,保护撮合循环的容量;
  • 撮合环路校验:委托在簿上排队期间,涨跌停价变了(除权、临停恢复重开集合竞价),原价格可能从合法变非法。这一层必须在撮合线程内复核,但只拦新进来的对手方,已排队的委托不溯及既往——规则不处罚排队时合法的单子。

两个校验点跑的是同一份预计算参数(按证券代码哈希索引的价格带表),参数由独立的"交易日初始化 + 公司行动事件"两个时机刷新。关键工程约束:校验必须是 O(1)。撮合循环里每一拍都要跑限价判断,如果是"查规则表 + 解释执行规则表达式",峰值时这里就是瓶颈。正确做法是把所有规则在开盘前编译成 per-security 的纯数据:{涨停价, 跌停价, 参考价, 有效标志位},运行时就地比较。

临停:比涨跌停更麻烦的状态机

盘中临时停牌(涨跌幅触发、重大事项)引入的不是价格问题,是撮合状态机问题。临停的系统语义:

  1. 触发:价格触及临停阈值时,交易所发停牌通知。注意通知到达会员柜台有毫秒到秒级的传播延迟,期间撮合还在跑——所以柜台必须以交易所正式回报为准,自己本地算"该停了"只是预警,绝不能本地先行停板(本地停而交易所没停,客户的单子在交易所成交了、本地却以为没成交,账直接烂掉);
  2. 冻结:停牌期间该证券的委托照常接收(交易所接受暂存)但不撮合,撤单通常允许——所以簿上的排队委托在停牌期持续减少,恢复撮合时队列形态和停前完全不同;
  3. 恢复:临停结束一般先进入集合竞价(重新定价),再转连续竞价。柜台的状态机要完整走"连续 → 停牌 → 集合竞价 → 连续"的迁移链,每一步的委托处理规则都不同。

历史上把这套规则系统打到极限的是 2016 年 1 月的指数熔断:熔断阈值(5%、7%)触发后全市场停牌 15 分钟,两档阈值间隔太近,第一档熔断恢复后恐慌盘涌出直接触发第二档,当天 9:57 恢复交易到 9:58 再次熔断,全天交易不足 15 分钟。系统层面的教训不在熔断本身,在于:规则引擎的每个参数(阈值、时长、恢复机制)都在全市场所有系统里同时生效,规则设计就是容量设计,阈值间隔小于恐慌情绪的释放时间,等于把全市场的委托洪峰压进恢复后的第一分钟。四天后熔断机制暂停,至今未恢复。

价格带校验:比例只是生成工具,绝对限价才是运行时真理涨停区:买入申报 > 涨停价拒单涨停价排队(一字板队列)连续撮合区按价格优先、时间优先成交跌停区:卖出申报 < 跌停价拒单跌停价排队(卖压堆积)涨停价前收 10.00跌停价 9.00取整方向:涨停向下取、跌停向上取有效幅度 ≠ 精确 10%(tick 取整偏差)校验必须是 O(1):开盘前把规则编译成per-security 价格带表,运行时就地比较双校验点:报单入口拒越界 + 撮合环路防基准价漂移;已排队委托不溯及既往临停 = 状态机问题:以交易所回报为唯一权威,本地预判只做预警不做动作

落到工程实践,涨跌停规则的系统形态可以总结为三句话:规则预编译成数据,运行时零解释;校验双点部署,入口挡错单、环路防漂移;临停状态机驱动,一切动作以交易所回报为准。规则引擎的价值不在"灵活",在把每次规则变更(注册制改笼子价、北交所改幅度)从"改代码发版本"变成"改参数刷配置"——金融行业监管规则一年数变,这个区别就是运维成本的区别。