在接入 A 股行情数据时,有一个经常被忽略但非常关键的细节:你拿到的是实时数据,还是延时数据?
我们在雪球、东方财富这类网站上看到的行情更新看起来很快,其实大多是延时数据。这在官网也会注明,比如“本页面所示行情数据为 T+0 延时15分钟,仅供参考”等。
延时行情对日常查看、趋势判断是足够的,但如果你在做以下这些事情,就会有明显影响:
-
高频或低延迟策略开发;
-
实盘交易系统对接;
-
实时风控与盘口建模;
-
多源行情同步与聚合分析。
在这些场景中,延时15秒甚至几秒钟都可能导致策略响应偏离真实市场状态。
相比之下,实时行情 API通过WebSocket 毫秒级推送最新市场数据,没有中间缓存或延迟,可以更直接地反映市场当下的状态。尤其是 Level 2 行情,还能提供更深的盘口信息,比如买卖五档、委托队列等。
这并不是说实时行情一定更好,关键在于你的应用是否真的需要它。如果你只是做中线选股或者参考日内波动,延时数据可能已经够用了;但若你需要交易决策或建模依赖市场瞬时状态,实时行情就变得必要了。
订阅K线
import asyncio
import json
import websockets
# A股行情的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:
# 发送初始化消息,这里订阅的是平安银行(000001.SZ)的1分钟K线数据
init_message = {
"code": 10004,
"trace": "423afec425004bd8a5e02e1ba5f9b2b0",
"data": {
"arr": [
{
"type": 1, # 1分钟K线
"codes": "000001.SZ" # A股股票代码,例如 平安银行
}
]
}
}
await websocket.send(json.dumps(init_message))
async def send_ping():
while True:
await asyncio.sleep(30)
ping_message = {
"code": 10010,
"trace": "423afec425004bd8a5e02e1ba5f9b2b0"
}
await websocket.send(json.dumps(ping_message))
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_task.cancel()
# 运行主函数
asyncio.run(connect_and_receive())
返回示例
{
"c": "11.25", // 收盘价
"h": "11.28", // 最高价
"l": "11.22", // 最低价
"o": "11.23", // 开盘价
"pca": "0.02", // 价格变化
"pfr": "0.18%", // 价格变化百分比
"s": "000001.SZ", // 股票代码
"t": 1747550648097, // 时间戳
"ty": 1, // K线类型:1 表示1分钟K线
"v": "258400", // 交易量(单位:股)
"vw": "11.2458" // 加权平均价格
}
订阅盘口数据
import asyncio
import json
import websockets
# A股行情的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:
# 发送初始化消息,订阅的是 A股平安银行(000001.SZ)的盘口数据
init_message = {
"code": 10002, # 盘口订阅的请求协议号
"trace": "423afec425004bd8a5e02e1ba5f9b2b0", # 可追溯ID(可随机生成)
"data": {
"codes": "000001.SZ" # A股股票代码,例如平安银行
}
}
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())
返回示例
{
"a": [
[
"11.25", // 卖盘价格1
"11.26", // 卖盘价格2
"11.27", // 卖盘价格3
"11.28", // 卖盘价格4
"11.29" // 卖盘价格5
],
[
"23000", // 卖盘数量1
"18000", // 卖盘数量2
"9500", // 卖盘数量3
"6000", // 卖盘数量4
"7200" // 卖盘数量5
]
],
"b": [
[
"11.24", // 买盘价格1
"11.23", // 买盘价格2
"11.22", // 买盘价格3
"11.21", // 买盘价格4
"11.20" // 买盘价格5
],
[
"26000", // 买盘数量1
"20000", // 买盘数量2
"10000", // 买盘数量3
"7500", // 买盘数量4
"8500" // 买盘数量5
]
],
"s": "000001.SZ", // A股股票代码(平安银行)
"t": 1747553102161 // 时间戳
}