第四章:延迟模型——滑点的隐形推手
做市交易里,滑点这东西,说白了就是「你看到的价,和你成交的价,不是一回事」。
为什么会这样?因为延迟。
我刚开始做外汇做市那会儿,总觉得滑点是市场太滑,后来才明白——
延迟才是真正的幕后黑手。你看到的报价,已经是100毫秒前的历史了。
4.1 网络延迟:从你的服务器到交易所的距离
网络延迟,就是数据包在物理线路上跑的时间。
光速虽然快,但光纤不是直的,路由器要处理,中间还有各种跳点。
我个人习惯把网络延迟分成三段:
- 客户端到聚合引擎:通常是你的交易服务器到流动性聚合服务器
- 聚合引擎到交易所:聚合器到各个流动性提供商
- 交易所内部:交易所的网关到撮合引擎
举个例子。我在新加坡机房,流动性提供商在伦敦。
物理距离大约1万公里,光速往返大约67毫秒。
但实际延迟通常在120-150毫秒之间。为什么?
因为中间有海底光缆的放大器、路由器的排队、还有各种协议开销。
你想想看,这150毫秒里,市场可能已经跳了3个点。
关键数据:
| 距离 | 理论最低延迟 | 实际典型延迟 |
|---|---|---|
| 同城(10km) | 0.1ms | 0.5-1ms |
| 同区域(500km) | 3ms | 8-15ms |
| 跨洲(10000km) | 67ms | 120-200ms |
我的经验: 如果你做高频做市,服务器必须放在交易所的同一数据中心。
哪怕只差一个机柜,延迟都能差0.1ms。别小看这0.1ms,滑点可能就差一个点。
4.2 交易所处理延迟:撮合引擎的「思考时间」
交易所不是收到订单就立刻成交的。
它要校验、要排队、要撮合。这个过程叫「处理延迟」。
我记得有一次,我观察某主流外汇交易所的撮合引擎。
它的处理延迟在正常行情下是2-5ms,但遇到非农数据发布时,能飙到50ms以上。
为什么会这样?
- 订单校验:检查你的账户余额、风控限制
- 价格校验:检查你的报价是否在可接受范围内
- 撮合排队:FIFO队列,前面订单多你就得等
- 日志写入:每个订单都要写磁盘,磁盘IO是瓶颈
避坑指南: 我曾经遇到过一个情况——交易所的处理延迟突然从3ms变成30ms。
原因是那天有大量套利订单涌入,撮合引擎的CPU被打满了。
嗯,从那以后,我每次接入新交易所,都会先做压力测试,看看它在极端情况下的处理延迟曲线。
4.3 聚合引擎延迟:多源数据的「融合之痛」
做市商通常不会只接一家流动性提供商。
我们会接5家、10家,甚至更多。这时候就需要聚合引擎。
聚合引擎的工作流程是这样的:
- 从各家LP接收报价
- 对报价进行归一化处理
- 生成最优报价(Best Bid/Offer)
- 把报价推送给交易系统
每一步都有延迟。我算过一笔账:
| 环节 | 延迟 | 说明 |
|---|---|---|
| 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 延迟模型的可视化
下面这张图,是我自己画的延迟模型流程图。
它展示了从报价到成交的完整路径,以及每个环节的延迟贡献。
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
优化延迟,我个人的优先级是这样的:
- 网络延迟:最优先。把服务器搬到交易所附近,用专线或VPN
- 聚合引擎延迟:其次。优化代码,减少不必要的处理,用内存数据库
- 交易所处理延迟:最后。选择处理速度快的交易所,避开高峰时段
我曾经踩过的坑: 有一段时间,我发现滑点突然变大。
查了三天,最后发现是聚合引擎的报价缓存设置有问题——缓存时间设成了100ms,但市场波动快的时候,100ms的报价已经过时了。
嗯,从那以后,我把缓存时间改成了10ms,滑点立刻降了一半。
总结一下:延迟模型是滑点控制的基础。
你只有知道延迟从哪里来,才能知道怎么优化。
别想着一步到位,先测量,再优化,一步一步来。