港股数据接入完整指南:A 股量化开发者的三个必知差异与全量接入实战
作者: TickDB Research · 发布: 2026/9/23 · 阅读: 9
标签: 知乎
换一个
market=HK参数,数据就来了——很多 A 股量化开发者第一次接港股时,是这么想的。
>
数据确实来了。但三个坑在等着你。
我见过不少做 A 股量化的朋友,在接港股数据时踩过同一批雷:策略在 A 股跑得好好的,搬到港股之后,回测曲线莫名其妙出现空洞;价格过滤逻辑在午休时段疯狂触发异常;仓位计算结果和实际可买数量对不上。
排查一圈,不是数据源的问题,是港股数据和 A 股数据在结构层面就不一样。
这篇指南从三个核心差异出发,然后覆盖港股行情数据的完整接入路径:实时行情、历史 K 线、盘口深度、逐笔成交、交易时段、标的参考数据,以及公司行动(分红、配股)。读完之后你会有一张可以直接用于代码 review 的检查清单。
在读之前:港股数据层全景
先看整体结构,再深入细节。
┌─────────────────────────────────────────────────────────────────────┐
│ 港股数据接入架构(4 层) │
├─────────────────────────────────────────────────────────────────────┤
│ Layer 4 接入层 │
│ REST API · WebSocket 推送 · MCP / AI-native │
├─────────────────────────────────────────────────────────────────────┤
│ Layer 3 公司行动层 │
│ 分红 · 配股 · 供股 · H 股 / 红筹差异 │
├─────────────────────────────────────────────────────────────────────┤
│ Layer 2 参考数据层 ← ⚠️ A 股量化手最容易忽略的一层 │
│ 交易时段(含午休)· Lot Size · 半日市日历 · 标的类型 │
├─────────────────────────────────────────────────────────────────────┤
│ Layer 1 行情层 │
│ 实时快照 · K 线 · 分时 · 盘口 · 逐笔 · 资金流 │
└─────────────────────────────────────────────────────────────────────┘
架构和 A 股四层大体对应,但 Layer 2 参考数据层的内容完全不同。三个坑都藏在这一层。
第一部分:三个必知差异
在进入完整接入流程之前,先把三个差异讲清楚。这是检验你的港股数据接入是否可靠的基础。
差异一:港股每天有一小时数据空洞
A 股假设: 交易日 9:30–15:00 连续推送。
港股事实: 港股每个交易日中午 12:00–13:00 为午间休市,期间没有任何成交数据。
这不是数据源的问题,是香港交易所(HKEX)的制度安排。HKEX 官方交易时段如下:
竞价开盘 09:00 – 09:30 集合竞价,接受挂单不成交
持续交易 09:30 – 12:00 正常撮合
午间休市 12:00 – 13:00 ← 数据空洞,非异常
持续交易 13:00 – 16:00 正常撮合
收市竞价 16:00 – 16:10 收市竞价撮合
踩坑场景: 把 A 股的异常检测逻辑(「超过 X 分钟没有新数据 = 触发告警」)直接用在港股上,中午一小时必然误报。
处理方式: 在开始写策略逻辑之前,先查询当前标的的交易时段,判断当前时间是否在有效交易窗口内。
用 TickDB 查询腾讯(700.HK)的交易时段:
import requests
resp = requests.get(
"https://api.tickdb.com/v1/market/trading-sessions",
params={"symbols": "700.HK"},
headers={"Authorization": "Bearer YOUR_TOKEN"}
)
sessions = resp.json()
print(sessions)
返回结构(基于 HKEX 官方时段;具体字段名待 Codex 实测确认):
{
"700.HK": {
"sessions": [
{"type": "pre_open", "start": "09:00", "end": "09:30"},
{"type": "continuous", "start": "09:30", "end": "12:00"},
{"type": "lunch_break", "start": "12:00", "end": "13:00"},
{"type": "continuous", "start": "13:00", "end": "16:00"},
{"type": "closing_call","start": "16:00", "end": "16:10"}
]
}
}
必查清单第一条: 你的异常告警逻辑里,有没有把 lunch_break 时段排除在外?
差异二:港股没有涨跌停板,A 股的价格过滤全部失效
A 股假设: 个股单日涨跌幅不超过 ±10%(科创板 ±20%),超过这个范围的价格变动可以视为异常。
港股事实: 港股没有涨跌停板制度。单日涨幅理论上无上限,跌幅亦然。这是 HKEX 的基本制度,不是例外情况。
踩坑场景: 一套做 A 股的策略,内置了「价格变动超过 15% 触发检查」的过滤逻辑。搬到港股之后,某标的因重大公告单日涨幅 40%,这条逻辑把它当作脏数据过滤掉,实盘信号丢失。
更隐蔽的情况:回测时某些极端行情的 K 线被过滤,导致回测结果比实盘乐观。
处理方式: 港股策略中,去掉基于固定涨跌幅阈值的价格合法性过滤。如果你的系统做多市场,必须在市场层面维护各市场的涨跌停规则,而不是用一套全局规则。
必查清单第二条: 你的数据清洗流程里,有没有针对港股关掉涨跌幅过滤?
差异三:Lot Size 不统一,「一手 = 100 股」在港股是错的
A 股假设: A 股每手 100 股,最小申报单位 100 股。
港股事实: 港股每只标的的 Lot Size(每手股数)由上市公司在上市时决定,不同标的不一样,而且可以在上市后通过股东大会决议调整。
常见的 Lot Size 分布:
| Lot Size | 代表性标的类型 |
|---|---|
| 100 股 | 腾讯(700.HK)等蓝筹 |
| 200 股 | 部分内地红筹股 |
| 500 股 | 中小市值标的 |
| 1000 股 | 低价股、部分科技股 |
| 2000 股 | 极少数低价标的 |
踩坑场景: 仓位计算公式直接用「资金 ÷ 股价 ÷ 100,取整,× 100」。当标的 Lot Size 是 500 时,计算出来的股数不是 500 的整数倍,下单系统报错,或者实际成交数量和预期不一致。
批量回测时,如果 Lot Size 用错,组合整体的资金利用率和实盘会有系统性偏差。
处理方式: 每次接入新的港股标的,先查 Lot Size,把它作为参数传进仓位计算模块。不要硬编码 100。
用 TickDB 查询 700.HK 的标的信息(含 Lot Size):
resp = requests.get(
"https://api.tickdb.com/v1/market/symbols",
params={"symbols": "700.HK"},
headers={"Authorization": "Bearer YOUR_TOKEN"}
)
info = resp.json()
lot_size = info["700.HK"]["lot_size"] # 腾讯为 100
print(f"每手股数:{lot_size}")
返回结构示例(700.HK):
{
"700.HK": {
"symbol": "700.HK",
"name": "腾讯控股",
"lot_size": 100,
"currency": "HKD",
"type": "equity",
"exchange": "HKEX"
}
}
注意 type 字段:港股市场除了普通正股(equity)之外,还有认股权证(warrant)和牛熊证(CBBC)。它们的价格行为、数据结构和交易规则完全不同。接入时必须先判断 type,不能把轮证当成正股处理。(type 字段具体枚举值待 Codex 实测确认)
必查清单第三条: 你的仓位计算模块,有没有从数据层动态获取 Lot Size,而不是写死 100?
第二部分:Layer 1 行情层
三个差异讲完,接下来是完整的港股行情数据接入。
实时快照
resp = requests.get(
"https://api.tickdb.com/v1/market/ticker",
params={"symbols": "700.HK"},
headers={"Authorization": "Bearer YOUR_TOKEN"}
)
quote = resp.json()["700.HK"]
print(f"最新价:{quote['last_price']} HKD")
print(f"涨跌幅:{quote['change_rate']}%") # 无涨跌停,可能超过 ±20%
和 A 股的区别:
change_rate无硬性上下限- 午休时段快照不更新(
last_price保持午休前最后成交价) - 货币单位是 HKD,不是 CNY
K 线历史
resp = requests.get(
"https://api.tickdb.com/v1/market/kline",
params={
"symbols": "700.HK",
"period": "1d",
"start": "2024-01-01",
"end": "2024-12-31",
"adjust": "qfq" # 前复权
},
headers={"Authorization": "Bearer YOUR_TOKEN"}
)
bars = resp.json()["700.HK"]["bars"]
运行后你应该看到:每条 K 线包含 open、high、low、close、volume、turnover,日期覆盖交易日(港股无数据的周末和公众假期自动跳过)。
港股复权注意: 港股存在大量配股、供股操作,复权因子的连续性比 A 股更复杂。建议使用数据源提供的前复权数据,而不是自行计算。
分时数据
resp = requests.get(
"https://api.tickdb.com/v1/market/intraday",
params={"symbols": "700.HK", "date": "2024-06-03"},
headers={"Authorization": "Bearer YOUR_TOKEN"}
)
ticks = resp.json()["700.HK"]["ticks"]
运行后你应该看到:分时数据在 12:00 出现间断,13:00 继续,这是正常的午休空洞,不是数据缺失。
盘口深度
resp = requests.get(
"https://api.tickdb.com/v1/market/order-book",
params={"symbols": "700.HK", "depth": 10},
headers={"Authorization": "Bearer YOUR_TOKEN"}
)
book = resp.json()["700.HK"]
逐笔成交
resp = requests.get(
"https://api.tickdb.com/v1/market/trades",
params={"symbols": "700.HK", "limit": 100},
headers={"Authorization": "Bearer YOUR_TOKEN"}
)
trades = resp.json()["700.HK"]["trades"]
资金流
resp = requests.get(
"https://api.tickdb.com/v1/market/capital-flow",
params={"symbols": "700.HK"},
headers={"Authorization": "Bearer YOUR_TOKEN"}
)
flow = resp.json()["700.HK"]
第三部分:Layer 2 参考数据层
这是 A 股量化手最容易跳过、也最容易踩坑的一层。
交易时段(接入第一步)
上文已经演示过 trading-sessions 接口。这里补充一个完整的时段判断逻辑:
from datetime import datetime, time
def is_trading_now(sessions: list) -> bool:
"""
判断当前是否在有效交易时段(排除午休)
sessions: trading-sessions 接口返回的 sessions 列表
"""
now = datetime.now().time()
for s in sessions:
if s["type"] == "lunch_break":
continue # 明确跳过午休时段
start = time.fromisoformat(s["start"])
end = time.fromisoformat(s["end"])
if start <= now <= end:
return True
return False
半日市(Half Day)
港股每年有若干个半日市,通常出现在圣诞前夕、除夕等节假日前。半日市当天,下午交易时段提前收市(通常 12:00 收盘)。
HKEX 每年提前公布半日市日历。建议通过 API 查询交易日历,而不是自己维护节假日列表:
resp = requests.get(
"https://api.tickdb.com/v1/market/trade-days",
params={"market": "HK", "year": "2024"},
headers={"Authorization": "Bearer YOUR_TOKEN"}
)
calendar = resp.json()
标的信息(Lot Size + type 字段)
上文已演示单标的查询。这里补充多标的批量查询:
symbols = ["700.HK", "9988.HK", "1299.HK"] # 腾讯、阿里、友邦
resp = requests.get(
"https://api.tickdb.com/v1/market/symbols",
params={"symbols": ",".join(symbols)},
headers={"Authorization": "Bearer YOUR_TOKEN"}
)
for sym, info in resp.json().items():
print(f"{sym}: lot_size={info['lot_size']}, type={info['type']}")
第四部分:Layer 3 公司行动层
分红(港股特有:派息以 HKD 计)
resp = requests.get(
"https://api.tickdb.com/v1/market/corporate-actions",
params={
"symbols": "700.HK",
"category": "dividend",
"start": "2024-01-01"
},
headers={"Authorization": "Bearer YOUR_TOKEN"}
)
dividends = resp.json()["700.HK"]
港股分红的特别注意:
- 派息以 HKD 结算(内地投资者通过港股通持有,最终换算成 CNY 到账)
- H 股(在港上市的内地企业)和纯港资公司的股息预扣税率不同
- 「中期股息」(Interim Dividend)和「末期股息」(Final Dividend)在同一标的的同一年度可能分两次派发
- 除权日(
ex_date)使用港股 T+2 交割规则,不是 A 股的 T+1
配股 / 供股
港股公司行动里,配股(Placing)和供股(Rights Issue)是影响价格连续性的重要事件。如果做回测,这些事件的复权处理是否正确,直接决定历史收益率计算的准确度。
resp = requests.get(
"https://api.tickdb.com/v1/market/corporate-actions",
params={
"symbols": "700.HK",
"category": "rights_issue,placing",
"start": "2020-01-01"
},
headers={"Authorization": "Bearer YOUR_TOKEN"}
)
第五部分:Layer 4 接入层
REST + WebSocket 推送
港股实时行情推荐 WebSocket 推送,避免 REST 轮询在高频更新时的延迟累积。
import asyncio, websockets, json
async def subscribe_hk():
url = "wss://ws.tickdb.com/v1/stream"
async with websockets.connect(url) as ws:
await ws.send(json.dumps({
"action": "subscribe",
"symbols": ["700.HK"],
"channels": ["ticker", "order_book"],
"token": "YOUR_TOKEN"
}))
async for message in ws:
data = json.loads(message)
if data.get("type") == "ticker":
print(f"{data['symbol']} 最新价: {data['last_price']}")
asyncio.run(subscribe_hk())
断线重连注意: 午休时段(12:00–13:00)期间推送会中断,13:00 后恢复。断线重连逻辑里,需要区分午休正常中断和网络异常,避免中午触发无效的重连风暴。
AI-native 接入(MCP)
如果你在用 AI 工作流或 LLM agent 辅助港股研究,TickDB 支持 MCP(Model Context Protocol)接入:
# Claude Desktop 配置示例
{
"mcpServers": {
"tickdb": {
"command": "npx",
"args": ["@tickdb/mcp-server"],
"env": {"TICKDB_TOKEN": "YOUR_TOKEN"}
}
}
}
配置完成后,可以直接用自然语言查询:「腾讯今天的分时走势是什么?」「700.HK 最近一次派息是什么时候?」
读者类型与最小接入组合
不同场景的港股开发者需要接入的数据层不同:
| 读者类型 | 核心需求 | 最小接入组合 |
|---|---|---|
| 港股量化策略回测 | 历史 K 线 + 复权 + Lot Size + 公司行动 | Layer 1(kline)+ Layer 2(symbols)+ Layer 3(corporate-actions) |
| 港股实盘交易系统 | 实时行情 + 交易时段 + Lot Size | Layer 1(ticker/order-book/trades)+ Layer 2(trading-sessions + symbols) |
| 港股研究工具 | 快照 + 分红历史 + 标的信息 | Layer 1(ticker)+ Layer 2(symbols)+ Layer 3(dividend) |
| A 股 / 港股多市场系统 | 以上全部 + 市场隔离配置 | Layer 1 + Layer 2 + Layer 3,针对 HK 市场单独维护涨跌停规则和 Lot Size 逻辑 |
A 股量化转港股数据层检查清单
从三个核心差异提炼出来的 22 条清单。策略上线前,逐条过一遍。
✅ 必查三条(最高优先级)
- [ ] 午休时段处理:你的异常告警逻辑,在 12:00–13:00 期间是否会误报?是否从
trading-sessions接口动态获取时段,而不是硬编码? - [ ] 涨跌停过滤:你的数据清洗和价格合法性检查,是否针对港股关掉了固定涨跌幅阈值过滤?
- [ ] Lot Size 动态获取:你的仓位计算模块,是否从
symbols接口获取lot_size,而不是写死 100?
✅ 行情层(8 条)
- [ ] 实时快照的
change_rate是否允许超出 ±20%? - [ ] K 线复权使用数据源提供的复权因子,而非自行计算?
- [ ] 分时数据中午 12:00–13:00 的间断,处理为「正常空洞」而非「数据缺失」?
- [ ] 盘口深度接入时,是否区分了竞价时段和持续交易时段的盘口含义?
- [ ] 逐笔成交是否处理了午休前后的时间戳连续性?
- [ ] 货币单位是否正确使用 HKD?
- [ ] 资金流数据的口径是否清楚(主动买、被动成交、大单统计的定义各不相同)?
- [ ] 历史 K 线是否包含了配股/供股导致的价格跳空的复权处理?
✅ 参考数据层(6 条)
- [ ] 交易时段是否从 API 动态获取,而不是硬编码 A 股的 9:30–15:00?
- [ ] 半日市日历是否纳入交易日历查询?
- [ ] 每个新接入的港股标的,是否先查
symbols接口获取 Lot Size? - [ ]
type字段判断:正股(equity)/ 权证(warrant)/ 牛熊证(CBBC)分别进入不同的处理分支? - [ ] 多市场系统中,港股(HK)和 A 股(SH/SZ)的市场配置是否完全隔离?
- [ ] 标的代码格式是否使用港股格式(如
700.HK),而不是写成00700.HK或700?
✅ 公司行动层(5 条)
- [ ] 分红是否区分了中期股息和末期股息?
- [ ] H 股和纯港资公司的股息预扣税率,是否在收益计算里正确区分?
- [ ] 配股/供股事件是否纳入了回测的价格连续性处理?
- [ ] 公司行动的
ex_date使用的是港股 T+2 交割日期规则,而不是 A 股的 T+1? - [ ] 是否订阅了公司行动事件推送,以便在实盘时自动更新复权因子?
✅ 接入层(3 条)
- [ ] WebSocket 断线重连逻辑是否处理了午休时段的正常中断(13:00 后自动重连,不触发告警)?
- [ ] 如果是多市场系统,是否为港股单独维护了订阅连接,避免 A 股和港股时段冲突影响订阅状态?
- [ ] 权限和账户配置是否支持港股数据访问(部分 token 按市场分配权限)?
附录 A:港股常用接口速查
| 接口 | 路径 | 主要参数 |
|---|---|---|
| 实时快照 | /v1/market/ticker | symbols=700.HK |
| K 线历史 | /v1/market/kline | symbols, period, start, end, adjust |
| 分时数据 | /v1/market/intraday | symbols, date |
| 盘口深度 | /v1/market/order-book | symbols, depth |
| 逐笔成交 | /v1/market/trades | symbols, limit |
| 资金流 | /v1/market/capital-flow | symbols |
| 交易时段 | /v1/market/trading-sessions | symbols=700.HK |
| 交易日历 | /v1/market/trade-days | market=HK, year |
| 标的信息 | /v1/market/symbols | symbols |
| 公司行动 | /v1/market/corporate-actions | symbols, category, start |
附录 B:错误码速查(港股常见)
| 错误码 | 含义 | 常见原因 |
|---|---|---|
| 40001 | 认证失败 | token 无效或已过期 |
| 2001 | 标的不存在 | 代码格式错误,如少了 .HK 后缀 |
| 1005 | 无权限 | 当前 token 未开通港股权限 |
| 3009 | 频率超限 | 请求过于频繁,需降低轮询频率 |
| 3010 | 数据范围超限 | K 线请求日期范围过大,分段请求 |
| WS 1008 | WebSocket 鉴权拒绝 | 订阅时 token 字段缺失或过期 |
附录 C:常见问题
Q:港股 symbol 格式是什么?
A:使用 [数字代码].HK 格式,如腾讯为 700.HK,阿里巴巴为 9988.HK,友邦保险为 1299.HK。代码前不需要补零(00700.HK 和 700.HK 等价,推荐使用后者)。
Q:我怎么知道今天是不是半日市?
A:通过 /v1/market/trade-days 接口查询,返回结果中会标注每个交易日是全日市还是半日市。不建议自己维护半日市列表,HKEX 有时会因特殊情况临时调整。
Q:港股数据和 A 股数据可以用同一套 WebSocket 连接订阅吗?
A:技术上可以在同一 WebSocket 连接里混合订阅不同市场的标的,但建议在应用层做市场隔离,分别处理不同市场的交易时段和数据更新逻辑,避免 A 股收盘后中断导致港股订阅受影响。
Q:轮证(warrant)和牛熊证(CBBC)的数据接入方式有什么不同?
A:接入路径相同(同样用 symbols=XXXXX.HK),但 type 字段值不同,行情数据的解读逻辑完全不同。到期日(expiry)、行使价(strike)等参数需要从 symbols 接口单独获取,不要用正股的估值逻辑处理它们。
Q:港股通和港股数据有什么关系?
A:港股通是内地投资者通过沪港通/深港通买卖港股的渠道,是交易层面的概念。数据层面,港股行情数据(包括港股通标的和非港股通标的)都通过 HKEX 数据体系获取,不因是否纳入港股通而有所不同。
附录 D:实测证据索引
| 章节 | 证据级别 | 来源 |
|---|---|---|
| 港股午休时段(12:00–13:00) | L2 | HKEX 官方交易时段公告 |
| 无涨跌停制度 | L2 | HKEX《证券市场规则》 |
| 腾讯 Lot Size = 100 | L2 | HKEX 标的信息页;待 Codex L1 实测确认 |
type 字段枚举值 | 待确认 | 待 Codex 实测返回具体枚举值 |
trading-sessions 返回格式 | 待确认 | 待 Codex 实测返回具体字段格式 |
symbols 接口 lot_size 字段 | 待确认 | 待 Codex 实测确认字段路径 |
L2 = 交易所官方文件 / 规则;L1 = TickDB API 实测返回
通过 TickDB API 获取实时行情数据
一个 API 接入外汇、加密货币、美股、港股、A股、贵金属和全球指数的实时行情。支持 WebSocket 低延迟推送,免费开始使用。
免费领取 API Key查看 API 文档