← 返回博客列表

【零依赖量化数据实战 #10】场内基金实时报价与清单全貌:4 个 URL 接进盘中看板

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

摘要:【零依赖量化数据实战 #10】场内基金实时报价与清单全貌:4 个 URL 接进盘中看板 系列:《零依赖量化数据实战》|零依赖 · 纯 GET · 不 import 任何 SDK 适用:想做场内基金(ETF/LOF

系列:《零依赖量化数据实战》|零依赖 · 纯 GET · 不 import 任何 SDK
适用:想做场内基金(ETF/LOF)盘中监控、ETF 全板异动扫描、基金清单维护,不想装库或对接多个数据源的开发者

你将得到什么

  • 4 个「场内基金实时/清单」端点的路径、返回字段和语义(单只实时行情 / 全部基金清单 / ETF 行情列表 / LOF 行情列表),照公开文档核对过的,不是猜的
  • 一段 fund_board_snapshot() 把 ETF 板 + LOF 板 + 全基金清单拉齐,做一张「场内基金全貌」快照;外加 fund_realtime(code) 对单只基金做深度查看
  • 字段名容错写法(候选键命中),对字段名不敏感、对形态(list / dict)不敏感
  • 完整可复制运行代码,把 你的智兔token 换成真实智兔证书即可直接跑

一、四个端点,一张语义表

「盘中看板」拆成 4 个端点,路径前缀分两类:实时单只走 /fund/,整板/清单走 /jh/

GET https://api.zhituapi.com/fund/real/ssjy/{code}   单只基金实时行情(价格/涨跌/量)
GET https://api.zhituapi.com/jh/list/all               全部基金清单(静态标的宇宙)
GET https://api.zhituapi.com/jh/hq/etflist             ETF 行情列表(整板实时报价)
GET https://api.zhituapi.com/jh/hq/loflist             LOF 行情列表(整板实时报价)

鉴权统一 ?token=<你的智兔token>ssjy单只维度,{code} 换成基金代码(文档示例 159001);etflist/loflist/list_all整板/全量列表,一次性返回所有标的的报价或清单,适合做扫描。

一个实际用法:先用 jh/hq/etflist 拿到整个 ETF 板的实时报价 → 按涨跌排序筛出异动 → 再用 fund/real/ssjy/{code} 对其中某只做深度查看(jh/list/all 则用来维护你自己的基金池子)。这就是盘中看板。

代码形态提醒/fund/real/ssjy{code} 按文档示例用基金代码(如 159001);/jh/* 同样用基金代码。与 #08 的 /jh/hq/list 不同,本篇用 etflist/loflist分类整板,粒度更细。

二、字段名不固定?用候选键命中

基金实时接口的返回字段名可能因数据源更新而变化。与其硬编码字段名(改了就全崩),不如用候选键列表命中抽取:

def _hit_key(d, candidates):
    """从字典中按候选键名列表命中第一个存在的键。"""
    for k in candidates:
        if k in d:
            return k
    return None

def _to_float(v):
    """把可能是字符串/数字/None 的值安全转 float,转不了返回 None。"""
    try:
        if v is None:
            return None
        return float(v)
    except (TypeError, ValueError):
        return None

def summarize_quote(name, data):
    """从实时报价/清单中抽取关键字段做汇总,对字段名不敏感、对形态不敏感。"""
    if data is None:
        return f"  {name}: 无数据"
    if isinstance(data, list):
        if not data:
            return f"  {name}: 0 条"
        first = data[0] if isinstance(data[0], dict) else {}
        code_key = _hit_key(first, ["code", "dm", "fundcode", "jjdm", "symbol"])
        name_key = _hit_key(first, ["name", "mc", "jjmc", "shortname"])
        price_key = _hit_key(first, ["price", "last", "new", "zxj", "dwjz", "nav", "close", "lastprice"])
        chg_key = _hit_key(first, ["change", "zdf", "pct", "zd", "chg", "changepct"])
        parts = [f"  {name}: {len(data)} 条"]
        if code_key:
            parts.append(f"首条代码={first.get(code_key)}")
        if name_key:
            parts.append(f"名称={first.get(name_key)}")
        if price_key:
            parts.append(f"价格键={first.get(price_key)}")
        if chg_key:
            parts.append(f"涨跌键={first.get(chg_key)}")
        return " | ".join(parts)
    if isinstance(data, dict):
        keys = list(data.keys())[:6]
        return f"  {name}: 聚合对象,键={keys}"
    return f"  {name}: {type(data).__name__}"

这样就算数据源把 dm 改成 jjdm,代码不用动。命不中也不报错——只是那行汇总少一个字段。

三、盘中看板:把整板拉齐做快照

核心不是「把四个接口都调通」,而是把整板数据归一后做异动扫描。我们关心两件事:

  1. ETF/LOF 整板各有多少只、首条长什么样(确认数据到位)
  2. 按涨跌绝对值筛出异动标的(阈值可调)
import sys, time
import requests

TOKEN = "你的智兔token"                  # ← 换成你的真实智兔token
BASE = "https://api.zhituapi.com"

REALTIME_ENDPOINTS = {
    "ssjy": ("/fund/real/ssjy/{code}", "单只基金实时行情"),
    "etflist": ("/jh/hq/etflist", "ETF 行情列表(整板实时报价)"),
    "loflist": ("/jh/hq/loflist", "LOF 行情列表(整板实时报价)"),
    "list_all": ("/jh/list/all", "全部基金清单(静态标的宇宙)"),
}


def fetch(name, code=None, token=TOKEN, timeout=15):
    """拉一个实时/清单端点,返回 (data, err)。"""
    path_tmpl, _ = REALTIME_ENDPOINTS[name]
    url = f"{BASE}{path_tmpl.format(code=code) if code is not None else path_tmpl}"
    try:
        r = requests.get(url, params={"token": token}, timeout=timeout)
    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


def fund_board_snapshot(token=TOKEN, sleep=0.2):
    """拉 ETF 板 + LOF 板 + 全部基金清单,做一张「场内基金全貌」快照。"""
    if token == "你的智兔token":
        print("[演示] TOKEN 为占位符,下面请求会返回错误码契约;请换成真实 token 后再跑。")
    snap = {}
    for name in ("etflist", "loflist", "list_all"):
        data, err = fetch(name, token=token)
        if err:
            print(f"  {name} ({REALTIME_ENDPOINTS[name][1]}): 暂不可用:{err}")
            snap[name] = None
        else:
            print(summarize_quote(name, data))
            snap[name] = data
        time.sleep(sleep)
    return snap


def fund_realtime(code, token=TOKEN):
    """单只基金实时行情深度查看。"""
    data, err = fetch("ssjy", code=code, token=token)
    if err:
        print(f"  ssjy (单只基金实时行情): 暂不可用:{err}")
        return None
    print(summarize_quote("ssjy", data))
    return data

sleep=0.2 是限频保护——3 个整板端点 + 0.2 秒间隔 ≈ 0.6 秒,远在限频内。要监控多只单基,把 fund_realtime 套一层循环,外面再撑一个更大的间隔即可。

四、代码自验结果

离线自测 6 项全 PASS(真实输出,不联网):

selftest PASS: _hit_key 命中 / 列表汇总 / 聚合对象 / 空数据兜底 / 字段名不敏感 / 异动过滤 共 6 项

其中「异动过滤」用的是合成数据(沪深300ETF 涨 1.2%、中证500ETF 跌 -0.5),断言涨跌绝对值 ≥ 0.5 时命中 2 只——这些是逻辑自验用的假数,不是真实行情

联网跑(占位 token)真实输出:

[演示] TOKEN 为占位符,下面请求会返回错误码契约;请换成真实 token 后再跑。
  etflist (ETF 行情列表(整板实时报价)): 暂不可用:404 102:Licence证书(你的智兔token)不存在
  loflist (LOF 行情列表(整板实时报价)): 暂不可用:404 102:Licence证书(你的智兔token)不存在
  list_all (全部基金清单(静态标的宇宙)): 暂不可用:404 102:Licence证书(你的智兔token)不存在
  ssjy (单只基金实时行情): 暂不可用:404 102:Licence证书(你的智兔token)不存在

四个端点契约一致,单端点失败不影响整体流程、程序友好退出。本文未编造任何基金实时报价/清单数值——换成覆盖该接口的正式证书后重跑,即可打印真实盘中看板。

五、坑与注意事项

坑 #1:102 不代表路径写对了。 鉴权发生在路由匹配之前。路径故意写错配无效 token,同样返回 102。路径合法性只能靠客户端按白名单自查——本文 4 个路径是照公开文档核对的。实测 HTTP 状态码是 404 而不是 403(前几篇写的是 403),重点是看到 102:Licence证书... 就知道是证书问题。

坑 #2:etflist/loflist 是整板,别当单只用。 这两个返回的是整个 ETF/LOF 板的实时报价列表(可能几百上千行),适合排序/扫描;要看单只深度,走 fund/real/ssjy/{code}。混用会把整板当单只解析,字段取不到。

坑 #3:清单(list_all)是静态宇宙,报价(etflist)是动态的。 jh/list/all 给的是基金池子(代码+名称),不含实时价;实时价要再走 etflist/ssjy。别指望从清单里拿到报价。

坑 #4:ssjy{code} 用基金代码,不是股票代码。 文档示例为 159001 这类基金代码;别拿 600519 这种股票代码去查基金实时行情,会拿不到数据。

小结与下篇预告

这篇你拿到了 4 个场内基金实时/清单端点(单只实时 / 全基金清单 / ETF 整板 / LOF 整板)、字段名容错抽取写法、以及一个把整板拉齐做盘中快照的模板,顺带避开了 102 误判、整板当单只、清单含报价、基金代码错用四个坑。

下一篇(#11)讲ETF 历史 K 线与均线——用 /jh/hq/lskx(历史 K 线)+ /jh/hq/zxkx(最新 K 线)+ /jh/hq/lsma(历史 MA)+ /jh/hq/zxma(最新 MA)把「盘中看板」升级成「技术面回看」,算最后一日涨跌幅与收盘价相对均线的偏离。

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

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

把代码里的 你的智兔token 换成你拿到的真实 token,上面的脚本就能直接打印基金实时报价与清单数据。

免责声明

本文仅演示公开数据接口的用法,所有代码示例均以占位 token 自验,未含任何真实基金实时报价/清单数据;文中合成数据仅为逻辑自验用途,不构成投资建议,亦不承诺收益。投资决策请基于你自己的判断与风险承受力。

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