**摘要:做行情看板、量化回测或盯盘工具时,最麻烦的往往不是业务逻辑,而是行情数据源。本文基于 DeepTick 的 REST 与 WebSocket 接口,完整演示港股、美股、A 股实时报价、历史 K 线与逐笔成交的接入方式,附 Python 可运行代码与字段说明。
一、背景
金融类应用开发中,行情数据通常需要覆盖三类能力:
- 快照报价:当前最新价、开高低、成交量额,用于看板、列表页;
- 历史 K 线:用于画图、技术指标计算与回测;
- 逐笔成交(Tick):用于高频盯盘、成交明细展示。
传统做法是 HTTP 轮询,简单但延迟高、请求量大。更合理的组合是:REST 拉快照和历史数据 + WebSocket 推实时数据。本文以 DeepTick 为例,把这条链路完整走一遍。
二、接入准备
2.1 认证方式
DeepTick 的 REST 接口通过请求头 deeptoken 认证,WebSocket 在建立连接时通过 additional_headers 传入同一个 token。
python
headers = {
"deeptoken": "your_api_key"
}
2.2 标的代码(symbol)规则
DeepTick 统一使用 代码.市场 格式,跨市场规则如下:
| 市场 | 后缀 | 示例 | 说明 |
|---|---|---|---|
| 港股 | .HK | 700.HK、9988.HK | 5 位数字代码 |
| 美股 | .US | AAPL.US、TSLA.US | 1–4 位字母 |
| A 股沪市 | .SH | 601398.SH | 60 开头 |
| A 股深市 | .SZ | 300750.SZ、000001.SZ | 00 / 30 开头 |
| 加密货币 | .CR | BTCUSDT.CR | 加密对 |
注意:REST 实时报价一次只能查 1 个标的;K 线接口单次最多 20 个标的;WebSocket 可在同一订阅中混合多市场。
三、REST 接口实战
3.1 实时报价:GET /api/v1/quote
拉取单个标的的当前最新价与当日统计,不含买卖盘口,逐笔成交请走 WebSocket tick。
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| symbols | string | 是 | 一个标的,如AAPL.US;传多个会返回错误码8005 |
Python 示例
python
import requests
url = "//api.deeptick.cc/api/v1/quote"
headers = {"deeptoken": "your_api_key"}
params = {"symbols": "AAPL.US"}
try:
resp = requests.get(url, headers=headers, params=params)
result = resp.json()
if result["code"] == 0:
q = result["data"][0]
print(f"标的:{q['s']}")
print(f"最新价:{q['ld']}")
print(f"开盘:{q['o']} 最高:{q['h']} 最低:{q['l']}")
print(f"成交量:{q['v']} 成交额:{q['tu']}")
else:
print("请求失败:", result["msg"])
except Exception as e:
print("请求异常:", str(e))
响应示例
json
{
"code": 0,
"msg": "ok",
"data": [
{
"s": "AAPL.US",
"ld": "225.215",
"o": "226.27",
"h": "226.92",
"l": "224.44",
"v": "16742235",
"tu": "3774688301.452",
"t": 1731689407000
}
]
}
字段说明(data[] 元素)
| 字段 | 类型 | 说明 |
|---|---|---|
| s | string | 标的代码 |
| ld | string/number | 最新价 |
| p | string/number | 前收 |
| o/h/l | string/number | 开 / 高 / 低 |
| v/tu | string/number | 成交量 / 成交额 |
| ch/chp | string/number | 涨跌额 / 涨跌幅(上游无则不出现) |
| ts | int | 交易状态:0正常、1停牌、2退市、3熔断,不是时间戳 |
| t | long | 行情时间戳(毫秒) |
这里有个容易踩的坑:ts 是交易状态而不是时间,真正的时间是 t。
3.2 历史 K 线:GET /api/v1/candles
用于补历史 K 线、绘图或回测,始终查上游、不走缓存,返回按时间升序排列。正在走的当前 K 线请订阅 WebSocket candle,不要轮询本接口。
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| symbols | string | 是 | 逗号分隔,单次最多 20 个,超限返回8006 |
| interval | enum | 否,默认5m | 1m/5m/15m/30m/60m/4h/1d/1w/1M;1h视为60m |
| limit | int | 否,默认 40 | 1~500,超限返回8007 |
| et | long | 否 | 截止时间(Unix 毫秒),缺省取最新 |
Python 示例
python
import requests
import datetime
url = "//api.deeptick.cc/api/v1/candles"
headers = {"deeptoken": "your_api_key"}
params = {
"symbols": "300750.SZ", # 宁德时代
"interval": "1d",
"limit": 10
}
try:
resp = requests.get(url, headers=headers, params=params)
result = resp.json()
if result["code"] == 0:
for item in result["data"]:
print(f"标的:{item['s']} 周期:{item['i']}")
for bar in item["d"]:
dt = datetime.datetime.fromtimestamp(bar["t"] / 1000)
print(
f"{dt:%Y-%m-%d} 开:{bar['o']} 高:{bar['h']} "
f"低:{bar['l']} 收:{bar['c']} 量:{bar['v']} 额:{bar['tu']}"
)
else:
print("请求失败:", result["msg"])
except Exception as e:
print("请求异常:", str(e))
响应示例
json
{
"code": 0,
"msg": "ok",
"data": [
{
"s": "300750.SZ",
"i": "1d",
"d": [
{
"t": 1723100000000,
"o": "535.0",
"h": "536.0",
"l": "534.5",
"c": "534.5",
"v": "104799385",
"tu": "56119888070.5"
}
]
}
]
}
字段说明
| 字段 | 类型 | 说明 |
|---|---|---|
| s | string | 标的代码 |
| i | enum | 周期 |
| d | array | K 线数组,时间升序 |
| d[].t | long | 该周期时间戳(毫秒) |
| d[].o/h/l/c | string/number | 开 / 高 / 低 / 收 |
| d[].v/d[].tu | string/number | 成交量 / 成交额 |
四、WebSocket 实时推送
连接地址:
text
一次 subscribe 必须是同一种 type(quote 或 tick),不能混写。topic 格式:
- 报价:quote.{market}.{symbol},如 quote.US.AAPL、quote.HK.700
- 逐笔:tick.{market}.{symbol},如 tick.US.AAPL
Python 示例(需 pip install websockets)
python
import asyncio
import json
import websockets
TOKEN = "your_api_key"
async def main():
async with websockets.connect(
"wss://api.deeptick.cc/ws/v1",
additional\_headers={"deeptoken": TOKEN}
) as ws:
print(await ws.recv()) # welcome
await ws.send(json.dumps({
"type": "subscribe",
"topics": [
"quote.US.AAPL", "tick.US.AAPL",
"quote.HK.700", "tick.HK.700"
],
"request\_id": "r1"
}))
while True:
frame = json.loads(await ws.recv())
ftype = frame.get("type")
data = frame.get("data", {})
if ftype == "quote":
print(f"[QUOTE] {data.get('s')} 最新价:{data.get('ld')} "
f"开:{data.get('o')} 高:{data.get('h')} 低:{data.get('l')} "
f"量:{data.get('v')} 额:{data.get('tu')}")
elif ftype == "tick":
print(f"[TICK] {data.get('s')} 价格:{data.get('ld')} "
f"数量:{data.get('v')} 时间:{data.get('t')}")
if __name__ == "__main__":
asyncio.run(main())
quote 数据帧
json
{
"type": "quote",
"topic": "quote.US.AAPL",
"ts": 1723100000000,
"data": {
"s": "AAPL.US",
"ld": "225.215",
"o": "226.27",
"h": "226.92",
"l": "224.44",
"v": "16742235",
"tu": "3774688301.452",
"t": 1731689407000
}
}
tick 数据帧
json
{
"type": "tick",
"topic": "tick.US.AAPL",
"ts": 1723100000000,
"data": {
"s": "AAPL.US",
"ld": "192.41",
"v": "100",
"t": 1723100000000
}
}
外层字段
| 字段 | 类型 | 说明 |
|---|---|---|
| type | enum | 帧类型:tick/quote/depth/candle/trade |
| topic | string | 订阅 topic 原文 |
| ts | long | 行情时间戳(毫秒) |
quote data 字段:s、ld、p、o/h/l、v/tu、ch/chp、ts(交易状态)、t(时间戳),含义同 3.1。
tick data 字段:s 标的、ld 成交价、v 成交数量、t 成交时间(毫秒)。
五、接入踩坑与注意事项
- ts 不是时间:报价里的 ts 是交易状态(0 正常 / 1 停牌 / 2 退市 / 3 熔断),时间字段是 t。
- 数值类型不固定:字段可能是 string 也可能是 number,落库或计算前统一 float() 转换,展示保留 2 位小数。
- 订阅不能混 type:一次 subscribe 只能全是 quote 或全是 tick,混写会失败。
- REST 单标的限制:/api/v1/quote 只接受 1 个 symbol,批量场景请用 WebSocket 订阅。
- K 线上限:单次最多 20 个标的、limit 最大 500,超限分别返回 8006、8007。
- 频率控制:免费版建议每秒不超过 5 次请求,高频需求升级套餐。
- 错误处理:code != 0 时读 msg;网络超时做重试,无数据时用缓存降级。
- 市场差异:A 股人民币、港股港币、美股美元,交易时间也不同,展示层需针对性适配。
六、总结
整体接入思路可以归纳为一条链路:
- 快照类需求(看板、列表)→ REST /api/v1/quote
- 历史类需求(绘图、回测)→ REST /api/v1/candles
- 实时类需求(盯盘、成交明细)→ WebSocket quote.* / tick.*
REST 负责「拉」,WebSocket 负责「推」,两者组合即可覆盖绝大多数行情场景。代码层面重点处理好三件事:字段类型统一、时间戳转换、错误码与重试。
免责声明:本文代码用于技术接入演示,不构成投资建议。行情数据的使用、展示、存储和再分发应遵守 DeepTick 服务条款及相关市场的数据授权要求。
GitHub:https://github.com/deeptick-cc/deeptick-realtime-market-data-api

