数据获取与清洗:打好因子分析的地基

做量化投资,有一句话我特别认同:垃圾进,垃圾出。你因子模型再漂亮,回测框架再炫酷,数据一塌糊涂,结果就是自欺欺人。

今天咱们就聊聊数据获取与清洗。这部分活儿看着不起眼,但我在项目里吃过不少亏。有一次,就因为某只股票停牌后数据没处理好,整个多因子组合的回测结果都偏了。嗯,从那以后,我对数据清洗再也不敢马虎。

1. 用pandas-datareader拉数据

我个人习惯用 pandas-datareader 来获取股票数据。它支持多个数据源,比如雅虎财经、FRED等。不过要注意,雅虎财经的接口偶尔会抽风,我建议你备个本地数据源。

import pandas as pd
import pandas_datareader.data as web
import datetime

# 设置时间范围
start = datetime.datetime(2020, 1, 1)
end = datetime.datetime(2023, 12, 31)

# 获取股票数据
ticker = 'AAPL'
df = web.DataReader(ticker, 'yahoo', start, end)

print(df.head())

你看,代码很简单。但实际项目中,你可能会同时拉几百只股票。这时候我建议用循环加异常处理,防止某只股票数据缺失导致整个程序崩溃。

小技巧: 如果数据源不稳定,可以加个重试机制。我一般用 time.sleep(1) 避免被服务器封IP。

2. 处理缺失值:别让空值毁了你的因子

数据拉下来后,第一件事就是检查缺失值。你想想看,如果某天某只股票停牌了,那天的价格就是NaN。直接扔掉?不一定。

# 检查缺失值
print(df.isnull().sum())

# 前向填充:用前一天的数据填充
df.fillna(method='ffill', inplace=True)

# 后向填充:用后一天的数据填充(一般用于开头缺失)
df.fillna(method='bfill', inplace=True)

为什么用前向填充?因为股票数据有连续性。今天停牌,明天复牌,价格通常跟前一天差不多。但要注意,如果连续停牌好几天,前向填充可能会失真。我遇到过一只股票停牌一个月,复牌后直接跳空,前向填充的数据完全不能用。

避坑指南: 我曾经因为没处理停牌数据,导致因子计算时出现极端值。后来我加了个规则:连续停牌超过5天,直接标记为异常,不参与因子计算。

3. 去极值处理:MAD方法

因子数据里经常有极端值。比如某只股票突然暴涨,市盈率变成几千倍。这种数据如果不处理,会严重扭曲你的因子组合。

我常用的方法是MAD(Median Absolute Deviation)。它比标准差更稳健,不容易被极端值带偏。

import numpy as np

def mad_detection(series, n=3):
    """
    MAD去极值方法
    n: 阈值倍数,默认3倍
    """
    median = series.median()
    mad = np.median(np.abs(series - median))
    # 计算MAD的修正系数
    modified_z_scores = 0.6745 * (series - median) / mad
    # 标记异常值
    outliers = np.abs(modified_z_scores) > n
    return outliers

# 示例:对市盈率因子去极值
pe_ratio = df['Close'] / df['Close'].shift(1)  # 假设这是市盈率
outliers = mad_detection(pe_ratio.dropna())

# 将异常值替换为中位数
pe_ratio_clean = pe_ratio.copy()
pe_ratio_clean[outliers] = pe_ratio.median()

这里有个细节:MAD的阈值n怎么选?我一般用3倍。但如果你发现数据噪声很大,可以放宽到4倍。反之,如果因子本身很稳定,2.5倍也行。这个得根据实际情况调。

核心要点: MAD方法的核心思想是用中位数代替均值,用绝对偏差代替标准差。这样即使数据里有几个极端值,也不会影响整体判断。

4. 数据清洗的整体流程

说了这么多,咱们把整个流程串起来。我画了个图,方便你理解。

数据获取与清洗流程 1. 数据获取 pandas-datareader 2. 缺失值处理 前向/后向填充 3. 去极值处理 MAD方法 数据源:雅虎、FRED等 注意停牌、节假日 阈值n=3倍MAD 最终输出:干净因子数据

这个流程看着简单,但每一步都有坑。我建议你每次处理完数据后,都做个简单的可视化检查。比如画个分布图,看看有没有异常值没处理干净。

5. 实战中的注意事项

最后,分享几个我在实战中总结的经验:

  • 数据频率要统一:日频数据就用日频,别混入周频或月频。我见过有人把日频和月频数据混在一起算因子,结果相关性全乱了。
  • 注意复权处理:股票有分红送股,价格会变化。我建议用后复权数据,这样历史价格才有可比性。
  • 保存原始数据:清洗前先备份一份原始数据。万一清洗逻辑出问题,还能回滚。这个习惯救过我很多次。
  • 批量处理时加日志:处理几百只股票时,加个日志记录每只股票的处理情况。哪只股票数据有问题,一目了然。
我的习惯: 每次清洗完数据,我都会生成一个数据质量报告。包括缺失率、异常值数量、数据时间跨度等。这样后续分析时心里有底。

好了,数据获取与清洗这部分就聊到这儿。记住,数据是量化投资的基石。你花在清洗上的每一分钟,都会在后续的因子分析和回测中得到回报。

专注资料整理