我记得刚开始接触美股实时行情时,对“延迟”的认知只停留在“好像有点慢”。直到有一次用收盘价策略做模拟,连续三天看到信号触发却成交在明显更差的价格上,我把日志拿出来细细分析,才发现从信号产生到程序拿到数据,平均过去了 280ms。那段时间我回测曲线和实盘曲线严重背离,这也让我下定决心搞清楚 API 延迟到底意味着什么。
延迟到底从哪里来的?别只盯着网速
很多同学以为延迟就是 ping 值,其实整条链路可以拆成三块:通信方式、物理距离、数据格式。我最开始用 HTTP GET 定时抓数据,一秒最多请求 5 次,如果遇上波动大的股票,大量 tick 直接漏掉。后来学习了 WebSocket,服务器主动推送,延迟一下子缩短到 50ms 以内。物理距离也很重要,API 服务器如果离交易所所在的数据中心近,数据在路上跑的时间就短。另外,消息格式也有影响,JSON 很通用但解析需要消耗 CPU,如果碰上高频 tick,积少成多的解析延迟会让策略反应变慢,有些接口用 Protobuf 就会快不少。
我看重的三个数据:不是一个“快”字能概括的
量化交易要求数据又快又准,我整理了一个简单的自检清单,每次试用新的行情 API 都会先看这几项:
| 指标 | 说明 | 我的及格线 |
|---|---|---|
| 端到端延迟 | 事件发生到策略看到数据的时间差 | 实时行情<100ms |
| 吞吐量 | 最高能处理多少条消息 | 每秒至少 1000 条 tick |
| 丢包率 | 数据传丢了多少 | 低于万分之一 |
除此之外,消息顺序必须是递增的。要是时间戳乱掉,算出来的技术指标就毫无意义。刚开始我忽略了这个细节,直到在对数收益计算里看到负数,才追踪到乱序问题。
动手测试才靠谱:我用 WebSocket 同时测了几家
我习惯在美股刚开盘那半小时做压力测试,因为这时的消息密度最高。当时写了一段简单的 WebSocket 订阅脚本,连接到不同服务商,把推送过来的 tick 记录时间戳,然后和本地基准对比。像 ALLTICK API 这类接口,订阅流程简单明了,一个连接就能直接收到逐笔数据。
import websocket
import json
def on_message(ws, message):
data = json.loads(message)
# 输出时间、股票代码、价格和成交量
print(f"时间: {data['ts']} 代码: {data['symbol']} 价格: {data['price']} 量: {data['volume']}")
def on_open(ws):
# 初始化订阅,传入需要监听的股票列表
sub_msg = {
"action": "subscribe",
"symbols": ["AAPL", "MSFT", "NVDA"]
}
ws.send(json.dumps(sub_msg))
ws = websocket.WebSocketApp(
"wss://api.alltick.co/stock/ws",
on_open=on_open,
on_message=on_message
)
ws.run_forever()
同样的网络,我测出来最快的一家延迟稳定在 60ms 左右,另一家很波动,有时候超过 200ms。选择靠谱的接口远比看宣传材料重要。
我的习惯:先求稳,再求快
做量化的同学们经常陷入“越快越好”的误区。其实,中位数延迟低但时不时飙升的接口,对实盘的伤害更大。我现在的原则是:优先选延迟分布均匀、丢包率几乎为零且有多条线路备份的服务。策略的持有期决定了你对延迟的容忍度,如果是分钟级信号,真的没必要去跟毫秒较劲。找一个适合自己策略节奏的 API,踏踏实实做研究,比什么都重要。
共同学习,写下你的评论
评论加载中...
作者其他优质文章
