← 返回博客列表

【零依赖量化数据实战 #23】沪深个股财务三表与股东结构

2026年08月28日 11:10 · 智兔数服 · 零依赖量化数据实战

摘要:【零依赖量化数据实战 #23】沪深个股财务三表与股东结构 系列:《零依赖量化数据实战》|零依赖 · 纯 GET · 不 import 任何 SDK 适用:想把单只沪深股票的「资产负债表 / 利润表 / 现金流量表

系列:《零依赖量化数据实战》|零依赖 · 纯 GET · 不 import 任何 SDK
适用:想把单只沪深股票的「资产负债表 / 利润表 / 现金流量表 / 财务指标 / 十大股东 / 股本」一次性拉成结构化数据的量化与基本面分析玩家;数据由智兔数服提供。

1. 你将得到什么

  • 6 个官方接口的最小封装,覆盖个股基本面三表 + 指标 + 股东
  • GET /hs/fin/balance/{code}?st=&et=:资产负债表
  • GET /hs/fin/income/{code}?st=&et=:利润表
  • GET /hs/fin/cashflow/{code}?st=&et=:现金流量表
  • GET /hs/fin/ratios/{code}?st=&et=:财务主要指标
  • GET /hs/fin/topholder/{code}?st=&et=:公司十大股东
  • GET /hs/fin/capital/{code}?st=&et=:公司股本表
  • 一个对字段名不敏感summarize_fin:三表/指标返回里「总资产 / 营业收入 / 现金流」等键名随上游变,用候选键命中,不写死。
  • 时间窗参数 st / et 均为 YYYYMMDD,不传则取全部历史数据。

2. 端点语义表

GET https://api.zhituapi.com/hs/fin/balance/{code}?token=你的智兔token&st=20240101&et=20241231
  -> 资产负债表;{code}=股票代码(如 000001.SZ);st/et 为 YYYYMMDD,可省略

GET https://api.zhituapi.com/hs/fin/income/{code}?token=你的智兔token          # 利润表
GET https://api.zhituapi.com/hs/fin/cashflow/{code}?token=你的智兔token       # 现金流量表
GET https://api.zhituapi.com/hs/fin/ratios/{code}?token=你的智兔token         # 财务主要指标
GET https://api.zhituapi.com/hs/fin/topholder/{code}?token=你的智兔token      # 公司十大股东
GET https://api.zhituapi.com/hs/fin/capital/{code}?token=你的智兔token        # 公司股本表

鉴权:token 走查询参数;{code} 为路径参数(必须带市场后缀,如 000001.SZ);st/et 可选查询参数;三表/指标多期为 list,单期可 dict。数据来自 智兔数服(www.zhituapi.com)。

3. 字段名不固定?用候选键命中

上游财务表字段名不统一(中英文混用、不同表键名不同)。统一用 _hit_key + _to_float 兜底抽取:

def _hit_key(d, candidates):
    for k in candidates:
        if k in d:
            return k
    return None

def _to_float(v):
    try:
        return None if v is None else float(v)
    except (TypeError, ValueError):
        return None

4. 核心模板函数

import requests

TOKEN = "你的智兔token"
BASE = "https://api.zhituapi.com"

def _hit_key(d, candidates):
    for k in candidates:
        if k in d:
            return k
    return None

def _to_float(v):
    try:
        return None if v is None else float(v)
    except (TypeError, ValueError):
        return None

def fetch(path, params=None):
    p = dict(params or {})
    p["token"] = TOKEN
    try:
        r = requests.get(f"{BASE}{path}", params=p, timeout=15)
    except requests.RequestException as e:
        return None, f"网络异常:{e}"
    if r.status_code != 200:
        return None, f"{r.status_code} {r.text.strip()[:140]}"
    try:
        payload = r.json()
    except ValueError:
        return None, f"非 JSON:{r.text[:140]}"
    if isinstance(payload, dict):
        detail = payload.get("detail") or payload.get("error")
        return None, f"业务错误:{detail or list(payload)[:6]}"
    return payload, None

# ===== #23 沪深个股财务三表与股东结构 =====

_FIN_TABLES = {
    "balance": "/hs/fin/balance",
    "income": "/hs/fin/income",
    "cashflow": "/hs/fin/cashflow",
}

def _get(path, code, st, et):
    params = {}
    if st:
        params["st"] = st
    if et:
        params["et"] = et
    return fetch(f"{path}/{code}", params=params or None)

def fin_statements(code, st=None, et=None):
    """资产负债表 / 利润表 / 现金流量表 三表合一"""
    out = {}
    for name, p in _FIN_TABLES.items():
        data, err = _get(p, code, st, et)
        out[name] = ("ERR", err) if err else data
    return out, None

def fin_ratios(code, st=None, et=None):
    """财务主要指标"""
    return _get("/hs/fin/ratios", code, st, et)

def top_holders(code, st=None, et=None):
    """公司十大股东"""
    return _get("/hs/fin/topholder", code, st, et)

def capital_table(code, st=None, et=None):
    """公司股本表"""
    return _get("/hs/fin/capital", code, st, et)

def summarize_fin(data, cand):
    """从一张表里抽第一个命中字段的值(演示字段名不固定时的容错)"""
    if isinstance(data, list) and data:
        row = data[0]
        if isinstance(row, dict):
            k = _hit_key(row, cand)
            return _to_float(row.get(k)) if k else None
    if isinstance(data, dict):
        k = _hit_key(data, cand)
        return _to_float(data.get(k)) if k else None
    return None

5. 代码自验结果

离线 selftest(合成数据,仅验证逻辑,不含任何真实行情):

PASS: #23 逻辑自验通过(合成数据,无真实行情)

联网实测(占位 token,真实返回):

--- 联网实测(占位 token,预期 404 102:Licence证书不存在)---
fin_statements -> ({'balance': ('ERR', '404 102:Licence证书(你的智兔token)不存在'), 'income': ('ERR', '404 102:Licence证书(你的智兔token)不存在'), 'cashflow': ('ERR', '404 102:Licence证书(你的智兔token)不存在')}, None)
fin_ratios     -> (None, '404 102:Licence证书(你的智兔token)不存在')
top_holders    -> (None, '404 102:Licence证书(你的智兔token)不存在')
capital_table  -> (None, '404 102:Licence证书(你的智兔token)不存在')

TOKEN = "你的智兔token" 换成你申请的真实 token,上述函数即可打印真实财务三表与股东结构数据。本文未编造任何真实数值。

6. 坑与注意事项

  1. 102 不代表路径对404 102 是「证书不存在」(鉴权先于路由),路径合法与否要靠客户端白名单自查。
  2. {code} 必须带市场后缀:写 000001 会路由错误,必须 000001.SZ / 600000.SH
  3. st/et 格式是 YYYYMMDD:如 20240101,不是 2024-01-01;省略则取全部历史。
  4. 三表多为 list(按期):抽字段时用 summarize_fin 取首期;要跨期对比直接遍历 list。
  5. 字段名不固定:「总资产」可能叫 total_assets 也可能叫 总资产,务必用候选键命中,别硬写英文键。
  6. 股东按持股比例倒序topholder 返回列表,ratio/持股比例 字段名随上游变,用候选键兜底排序。

7. 小结与下篇预告

本篇把「基本面三表 + 指标 + 股东」拧成了 6 个零依赖接口的最小封装,重点解决了股票代码带市场后缀时间窗 YYYYMMDD财务字段名中英文混用三个坑,配 summarize_fin 候选键命中即可一行取数。

下一篇计划写 #24《指数技术指标实战:MACD·MA·KDJ·BOLL》:讲解如何直接消费官方已算好的指数 MACD、MA、KDJ、BOLL 指标序列,用最近 N 条数据一行出金叉死叉、多空头排列、超买超卖、开口收口等信号。

8. 免责声明

本文仅演示公开数据接口的用法,所有代码示例均以占位 token 自验,未含任何真实数据;文中合成数据仅为逻辑自验用途,不构成投资建议,亦不承诺收益。


免费领取证书
数据来自 智兔数服(www.zhituapi.com):零 SDK、纯 GET、免费版即可起步。

领取路径:进入 www.zhituapi.com → 点击「请求证书」→「证书获取」→「免费版」(邮箱验证 3 步即可拿到 token)。

把代码里的 你的智兔token 换成你拿到的真实 token,上面的脚本就能直接打印沪深个股财务三表与股东结构数据。

想亲自试一下?免费获取证书