【零依赖量化数据实战 #21】北交所公司财务三表:4 个 URL 看资产、盈利与现金流
摘要:【零依赖量化数据实战 #21】北交所公司财务三表:4 个 URL 看资产、盈利与现金流 系列:《零依赖量化数据实战》|零依赖 · 纯 GET · 不 import 任何 SDK 适用:想做北交所(BJ)公司基本面
系列:《零依赖量化数据实战》|零依赖 · 纯 GET · 不 import 任何 SDK
适用:想做北交所(BJ)公司基本面财务分析、把 #18 的「北交所实时行情」升级到「财务面」的开发者
你将得到什么
- 4 个「北交所财务三表」端点的路径、参数和语义(资产负债表 / 利润表 / 现金流量表 / 财务比率),照公开文档核对过的,不是猜的
- 一段
fin_sheet(code)把一家北交所公司的四张表一次性拉齐,整理成「三表 + 比率」概览 - 字段名容错写法(候选键命中
_hit_key),对字段名不敏感、对返回形态(list / dict)不敏感 - 完整可复制运行代码,把
你的智兔token换成真实智兔证书即可直接跑
一、四个端点,一张语义表
北交所公司的财务三表 + 比率,统一走 /bj/fin/ 前缀,股票代码是路径参数(如 920547.BJ),开始/结束时间是可选的查询参数 st / et(格式 YYYYMMDD,不填则为全部历史):
GET https://api.zhituapi.com/bj/fin/balance/{code}?token=<你的智兔token>&st=&et= 资产负债表
GET https://api.zhituapi.com/bj/fin/income/{code}?token=<你的智兔token>&st=&et= 利润表
GET https://api.zhituapi.com/bj/fin/cashflow/{code}?token=<你的智兔token>&st=&et= 现金流量表
GET https://api.zhituapi.com/bj/fin/ratios/{code}?token=<你的智兔token>&st=&et= 财务比率
- 这是按股票代码拉历史财务的接口,每个端点返回的是多期数据(不同报告期一行)。
- 与 #17 的
/hs/gs/*(沪深公司简介/财务指标/股东)定位不同:这里是北交所的完整三表 + 比率,颗粒度更细(资产、负债、收入、利润、经营/投资/筹资现金流、ROE、负债率等)。
二、先把"拿数据"这件小事解决
只依赖 requests,不引入任何 SDK。小工具沿用本系列一致写法:
import requests
BASE = "https://api.zhituapi.com"
TOKEN = "你的智兔token"
HEADERS = {"User-Agent": "Mozilla/5.0"}
def fetch(url):
"""GET 一个 JSON 端点,返回 (data, err)。"""
try:
r = requests.get(url, headers=HEADERS, timeout=10)
try:
return r.json(), None
except Exception:
return None, "JSON 解析失败, HTTP %d, body=%s" % (r.status_code, r.text[:200])
except Exception as e:
return None, "请求异常: %s" % e
def _hit_key(row, *keys):
"""在 dict 里按候选键顺序命中第一个存在且不空的值。"""
if not isinstance(row, dict):
return None
for k in keys:
if k in row and row[k] not in (None, ""):
return row[k]
return None
def _to_float(s):
"""把 '3.5%' / '1,234.56' / 'NaN' 规整成 float;无法解析返回 None。"""
if s is None:
return None
if isinstance(s, (int, float)):
return float(s)
t = str(s).replace("%", "").replace(",", "").strip()
try:
v = float(t)
return v if v == v else None # NaN -> None
except Exception:
return None
def _coerce_list(payload):
"""接口返回可能是 list,也可能是 {'data': [...]};统一成 list。"""
if isinstance(payload, list):
return payload
if isinstance(payload, dict):
for k in ("data", "list", "items", "result", "rows"):
if isinstance(payload.get(k), list):
return payload[k]
return []
要点:fetch 永远返回 (data, err);_hit_key 用候选键顺序命中,字段名差异不崩;_coerce_list 把 list / {"data":[...]} 两种形态抹平。
三、核心模板:fin_sheet()
把一家北交所公司的四张表一次性拉齐,各取最新一期做概览:
SHEETS = {
"资产负债表": "/bj/fin/balance",
"利润表": "/bj/fin/income",
"现金流量表": "/bj/fin/cashflow",
"财务比率": "/bj/fin/ratios",
}
def fin_sheet(code, token=TOKEN, st="", et=""):
"""拉取某北交所股票的四张财务表,整理成概览。"""
out = {}
for label, path in SHEETS.items():
url = "%s%s/%s?token=%s" % (BASE, path, code, token)
if st:
url += "&st=%s" % st
if et:
url += "&et=%s" % et
data, err = fetch(url)
if err:
out[label] = {"err": err, "rows": 0, "latest": None}
continue
rows = _coerce_list(data)
latest = rows[0] if rows else None
out[label] = {"err": None, "rows": len(rows), "latest": latest}
return out
if __name__ == "__main__":
import json
fs = fin_sheet("920547.BJ")
print(json.dumps(fs, ensure_ascii=False, indent=2, default=str))
跑起来后,fs["资产负债表"]["rows"] 是报告期期数,fs["财务比率"]["latest"] 是最近一期的 ROE / 负债率等。st / et 不填默认全部历史;想只看某段区间,传 st="20230101"、et="20231231" 即可。
四、代码自验结果
离线 selftest(合成数据,仅验证逻辑,非真实行情):
selftest PASS
自验覆盖了:候选键命中(_hit_key 在 date/rq 等不同字段名下都能取到值)、_to_float 对 12.5% / 1,200.5 / NaN / None 的解析、list 与 {"data":[...]} 两种返回形态的统一、以及 fin_sheet 在合成数据下的整理逻辑(四表各 1 期、总资产 1200.5、ROE 12.5 均被正确解析)。
联网实测(占位 token,真实 HTTP 响应原样保留):
{
"资产负债表": {"err": "JSON 解析失败, HTTP 404, body=102:Licence证书(你的智兔token)不存在\n", "rows": 0, "latest": null},
"利润表": {"err": "JSON 解析失败, HTTP 404, body=102:Licence证书(你的智兔token)不存在\n", "rows": 0, "latest": null},
"现金流量表": {"err": "JSON 解析失败, HTTP 404, body=102:Licence证书(你的智兔token)不存在\n", "rows": 0, "latest": null},
"财务比率": {"err": "JSON 解析失败, HTTP 404, body=102:Licence证书(你的智兔token)不存在\n", "rows": 0, "latest": null}
}
四个端点都返回 404 102:Licence证书(你的智兔token)不存在 —— 这是鉴权先于路由的结果:路径本身合法,但占位 token 没有对应证书。换上你自己的真实 token,上面的脚本就能直接打印北交所公司财务三表数据。文中所有数字均为占位 token 下的自验结果,不编造任何真实财务数值。
五、坑与注意事项
- 代码是路径参数,不是查询参数:
920547.BJ要拼进路径(/bj/fin/balance/920547.BJ),少了会 404;st/et才是查询参数。 - 市场后缀别省:北交所代码带
.BJ,和沪深.SH/.SZ不同,喂错市场后缀拉不到数据。 - 返回是多期数组:每个端点返回若干报告期(一行一期),取
rows[0]是"最新一期"还是"最早一期"以实际返回顺序为准,别假设;必要时按日期字段排序。 - 字段名以实际返回为准:文档给的是表语义,具体字段名(总资产是
total_assets还是别的)以你换真实 token 后的返回为准;本文用_hit_key做了容错。 - 不要自创接口:本文四个端点全部来自官方文档,未做任何路径拼接或猜测。
六、小结与下篇预告
至此,#09–#21 把数据面完整铺开:基金链(#09–#13) → A股异动/可转债/港股通/公司面(#14–#17) → 北交所实时(#18) → 沪深指数(#19) → 行业板块分类(#20) → 北交所财务三表(#21)。本阶段(#09–#21)收尾。
后续可继续向深度维度扩展:港股通成交排名与历史(/ht/nbzj/* 的 pm/ls 系列)、沪深个股财务三表(/hs/fin/*)、指数技术指标(/hz/history/* 的 MACD/MA/BOLL/KDJ),把数据面从「分类 / 实时」推进到「财务 / 技术」深度分析。
免费领取证书
数据来自 智兔数服(www.zhituapi.com):零 SDK、纯 GET、免费版即可起步。
领取路径:进入 www.zhituapi.com → 点击「请求证书」→「证书获取」→「免费版」(邮箱验证 3 步即可拿到 token)。
把代码里的 你的智兔token 换成你拿到的真实 token,上面的脚本就能直接打印北交所公司财务三表数据。
免责声明
本文仅演示公开数据接口的用法,所有代码示例均以占位 token 自验,未含任何真实数据;文中合成数据仅为逻辑自验用途,不构成投资建议,亦不承诺收益。