在构建量化交易系统时,行情数据接口是基础模块之一。如何选择通信协议,直接影响到系统的延迟、带宽占用、以及数据处理架构的复杂度。HTTP 和 WebSocket 是两种常用的通信协议,本文从实际使用场景出发,特别是围绕行情接口的接入,阐述二者的本质区别和适用场景。
一、协议概览
HTTP
HTTP 是一种请求-响应式协议。客户端(如你的交易系统)发起请求,服务器返回对应的响应。通信完成后,连接即被关闭(除非是 HTTP/1.1 中的 keep-alive 或 HTTP/2 的多路复用机制)。
适用场景:
-
低频请求(如查询某只股票的当日K线)
-
单次数据获取(如请求账户余额、历史数据下载)
-
不需要持续连接
WebSocket
WebSocket 是一种全双工、持久连接协议。在初始阶段通过 HTTP 进行握手,随后升级为 WebSocket 连接。这种连接在客户端和服务器之间保持打开状态,可以双向推送数据。
适用场景:
-
高频数据更新(如tick-by-tick成交数据、盘口数据)
-
实时推送需求强烈的系统
-
事件驱动架构
二、在行情接口中的应用对比
以下从量化交易中常见的行情数据获取需求出发,对比二者差异:
需求场景 | 推荐协议 | 理由 |
查询某支股票的日K线数据 | HTTP | 一次性请求,无需保持连接 |
每秒轮询一次报价(如自建策略模拟) | HTTP(低效) | 实现上可行但消耗资源大、延迟高 |
订阅多只股票的tick行情 | WebSocket | 实时推送,低延迟,占用带宽更小 |
实时盘口订阅(Level 2) | WebSocket | 需要毫秒级推送能力 |
大盘异动监测、自动下单触发 | WebSocket | 需要事件驱动响应机制 |
三、技术层面对比
特性 | HTTP | WebSocket |
连接模式 | 请求-响应 | 持久连接,全双工 |
延迟 | 高(每次连接+握手) | 低(数据推送直接送达) |
带宽利用率 | 低 | 高(头部少,数据压缩更好) |
服务端主动推送 | 不支持 | 支持 |
数据压缩 | 可配置(GZIP等) | 多支持原生压缩(如 permessage-deflate) |
并发连接限制 | 高 | 较低(通常一个连接可多主题订阅) |
实现复杂度 | 低 | 相对高,需管理连接状态 |
四、对系统架构的影响
-
使用 HTTP 接入行情,需要在客户端自行轮询,策略上可能存在延迟(如1秒级别),不适用于高频交易。
-
使用 WebSocket 接入行情,服务端可将 tick 数据实时推送,适合做微秒级监控、事件触发的策略系统,如市场做市、闪电交易、套利策略。
-
对于策略开发者而言,WebSocket 可以极大简化行情监听逻辑,不需考虑轮询频率、数据丢失等问题,只需处理接收到的消息事件即可。
五、实际接入示例对比
HTTP 示例
import requests
api_url = 'https://data.infoway.io/stock/batch_kline/1/10/002594.SZ%2C00285.HK%2CTSLA.US'
# 设置请求头
# 申请API Key: www.infoway.io
headers = {
'User-Agent': 'Mozilla/5.0',
'Accept': 'application/json',
'apiKey': 'yourApikey'
}
# 发送GET请求
response = requests.get(api_url, headers=headers)
# 输出结果
print(f"HTTP code: {response.status_code}")
print(f"message: {response.text}")
WebSocket 示例
import asyncio
import json
import websockets
# 美股行情的websocket订阅地址
WS_URL = "wss://data.infoway.io/ws?business=stock&apikey=yourApiKey"
# 请先在官网https://infoway.io 申请免费API key
async def connect_and_receive():
async with websockets.connect(WS_URL) as websocket:
# 发送初始化消息,这里订阅的是苹果股票的1分钟K线数据
init_message = {
"code": 10004, # K线请求协议号
"trace": "423afec425004bd8a5e02e1ba5f9b2b0", # 可追溯ID(随机字符串)
"data": {
"arr": [
{
"type": 1, # 1分钟K线
"codes": "AAPL" # 订阅的股票代码
}
]
}
}
await websocket.send(json.dumps(init_message))
# 设置ping任务
async def send_ping():
while True:
await asyncio.sleep(30)
ping_message = {
"code": 10010,
"trace": "423afec425004bd8a5e02e1ba5f9b2b0"
}
await websocket.send(json.dumps(ping_message))
# 启动ping任务协程
ping_task = asyncio.create_task(send_ping())
try:
# 持续接收消息
while True:
message = await websocket.recv()
print(f"Message received: {message}")
except websockets.exceptions.ConnectionClosedOK:
print("Connection closed normally")
finally:
# 取消ping任务
ping_task.cancel()
# 运行主函数
asyncio.run(connect_and_receive())
六、选型建议
在量化交易中,不同的行情接口需求应采用不同的通信协议:
-
获取历史数据、低频K线数据:使用 HTTP 即可,简单、易于管理。
-
实时行情、盘口数据、tick 数据:推荐使用 WebSocket,延迟更低,效率更高。
此外,大多数主流行情服务商也会根据数据类型分别提供 HTTP 和 WebSocket 接口,比如:
-
REST API 提供基础查询;
-
WebSocket API 提供实时行情订阅。
因此,不要将 HTTP 和 WebSocket 视为竞争关系,而应视为互补工具。一个成熟的策略系统,应根据数据特性和处理需求合理混用两者。