一、行情系统概述:高频交易对行情数据的极致要求
做量化系统这些年,我最大的感触就是——行情数据这东西,真不是闹着玩的。
很多人以为行情处理就是「收到数据→解析→推送」,简单得很。但等你真正上了高频交易的战场,你会发现每一微秒都在烧钱。我有个朋友,他们团队曾经因为行情链路上多了一个 3 微秒的抖动,导致套利策略连续三天跑输对手。3 微秒,你眨个眼都不止这个时间。
高频交易对行情数据的极致要求
说白了,高频交易对行情数据的要求就三个字:快、准、稳。
- 快:数据从交易所到策略引擎,延迟要控制在微秒级。我见过最极端的场景,FPGA 直连网卡,从物理层解析到策略触发,全程不到 500 纳秒。
- 准:行情数据不能丢,不能乱序。你想想看,如果某笔成交的 tick 丢了,你的订单簿可能就永远对不上了。
- 稳:延迟抖动要小。偶尔一次 10 微秒的延迟,比稳定 5 微秒更可怕。因为策略的预期会被打乱。
核心观点:在高频交易领域,延迟不是「快慢问题」,而是「生死问题」。每微秒的优化,都可能直接转化为利润。
延迟的代价:微秒级竞争
你可能觉得,一微秒能干啥?
我举个例子。假设你的策略是跨交易所套利,A 交易所比 B 交易所快 5 微秒收到行情。如果对手比你快这 5 微秒,他就能先于你挂单。等你的订单到达时,价差已经被吃掉了。
这 5 微秒的差距,就是盈亏的分水岭。
我记得有一次帮客户做性能调优,发现他们的行情处理线程在收到数据后,居然先打了一条日志再解析。就这一条日志 I/O,多了 2 微秒。去掉之后,策略的胜率从 51% 提到了 54%。
嗯,细节决定成败,这话在量化领域一点不假。
| 延迟来源 | 典型耗时 | 优化手段 |
|---|---|---|
| 网络传输(光纤) | ~5 ns/m | 物理托管、缩短链路 |
| 内核协议栈 | ~1-10 μs | DPDK、内核旁路 |
| 数据解析 | ~0.5-5 μs | 零拷贝、预分配内存 |
| 日志输出 | ~1-100 μs | 异步日志、关闭调试 |
避坑提醒:我曾经见过一个团队,花了大价钱买 FPGA 加速卡,结果行情链路中一个普通的 Java GC 停顿就把所有优化都毁了。硬件再快,软件拖后腿也是白搭。
行情处理的两大模式:中断 vs 轮询
聊完了延迟的代价,我们来看看行情处理的核心问题——CPU 怎么知道行情数据到了?
目前主流就两种模式:中断模式和轮询模式。这两种模式,说白了就是「被动等通知」和「主动去问」的区别。
中断模式
中断模式,就是网卡收到数据后,主动发一个信号给 CPU:「嘿,数据来了,快来处理!」
优点很明显:CPU 不用一直盯着,省电、省资源。适合数据量不大、偶发性的场景。
但缺点也很致命:中断处理本身有开销。每次中断都要保存上下文、跳转到中断处理函数、再恢复上下文。这一套下来,少说也要几微秒。在高频交易场景下,这几乎不可接受。
我见过一个极端案例:某交易所行情爆发时,每秒产生 10 万笔 tick。如果每笔都走中断,CPU 光处理中断就占用了 80% 的资源,根本没时间跑策略。
轮询模式
轮询模式就简单粗暴了:CPU 不停地问网卡:「有数据吗?有数据吗?有数据吗?」
这样做的好处是:延迟极低且稳定。没有中断的开销,数据一到就能立刻取走。在高频交易中,轮询几乎是标配。
但代价是:CPU 占用率 100%。你想想看,一个核啥也不干,就搁那循环检查。不过话说回来,在高频交易里,CPU 核本来就是为了跑策略而生的,浪费一点轮询的开销,换来微秒级的延迟优势,值了。
| 对比维度 | 中断模式 | 轮询模式 |
|---|---|---|
| 延迟 | 较高(~5-20 μs) | 极低(~0.1-1 μs) |
| CPU 占用 | 低(按需触发) | 高(持续占用) |
| 延迟抖动 | 大(受中断频率影响) | 小(稳定循环) |
| 适用场景 | 低频、非实时 | 高频、实时交易 |
我的建议:如果你的策略对延迟要求不高(比如分钟级调仓),用中断模式完全够用,还能省 CPU。但如果你在做高频做市或套利,老老实实上轮询。别犹豫。
核心逻辑框架图
下面这张图,是我自己总结的行情处理核心逻辑。你可以看到,从数据源到策略引擎,每一步都有延迟优化的空间。
从这张图你可以看到,行情处理不是单一环节的问题。从数据源到策略引擎,每一层都有延迟优化的空间。而中断 vs 轮询的选择,只是其中一环。
我个人习惯是:先确定延迟目标,再选择模式。如果你的目标延迟在 10 微秒以上,中断模式完全够用。但如果你的目标是 1 微秒以内,轮询是唯一的选择。
一句话总结:行情处理的核心,就是在「快」和「省」之间找到平衡。高频交易选择了「快」,所以轮询模式成了主流。但别忘了,轮询不是银弹,它只是解决了「如何通知 CPU」这个问题。后续的解析、订单簿维护、策略触发,每一步都还有优化空间。