A股实时行情 API 接入指南:Python 覆盖行情、复权、基本面与 WebSocket

早期做A股策略,我用Python拉通了日K线,回测曲线挺好看,以为数据层搞定了。实盘上线后问题一个接一个:除权日跳空被策略当成下跌信号,两天后才反应过来是K线没做复权;想估滑点,发现手里只有K线,没有盘口,只能拍一个固定值;想做多因子,打开数据源一看,基本面覆盖哪些标的、不覆盖哪些,谁也说不清。

这些坑不是因为接口调不通,而是因为一开始就没看清A股数据到底有几层。

A股数据远不止"行情"两个字。至少分四层:行情、参考数据、基本面、接入方式。缺一层,你的策略就会在某个节点翻车。

这篇文章要做两件事:第一,把A股数据的四层结构摊开,让你在写第一行接入代码前就能画出数据架构图;第二,以一套统一API服务为具体参考,把每一层的实际能力、字段结构、边界条件讲清楚,并给出可直接运行的Python代码。


一、A股数据能力全景图

先看整体结构。从数据到用户,是一条四层的链路:

复制代码
┌─────────────────────────────────────────────────────────────┐
│                     接入层(怎么拿)                          │
│   REST  │  WebSocket  │  AI 原生(Skill / MCP / CLI)        │
└──────────────────────────┬──────────────────────────────────┘
                           │
┌──────────────────────────▼──────────────────────────────────┐
│                   基本面层(公司是什么)                      │
│  公司档案 │ 财务三表 │ 估值 │ 行业 │ 股东 │ 事件日历          │
└──────────────────────────┬──────────────────────────────────┘
                           │
┌──────────────────────────▼──────────────────────────────────┐
│                 参考数据层(什么时候、对什么)                 │
│  交易日历 │ 交易时段 │ 标的信息 │ 指数计算 │ 符号目录          │
└──────────────────────────┬──────────────────────────────────┘
                           │
┌──────────────────────────▼──────────────────────────────────┐
│                   行情层(市场发生了什么)                     │
│  快照 │ K线 │ 复权因子 │ 分时 │ 盘口 │ 逐笔 │ 资金流          │
└─────────────────────────────────────────────────────────────┘

行情是地基,参考数据是框架,基本面是纵深,接入层是出口。四层缺一层,你的数据管道就会在某个节点断掉。

下面的内容以 TickDB 为参考实现。它的A股能力覆盖了这四层,并且提供REST、WebSocket、AI原生三种接入方式。先建立结构,再看细节和代码。

覆盖范围速查

维度 能力
交易所 上交所 SSE + 深交所 SZSE
标的 全部A股标的 + 主要指数
数据品类 Tick / Trade / Depth (L2)、K线、分时、复权因子、资金流、基本面
实时性 实时快照与逐笔推送,具体更新频率以官方文档和实测为准
历史深度 产品支持最长10年K线
接入方式 REST + WebSocket + AI原生(Skill / MCP / CLI)
基本面包围 沪市 + 深市个股,不含北交所 / ETF

统一响应结构与鉴权

在写第一行代码前,先把两件事固定下来,后面所有端点都复用。

REST 响应统一为 {code, message, data} 包装。 code=0 表示成功,data 内是该端点的业务数据。不同端点的 data 结构不同:有的是数组,有的是对象,有的还有二级嵌套。不能假设 data 就是行情字段本身。

REST 认证 Header 是 X-API-Key 实测 X-TickDB-Key 返回 401,业务码 1002,提示须通过 X-API-Key 提供。

先把这两个基础封装写好,后面所有代码块直接复用:

python 复制代码
# 测试环境:API 行为实测于 Python 3.14.2 / macOS 15.5 / 2026-09-16
# 发布机兼容性:Python 3.11 / Ubuntu 22.04 需补跑
# 以下代码按实测响应结构编写

import os
import requests

BASE_URL = "https://api.tickdb.ai/v1"
API_KEY = os.getenv("TICKDB_API_KEY")

def _headers() -> dict:
    """统一认证Header,不硬编码密钥"""
    if not API_KEY:
        raise RuntimeError("请先设置环境变量 TICKDB_API_KEY")
    return {"X-API-Key": API_KEY}

def unwrap(resp: requests.Response) -> dict:
    """
    统一解包 {code, message, data} 包装
    
    成功返回 data;业务错误抛出 RuntimeError。
    注意:HTTP 认证失败时 code 可能是字符串,不能直接和 0 比较,
    所以先 raise_for_status() 再解析业务码。
    """
    resp.raise_for_status()
    payload = resp.json()
    if payload.get("code") != 0:
        raise RuntimeError(f"API业务错误: code={payload.get('code')} message={payload.get('message')}")
    return payload["data"]

这段封装解决了三个坑 :密钥不硬编码、认证错误先于业务错误被捕获、data 解包统一。


二、行情层:Python接入实时快照与K线

行情层是地基。地基不稳,上面全塌。

品类 能力覆盖 解决什么问题
实时快照 单标的/批量/全市场;open缺失表示集合竞价进行中 盯盘、开盘信号、下单前校验
K线与历史 1分钟到月线多个周期;A股5种复权 回测、因子、图表
复权因子 每笔公司行动对应前复权/后复权两条记录 自建复权逻辑、跨数据源校验
分时 分钟级价格路径 日内研究、开盘冲击
盘口深度 多档买卖盘 滑点估算、流动性分析
逐笔成交 逐笔明细、VWAP、聚合成交 订单流研究、执行系统
资金流 主力净流入、主力买卖量、散户净流入 情绪因子、资金监控

2.1 REST接入实时快照

参数用 symbols,返回 data 是数组。 单数 symbol 实测也被接受,但统一写复数,避免单复数歧义。

python 复制代码
def get_ticker(symbol: str) -> dict:
    """
    获取单标的实时快照
    
    Args:
        symbol: 标的代码,如 "688256.SH"(沪市)或 "000001.SZ"(深市)
    
    Returns:
        data 数组中的第一条记录;空数组时抛出未找到
    """
    url = f"{BASE_URL}/market/ticker"
    params = {"symbols": symbol}
    
    try:
        resp = requests.get(url, headers=_headers(), params=params, timeout=10)
        data = unwrap(resp)
        if not data:
            raise RuntimeError(f"未找到标的: {symbol}")
        # last_price: 最新价,open: 开盘价,prev_close: 昨收价
        # volume_24h: 成交量,high_24h/low_24h: 24小时最高/最低
        # timestamp: Unix毫秒时间戳
        first = data[0]
        print(f"symbol={first.get('symbol')} last={first.get('last_price')} open={first.get('open')}")
        return first
    except requests.RequestException as e:
        print(f"请求失败: {e}")
        raise

if __name__ == "__main__":
    result = get_ticker("688256.SH")
    print(result)

data 数组内单条记录的字段如下(字段级示意,非原始响应全文):

json 复制代码
{
  "symbol": "688256.SH",
  "name": "寒武纪",
  "type": "stock",
  "category": "CN",
  "last_price": "1086.58",
  "open": "1055.00",
  "prev_close": "1053.98",
  "volume_24h": "9102334",
  "high_24h": "1092.50",
  "low_24h": "1048.00",
  "timestamp": 1754118000000
}

A股集合竞价期间,open字段缺失是合法状态,不是接口出错。 用open是否存在判断是否进入正式交易,比比较当前时间更稳健。这个判断决定了你的开盘信号是在正式交易后触发,还是在集合竞价期间就误触发。

另一个坑:不存在标的返回 HTTP 200,data 是空数组。 不能把 HTTP 200 直接当成有行情。上面代码里 if not data 就是为了处理这种情况。

2.2 REST接入K线

K线的时间参数是 start_time/end_time(Unix 毫秒),不是 beg_day/end_day

我一开始把交易日历的参数习惯带到K线,用 beg_day/end_day 请求。返回是200,看着像成功,但拉回来的数据范围根本没被限制在指定窗口------200不等于参数生效 。改成 start_time/end_time 毫秒值后,时间窗才真正生效。

python 复制代码
from datetime import datetime, timezone

def to_ms(date_str: str) -> int:
    """把 'YYYY-MM-DD' 转为 Unix 毫秒时间戳(UTC)"""
    dt = datetime.strptime(date_str, "%Y-%m-%d").replace(tzinfo=timezone.utc)
    return int(dt.timestamp() * 1000)

def get_kline(symbol: str, interval: str = "1d", adjust: str = "forward",
              beg_day: str = "2026-08-01", end_day: str = "2026-08-31",
              limit: int = 100) -> list:
    """
    获取历史K线
    
    Args:
        symbol: 标的代码,如 "688256.SH"
        interval: K线周期,支持 1m/5m/15m/30m/1h/4h/1d/1w/1M
        adjust: 复权方式,A股支持 none/forward/backward/forward_add/backward_add
        beg_day / end_day: 日期字符串,内部转为毫秒时间戳
        limit: 返回条数,最大1000
    
    Returns:
        klines 列表
    """
    url = f"{BASE_URL}/market/kline"
    params = {
        "symbol": symbol,
        "interval": interval,
        "adjust": adjust,
        "start_time": to_ms(beg_day),
        "end_time": to_ms(end_day),
        "limit": limit,
    }
    
    try:
        resp = requests.get(url, headers=_headers(), params=params, timeout=10)
        data = unwrap(resp)
        # K线数组在 data.klines,不是顶层 klines
        klines = data.get("klines", [])
        # open/high/low/close: OHLC价格,volume: 成交量
        # timestamp: 周期起始时间,UTC格式
        print(f"获取到 {len(klines)} 条K线,最新一条: {klines[-1] if klines else '无'}")
        return klines
    except requests.RequestException as e:
        print(f"请求失败: {e}")
        raise

if __name__ == "__main__":
    klines = get_kline("688256.SH")
    print(klines)

data.klines 数组内单条记录(字段级示意):

json 复制代码
{
  "timestamp": "2026-08-01T00:00:00Z",
  "open": 1040.00,
  "high": 1068.88,
  "low": 1030.01,
  "close": 1053.98,
  "volume": 8234521
}

接口返回已结束周期的历史K线;当前形成中的周期用另一个接口(/market/kline/latest)。这个区分很重要------把形成中的bar当成已收盘bar用,会产生前视式信号。

2.3 复权因子

复权因子不是比例,是仿射变换。

每一笔公司行动对应一条前复权、一条后复权记录,公式是:

复制代码
adjusted_price = raw_price × factor_a + factor_b

A股市场的factor_b恒为0,所以实际就是 raw_price × factor_a。它的价值在于:你可以自己控制复权逻辑,而不是依赖数据源替你算。

前复权适合实时信号和最新价格对齐,后复权适合长期历史比较。混用会产生系统性误差------等价于在同一个价格序列里插入两套时间基准。

复权因子的响应路径比较深:data.data[symbol] 这是实测发现的,不能凭直觉猜。

python 复制代码
def get_ex_factors(symbol: str, beg_day: str = "2026-01-01",
                   end_day: str = "2026-09-16") -> list:
    """获取复权因子,返回该标的的因子记录列表"""
    url = f"{BASE_URL}/market/kline/ex-factors"
    params = {
        "symbol": symbol,
        "start_time": to_ms(beg_day),
        "end_time": to_ms(end_day),
    }
    
    try:
        resp = requests.get(url, headers=_headers(), params=params, timeout=10)
        data = unwrap(resp)
        # 实测路径:data.data[symbol],每个元素含 timestamp/adjust/factor_a/factor_b
        factors = data.get("data", {}).get(symbol, [])
        print(f"复权因子记录数: {len(factors)}")
        if factors:
            print(f"样例: adjust={factors[0].get('adjust')} factor_a={factors[0].get('factor_a')} factor_b={factors[0].get('factor_b')}")
        return factors
    except requests.RequestException as e:
        print(f"请求失败: {e}")
        raise

2.4 盘口、逐笔、资金流

盘口 返回多档买卖盘。data 内单条记录(字段级示意):

json 复制代码
{
  "symbol": "688256.SH",
  "bids": [
    {"price": 1086.00, "size": 200},
    {"price": 1085.50, "size": 300}
  ],
  "asks": [
    {"price": 1086.50, "size": 100},
    {"price": 1087.00, "size": 350}
  ]
}

盘口对时延极度敏感。用之前必须验证目标市场的实际可用性,不能从接口存在推断全市场覆盖。

逐笔成交返回逐笔明细,含价格、数量、时间、方向。逐笔是判断真实买卖力量的原始材料,比K线更早反映市场意图。

资金流 返回主力净流入、主力买卖量、散户净流入等字段。A股资金流有三种常见口径------成交方向归因、大单资金流、主力资金流。这三个定义在不同数据源之间完全不兼容。用两个来源的资金流数据做比较,等于用两把不同刻度的尺子量同一个东西。

2.5 行情层的关键认知

如果你只接了K线和ticker,你的策略在除权日、集合竞价、停牌、换月这四个节点上,一定会有一次莫名其妙的回撤。


三、参考数据层:交易日历与交易时段

参考数据层是框架。没有框架,行情数据就是一堆不知道能不能用的数字。

品类 能力覆盖 解决什么问题
交易日历 按市场维护的交易日列表,含节假日 回测时间序列、缺口识别
交易时段 集合竞价、连续竞价、午休、收盘的完整分段 实时策略状态机
标的基础信息 名称、交易所、币种、股本、EPS、BPS、股息率 估值计算、身份确认
指数计算 市场宽度、涨跌家数等汇总指标 大盘分析、状态识别
符号目录 全市场可查询标的清单 选股候选池、UI适配

3.1 交易日历

这个端点的参数和K线完全不一样:必须带 market=CN,日期格式是 YYYYMMDD 紧凑格式,不是 YYYY-MM-DD

我一开始用 from/to 请求,返回400。后来加 market=CN 但日期带连字符,还是400。改成 20260901 这种紧凑格式才成功。

同一个API体系内,不同端点的参数命名和格式不统一,这是接入时最容易踩的坑。 不要假设K线用什么,交易日历就用什么。

python 复制代码
def get_trade_days(market: str = "CN",
                   beg_day: str = "20260901",
                   end_day: str = "20260930") -> dict:
    """
    获取交易日历
    
    注意:日期格式必须是 YYYYMMDD,不是 YYYY-MM-DD;
    且必须带 market 参数,否则返回400。
    """
    url = f"{BASE_URL}/market/trade-days"
    params = {"market": market, "beg_day": beg_day, "end_day": end_day}
    
    try:
        resp = requests.get(url, headers=_headers(), params=params, timeout=10)
        data = unwrap(resp)
        days = data.get("trade_days", [])
        half_days = data.get("half_trade_days", [])
        print(f"交易日数量: {len(days)},半日市数量: {len(half_days)}")
        if days:
            print(f"首日: {days[0]},末日: {days[-1]}")
        return data
    except requests.RequestException as e:
        print(f"请求失败: {e}")
        raise

A股、港股、美股、期货的休市安排不同,多市场研究必须按市场维护独立的交易日历。 "默认按工作日"是回测最常见的陷阱------如果回测框架里的交易日历和真实市场不一致,信号触发时间会系统性偏移。

3.2 交易时段

返回的 data 是数组,不是对象。 每个元素含 markettrading_sessions,每段含 begin_timeend_time

python 复制代码
def get_trading_sessions(market: str = "CN") -> list:
    """获取交易时段,返回 data 数组"""
    url = f"{BASE_URL}/market/trading-sessions"
    params = {"market": market}
    
    try:
        resp = requests.get(url, headers=_headers(), params=params, timeout=10)
        data = unwrap(resp)
        # data 是数组,遍历取 trading_sessions
        for item in data:
            sessions = item.get("trading_sessions", [])
            print(f"market={item.get('market')} 时段数={len(sessions)}")
            for s in sessions:
                print(f"  {s.get('begin_time')} - {s.get('end_time')}")
        return data
    except requests.RequestException as e:
        print(f"请求失败: {e}")
        raise

返回市场当天的开收市时段。A股集合竞价(9:15--9:25、14:57--15:00)、港股午休(12:00--13:00)、期货夜盘,这些是"数据有但不能按普通逻辑使用"的时段。不处理会导致策略在错误状态下运行。

3.3 标的基础信息

返回名称、交易所、币种、股本、EPS、BPS、股息率。估值计算的起点:当前价除以BPS就是PB,当前价除以EPS就是PE。

3.4 参考数据层的关键认知

交易日历和交易时段不是可选知识,是必须在数据层明确处理的事实。 否则你的日内数据里会有一段"空洞",或者策略在非交易时段收到错误信号。


四、基本面层:覆盖边界比覆盖数量更重要

基本面层是纵深。行情告诉你价格怎么走,基本面告诉你这家公司值多少。

覆盖边界先说清楚:本文使用的数据服务,基本面接口覆盖沪市和深市个股,不覆盖北交所个股,不覆盖沪市和深市的ETF。

品类 能力覆盖 解决什么问题
公司档案与高管 公司信息、业务简介、管理层名单 公司研究起点、治理分析
财务三表 利润表/资产负债表/现金流量表;最新期、年度、TTM 多因子、盈利质量
业务与地区分部 按业务线或地区拆分的收入结构 收入结构分析、地缘风险
估值指标 PE/PB/PS/股息率;快照+时序+一年高低位 估值分位、风格轮动
行业分析 同业公司、行业估值分布、行业排行、分类树 横向比较、行业轮动
资本行动 分红(含TTM)、回购、公司行动 事件驱动、回测复权
股东与基金 最新股东结构、前十大股东、基金持仓 筹码分析、机构行为
新闻与事件日历 个股新闻+全市场日历 事件驱动、风控禁入日

4.1 财务三表与估值

TTM口径只支持利润表和现金流量表,资产负债表不适用------这是财务分析的基本常识,但很多数据源不会主动告诉你。

估值字段有两个实测坑:字段名是大写 PE/PB/PS/DvdYld,且嵌在 data.metrics 下,每项还有 value 字段。 不是直接的小写 pe/pb/ps/dividend_yield

python 复制代码
def get_valuation_latest(symbol: str) -> dict:
    """获取估值快照,返回 metrics 字典"""
    url = f"{BASE_URL}/fundamentals/valuation/latest"
    params = {"symbol": symbol}
    
    try:
        resp = requests.get(url, headers=_headers(), params=params, timeout=10)
        data = unwrap(resp)
        # 实测路径:data.metrics["PE"]["value"]
        metrics = data.get("metrics", {})
        pe = metrics.get("PE", {}).get("value")
        pb = metrics.get("PB", {}).get("value")
        ps = metrics.get("PS", {}).get("value")
        dvd = metrics.get("DvdYld", {}).get("value")
        print(f"PE={pe} PB={pb} PS={ps} DvdYld={dvd}")
        return metrics
    except requests.RequestException as e:
        print(f"请求失败: {e}")
        raise

估值字段必须注明价格基准日,否则数字没有可比意义。 跨公司比较时必须确认币种一致,跨期比较时必须确认报告期对齐。

4.2 资本行动与股东

资本行动包含分红历史(含TTM)、回购记录、公司行动(拆股、合股、配股、代码变更)。分红除权日是A股价格出现向下跳空的触发日,回测时必须处理,否则系统会把除权跳空误判为价格下跌信号。

股东与基金包含最新股东结构、前十大股东、单股东明细、基金持仓。股东数据有披露延迟,不能当成实时信号使用。

4.3 基本面层的关键认知

知道不覆盖什么,比知道覆盖什么更重要。 沪市深市个股覆盖,北交所和ETF不覆盖------这个边界决定了你的多因子选股范围。


五、接入层:REST / WebSocket / AI原生

接入层是出口。同一套数据,三种接入路径,对应三种使用场景。

接入方式 认证 适用场景 关键特性
REST X-API-Key Header 研究、回测、批量拉取 字段结构固定,有错误码
WebSocket api_key Query 实时看板、盘中止损 密钥过期返回1008
AI原生 X-TickDB-Key Header Agent工作流、自然语言取数 先取结构化事实,再分析

5.1 WebSocket接入实时行情

WebSocket 订阅消息格式和 REST 完全不同。 我一开始按直觉写 {"action":"subscribe","channel":"ticker","symbol":"..."},服务端返回 code=2001 Unknown command

实测成功的格式是 {"cmd":"subscribe","data":{"channel":"ticker","symbols":["..."]}}cmd 不是 action,用数组 symbols 不是单数 symbol,外层套 data

先安装依赖:

shell 复制代码
pip install requests websockets certifi
python 复制代码
# 测试环境:API 行为实测于 Python 3.14.2 / macOS 15.5 / 2026-09-16
# 发布机兼容性:Python 3.11 / Ubuntu 22.04 需补跑

import os
import ssl
import json
import asyncio
import certifi
import websockets

api_key = os.getenv("TICKDB_API_KEY")

async def subscribe_realtime(symbol: str = "688256.SH"):
    """
    订阅实时行情
    
    频道说明:
    - ticker: 实时快照
    - depth: 盘口深度
    - trade: 逐笔成交
    
    订阅消息格式实测为 cmd/data/symbols,不是 action/channel/symbol。
    密钥过期时,服务端通过 close code 1008 关闭连接,
    同时发送JSON消息说明原因。重连逻辑必须区分正常断线和密钥过期。
    """
    url = f"wss://api.tickdb.ai/v1/realtime?api_key={api_key}"
    ssl_context = ssl.create_default_context(cafile=certifi.where())
    
    try:
        async with websockets.connect(url, ssl=ssl_context) as ws:
            # 实测成功格式:cmd + data + symbols 数组
            sub_msg = {
                "cmd": "subscribe",
                "data": {"channel": "ticker", "symbols": [symbol]},
            }
            await ws.send(json.dumps(sub_msg))
            print(f"已发送订阅: {sub_msg}")
            
            async for message in ws:
                # 行情推送字段待交易时段补测,这里原样打印
                print(message)
    except websockets.exceptions.ConnectionClosedError as e:
        if e.code == 1008:
            print("密钥过期,需要刷新API Key后重连")
        else:
            print(f"连接关闭: code={e.code} reason={e.reason}")
    except Exception as e:
        print(f"连接异常: {e}")
        raise

if __name__ == "__main__":
    asyncio.run(subscribe_realtime())

关于 TLS :实测在 macOS 上用默认系统证书链连接失败,改用 certifi 提供的 CA 后连接成功。这不是服务端问题,是本地证书链问题。参考代码里显式使用 certifi,能提高跨环境运行稳定性。

关于 ticker 推送字段 :本次实测连接成功、订阅确认成功,但等待窗口内未收到 ticker 行情消息。因此上面的代码只做原样 print(message),不解析字段。交易时段补测后再添加字段访问示例。

5.2 AI原生接入

Skill、MCP、CLI三档,通过 X-TickDB-Key 认证,让Agent直接调用结构化市场数据。

  • Skill:"对话即用·零配置",适合PM/研究员/轻度用户
  • MCP:"一个托管HTTPS端点,让你的AI编码助手一次连接即获得行情数据工具"
  • CLI:"终端直查实时行情,JSON/表格双输出,为脚本和自主Agent设计"

AI原生接入的意义不是"让AI帮你查价格",而是让模型先取得带标的、字段和时间戳的事实,再进行分析。 顺序反了,分析结论就没有可追溯的数据基础。

5.3 接入层的关键认知

AI工作流中的行情数据,必须在模型推理之前到位。 让模型用记忆猜价格,是把分析过程变成幻觉生成过程。


六、四类读者的最小可用组合

不同角色的人,不需要接同一套数据。

个人量化开发者

最小组合:K线(含复权)+ 实时快照 + 交易日历 + 标的基础信息

起步路径:先用K线搭回测框架,确认复权口径统一;再加上实时快照做信号触发;交易日历处理非交易日空值;标的基础信息用于估值筛选。

最容易踩的坑:K线没做复权,除权日跳空被策略当成下跌信号。

小团队数据工程师

最小组合:交易日历 + 交易时段 + 复权因子 + 标的信息 + 基本面

起步路径:先把参考数据层建好,再做行情管道;复权因子用于自建复权逻辑;基本面用于多因子研究。

最容易踩的坑:交易日历没按市场分开维护,多市场回测的时间轴对不齐。

AI工具使用者

最小组合:MCP/Skill/CLI + 实时快照 + 事件日历

起步路径:先用MCP或CLI接入实时快照,让Agent能取到带时间戳的事实;再加上事件日历,让Agent知道今天有什么值得关注的事件。

最容易踩的坑:让模型用训练数据里的历史价格回答"现在多少钱",而不是先调接口取最新价格。

金融应用团队

最小组合:REST + WebSocket + 多市场统一接入 + 断线重连 + POC验收维度

起步路径:先做POC验收,确认目标市场的字段结构、实时性覆盖、边界处理;再做生产接入,实现断线重连和状态恢复。

最容易踩的坑:没有区分正常断线和密钥过期(1008),重连逻辑一刀切。


七、错误码与常见问题

7.1 错误码速查

HTTP 业务码 含义
400 2001 港股/美股不支持加法复权
401 1005 API Key过期
403 3009 接口未开放
403 3010 市场未开放
404 40404 上游无数据
404 40405 查询条件无有效业务数据
422 5006 复权基础数据不可用
429 --- 请求频率超限
503 5005 复权因子不可用
WS close 1008 --- 密钥过期

实测补充 :错误 API Key 返回 HTTP 401,body 里 code 是字符串 "Invalid or expired token",不是整数。不要假设业务码永远是整数 ,先 raise_for_status(),再按需解析 body。

7.2 常见问题

Q:A股集合竞价期间为什么没有开盘价?

A:集合竞价期间(9:15--9:25、14:57--15:00)open字段缺失是合法状态。只有9:25统一撮合之后,open才会出现。

Q:基本面数据覆盖北交所吗?

A:本文使用的数据服务,基本面接口覆盖沪市和深市个股,不覆盖北交所个股,也不覆盖沪市和深市的ETF。

Q:资金流数据可以直接当买卖信号吗?

A:不能。资金流是市场参与者行为的量化描述,不是买卖信号。而且不同数据源的资金流口径不兼容,引用前必须先冻结口径定义。

Q:WebSocket断线后怎么处理?

A:要区分正常断线和密钥过期。密钥过期时服务端返回close code 1008并发送JSON消息说明原因,两种情况的处理方式不同。

Q:TradingView图表可以直接用这套数据吗?

A:REST API可以作为TradingView UDF后端的数据源层,但需要开发者自己实现UDF协议的包装层。

Q:为什么K线和交易日历的参数格式不一样?

A:实测发现K线用 start_time/end_time 毫秒值,交易日历用 market=CN + YYYYMMDD 紧凑格式。同一API体系内不同端点参数不统一,接入时必须逐个端点看文档和实测,不能凭直觉类推。


八、A股数据接入检查清单

把下面这张表填完,你的数据架构图就出来了。

能力层 品类 是否需要 是否已接入
行情 实时快照
行情 K线(含复权)
行情 复权因子
行情 分时
行情 盘口深度
行情 逐笔成交
行情 资金流
参考 交易日历
参考 交易时段
参考 标的信息
参考 指数计算
参考 符号目录
基本面 公司档案
基本面 财务三表
基本面 估值指标
基本面 行业分析
基本面 资本行动
基本面 股东与基金
基本面 新闻与日历
接入 REST
接入 WebSocket
接入 AI原生

九、关于本文参考的统一数据服务

本文全程以 TickDB 作为参考实现,把A股数据的四层能力落到具体的接口、字段和边界。官网截至2026-09-15描述的核心能力如下:

维度 能力
覆盖范围 上交所、深交所全部A股标的;主要指数;另有美股、港股、期货、外汇
数据品类 Tick / Trade / Depth (L2)、K线、分时、复权因子、资金流、基本面
实时性 实时快照与逐笔推送;WebSocket支持ticker、depth、trade三个A股频道
历史深度 产品支持最长10年K线
接入方式 REST + WebSocket + AI原生(Skill / MCP / CLI),统一X-API-Key认证
基本面包围 沪市 + 深市个股;不覆盖北交所个股,不覆盖沪市和深市ETF

TickDB 是面向开发者、量化研究和 AI 应用的统一实时市场数据服务。

如果决定试一下,怎么开始?

先按文末检查清单,列出你自己策略实际需要的数据层。然后从最小可用组合入手------多数个人量化开发者只需要K线(含复权)+ 实时快照 + 交易日历 + 标的基础信息这四类。跑通之后再决定是否扩展到盘口、逐笔、基本面。


十、总结

A股行情数据不是"拿到K线就够了"------至少有行情、参考数据、基本面、接入方式四层能力,每层解决不同的问题。

在项目初期就看清完整的数据全景图,比在回测失败后逐个排查遗漏的成本低得多。

三层立意链收束

  • 工程代价:字段schema不对导致parser重写,交易日历没分开维护导致多市场回测时间轴对不齐,工期以天计;参数名不统一导致200返回但过滤不生效,排查半天才发现时间窗根本没起作用。
  • 决策风险:OHLCV对不齐,回测结果偏移方向不可预测;复权口径混用,等价于在同一个价格序列里插入两套时间基准。
  • 可证明机制:文末检查清单 + 完整可运行代码 + 错误码速查表,可以直接带进POC验收。

我这轮踩坑最深的三个点,你可以直接避开

  1. K线时间参数不是 beg_day/end_day,是 start_time/end_time 毫秒值。
  2. 交易日历必须带 market=CN,日期格式是 YYYYMMDD
  3. WebSocket订阅用 cmd/data/symbols,不是 action/channel/symbol

附录A:常见接口示例

端点 功能
/market/ticker 单标的/批量行情快照
/market/ticker/cn-stock A股全市场快照
/market/kline 历史K线
/market/kline/latest 最新K线
/market/kline/ex-factors 复权因子
/market/intraday 分时数据
/market/depth 盘口深度
/market/trades 逐笔成交
/market/trades/vwap VWAP
/market/capital-flow 资金流
/market/trade-days 交易日历
/market/trading-sessions 交易时段
/market/stock-info 标的基础信息
/market/calc-index 指数计算指标
/market/intervals/kline 可用K线周期
/symbols/available 符号目录
/fundamentals/profile 公司档案
/fundamentals/financials/latest 最新财务
/fundamentals/financials/ttm TTM财务
/fundamentals/valuation/latest 估值快照
/fundamentals/valuation/ts 估值时序
/fundamentals/dividends 分红历史
/fundamentals/corp-actions 公司行动
/fundamentals/shareholders/top 前十大股东
/fundamentals/calendar 财经日历
/fundamentals/news 个股新闻
/realtime WebSocket实时订阅

文中实测数据来自2026-09-15的API调用,样本标的为688256.SH(寒武纪)和600519.SH(贵州茅台)。API行为实测环境:Python 3.14.2 / macOS 15.5 / 2026-09-16。Python 3.11 / Ubuntu 22.04 兼容性待发布机补跑确认。动态数值以官网和官方文档当前口径为准。样本标的仅用于技术演示,不构成投资建议。

相关推荐
生信大杂烩1 小时前
Xenium H&E空间原位可视化——细胞轮廓、基因表达与转录本可视化
python·算法·数据分析
东莞市云毅网络有限公司1 小时前
用标准库做网页正文抽取:从 HTML 到结构化字段的轻量实现
python·sqlite·自动化运维·geo·数据监测
高级程序源1 小时前
django校企合作实习基地管理系统82506-计算机课程设计、毕业设计
vue.js·后端·python·mysql·django·课程设计·pygame
东方芷兰1 小时前
Agent 技术摘要 02 —— 区块链、比特币、挖矿、ETF、比特币疯涨事件、以太坊、以太币、显卡荒事件
人工智能·笔记·python
贝猫说python1 小时前
阿里云部署qwen 大模型从0-1,第2步:阿里云平台创建ubuntu实例
python
峥嵘life1 小时前
2026华为AI码道 CodeArts 使用分享:Windows端 + 服务器CLI 实战总结
android·大数据·开发语言·python
贝猫说python1 小时前
阿里云部署qwen 大模型从0-1,第3步:阿里云服务器上部署大模型
python
少陽君1 小时前
服务器服务检查报告
python
x秀x2 小时前
sam3新手使用教程
开发语言·python