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)
四、数据落地与初步清洗
落地层建议采用“原始层 + 清洗层”两层结构。原始层只追加、不改写,保留源格式;清洗层做类型转换、字段标准化和基础校验。这样即使清洗规则调整,也能从原始层重放。
初步清洗至少包含以下动作:
- 类型转换:价格转 decimal,成交量转整型,时间转标准时间戳。
- 字段映射:把各源字段统一到内部 schema,如 last_price、open_price、volume。
- 空值与异常过滤:价格小于等于零、成交量负值、时间戳越界直接标记为可疑。
- 单位统一:手与股、元与分、百分比与小数统一换算。
- 打标:为每条记录附加 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
完成上述步骤后,数据才具备进入交叉校验的条件。接入层的质量直接决定差异修复的效率:源标识清晰、时间对齐、口径明确、异常有标记,后续的比对才能聚焦在真正的数据差异上,而不是反复排查接入噪声。