A股逐笔数据质量怎么评估?从实时订阅到历史明细对账

TickDB Research ·

A股逐笔数据质量怎么评估?从实时订阅到历史明细对账

image.png

接口返回成功、字段齐全、成交价看起来正常,是否就意味着逐笔数据可以直接用于历史分析?还不够。同一条成交在两次查询里可能更换 ID,方向字段可能出现约定之外的值,最近 1,000 条也未必覆盖整个交易日。

本文以中际旭创、新易盛、宁德时代的实际成交明细查询为例,把数据质量拆成可执行的检查,并说明如何将实时订阅落库与历史回查连接起来。本次实查完成于 2026 年 10 月 13 日晚间;实测对象是最近成交窗口,没有完成盘中 WebSocket 采集,也没有取得任意历史日期的全日逐笔。

先定义“历史明细”到底是什么

实时订阅回答“连接期间收到哪些记录”;最近成交查询回答“当前可返回的最近 N 条是什么”;按日期检索的历史逐笔回答“指定日期、指定区间的记录是否齐全”。三者不能互相替代。

本次查阅的 REST 文档提供 symbol、limit、type 参数,limit 最大为 1,000,没有列出日期范围或分页游标。因此,这里的历史分析分为两层:实际回查最近成交窗口;设计将实时消息持续落库,逐日形成可追溯历史。不能为前一种接口虚构 start、end 或 cursor 参数,也不能因为没有查到某项参数,就断言服务的所有产品均不提供历史逐笔。

更细的一层是“逐笔”的来源粒度:一条接口记录是否对应一笔交易所原始成交,是否由快照差分、合并或其他处理得到,需要单独确认。只有字段名和记录条数,无法证明它是交易所完整逐笔流。

用三只活跃标的建立样本

选取当日成交活跃的三只创业板股票作为案例。连接器快照显示,中际旭创、新易盛、宁德时代的当日累计成交额分别约为 221.13 亿、146.14 亿、119.07 亿元。这只是样本选择依据,不是我们对全市场重新计算的热度排名;三个样本也不能代表所有 A 股板块。

对每只股票调用一次最近成交查询,limit=1000,并保存原始响应。下面的时间全部转换为北京时间,日期均为 2026-10-13。

标的样本起止时间(各 1,000 条)unknown 方向记录
中际旭创 300308.SZ14:08:51—15:30:0035 条 / 3.5%
新易盛 300502.SZ14:09:12—15:30:0042 条 / 4.2%
宁德时代 300750.SZ14:08:24—15:30:0026 条 / 2.6%

三份样本中,price、quantity、timestamp、side 均未发现空值,价格与数量均为正数;按响应顺序没有发现时间倒退,单份响应内没有重复 ID。这些都是样本内的检查结果,不能据此给出全日完整率或“零丢包”的结论。

image.png

图 1:2026-10-13 的最近查询窗口中,中际旭创、新易盛、宁德时代的 unknown 方向分别为 35/1,000、42/1,000、26/1,000。未知方向不等于缺失成交,这些比例不能用于评价全日完整性。

维度一:字段有效,业务含义也要成立

文档将成交方向列为 buy、sell、neutral,实际返回却还出现 unknown。严格按三种枚举解析的客户端可能报错;把 unknown 自动转为 neutral,又会把“未知”改成“中性”,改变分析口径。

建议保留 side_raw,把无法解释的方向标记为未知。计算方向占比时同时报告未知率;需要方向的计算仅使用已知方向记录,并明确分母。本文中的 3.5%、4.2%、2.6% 都以各自 1,000 条为分母。buy/sell 的判定方法也需核实,不能直接解释成真实资金流入流出。

数量字段同样不能只验证“能转成整数”。已读取的逐笔页面只写了“成交数量”,没有说明 A 股 quantity 的单位。本次原始数量合计分别是 37,323、52,721、69,111,但在确认“股、手或其他单位”之前,不将其写成成交股数或计算成交金额。更不能拿这段尾部窗口的数量除以全天快照成交量,称为数据完整率。

价格还有一个容易忽略的细节:原始响应存在 734.1199951171875 这样的长小数。按 0.01 网格检查,三份样本分别有 859、929、953 条不恰好落在网格上。这与浮点表示误差的表现相符,但仅凭响应不能确定服务内部实现。

处理时保留原字符串,使用 Decimal 计算;展示值可以按已核实的价格档位处理,原值不要覆盖。Decimal 能避免继续引入二进制浮点运算误差,不能恢复上游已经损失的精度。自动四舍五入也不应掩盖真正的异常报价。

维度二:时间合法,不等于粒度正确

三份样本的相邻记录对各有 999 组,其中间隔恰好 3 秒的分别为 963、956、972 组,占 96.40%、95.70%、97.30%。这种明显节奏值得进一步确认上游采样或聚合方式。

这不是“3 秒延迟”的测量,也不能由此断言每 3 秒只发生一笔交易。当前只有事件时间,没有实时接收时间、交易所序列和独立完整参考流。将这些记录直接用于订单流重建或逐笔微观结构回测,证据不足。

同时,不应把 15:00 后的记录一律认作脏数据。深交所《交易规则(2026 年修订)》规定了 15:05—15:30 的盘后固定价格交易时段。本次三份样本分别有 36、43、27 条时间晚于 15:00;时间规则应结合证券、日期和会话判定。交易规则能说明盘后时段存在,不能单独证明每条返回记录都是真实且分类正确的盘后成交。

实时采集时至少分别保存 event_ts 和 received_at。二者相减只能称为“观测到的数据年龄”,其中还包含时钟偏差、上游处理和本地排队;未做时钟校准和链路拆分时,不应称为纯网络延迟。盘后执行历史查询时,请求时间减成交时间更不能当作实时延迟。

维度三:ID 在单次响应内唯一,跨窗口是否稳定?

对中际旭创再发起 limit=100 的查询,结果中的 100 条成交内容与前一份 1,000 条响应的尾部完全一致,但对应 ID 全部不同。

例如,时间戳为 1791874431000、价格为 734.1199951171875、数量为 20、方向为 sell 的记录,在大窗口中的 ID 是 1791874431000_900,在小窗口中变为 1791874431000_0。这是本次两个查询窗口的观察,不能外推成所有市场、所有日期的 ID 生成规则。

image.png

图 2:本次 300308.SZ 的两次查询中,100/100 条成交内容匹配,0/100 条 ID 与内容同时匹配。示例 ID 分别为 1791874431000_900 和 1791874431000_0。内容按 timestamp、price、quantity、side 对比;该结果不是丢包率,也不能证明交易所事件身份。

工程上的直接影响是:如果用 id 做跨请求主键,轮询或回补后可能把同一内容重复计入;如果只用时间戳做主键,又可能覆盖同一毫秒内的合法成交。

可先用“证券 + 时间戳 + 价格 + 数量 + 方向”做诊断指纹,以多重集合比较出现次数,而不是直接 set 去重。不同真实成交仍可能拥有相同指纹,因此指纹只能帮助对账,不能替代稳定的交易所事件标识。原始层保留请求批次、连接会话及消息序号;存在歧义的记录留待核查,不静默删除。

把观察写成能复跑的检查

下面是最近窗口的请求示例,按本次读取的官方快速开始使用 X-API-Key。需要有效密钥及相应行情权限;本次真实查询通过连接器完成,下面这条 curl 命令未在本机直接执行。

curl --fail-with-body --get \
  'https://api.tickdb.ai/v1/market/trades' \
  -H "X-API-Key: ${MARKET_API_KEY}" \
  --data-urlencode 'symbol=300308.SZ' \
  --data-urlencode 'type=stock' \
  --data-urlencode 'limit=1000' \
  -o recent-1000.json

再将 limit 改为 100,保存为 recent-100.json。以下 Python 代码比较两份成功响应,以 Decimal 保留十进制数值含义,以 Counter 保留相同内容的出现次数。它是诊断代码,不会修改或去重原始记录。

import json
from collections import Counter
from decimal import Decimal

def read(path):
    with open(path, encoding="utf-8") as f:
        obj = json.load(f)
    if obj.get("code") != 0:
        raise ValueError("Request failed")
    return obj["data"]["trades"]

def key(r):
    return (r["timestamp"], Decimal(r["price"]),
            Decimal(r["quantity"]), r["side"])

a = read("recent-1000.json")
b = read("recent-100.json")
x, y = Counter(map(key, a)), Counter(map(key, b))
print("payload overlap:", sum((x & y).values()))
x = Counter((r.get("id"), key(r)) for r in a)
y = Counter((r.get("id"), key(r)) for r in b)
print("id + payload overlap:", sum((x & y).values()))

对本次保存的两个原始响应提取业务 JSON 后执行,输出分别为 100 和 0。若盘中执行,两次查询之间窗口会前移,应先确认重叠时间范围;较低的重叠数本身不能证明丢失。附件脚本还会统计字段、方向、乱序、重复内容和价格网格异常。

从实时订阅建立可核查的历史

本次核实的实时地址与订阅消息如下。A 股 trade 消息的单笔字段直接位于 data,不能照搬港美股 data.trades 数组的解析方式;文档中的 A 股消息示例也没有可供跨端匹配的 id。这部分已核对文档,未完成在线订阅实测。

import os
from urllib.parse import urlencode

ws_url = "wss://api.tickdb.ai/v1/realtime?" + urlencode({
    "api_key": os.environ["MARKET_API_KEY"]
})
subscription = {
    "cmd": "subscribe",
    "data": {"channel": "trade",
             "symbols": ["300308.SZ", "300502.SZ", "300750.SZ"]}
}
# Pass ws_url and subscription to a WebSocket client.
# Do not print ws_url: it contains a credential.

实际落地时,先保存完整原始消息和接收时间,再生成标准记录。连接成功不等于订阅成功,应记录订阅反馈及首条数据;重新连接后重新订阅,并记录断线区间。原始层与分析层分开,解析失败或未知枚举可以隔离处理,但不能直接丢弃。

历史分析按交易日和会话读取落库记录,先确认缺口,再计算逐分钟记录数、数量和价格统计。在窗口、单位、粒度、会话一致的前提下,比较实时落库与回查结果的记录多重集合;有稳定标识时再检查事件级覆盖。若以 B 为参考窗口、A 为本地窗口,诊断匹配率可以写为 sum(min(A[k], B[k])) / sum(B[k]),但它只是“相对参考窗口的匹配率”。B 也可能缺数据,不能因此称为市场真实完整率。

断线回补尤其受最近 N 条上限约束:如果回查最早时间已经晚于断线开始,说明该窗口不足以验证整个断线区间。应标记不可验证区间,使用已确认的历史数据渠道补足,或排除该区间的完整性敏感分析。不能把重连成功当作历史自动补齐。

这批数据能给出什么结论

当前证据支持三类结论:样本字段与正值检查通过;方向枚举、价格精度表现和跨窗口 ID 稳定性需要适配或进一步核实;全日完整率、交易所原始逐笔粒度、实时数据年龄和实时—历史一致性尚未测得。

对于成交明细展示,这些记录可以用于检查解析与展示逻辑;对于数量、成交额或买卖方向分析,先确认单位与方向定义;对于逐笔回测与订单流分析,还必须取得粒度、完整性和事件身份的证据。数据质量的验收结果应落在具体用途上:哪些检查已经通过,哪些统计受限,哪些区间仍不可验证。

查看相关行情工具

相关文章

新手入门量化投资:用A股港股美股真实数据,手把手教你3步上手

你是不是也经常听到“量化投资”这个词,觉得那是数学天才和程序员才能玩的高端操作? 其实真没那么神秘。今天我就用A股(平安银行)、港股(腾讯)、美股(苹果)的真实数据(见文末截图),带你走一遍量化入门的完整流程。不讲复杂公式,不写代码,只告诉你:量化到底是什么,普通人怎么学,需要什么工具。 --- 一、量化投资,说白了就是“让数据帮你做决定” 很多人炒股靠感觉:“平安银行跌多了,买点。” 但

TickDB Research ·

Python 股票行情 API 实战:用 React 构建实时行情与 K 线面板,支持美股历史数据下载

Python 股票行情 API 实战:用 React 构建实时行情与 K 线面板,支持美股历史数据下载 接入一个行情 API,通常只需要几行请求代码。把 A 股、港股、美股、外汇、黄金、指数和加密资产放进同一个可用的页面,还需要解决另一组问题:代码可能存在歧义,涨跌幅的统计窗口不同,部分品种没有成交量,股票休市后仍然会返回最后一条报价,历史 K 线的最后一根也可能继续变化。 这篇文章用 Re…

TickDB Research ·

跨市场行情应用的涨跌幅:同刻黄金−0.69%还是+0.24%

做跨市场行情App,最容易被用户截图投诉的,是价格旁边那个红绿百分比。同一刻、同一个金价,涨跌可以是−0.69%,也可以是+0.24%。本文拆解涨幅榜、价格提醒、持仓页、首页详情页4个最容易出错的场景,附一张跨市场分母清单。 做跨市场行情App,最容易被用户截图投诉的,往往是价格旁边那个红绿百分比。 2026年10月13日周二,北京时间10:56,黄金4,175.15美元。同一个价格,我按5…

TickDB Research ·

A股美股港股行情看板Demo三天、上线三个月:拆解7个返工点

同一张行情表,寒武纪的成交额自己算是5,414万元,接口给的是54.20亿元,差了100倍,原因只是一个单位。行情看板三天就能接通,上线后的返工,几乎都来自界面上说不清“自己是什么”的数字。 本文依据上交所、港交所的一手文件,加上10月12日盘中对7类资产的实测,给你四样东西: 一张“价格身份证”:每个数字上线前要答的5个问题 7个返工点逐条拆:钱在哪里算错、为什么会错 一份可以直接发给数据…

TickDB Research ·

自选股越来越多,A 股、港股、美股的行情怎么接?

自选股越来越多,A 股、港股、美股的行情怎么接? 每天看自选股,少不了打开行情页面、翻一遍列表,再点进几只股票看看。二三十只还好;要是 A 股、港股、美股都有关注的公司,名单分在几处,来回切换就有点费劲了。 这时很容易冒出一个小想法:做张自己的看板,把几个市场的自选股放在一起,价格、涨跌幅和成交额一起更新,符合条件时提醒一下。工具能先帮自己省下这些重复操作,就已经有了用处。 用着用着,股票池…

TickDB Research ·