amBrain
FinTechOct 7, 2026阅读时长8分钟

行情一繁忙订单簿就卡住?如何修复行情数据源,以及谁能做到

行情数据Order Book交易终端谁来做
图片加载失败

行情繁忙时,如果交易屏幕上的订单簿卡住或跳变,问题通常出在行情数据源上:它在接入时丢了更新,把订单簿拼错了,或者发往数百块屏幕的速度太慢。先测量你最忙的那一小时,再用那一天的录制数据测试每一家公司。

如果在行情繁忙时,你交易屏幕上的订单簿卡住、跳变,或者显示出不可能的价格,故障通常出在三个地方之一:更新在交易所行情接入的地方丢失,订单簿拼装出错,或者订单簿送到数百块屏幕上的速度太慢。在聘用任何人之前,先测量你最忙的那一小时,然后用那一天的录制数据去测试你考虑的每一家公司。

简短的答案:交易所给它发出的每一条更新都编了号。构建良好的系统会立刻发现缺失的编号,把订单簿标记为已过时,然后重建。麻烦始于缺口没被发现、重建要花好几秒,或者一条慢连接拖住了所有交易员。把你最忙那一天的行情录下来,把对它的回放当作每家公司都必须通过的测试:买产品之前要测,请团队为你开发时,也要把它作为第一阶段的验收标准。

行情数据源出故障时,屏幕上是什么样子?

它出现在最忙的时刻,比如央行发布公告或者开盘时。屏幕上的订单簿停住一两秒,然后跳变。已经撤销的订单仍然显示着。有时买方的最高出价高于卖方的最低要价,这叫作交叉订单簿(crossed book)。在单一交易所里,除了开盘和收盘集合竞价之外,这样的订单会立即撮合成交。所以,如果你的屏幕上某一家交易所的订单簿出现交叉,就说明你那份订单簿副本是错的。

接着,客服会收到两位交易员发来的截图:同一个品种,他们看到的订单簿却不一样。又或者,有交易员对某笔订单的成交价提出异议,因为屏幕上显示的是另一个价格。

更新为什么会丢失,或者乱序到达?

交易所的订单簿行情是一连串细小的变动:新增一笔订单、撤销一笔订单、发生一笔成交。你的系统从订单簿的一份完整副本(称为快照)出发,按顺序应用这些变动。每个变动都有编号,所以缺了哪一个能被发现。Nasdaq 在其 TotalView-ITCH 5.0 行情的规范中说,这条行情“由一系列带序号的消息组成”,也就是按顺序编了号。

行情繁忙时,变动的流量急剧上升。有些在路上或在你自己的服务器内部丢失,有些到达的顺序被打乱。如果系统没发现缺口,它就会把收到的东西照单全收,显示一份已经和交易所对不上的订单簿。如果它发现了缺口,却要花好几秒才能恢复,屏幕就会停住不动。

交易所默认客户会丢更新。CME Group 在其 MDP 3.0 行情的文档中说,出现缺口之后,“应当假定客户端系统中维护的所有订单簿都可能不再处于正确的最新状态”。

行情在系统的哪个环节出问题?

一共三处,每一处都需要各自的修复方法。工程师把第三处称为扇出(fan-out),因为一条更新流会像扇子一样展开,分发到许多屏幕上。上面链接的那篇技术文章详细讲了这三处。

第一处是接入环节,也就是交易所行情到达的地方。有些交易所提供了找回丢失数据的办法。Nasdaq 的传输协议之一 MoldUDP64,能让接收方“发现并重新请求丢失的数据包”。CME 把同一条数据流分别通过名为 A 和 B 的两条线路各发一次,并另外运行一条快照行情,用来把订单簿更新到最新状态。如果你的系统发现不了缺口,这些都无济于事。

接下来是拼装订单簿,这里的风险在于一个变动被应用两次、顺序错乱,或者被应用到错误的快照上。加密货币交易所 Binance 在它的指南里列出了把快照与实时数据流衔接起来的确切步骤。不按这些步骤构建的订单簿照样显示价格,看上去也没问题,但价格是错的。

最后是扇出:订单簿被发送给数百个交易员会话,每块已连接的屏幕对应一个会话。用着不稳定移动网络的交易员,或者一台已经卡住的终端,读取更新的速度都很慢。如果服务器等着这个会话,其他所有会话也都得跟着等。放任这个会话积压的更新无限增长也好不到哪里去,因为服务器会耗尽内存,让所有人一起宕掉。

在构建良好的系统里,服务器只对更新排一次序,然后把同样的结果发给每一个会话。落后的会话要么直接拿到订单簿的最新画面、跳过中间的步骤,要么被服务器断开并告知原因,屏幕随后重新连接,拿到一份新的副本。一条行情可能同时在不止一个地方出问题。

在雇任何人之前,我们该测量什么?

取过去一个月里最忙的那一小时,收集它的以下数字:

  • 缺口:系统在每个交易所的行情源上发现缺失更新编号的次数。如果系统根本不统计这个数,这就是你的第一个发现
  • 恢复时间:每次重建花了多长时间,以及这段时间里交易员看到的是什么
  • 延迟:从交易所在消息上打的时间戳,到这条更新离开你的服务器发往交易员的那一刻;在几台测试终端上,还要一直测到屏幕上显示为止。取中位数和第 99 分位数,即每 100 条更新中有 99 条都不超过的那个时间。服务器的时钟要与一个准确的时间源保持同步,否则这些数字毫无意义
  • 会话:有多少个会话落后、落后了多少,有多少个被断开,以及每一次断开的原因

然后把一个繁忙日子的原始行情原样录下来,连同每个数据包到达的时间。按真实速度和更快的速度回放这份录制数据,就是你给名单上每家公司出的测试,每次修复之后也要重做一遍。

修好自己的处理器、买一套现成的,还是重建扇出层?

接收交易所行情并维护订单簿的软件,叫作行情处理器(feed handler)。你有三条路可选,你的测量结果应该指向其中一条。后两条可以结合起来。

什么时候值得修我们自己的行情处理器?

如果测量结果指向一个明确的故障,比如缺口没被发现或者重建太慢,而且熟悉这套代码的人还在,那就修好你现有的行情处理器。

  • 适用情况:故障能明确指出,而设计在其他方面运转正常
  • 你要付出的:工程开发的时间,以及一套能回放你录制数据的测试平台
  • 代码归谁:归你
  • 局限:如果问题出在把订单簿发送到屏幕上,修好接入环节也无济于事

什么时候应该买行情处理器或托管行情服务?

现成的行情处理器是一款授权使用的软件:它接入交易所,发现缺口,把一份正确、最新的订单簿交给你的系统。托管行情服务更进一步:由行情数据供应商去接入各家交易所,你只从它那里接收一条统一格式的数据流。

  • 适用情况:要接很多家使用标准格式的交易所,又不想跟进每家交易所对其行情做的每一次改动
  • 你要付出的:许可费用,以及把产品接入你的系统的工作量。无论数据由谁提供,交易所自己的数据费用和许可条款通常仍然适用
  • 仍由你负责的:把订单簿送到数百块交易员屏幕上,以及处理慢会话
  • 代码归谁:产品归供应商所有。对接部分以及之后的一切归你所有

什么时候应该请团队重建扇出层?

如果接入环节运转正常,问题却依然存在,那就重建向交易员发送数据的那一层。表现是:交易员仍然看到不同的订单簿,一个慢会话拖累其余所有会话,或者你计划服务的会话数量要比现在多得多。

  • 适用情况:延迟是在你的服务器和屏幕之间增长,而不是在交易所和你的服务器之间
  • 你要付出的:工程开发和测试的时间,以及上线后负责运行系统的人员
  • 代码归谁:归你,前提是合同里写明了这一点

聘用一家公司之前,怎样考察它?

让你名单上的每一家公司都接受同样的五项测试:

  • 用这家公司交付或演示的东西回放你的录制数据,先按真实速度,再以几倍速。把它的缺口、重建、恢复时间和延迟,与你现有系统的数字做比较
  • 它如何发现缺口。好的回答会说:只有当一个变动的编号正好是预期的下一个时,系统才应用它。如果缺了某个编号,系统会稍等片刻,然后重新请求这个变动,或者重建订单簿。在此之前,它会把订单簿标记为已过时。要问清这段时间里交易员看到的是什么
  • 一个慢交易员会带来什么。请对方在回放过程中故意让一个会话变慢。其他会话的延迟不应该随之变化
  • 它如何测量延迟:从哪个时间戳测到哪个点,用的是哪个分位数、什么负载和硬件,以及时钟怎样保持同步
  • 代码归谁所有,以及对于这家公司保留为己有的部分,你按什么条款使用

有哪些危险信号?

  • 还没有人看过你的测量数据,第一个回答就是“我们会加服务器”
  • “我们用的是可靠连接,所以什么都不会丢。”Binance 通过 WebSocket 推送更新,这种连接在传输途中不会丢数据,可它的指南照样告诉客户端:事件被跳过时该怎么办

amBrain 在其中处于什么位置?

amBrain 构建算法交易基础设施:订单执行、行情数据和交易前风控。

amBrain 网站上有一句话:“交易终端开发、订单管理系统和 FIX 协议交易所对接。”

amBrain 诊断交易和广告技术领域的慢系统:对运行中的平台做端到端测量,报告会指明时间耗在了哪里。

amBrain 自 2019 年起开发软件。它用一句话描述自己的团队:“团队规模最多 40 人,其中约 75% 是资深人员。”它有三种合作方式:整体交付、专属团队,或工程师嵌入你的团队。客户拥有产品与代码的全部所有权,amBrain 的可复用组件除外。

本文不是案例研究,也不描述任何客户项目。本文没有引用 amBrain 所建任何系统的延迟数字,也不给出任何价格或工期。

如果 amBrain 在你的候选名单上,就向它提出与其他每家公司同样的五个问题,并把你的录制数据作为你们约定的任何工作的验收标准。

常见问题

  • 加服务器能解决问题吗?单靠加服务器不行。如果系统乱序应用变动,或者要等最慢的会话,服务器再多也只会重复同样的故障。等测量结果显示现有服务器的容量快用完了,再加服务器
  • 能不能把更新合并起来、少发一些?对订单簿来说可以。工程师把这叫作合并推送(conflation),有些交易所自己就这么做。Binance 的文档把其现货订单簿变动数据流的更新速度定为 1000 ms 或 100 ms。要告诉交易员,这条数据流显示的是最新的画面,而不是每一步。成交和订单确认不要合并,因为丢掉任何一条,成交历史就错了
  • 我们必须用 Rust 或 C++ 重写吗?不一定。漏掉的缺口、等着最慢会话的服务器,都是设计缺陷,换一种新语言消除不了。Rust 和 C++ 没有垃圾回收器,也就是那种会让用 Java 或 Go 等语言写的程序暂停的自动内存清理机制。这对系统中处理每一条更新的那些部分有帮助。不管用什么语言,都要请对方拿出高峰时实测的延迟
  • 修复要多长时间?这取决于故障出在哪里,以及你有多少家交易所和多少个会话。请每家公司为第一阶段报价并给出时间表,这一阶段要涵盖测量工作和一套能回放你录制数据的测试环境。以上面五项测试作为验收标准

手头有类似的设计?

带上您当前的架构和让您担心的故障场景,我们用半小时一起梳理。