4. 逐笔数据源接入与原始校验

逐笔数据管线的一切下游计算——快照重建、指标聚合、异常检测——都建立在“原始逐笔记录可信”这一前提上。如果接入环节把一条字段错位、时间戳倒序或价格精度错误的记录放进了管线,后续再精巧的校验逻辑也只能在错误数据上做二次加工。因此本节聚焦管线最前端的三件事:格式校验、字段完整性检查、初始快照比对。它们共同回答一个问题:这批刚进来的逐笔数据,是否可以被信任并进入后续处理。

一、接入时的格式校验:先确认“能解析”,再谈“对不对”

逐笔数据通常以两种形态到达:交易所或数据商推送的实时流(如基于 TCP 的二进制/文本协议),以及落盘的逐笔成交/逐笔委托文件(CSV、JSON Lines 或自定义二进制)。无论哪种形态,第一步都是结构级校验,即验证记录能否按约定格式被完整切分和解析。

以常见的逐笔成交文本行为例,约定字段顺序为:证券代码, 成交时间, 成交编号, 成交价格, 成交数量, 买卖方向, 通道号。格式校验至少要覆盖以下几点:

  • 字段数量:按分隔符切分后字段数必须等于约定数量,多一个或少一个都说明记录被截断或串行。
  • 类型可转换:价格、数量、时间必须能转换为数值或时间类型;转换失败即判为格式错误。
  • 编码与分隔符:确认字符编码(如 UTF-8/GBK)与分隔符一致,避免中文或特殊字符导致错位。
  • 记录边界:流式接入时,一条记录必须完整结束(换行或长度前缀匹配),防止半包被当作完整记录解析。

实操中建议把格式校验写成“解析即校验”的函数:解析成功返回结构化对象,失败则记录原始行、行号、失败原因,并进入隔离区而不是直接丢弃。这样既保证管线不被脏数据污染,又保留了排查线索。

# 示例:逐笔成交行格式校验(示例参数,非实测)
def parse_tick(line, lineno):
    parts = line.rstrip("\n").split(",")
    if len(parts) != 7:
        return None, f"line {lineno}: 字段数={len(parts)},期望7"
    code, t, trade_id, price, qty, side, chan = parts
    try:
        price = float(price); qty = int(qty)
    except ValueError:
        return None, f"line {lineno}: 数值转换失败"
    if price <= 0 or qty <= 0:
        return None, f"line {lineno}: 价格/数量非正"
    return dict(code=code, time=t, trade_id=trade_id,
                price=price, qty=qty, side=side, chan=chan), None

二、字段完整性检查:区分“缺失”与“非法”

格式能解析,不代表字段内容可用。字段完整性检查要逐字段判断三类问题:空值、越界、枚举非法。以逐笔委托为例,关键字段包括证券代码、委托时间、委托编号、方向、价格、数量、委托类型。检查要点如下:

字段完整性规则(示例)典型异常
证券代码非空,符合市场代码规则(如6位数字+市场后缀)空串、含空格、长度不符
委托时间可解析为 HH:MM:SS 或毫秒时间戳,落在交易时段内时间缺失、超出 09:15–15:00
方向取值属于 {买, 卖} 或约定枚举空值、未知枚举
价格大于0,且符合最小价格变动单位0、负数、精度超限
数量正整数,且为最小交易单位整数倍0、负数、非整倍

这里要特别强调“缺失”与“非法”要分开统计。缺失往往指向接入链路问题(字段没推、截断、映射表缺列),非法则更多指向数据源本身或单位/精度约定不一致。两类问题的处置路径不同:缺失应回查接入配置与协议版本,非法应回查数据源口径与字段映射。把两者混在一个“错误率”里,会让排障失去方向。

建议为每个字段维护一张“完整性规则表”,规则以配置而非硬编码形式存在。当交易所调整字段口径(例如新增委托类型枚举)时,只需更新配置并回归测试,而不必改动解析代码。

三、初始快照比对:用“已知正确”锚定“刚接入”

格式与字段检查只能保证单条记录“长得像对的”,无法发现系统性偏差,例如价格整体放大了100倍、买卖方向被整体颠倒、时间戳统一偏移了时区。这类问题最有效的发现手段是初始快照比对:选取一个已知正确的基准时点(如开盘前快照或上一交易日收盘快照),用接入的逐笔数据从该基准开始重放,重建出目标时点的快照,再与数据源提供的官方快照逐字段比对。

比对的核心是“同口径”:两边必须是同一时点、同一证券范围、同一字段定义。实操中通常比对以下字段:最新价、成交量累计、成交额累计、买一/卖一价量、委托笔数。若重放快照与官方快照在这些字段上一致(在约定容差内),说明接入的逐笔数据在方向和量级上没有系统性错误;若出现整体性偏差,则优先怀疑单位、精度、方向映射或时区。

逐笔数据接入与原始校验链路 交易所/数据商 逐笔成交/委托流 ① 格式校验 字段数/类型/边界 解析失败→隔离区 ② 字段完整性 空值/越界/枚举 缺失与非法分开统计 ③ 初始快照比对 基准快照重放→逐字段比对 发现系统性偏差 隔离区 原始行+行号+原因 基准快照(已知正确) 开盘前/上日收盘 比对判读(示例容差) ✓ 一致:最新价、累计量额、买卖一档在容差内 → 放行 △ 整体偏移:价格×100 / 方向颠倒 / 时区偏移 → 查映射 ✗ 局部缺失:某证券无记录 → 查接入范围与代码表 进入下游管线 快照重建/指标聚合

四、把三项校验串成可执行的接入闸门

三项校验不应各自为政,而应组成一道“接入闸门”:格式校验不过的记录进隔离区;字段完整性检查按字段维度输出缺失率与非法率;快照比对给出整体一致性结论。闸门的放行条件建议明确为:格式错误率低于约定阈值、关键字段缺失率为零、快照比对在容差内一致。任一条件不满足,则阻断下游并输出诊断报告。

下面是一份可直接参考的接入校验记录表,用于每次数据源接入或口径变更后填写:

检查项检查内容示例结果结论
格式校验字段数、类型转换、记录边界10万行中12行字段数异常隔离12行,其余放行
字段完整性空值、越界、枚举非法方向字段空值0,价格越界3条越界记录回查数据源
快照比对最新价、累计量额、买卖一档500只证券中498只一致2只差异需定位
综合判定三项是否同时满足放行条件差异证券已定位为停牌无成交放行
快照比对发现“整体性偏差”时,不要急于修改下游逻辑去“适配”数据。整体偏差几乎总是接入侧的映射或单位问题,例如价格字段被当作“分”而实际是“元”、买卖方向枚举映射反了、时间戳未做时区归一。应先回到字段映射表逐项核对,再重新比对。

最后需要强调一个容易被忽视的点:初始快照比对要保留可复现的基准。基准快照、重放起止时间、比对字段与容差都应记录在案。这样当后续某天发现数据异常时,可以回到最近一次通过的基准重新比对,快速判断问题是“一直存在但没发现”还是“某次变更后引入”。接入环节的严谨,正是整条逐笔数据管线可信度的起点。