第四章:延迟模型——滑点的隐形推手

做市交易里,滑点这东西,说白了就是「你看到的价,和你成交的价,不是一回事」。
为什么会这样?因为延迟。

我刚开始做外汇做市那会儿,总觉得滑点是市场太滑,后来才明白——
延迟才是真正的幕后黑手。你看到的报价,已经是100毫秒前的历史了。

4.1 网络延迟:从你的服务器到交易所的距离

网络延迟,就是数据包在物理线路上跑的时间。
光速虽然快,但光纤不是直的,路由器要处理,中间还有各种跳点。

我个人习惯把网络延迟分成三段:

  • 客户端到聚合引擎:通常是你的交易服务器到流动性聚合服务器
  • 聚合引擎到交易所:聚合器到各个流动性提供商
  • 交易所内部:交易所的网关到撮合引擎

举个例子。我在新加坡机房,流动性提供商在伦敦。
物理距离大约1万公里,光速往返大约67毫秒。
但实际延迟通常在120-150毫秒之间。为什么?

因为中间有海底光缆的放大器、路由器的排队、还有各种协议开销。
你想想看,这150毫秒里,市场可能已经跳了3个点。

关键数据:

距离理论最低延迟实际典型延迟
同城(10km)0.1ms0.5-1ms
同区域(500km)3ms8-15ms
跨洲(10000km)67ms120-200ms

我的经验: 如果你做高频做市,服务器必须放在交易所的同一数据中心。
哪怕只差一个机柜,延迟都能差0.1ms。别小看这0.1ms,滑点可能就差一个点。

4.2 交易所处理延迟:撮合引擎的「思考时间」

交易所不是收到订单就立刻成交的。
它要校验、要排队、要撮合。这个过程叫「处理延迟」。

我记得有一次,我观察某主流外汇交易所的撮合引擎。
它的处理延迟在正常行情下是2-5ms,但遇到非农数据发布时,能飙到50ms以上。

为什么会这样?

  • 订单校验:检查你的账户余额、风控限制
  • 价格校验:检查你的报价是否在可接受范围内
  • 撮合排队:FIFO队列,前面订单多你就得等
  • 日志写入:每个订单都要写磁盘,磁盘IO是瓶颈

避坑指南: 我曾经遇到过一个情况——交易所的处理延迟突然从3ms变成30ms。
原因是那天有大量套利订单涌入,撮合引擎的CPU被打满了。
嗯,从那以后,我每次接入新交易所,都会先做压力测试,看看它在极端情况下的处理延迟曲线。

4.3 聚合引擎延迟:多源数据的「融合之痛」

做市商通常不会只接一家流动性提供商。
我们会接5家、10家,甚至更多。这时候就需要聚合引擎。

聚合引擎的工作流程是这样的:

  1. 从各家LP接收报价
  2. 对报价进行归一化处理
  3. 生成最优报价(Best Bid/Offer)
  4. 把报价推送给交易系统

每一步都有延迟。我算过一笔账:

环节延迟说明
LP报价传输5-20ms各家LP的服务器位置不同
报价归一化1-3ms格式转换、精度调整
最优报价计算0.5-2ms排序、去重、价格合并
报价推送1-5ms推送到交易客户端

加起来,聚合引擎的端到端延迟大约在10-30ms之间。
你想想看,这30ms里,市场可能已经变了。

核心问题: 聚合引擎的延迟会导致「报价过时」。
你看到的报价是30ms前的,但你以为是最新的。
当你下单时,实际成交价可能已经偏离了。

4.4 三种延迟如何叠加影响滑点

现在我们把三种延迟串起来看:

假设你在新加坡,交易EUR/USD:

  • 网络延迟(新加坡→伦敦):120ms
  • 交易所处理延迟:5ms
  • 聚合引擎延迟:20ms

总延迟 = 120 + 5 + 20 = 145ms

145毫秒,EUR/USD能波动多少?
在正常行情下,大约0.5-1个点。
在数据发布时,可能3-5个点。

这就是滑点的来源。你看到的报价是145ms前的,成交价是现在的。

我的建议: 做滑点控制,第一步就是测量你的总延迟。
我习惯在每个环节打时间戳,从报价生成到订单成交,全程记录。
这样你就能知道,滑点到底来自哪个环节。

4.5 延迟模型的可视化

下面这张图,是我自己画的延迟模型流程图。
它展示了从报价到成交的完整路径,以及每个环节的延迟贡献。

外汇做市延迟模型流程图 流动性提供商 LP 1 / LP 2 / LP 3 网络传输 延迟:50-200ms 聚合引擎 延迟:10-30ms 交易系统 报价展示 + 下单 网络传输 延迟:50-200ms 交易所撮合引擎 处理延迟:2-50ms 成交结果返回 滑点 = 预期价 - 成交价 总延迟 = 网络 + 聚合 + 交易所 = 100-400ms + 10-30ms + 2-50ms = 112-480ms 滑点风险:高 数据源 网络传输 聚合处理 交易系统 交易所 成交结果

4.6 如何测量和优化延迟

测量延迟,我推荐用「时间戳链」的方法:

// 伪代码示例:在每个环节打时间戳
long t1 = System.nanoTime();  // 报价生成
// ... 网络传输 ...
long t2 = System.nanoTime();  // 聚合引擎收到
// ... 聚合处理 ...
long t3 = System.nanoTime();  // 报价推送给交易系统
// ... 下单 ...
long t4 = System.nanoTime();  // 订单发送
// ... 网络传输 ...
long t5 = System.nanoTime();  // 交易所收到
// ... 撮合 ...
long t6 = System.nanoTime();  // 成交返回

// 计算各环节延迟
double networkLatency1 = (t2 - t1) / 1_000_000.0;  // ms
double aggLatency = (t3 - t2) / 1_000_000.0;       // ms
double networkLatency2 = (t5 - t4) / 1_000_000.0;  // ms
double exchangeLatency = (t6 - t5) / 1_000_000.0;  // ms

优化延迟,我个人的优先级是这样的:

  1. 网络延迟:最优先。把服务器搬到交易所附近,用专线或VPN
  2. 聚合引擎延迟:其次。优化代码,减少不必要的处理,用内存数据库
  3. 交易所处理延迟:最后。选择处理速度快的交易所,避开高峰时段

我曾经踩过的坑: 有一段时间,我发现滑点突然变大。
查了三天,最后发现是聚合引擎的报价缓存设置有问题——缓存时间设成了100ms,但市场波动快的时候,100ms的报价已经过时了。
嗯,从那以后,我把缓存时间改成了10ms,滑点立刻降了一半。

总结一下:延迟模型是滑点控制的基础。
你只有知道延迟从哪里来,才能知道怎么优化。
别想着一步到位,先测量,再优化,一步一步来。