数据工程(上):数据源选择与清洗对齐

做量化因子挖掘,数据就是你的原材料。原材料不行,再好的模型也白搭。我见过太多人一上来就调模型参数,结果回测跑得飞起,实盘一塌糊涂——十有八九是数据出了问题。

这一章,咱们就聊聊数据工程的上半场。说白了,就是搞清楚三件事:数据从哪来、怎么洗干净、怎么对齐

一、数据源选择:日频、高频、另类数据

数据源的选择,直接决定了你能挖出什么样的因子。我个人习惯把数据分成三大类:

1. 日频数据

这是最基础的数据源。包括开盘价、收盘价、最高价、最低价、成交量、成交额。A股市场,我一般用Wind或聚宽的数据。美股的话,Yahoo Finance免费但精度一般,QuantQuote付费但质量好。

注意:日频数据看似简单,坑却不少。比如复权问题——前复权还是后复权?我建议用后复权做回测,前复权做实时信号。为什么?后复权不会改变历史价格形态,而前复权会引入未来信息。

核心原则:回测用后复权,实盘用前复权。千万别混用。

2. 高频数据

高频数据,一般指分钟级或Tick级数据。做高频因子,比如订单簿不平衡、微观结构因子,这些数据必不可少。

我在项目中遇到过一个问题:某交易所的Tick数据,时间戳居然有重复。后来发现是撮合引擎的bug。嗯,这里要注意——高频数据一定要做时间戳去重和排序

高频数据的常见来源:

  • 国内:聚宽、米筐、掘金
  • 国外:QuantConnect、Alpaca、Polygon
我的建议:如果刚开始做因子挖掘,别碰高频。先拿日频数据跑通流程,再考虑高频。否则数据量太大,清洗成本会让你崩溃。

3. 另类数据

另类数据,说白了就是非传统金融数据。比如新闻情感、卫星图像、电商销量、招聘数据。这些数据往往能挖出独特的alpha。

举个例子。我曾经用招聘网站的数据,统计某家公司的招聘岗位数量变化。如果研发岗突然暴增,说明公司在扩张,股价大概率要涨。这个因子在科技股上效果不错。

另类数据的难点在于:

  • 结构化程度低:新闻文本、图片,需要NLP或CV处理
  • 频率不固定:有的数据每周更新,有的实时推送
  • 噪声大:信号弱,需要大量预处理

二、数据清洗与对齐

数据清洗,是量化工程师最枯燥但最重要的工作。我常说一句话:脏数据进,脏因子出

1. 常见的数据问题

问题类型 表现 处理方法
缺失值 某天某只股票没有交易数据 向前填充、插值、或直接删除
异常值 价格突然跳涨100倍 用中位数或MAD方法剔除
重复值 同一时间戳出现多条记录 去重,保留最后一条
时间戳错乱 后一条数据的时间早于前一条 排序后检查,删除异常

你想想看,如果某只股票因为停牌导致数据缺失,而你直接用向前填充——那这个因子值就会一直不变,回测里看起来完美,实盘里就是个坑。

我曾经踩过的坑:用pandas的fillna(method='ffill')处理停牌数据。结果停牌期间因子值不变,回测收益高得离谱。后来发现,停牌期间根本不应该有交易信号。正确的做法是:停牌日标记为NaN,计算因子时跳过。

2. 数据对齐

数据对齐,就是把不同频率、不同来源的数据,对齐到同一个时间轴上。这是数据工程里最容易被忽视的一环。

举个例子。你有日频的股票价格数据,还有周频的宏观经济数据。你想把两者合并到一个DataFrame里。怎么做?

import pandas as pd

# 日频数据
price_df = pd.DataFrame({
    'date': pd.date_range('2023-01-01', '2023-12-31', freq='D'),
    'close': np.random.randn(365)
})

# 周频数据
macro_df = pd.DataFrame({
    'date': pd.date_range('2023-01-01', '2023-12-31', freq='W'),
    'gdp_growth': np.random.randn(53)
})

# 对齐:将周频数据向前填充到日频
price_df = price_df.set_index('date')
macro_df = macro_df.set_index('date')

# 合并,使用向前填充
aligned_df = price_df.join(macro_df, how='left')
aligned_df['gdp_growth'] = aligned_df['gdp_growth'].ffill()

这里的关键是向前填充。为什么不是向后填充?因为你在t时刻只能知道t之前的信息。向后填充会引入未来数据,造成未来函数。

三、生存偏差与前瞻偏差

这两个偏差,是回测里最隐蔽的杀手。我见过不少团队,因子回测年化收益30%,实盘直接腰斩。查到最后,都是这两个偏差在作祟。

1. 生存偏差

生存偏差,说白了就是你只用了现在还活着的股票做回测。那些退市的、被ST的股票,都被你忽略了。

你想想看,如果只选活下来的股票,那回测收益肯定偏高。因为那些表现差的股票已经被淘汰了。

如何避免

  • 回测时,必须包含所有曾经存在过的股票
  • 使用退市公司的数据,直到其退市那一天
  • 不要只从当前的中证500或沪深300成分股里选
我的经验:我一般从Wind或CSMAR拉取全A股的历史数据,包括已退市的。虽然数据量大一些,但回测结果更真实。

2. 前瞻偏差

前瞻偏差,就是你在回测时用到了未来才知道的信息。比如用今天的财务数据去预测今天的收益——但财务数据通常要滞后1-2个月才公布。

我曾经犯过一个低级错误:用季报数据做因子,但季报的截止日期是3月31日,实际公布日期可能是4月30日。我直接用了3月31日的数据,结果回测收益高得离谱。后来才发现,4月30日之前,市场根本不知道这些数据。

如何避免

  • 使用数据的实际公布日期,而不是数据截止日期
  • 对于财务数据,建议使用「最新可用」原则
  • 回测时,加入1-2个月的滞后
一个小技巧:在数据集中加入一个「公布日期」字段。回测时,只使用公布日期之前的数据。这样就能彻底避免前瞻偏差。

四、知识体系总览

下面这张图,概括了本章的核心逻辑。你可以把它当作数据工程的检查清单。

数据工程(上)知识体系 数据源选择 日频数据 高频数据 另类数据 数据清洗与对齐 缺失值处理 异常值剔除 时间对齐 偏差控制 生存偏差 前瞻偏差 核心原则:数据质量 > 模型复杂度 先花80%时间搞定数据,再用20%时间调模型

这张图把数据工程拆成了三个模块:数据源选择、数据清洗与对齐、偏差控制。每个模块都有对应的处理方法和注意事项。做因子挖掘之前,建议先对照这张图,检查自己的数据流程是否完整。

好了,数据工程的上半场就聊到这儿。记住一句话:数据干净了,因子就成功了一半。下一章,咱们接着聊数据工程的下半场——特征工程与数据存储。


公众号:蓝海资料掘金营,微信deep3321