定义
发送增量变化的数据源,依赖每一次变化都按顺序到达。因此每一个数据包或者消息都带着一个按已知步长递增的数字。接收方把每一个新数字和上一个比较:正好大一就正常,更小是重复,更大就是缺口。
像芝商所 MDP 3.0 这样的交易所数据源给它们的数据包编号,并把每条通道在两份冗余的数据源上公布,这样在一份上丢掉的包可以从另一份取到。注意这个设计承认了丢包是常态——它不是异常处理,而是主路径的一部分。
算例一:检测一个缺口
数据包 1041 和 1042 到了,然后是 1045。1043 和 1044 这两个包缺失了。它们所携带的任何订单簿更新都是未知的,所以在 1045 之后持有的那个簿,在恢复完成之前不能被信任。
算例二:把快照和数据流缝起来
币安发送的深度更新带着一个首 id U 和一个末 id u,而一个单独的快照带着 lastUpdateId。在现货上,设快照为 L = 500:丢弃那些 u 不超过 500 的缓冲事件;保留的第一个事件必须满足 U <= 501 <= u,比如 U = 498 而 u = 503;之后每一个事件必须从前一个的 u + 1 开始,这里是 U = 504。
USD-M 合约用的是另一条链接规则:一个 pu 字段必须等于前一个的 u。把一个市场的规则用到另一个市场上,要么会在重新同步上死循环,要么会让一个缺口通过——而后者不报任何错误。
在 Senzoukria 里
币安订单簿同步器把这些流程作为一个单独的、带测试的模块来实现,现货和 USD-M 的规则分开保存;而在检测到缺口时它从一个新快照重新同步,而不是去打补丁。它的源码解释了理由:一次错误的缝接不会抛出任何错误,它产生的是一个看起来正常、但其中的价位已经不存在的簿——这是一张流动性热力图上最糟糕的那种缺陷。
对芝商所数据,交易所层面的恢复由数据商处理。在一个被断线中断的 Databento 实时成交会话上,软件从最后收到的那笔成交的时间戳加一纳秒重新打开它,这样中间那些成交是被回放而不是被丢掉;而 MBP-10 的订单簿不被回放。
常见错误
- 在出现缺口之后继续应用更新,因为那个簿看起来还挺合理。
- 用时间戳而不是序列号去检测丢失。
- 把一个场所的缝接规则用到另一个场所或者另一个市场上。
相关内容
同一栏目
其他语言版本
常见问题
- 出现序列号缺口之后,一个平台该做什么?
- 停止信任这个簿,通过一次回放或者一个新快照来恢复,然后才恢复应用更新。在这期间继续画那个过时的簿,会显示出可能已经不存在的流动性。
- 成交数据源也会有序列号缺口吗?
- 会。成交里的一个缺口意味着漏掉的成交,这会低估成交量,并在受影响的那些价格上扭曲 Delta。在数据源提供回放的情况下,通过回放恢复能把它们补回来。