第1章:数据源与数据清洗

做因子挖掘这么多年,我最大的感触就是——数据决定上限,模型只是逼近这个上限。说白了,你数据是垃圾,再牛的因子也白搭。今天咱们就从最基础的数据源和数据清洗聊起。

1.1 常见数据源

我个人习惯把数据源分成三类:行情数据、财务数据、另类数据。这三类各有各的脾气,处理方式也完全不同。

行情数据

这是最基础的数据。包括日线、分钟线、Tick级数据。我刚开始做量化时,以为行情数据就是K线那几列,后来发现坑多着呢。

  • 日线数据:开高低收、成交量、成交额。注意复权问题,前复权和后复权差别很大。
  • 分钟数据:5分钟、15分钟、30分钟。我遇到过分钟数据时间戳不对齐的问题,后来发现是交易所撮合机制导致的。
  • Tick数据:逐笔成交。这个数据量巨大,一天下来几个G很正常。
我的经验:行情数据最好从Wind、聚宽、Tushare这些平台拿。别自己爬,容易被封IP不说,数据质量也没保证。

财务数据

财务数据是因子挖掘的富矿。但这里有个大坑——财务数据发布有滞后性。比如一季报要在4月底前发布,但你3月份做因子时,用的还是去年的数据。

  • 资产负债表:总资产、净资产、负债率
  • 利润表:营收、净利润、毛利率
  • 现金流量表:经营现金流、投资现金流
注意:财务数据一定要做「对齐处理」。比如2024年4月的数据,实际对应的是2023年年报。我曾经因为没对齐,回测结果漂亮得不行,实盘直接崩了。

另类数据

这个就五花八门了。新闻舆情、电商数据、卫星图像、甚至信用卡消费数据。我有个朋友专门做「上市公司食堂外卖订单量」的因子,据说效果还不错。

  • 舆情数据:新闻情感分析、社交媒体热度
  • 产业链数据:上下游价格、库存数据
  • 宏观数据:GDP、CPI、PMI

1.2 数据缺失值处理

数据缺失是家常便饭。你想想看,A股有停牌、有新股上市、有退市,数据怎么可能完整?

缺失值类型

类型 原因 处理方式
完全随机缺失 数据采集故障 直接删除或插值
随机缺失 停牌、节假日 前向填充
非随机缺失 退市、ST 需谨慎处理

处理策略

我个人习惯用这几种方法:

  1. 删除法:缺失比例超过50%的字段,直接删掉。别心疼,留着也是噪音。
  2. 前向填充:用上一个有效值填充。适合行情数据,比如停牌期间用停牌前价格。
  3. 插值法:线性插值或多项式插值。适合财务数据,比如季度数据之间的月份。
  4. 模型预测:用其他字段预测缺失值。这个比较重,一般不用。
# 前向填充示例
import pandas as pd

df['close'].fillna(method='ffill', inplace=True)

# 线性插值
df['revenue'].interpolate(method='linear', inplace=True)
避坑指南:我曾经在回测时用了前向填充,结果停牌复牌后直接跳空,因子值突变,回测曲线漂亮得不像话。后来发现是填充逻辑没处理好复牌当天的数据。

1.3 异常值检测与处理

异常值这东西,说白了就是数据里的「刺头」。可能是数据录入错误,也可能是真实的极端行情。

检测方法

  • 3σ原则:超过均值±3倍标准差的值视为异常。适合正态分布的数据。
  • 箱线图法:超过1.5倍IQR的值视为异常。这个更稳健,不受极端值影响。
  • MAD法:中位数绝对偏差。我比较喜欢这个,对异常值不敏感。
# MAD法检测异常值
import numpy as np

def detect_outliers_mad(data, threshold=3.5):
    median = np.median(data)
    mad = np.median(np.abs(data - median))
    modified_z_scores = 0.6745 * (data - median) / mad
    return np.abs(modified_z_scores) > threshold

处理策略

检测到异常值后怎么办?我的建议是:

  1. 先分析原因:是数据错误还是真实事件?比如2015年股灾时的极端波动,那是真实事件,不能删。
  2. 截尾处理:将异常值替换为上下限值。比如用99%分位数替换。
  3. 分箱处理:将连续值离散化,减少极端值影响。
注意:千万别一刀切地删除所有异常值。我记得有一次做波动率因子,把2015年股灾的数据全删了,结果因子在正常行情下表现很好,但一遇到波动就失效。

1.4 数据对齐与重采样

数据对齐是特征工程里最容易被忽视的环节。你想想看,日线数据是每天一条,财务数据是每季度一条,舆情数据可能每分钟一条。怎么对齐?

时间对齐

我一般用「向后对齐」原则。比如财务数据发布日,对齐到发布日之后的第一个交易日。这样能避免未来信息泄露。

# 财务数据对齐到交易日
financial_data.index = financial_data.index + pd.offsets.BDay(1)

频率对齐

不同频率的数据要统一。我的习惯是:

  • 高频转低频:用聚合函数,比如分钟数据转日线用收盘价。
  • 低频转高频:用插值或前向填充。比如季度财务数据转月度,用前向填充。

重采样技巧

Pandas的resample函数很强大,但要注意边界问题。

# 日线转周线
weekly_data = daily_data.resample('W').agg({
    'open': 'first',
    'high': 'max',
    'low': 'min',
    'close': 'last',
    'volume': 'sum'
})
我的习惯:重采样时一定要检查边界。比如周线是从周一开始还是周日开始?不同交易所的交易日历不一样,A股和港股就有差异。

知识体系总览

下面这张图是我自己整理的,把本章的核心逻辑串起来了。你看一眼就能明白数据从哪来、怎么洗、怎么对齐。

数据源与数据清洗知识体系 数据源 行情数据 财务数据 另类数据 数据清洗 缺失值处理 异常值检测 数据对齐 特征工程 因子构建 特征选择 模型输入 缺失值处理策略 删除法 缺失>50%直接删 前向填充 停牌数据用ffill 插值法 线性/多项式插值 模型预测 复杂场景使用 异常值检测方法 3σ原则 正态分布适用 箱线图法 1.5倍IQR MAD法 中位数绝对偏差

嗯,数据清洗这块就这些。别小看这些基础工作,我见过太多人因子做得花里胡哨,结果数据源都没搞干净,回测和实盘完全是两码事。记住一句话:数据干净了,因子就成功了一半。

专注资料整理