数据基础设施:行情数据获取与清洗
做量化研究,最怕什么?
不是策略不赚钱,而是数据有问题。我见过太多人,花几个月写了个漂亮的因子,结果回测曲线完美,实盘一跑就崩——最后发现是数据没对齐。
今天咱们就把数据基础设施这块彻底讲透。说白了,这是所有Alpha因子的地基。地基不稳,楼盖得再高也得塌。
一、行情数据获取:日线与分钟线
行情数据分两种:日线和分钟线。我个人习惯把日线叫「慢数据」,分钟线叫「快数据」。两者用途完全不同。
1. 日线数据
日线是基础中的基础。包含:开盘价、最高价、最低价、收盘价、成交量、成交额。
获取渠道我列一下:
- 免费源:Tushare、AKShare、Baostock
- 付费源:Wind、Choice、聚宽、米筐
- 自建源:从交易所原始数据解析(不推荐,太折腾)
我在项目中遇到过一个问题:免费数据经常缺字段。比如某天某只股票的成交量突然为0,但实际是停牌。如果你不做处理,因子计算直接崩掉。
2. 分钟线数据
分钟线我一般用5分钟和30分钟。为什么?
- 5分钟:捕捉日内波动,适合高频因子
- 30分钟:兼顾日内信息和噪声过滤
获取分钟线有个坑:不同数据源的分钟线「对齐方式」不一样。有的按自然时间切,有的按交易时间切。你想想看,如果9:31的数据被算到9:30这根K线里,那你的因子就偏了。
二、财务数据清洗:比想象中麻烦
财务数据,说白了就是上市公司的三张表:资产负债表、利润表、现金流量表。
但你以为直接拿来用就行?太天真了。
常见脏数据问题
| 问题类型 | 表现 | 处理方法 |
|---|---|---|
| 缺失值 | 某期净利润为空 | 前向填充(ffill)或行业均值填充 |
| 异常值 | 毛利率>100%或<0% | 截断处理或标记为缺失 |
| 口径变更 | 会计准则调整导致数据不连续 | 按最新口径回溯调整 |
| 合并报表 vs 母公司报表 | 两个口径数据混在一起 | 统一使用合并报表数据 |
我曾经踩过一个坑:用净利润算ROE,结果某公司突然净利润暴涨10倍。一查,原来是卖了一套房产。这种非经常性损益如果不剔除,你的因子就是假的。
三、复权处理:前复权还是后复权?
这个问题,我每次讲课都有人问。直接说结论:
- 做因子研究:用后复权
- 做回测交易:用前复权
为什么?
后复权保留了历史价格的真实涨幅。你想想看,如果你用前复权,10年前的价格可能变成负数——这还怎么算因子?
但回测时,前复权更贴近实际交易场景。因为你在回测时只能看到「当前视角下的历史价格」。
复权代码示例
import pandas as pd
import numpy as np
def adjust_price(df, method='forward'):
"""
df: 包含 close, adj_factor 的DataFrame
method: 'forward' 前复权, 'backward' 后复权
"""
if method == 'forward':
# 前复权:用最新复权因子调整历史价格
latest_adj = df['adj_factor'].iloc[-1]
df['adj_close'] = df['close'] * df['adj_factor'] / latest_adj
elif method == 'backward':
# 后复权:用最早复权因子调整所有价格
first_adj = df['adj_factor'].iloc[0]
df['adj_close'] = df['close'] * df['adj_factor'] / first_adj
return df
四、数据对齐与频率转换
这是最容易被忽视的环节。我把它叫做「数据对齐的艺术」。
1. 时间对齐
不同数据源的时间戳可能不一样。比如:
- 行情数据:精确到毫秒
- 财务数据:精确到天
- 因子数据:精确到分钟
对齐原则很简单:高频向低频对齐。比如你要做日频因子,就把分钟线聚合成日线,而不是把日线拆成分钟线。
2. 频率转换
频率转换有三种方式:
| 转换方向 | 方法 | 适用场景 |
|---|---|---|
| 高频→低频 | 聚合(OHLCV) | 分钟线转日线 |
| 低频→高频 | 填充(ffill/bfill) | 财务数据转日频 |
| 等频→等频 | 重采样 | 5分钟转15分钟 |
嗯,这里要注意:低频转高频时,千万别用插值法。财务数据是离散的,插值出来的数字毫无意义。老老实实用前向填充。
五、知识体系总览
下面这张图,是我做数据基础设施时的核心逻辑。你可以把它当作一个检查清单:
这张图我每次做新项目都会贴墙上。从左到右,从上到下,每一步都不能跳过。