这篇是教程,不是 reference。读完你能拿到一个真正能跑、能扩展的港股估值看板雏形。
0. 你需要什么
- Python 3.10+(推荐 3.12)
- 一个 HKFilings 账号(免费注册)—— Free 套餐每月 10 份够你跑这个 demo
- 15 行 Pandas / 30 行 Streamlit 的基础
1. 安装 + 配置
pip install hkfilings pandas streamlit
# 或用 uv(更快)
uv pip install hkfilings pandas streamlit
配 API key:登录后到 /settings → API 创建一把 key(注册时已签发的默认 key 也能用)。
export HKFILINGS_API_KEY="sk_..."
# 或者写到 .env,python-dotenv 加载
2. SDK 基础用法
SDK 把所有 REST 端点包成同步 + 异步两套接口。看 5 个最常用的:
from hkfilings import HKFilingsClient
client = HKFilingsClient() # 自动读 env var HKFILINGS_API_KEY
# (1) 提交分析任务(按 ticker + 年度)
task = client.submit_task(
ticker="00700",
period="FY2024", # 或 "FY2024H1" / "FY2024Q3"
language="zh",
)
print(task.task_id, task.duplicate) # 重复提交会返回已有 task_id + duplicate=True
# (2) 等任务完成(轮询 + SSE 双模式)
result = client.wait_for_task(task.task_id, timeout_sec=600)
# 或者用流式:
# for event in client.stream_task(task.task_id):
# print(event.kind, event.payload)
# (3) 拿结构化事实
facts = client.get_facts(ticker="00700", period="FY2024")
print(facts.revenue, facts.net_income_attributable, facts.operating_cash_flow)
# 每个 fact 是一个对象,含 .value / .source_page / .bbox / .validation_status
# (4) 跨期矩阵
matrix = client.get_company_matrix(ticker="00700", metric="revenue", periods=4)
# pandas.DataFrame: rows=periods, cols=[revenue, yoy_pct, source_page]
# (5) 行业模板信号
signals = client.get_layer2_signals(ticker="00700")
print(signals.industry_template, signals.supply_chain_nodes, signals.catalysts)
3. 30 行:50 家港股的横向估值脚本
我们用 HKFilings 拿三个数字(净利润、净资产、EBITDA),再用 Yahoo Finance 拿股价计算 P/E / P/B / EV/EBITDA。
import asyncio
import pandas as pd
import yfinance as yf
from hkfilings import AsyncHKFilingsClient
TICKERS = ["00700", "09988", "03690", "01299", "01211", "01810",
"00939", "01398", "02318", "00388", "00005", "09618",
"09868", "09866", "02015", "01024", "02382", "09626",
"02020", "02269"] # 加更多 ticker 即可
async def fetch_one(client, ticker):
facts = await client.get_facts(ticker=ticker, period="latest")
return {
"ticker": ticker,
"net_income": facts.net_income_attributable.value,
"equity": facts.shareholders_equity.value,
"ebitda": facts.ebitda.value if facts.ebitda else None,
"cash": facts.cash_and_investments.value,
"currency": facts.reporting_currency,
}
async def main():
async with AsyncHKFilingsClient() as client:
rows = await asyncio.gather(*[fetch_one(client, t) for t in TICKERS])
df = pd.DataFrame(rows)
# 拉股价
yf_tickers = [f"{t}.HK" for t in df["ticker"]]
quotes = yf.download(yf_tickers, period="1d")["Adj Close"].iloc[-1]
df["price"] = df["ticker"].map(lambda t: quotes.get(f"{t}.HK"))
# 估算(需要根据币种统一,这里简化)
df["pe"] = df["price"] / (df["net_income"] / 1e9) # 简化的 P/E
df["pb"] = df["price"] / (df["equity"] / 1e9)
df["ev_ebitda"] = (df["price"] - df["cash"] / 1e9) / (df["ebitda"] / 1e9)
df_sorted = df.sort_values("pe").round(2)
print(df_sorted[["ticker", "pe", "pb", "ev_ebitda"]].to_string(index=False))
asyncio.run(main())
跑一下:
$ python valuation.py
ticker pe pb ev_ebitda
00939 4.6 0.5 n.a.
01398 4.8 0.5 n.a.
00005 7.2 0.9 n.a.
00388 24.1 8.1 16.8
00700 18.5 3.2 11.4
09988 13.7 1.5 9.8
...
20 行核心代码就跑出来了。当然真实研究需要:
- 币种统一(RMB / HKD / USD → 选一个)
- 用 forward EPS / 一致预期净利润 而不是 TTM
- 剔除一次性项目(用调整后净利润)
- 同业相对估值(行业中位数对比)
4. 给它套个 Streamlit dashboard
另存为 app.py:
import streamlit as st
import pandas as pd
# ... (复用上面的 fetch_one + main 逻辑,async 部分用 asyncio.run 包) ...
st.set_page_config(page_title="HK Valuation Dashboard", layout="wide")
st.title("港股估值看板 · HKFilings")
industries = {
"互联网": ["00700", "09988", "03690", "01810", "09618", "01024", "09626"],
"银行": ["00939", "01398", "00005"],
"保险": ["01299", "02318"],
"新能源汽车": ["01211", "09868", "09866", "02015"],
}
selected = st.multiselect("选择行业", list(industries.keys()), default=["互联网"])
tickers = [t for ind in selected for t in industries[ind]]
df = run_pipeline(tickers) # 复用上面的逻辑
st.dataframe(df[["ticker", "pe", "pb", "ev_ebitda"]].style.background_gradient(subset=["pe"], cmap="RdYlGn_r"))
# 图表
import altair as alt
st.altair_chart(
alt.Chart(df).mark_circle(size=200).encode(
x="pe:Q", y="pb:Q", color="ticker:N",
tooltip=["ticker", "pe", "pb", "ev_ebitda"]
).properties(height=400),
use_container_width=True,
)
跑:
streamlit run app.py
30 分钟你就有了一个浏览器里可交互、能按行业过滤、能看散点图的港股估值看板。
5. 下一步扩展
- 历史回测:用
client.get_company_matrix拿历史 4 期数据,画 P/E 走势 - Forward 估值:接 Wind / 同花顺一致预期净利润数据补 forward EPS
- 分行业模板:银行业用 P/B / 不良率 / ROE 三维;保险业用 P/EV / NBV 增长;REIT 用 P/NAV / DPU 收益率 + Gearing
- 催化剂叠加:用
client.get_layer2_signals拿未来 12 个月催化剂时间线,与估值 + 价格走势对齐
常见坑
- 币种:港股 50 家用三种币种披露(RMB / HKD / USD)。一定要先归一再算估值。HKFilings 的
facts.reporting_currency给你币种标签。 - 同股不同权:阿里 / 美团 / 小米 / 小鹏 / 蔚来 / 理想 / 京东 / 快手 / B 站都是。EPS 计算需要按 ADS 或股票面值统一。
- 剥离 / 重组:去年的净利润可能包含已剥离业务。看 MD&A「持续经营业务净利润」更可比。HKFilings 校验规则会标 flag。
结语
HKFilings 不替代你的判断 —— 它替代你抄 PDF 的那段。把研究员的时间从「找数字」迁移到「想数字」上。免费试一份 或 看完整 API 文档。