3. 多源数据接入

多源行情交叉校验的第一步,不是写校验规则,而是把不同来源的数据稳定、可追溯地接进来。接入层如果设计得粗糙,后续的差异比对就会变成“在噪声里找信号”。本节围绕行情源类型、接入通道、实时与历史获取、落地与初步清洗四个环节展开,目标是让每一行数据都能回答三个问题:来自哪里、什么时候到的、经过了哪些处理。

一、主流行情源的类型与特征

行情源可以按“授权与分发方式”分为交易所直连、券商柜台、专业数据商和公开接口四类。它们的延迟、字段完整度、复权处理和稳定性差异很大,直接决定了校验策略。

类型典型代表延迟量级字段特点接入难点
交易所直连Level-1/Level-2 行情毫秒级逐笔、盘口完整授权成本高、专线要求
券商柜台柜台行情转发百毫秒级含账户相关字段接口协议私有、限流
专业数据商Wind、聚源等秒级至分钟级清洗好、含复权因子按量计费、字段口径差异
公开接口财经网站、开源库秒级至延迟字段少、易缺失稳定性差、无SLA

选择源时不要只看“快”,而要看“口径是否可对齐”。例如同一只股票的收盘价,交易所直连是未复权原始价,数据商可能已做前复权,两者直接比对必然产生大量伪差异。因此接入阶段就要记录每个源的复权口径、时区、货币单位和字段语义。

二、API与文件两种接入方式

API 接入适合实时和准实时场景,文件接入适合历史回补和批量校验。两者在工程实现上要区别对待。

API 接入的核心是连接管理、限流与重试。以 REST 行情接口为例,典型调用如下:

GET /v1/quote?symbol=600519.SH&fields=last,open,high,low,volume,ts
Headers:
  Authorization: Bearer <>
  X-RateLimit: 100/s

响应:
{
  "symbol": "600519.SH",
  "last": 1688.00,
  "open": 1670.00,
  "high": 1695.50,
  "low": 1665.20,
  "volume": 3214500,
  "ts": "2024-06-11T14:30:00+08:00"
}

文件接入常见 CSV、Parquet 和二进制快照。CSV 可读性好但类型易丢失,Parquet 适合列式批量分析。无论哪种,都要在落地时保留原始文件与校验和,便于回溯。

建议为每个源建立独立的接入配置:源标识、协议、地址、认证方式、限流参数、字段映射表、时区、复权口径。配置即文档,避免口头约定。

三、实时与历史数据的获取策略

实时数据追求低延迟与顺序性,历史数据追求完整性与一致性。二者不能共用同一套落地逻辑。

  • 实时获取:采用长连接或轮询,维护心跳与断线重连;按 symbol 分区消费,保证同一标的的消息有序。
  • 历史获取:按交易日或时间窗口分页拉取,记录已拉取区间,支持断点续传;对缺失交易日做补拉。
  • 对齐时间:统一转换为 UTC 或交易所本地时区,并保留原始时间戳字段。
  • 去重:以“源+标的+时间戳+字段”为幂等键,重复消息直接丢弃或覆盖。

下面是一个实时接入的伪代码结构,体现重连与幂等落库:

while not stopped:
    conn = connect(source)
    while conn.alive:
        msg = conn.recv()
        key = (source, msg.symbol, msg.ts)
        if not seen(key):
            raw_store.write(msg)
            seen.add(key)
    sleep(backoff)
    backoff = min(backoff * 2, 30)

四、数据落地与初步清洗

落地层建议采用“原始层 + 清洗层”两层结构。原始层只追加、不改写,保留源格式;清洗层做类型转换、字段标准化和基础校验。这样即使清洗规则调整,也能从原始层重放。

初步清洗至少包含以下动作:

  1. 类型转换:价格转 decimal,成交量转整型,时间转标准时间戳。
  2. 字段映射:把各源字段统一到内部 schema,如 last_price、open_price、volume。
  3. 空值与异常过滤:价格小于等于零、成交量负值、时间戳越界直接标记为可疑。
  4. 单位统一:手与股、元与分、百分比与小数统一换算。
  5. 打标:为每条记录附加 source_id、ingest_time、batch_id,便于后续差异定位。
常见误区:在接入阶段就做“修正”。例如发现某源价格异常就手动改掉,这会掩盖源本身的差异,导致后续交叉校验失去意义。接入层只做标记,不做业务修正。

下面是一段清洗日志示例,展示可疑记录的标记方式:

2024-06-11 14:30:01 INFO  ingest source=api_a symbol=600519.SH last=1688.00 status=ok
2024-06-11 14:30:01 WARN  ingest source=file_b symbol=000001.SZ last=-1.00 status=suspect reason=price_non_positive
2024-06-11 14:30:02 INFO  ingest source=api_c symbol=600519.SH last=1688.00 status=ok batch=20240611_1430

完成上述步骤后,数据才具备进入交叉校验的条件。接入层的质量直接决定差异修复的效率:源标识清晰、时间对齐、口径明确、异常有标记,后续的比对才能聚焦在真正的数据差异上,而不是反复排查接入噪声。

多源行情接入:从源到可校验数据 交易所直连 毫秒级 · 逐笔 券商柜台 百毫秒 · 私有协议 专业数据商 秒级 · 含复权 公开接口 延迟 · 无SLA 接入通道 API 拉取 限流 · 重试 · 心跳 文件导入 CSV · Parquet 实时 / 历史 分区 · 断点续传 原始层 只追加 · 保留源格式 校验和 · batch_id 清洗层 类型 · 映射 · 单位 异常打标 · 不修正 可校验数据 源标识 · 时间对齐 口径明确 接入层只做标记与标准化,不做业务修正