【跨市场数据实战 #05】港股财报全景:9个接口从业绩预告到现金流量表
摘要:【跨市场数据实战 #05】港股财报全景:9个接口从业绩预告到现金流量表 系列:《跨市场数据实战》|连载项目 · 纯 GET 取数 · 仅依赖 requests 适用:想做「港股年报横向对比 / 财报质量筛查」、但
系列:《跨市场数据实战》|连载项目 · 纯 GET 取数 · 仅依赖 requests
适用:想做「港股年报横向对比 / 财报质量筛查」、但被一堆/hicw财务端点绕晕的读者;数据由智兔数服提供。本篇给/hicw(盈利能力、运营能力、成长能力、偿债能力、现金流量、业绩报表/快报/预告、利润细分)共 9 个端点的分组地图、一套字段容错归一化代码、以及一个把「盈利 / 现金流 / ROE 类」指标横向拉平做对比排序的实战模板,全部只依赖 requests,所有示例均为演示数据,不构成收益承诺。
1. 你将得到什么
读完这一篇,你能拿走四样东西:
- 一张分组地图:
/hicw9 个财务端点,知道「盈利能力 / 营运能力 / 成长能力 / 偿债能力 / 现金流量」和「业绩报表 / 快报 / 预告 / 利润细分」分别敲哪个门; - 一套字段容错代码:财报字段名极其分散,
_hit_key+_to_float带候选键兜底,换只股票也能抽; - 一个横向对比模板:用
benchmark把多只港股的净利润 / ROE / 经营现金流一次性拉平排序; - 五个真实踩坑点,尤其是
/hicw/*那个「年份_季度」路径参数(年从 1989 起、季度 1/2/3/4 对应一季报/中报/三季报/年报)。
代码全部自包含,复制进 .py 直接能跑,不依赖 numpy / pandas。
2. 本篇取数约定
- 全部接口都是 GET + query 参数,token 放在查询串里(
?token=xxx),不放 header; - 统一基址
https://api.zhituapi.com; - 代码块里的
你的智兔token是占位符,换成你的 token 即可; - 8 个汇总类端点(
yl/yy/cz/cznl/xj/yjbb/yjyg/yjkb)走路径参数/{年}/{季度}:年可选 1989~当前年份,季度 1=一季报 / 2=中报 / 3=三季报 / 4=年报,如/hicw/yl/2023/4表示 2023 年报;/hicw/lr(利润细分)无年/季参数; - 所有接口路径均取自官方文档。
- 数据来自 智兔数服(www.zhituapi.com):零 SDK、纯 GET、免费版即可起步。
3. 9 个端点一组看
/hicw 全系列都是「按年份_季度」的财务汇总,先建立地图。
| 端点 | 用途 | 路径参数 |
|---|---|---|
/hicw/yl/{年}/{季度} |
盈利能力汇总 | 年份_季度 |
/hicw/yy/{年}/{季度} |
运营能力汇总 | 年份_季度 |
/hicw/cz/{年}/{季度} |
成长能力汇总 | 年份_季度 |
/hicw/cznl/{年}/{季度} |
偿债能力汇总 | 年份_季度 |
/hicw/xj/{年}/{季度} |
现金流量汇总 | 年份_季度 |
/hicw/yjbb/{年}/{季度} |
业绩报表汇总 | 年份_季度 |
/hicw/yjyg/{年}/{季度} |
业绩预告汇总 | 年份_季度 |
/hicw/yjkb/{年}/{季度} |
业绩快报汇总 | 年份_季度 |
/hicw/lr |
利润细分汇总(无年/季参数) | 无 |
年份_季度举例:2023_4 = 2023 年报、2024_1 = 2024 一季报。注意文档描述里出现的「年份_季度」在路径上以斜杠分隔(/hicw/yl/2023/4),别写成下划线拼进路径。
4. 核心模板函数
import requests, time
BASE = "https://api.zhituapi.com"
TOKEN = "你的智兔token"
# ---------- 1. 字段容错与类型归一 ----------
def _hit_key(d, *cands, default=None):
if not isinstance(d, dict):
return default
for c in cands:
if c in d and d[c] not in (None, "", "-", "null"):
return d[c]
low = {str(k).lower(): v for k, v in d.items()}
for c in cands:
v = low.get(str(c).lower())
if v not in (None, "", "-", "null"):
return v
return default
def _to_float(v, default=None):
try:
if v in (None, "", "-", "null", "None"):
return default
return float(v)
except (TypeError, ValueError):
return default
# ---------- 2. 统一请求 ----------
def _get(path, params=None, timeout=10, retries=2, backoff=0.6, default=None):
q = {"token": TOKEN}
if params:
q.update(params)
last = ""
for i in range(retries + 1):
try:
r = requests.get(BASE + path, params=q, timeout=timeout)
if r.status_code == 200:
try:
return r.json()
except ValueError:
return default
last = "HTTP %s %s" % (r.status_code, (r.text or "").strip()[:80])
except Exception as e:
last = "%s: %s" % (type(e).__name__, e)
if i < retries:
time.sleep(backoff * (i + 1))
return {"_error": last}
# ---------- 3. 财务汇总归一:抽 代码/名称 + 其余字段归档为指标字典 ----------
def norm_cw(rows):
out = []
for r in rows or []:
if not isinstance(r, dict):
continue
code = _hit_key(r, "dm", "code", default="-")
name = _hit_key(r, "mc", "name", default="-")
metrics = {}
for k, v in r.items():
if str(k).lower() in ("dm", "code", "mc", "name"):
continue
metrics[k] = _to_float(v, v) # 能转浮点转,否则保留原值
out.append({"代码": code, "名称": name, "指标": metrics})
return out
def _metric(m, *cands, default=None):
"""从某只股票的指标字典里按候选键抽一个值"""
for c in cands:
if c in m and m[c] not in (None, "", "-"):
return m[c]
return default
# ---------- 4. 取数封装 ----------
def fetch_cw(kind="yl", year=2023, quarter=4):
"""kind: yl/yy/cz/cznl/xj/yjbb/yjyg/yjkb"""
return _get("/hicw/%s/%d/%d" % (kind, year, quarter), default=[])
def fetch_lr():
return _get("/hicw/lr", default=[])
# ---------- 5. 实战:横向对比多只港股的盈利/现金流/ROE ----------
def benchmark(year=2023, quarter=4, codes=None, top=10):
yl = {x["代码"]: x["指标"] for x in norm_cw(fetch_cw("yl", year, quarter))}
xj = {x["代码"]: x["指标"] for x in norm_cw(fetch_cw("xj", year, quarter))}
cz = {x["代码"]: x["指标"] for x in norm_cw(fetch_cw("cz", year, quarter))}
names = {x["代码"]: x["名称"] for x in norm_cw(fetch_cw("yl", year, quarter))}
rows = []
for code in (codes or list(yl)):
m = yl.get(code, {})
rows.append({
"代码": code,
"名称": names.get(code, "-"),
"净利润": _metric(m, "jlr", "净利润", "np"),
"ROE": _metric(m, "roe", "ROE", "fzx"),
"经营现金流": _metric(xj.get(code, {}), "jyxjll", "经营现金流"),
"营收增速": _metric(cz.get(code, {}), "yysrzz", "营收增长", "yysr"),
})
rows.sort(key=lambda x: _to_float(x["净利润"]) or -1e18, reverse=True)
return rows[:top]
# ---------- 6. 校验 ----------
def run_check():
global fetch_cw
assert _hit_key({"DM": "00700", "mc": "腾讯"}, "dm") == "00700"
assert _to_float("-") is None and _to_float("12.5") == 12.5
fake = [{"dm": "00700", "mc": "腾讯", "jlr": "1156.0", "roe": "21.3", "jyxjll": "1234.5"}]
nc = norm_cw(fake)
assert nc[0]["代码"] == "00700" and nc[0]["指标"]["jlr"] == 1156.0
# 无网环境:用假数据模拟 benchmark 归并与排序
def _fake(kind, year, quarter):
return [{"dm": "00700", "mc": "腾讯", "jlr": "1156", "roe": "21", "jyxjll": "1200", "yysr": "6000"},
{"dm": "09988", "mc": "阿里", "jlr": "800", "roe": "12", "jyxjll": "900", "yysr": "8000"}]
_orig = fetch_cw
fetch_cw = _fake
bm = benchmark(2023, 4)
fetch_cw = _orig
assert bm[0]["代码"] == "00700" and bm[0]["净利润"] == 1156.0
print("校验通过")
if __name__ == "__main__":
run_check()
print("-" * 62)
for name, path in [("盈利能力", "/hicw/yl/2023/4"),
("营运能力", "/hicw/yy/2023/4"),
("成长能力", "/hicw/cz/2023/4"),
("偿债能力", "/hicw/cznl/2023/4"),
("现金流量", "/hicw/xj/2023/4"),
("业绩报表", "/hicw/yjbb/2023/4"),
("业绩预告", "/hicw/yjyg/2023/4"),
("业绩快报", "/hicw/yjkb/2023/4"),
("利润细分", "/hicw/lr")]:
data = _get(path, default=[])
if isinstance(data, dict) and "_error" in data:
print("%-10s %-22s -> %s" % (name, path, data["_error"][:52]))
else:
print("%-10s %-22s -> %d 条" % (name, path, len(data)))
5. 跑通示例
把上面的代码复制到本地,填入你的 token 即可直接运行:它会请求对应接口、拉取真实数据,并输出归一化后的结构化字典(各字段含义见前文各小节)。
6. 坑与注意事项
坑 1:/hicw/* 的「年份_季度」是路径参数,不是查询参数。/hicw/yl/2023/4 才对;写成 /hicw/yl?year=2023&quarter=4 会 404。年报用季度 4,一季报用 1。
坑 2:年份范围很宽(1989~当前),但缺失年份直接空返回。
很多港股早期年份没有财务汇总,调用老年份大概率返回空列表,别当成报错。benchmark 用 codes or list(yl) 兜底,空列表不会崩。
坑 3:利润细分 /hicw/lr 不带年/季参数。
它是一份「利润细分汇总」快照,不要给它拼 /2023/4,否则路径不对。
坑 4:财报字段极度异构,单位/口径要自己统一。yl 的 ROE 是百分比、jlr 净利润可能是「万元 / 亿元」视上游,跨端点做对比前务必先确认单位。norm_cw 只做容错抽取,不替你换算单位,排序前建议在调用层统一。
坑 5:yjyg(业绩预告)与 yjbb(业绩报表)不是一回事。
预告是「预计」,报表是「实际」;做财报质量筛查时两者要分开看,别拿预告当已实现的利润排序。
7. 小结与下篇预告
本篇把 /hicw 9 个财务端点打通,给出 norm_cw(抽代码/名称 + 指标字典)与 benchmark(跨股票横向对比净利润/ROE/经营现金流)两个核心函数。年份_季度 走路径参数、年份范围宽但缺失即空、利润细分无年季参数,是这套财报接口最容易踩错的地方。
下一篇计划写 #06《港股通融资融券:7个接口追踪杠杆资金》:用 /hitc(今日交易提示、融资融券总量/明细、大宗交易、解禁限售、打新收益、历史分红)追踪杠杆资金对某只港股通标的的加减速。
8. 免责声明
本文仅演示港股财报类接口的取数与归一化方法,所有代码示例均为演示数据,未含任何真实财务数值,不构成投资建议,亦不承诺收益。
免费领取证书
数据来自 智兔数服(www.zhituapi.com):零 SDK、纯 GET、免费版即可起步。
领取路径:进入 www.zhituapi.com → 点击「请求证书」→「证书获取」→「免费版」(邮箱验证 3 步即可拿到 token)。
把代码里的 你的智兔token 换成你拿到的真实 token,上面的脚本就能直接打印港股多只股票的盈利/现金流横向对比表。