一、行情数据概览:为什么需要多市场数据清洗?
说实话,我刚入行那会儿,也天真地以为行情数据就是「拿来就用」的东西。
直到有一次,我同时接了三个交易所的 BTC 数据——一个用毫秒时间戳,一个用微秒,还有一个干脆把时间戳写成了字符串。嗯,那天的对齐工作,让我加班到凌晨三点。
所以这节课,我想跟你聊聊:为什么多市场数据清洗是绕不开的坎?
1.1 多市场数据的「脏」到底在哪?
你想想看,不同交易所、不同数据源,它们的数据格式、精度、缺失情况,简直像三个不同国家的人说三种方言。
我总结了几类最常见的「脏数据」:
- 时间戳不统一:有的用 UTC,有的用本地时间,有的甚至不带时区信息。
- 精度差异:A 交易所价格保留 2 位小数,B 交易所保留 8 位。对齐时直接截断?那精度损失你扛得住吗?
- 缺失值:某个品种在某段时间内没有交易,数据源直接留空,或者填了个 0。0 和缺失,在回测里可是天壤之别。
- 重复数据:同一个 tick 被推送了两次,或者 CSV 文件里出现了完全相同的行。
- 异常值:比如价格突然跳了 100 倍,明显是数据错误。我见过有人没做清洗,直接拿这种数据跑策略,结果回测曲线美如画,实盘亏成狗。
核心观点:多市场数据清洗,不是为了「干净」而干净,而是为了后续的策略回测、风险分析能站得住脚。数据不干净,模型再牛也是白搭。
1.2 常见数据源及其特点
做量化交易,你绕不开这三种数据源。我一个个说。
1. 交易所 API
这是最直接的方式。实时性高,数据新鲜。但问题也不少:
- 限流:很多交易所对 API 调用次数有限制。你想想看,如果你同时拉 10 个品种的深度数据,一不小心就被封了。
- 数据格式不统一:REST API 返回 JSON,WebSocket 推送的是二进制流。解析起来各有各的坑。
- 断连风险:网络波动、交易所维护,都可能让你丢数据。我习惯在本地做一层缓存,防止断连后数据断层。
我的小技巧:拉 API 数据时,一定要记录请求时间戳和响应时间戳。这样即使数据本身的时间戳有问题,你还能用本地时间做参考。
2. CSV 文件
很多数据供应商会提供历史数据的 CSV 导出。优点是结构简单,容易处理。但坑也不少:
- 编码问题:有的 CSV 是 UTF-8,有的是 GBK。我遇到过用 Excel 打开乱码,结果整列数据都错位的情况。
- 分隔符不统一:有的用逗号,有的用制表符,有的甚至用分号。你写解析器时得留个心眼。
- 表头缺失或重复:有些 CSV 文件第一行是注释,第二行才是表头。还有些文件在中间插入了空行。
# 一个典型的 CSV 解析陷阱
# 文件内容:
# Date,Open,High,Low,Close,Volume
# 2024-01-01,100.5,101.2,99.8,100.9,10000
# ,,,,,
# 2024-01-02,101.0,102.1,100.3,101.5,12000
# 注意第二行全是空值,如果不处理,pandas 会把它当成有效数据
import pandas as pd
df = pd.read_csv('data.csv')
df = df.dropna(how='all') # 去掉全空行
3. 数据库
专业团队会用数据库来存储行情数据。常见的有 InfluxDB(时序数据库)、PostgreSQL(关系型)、MongoDB(文档型)。
- InfluxDB:天生为时序数据设计,查询快,但做复杂 join 很痛苦。
- PostgreSQL:支持事务,数据一致性高。但写入大量 tick 数据时,性能可能成为瓶颈。
- MongoDB:灵活,适合存储非结构化的行情数据(比如深度快照)。但查询效率不如 InfluxDB。
注意:从数据库取数据时,别忘了检查索引。我曾经从 PostgreSQL 里拉一年的分钟线数据,没加索引,结果跑了 20 分钟。加了索引后,3 秒搞定。
1.3 知识体系总览
下面这张图,是我自己梳理的多市场数据清洗核心逻辑。你可以把它当作本章的「地图」:
说白了,不管数据从哪来,最终都要经过清洗层,变成一套标准化的数据。这样你才能放心地拿去跑策略、做分析。
1.4 避坑指南:我踩过的三个坑
最后,分享几个我亲身经历过的教训:
- 坑一:时间戳的时区问题。我曾经从两个交易所拉数据,一个用 UTC+0,一个用 UTC+8。直接合并后,发现策略信号总是「提前」或「滞后」了 8 小时。后来我强制所有数据统一转成 UTC 时间戳,才解决。
- 坑二:CSV 里的隐藏字符。有一次我读 CSV 文件,发现某列数据总是多了一个不可见的换行符。排查了半天,才发现是文件末尾的 BOM 头在作怪。从那以后,我读 CSV 都会加一句
encoding='utf-8-sig'。 - 坑三:API 返回的「0」不是真的 0。有些交易所,当某个价格没有更新时,会返回 0 而不是 null。如果你不做区分,回测时就会以为价格真的跌到了 0,然后触发一堆错误的交易信号。
一句话总结:多市场数据清洗,本质上是在跟「不确定性」做斗争。你每多处理一个细节,后续的分析就多一分可靠。