数据准备:获取股票行情数据,清洗与对齐

做多因子策略,数据就是你的弹药。弹药不行,枪法再好也白搭。

我个人习惯把数据准备分成三步:获取、清洗、对齐。这三步走扎实了,后面的因子合成才能放心跑。今天咱们就聊聊这块。

一、获取行情数据:日线与分钟线

先说说数据源。我常用的有 tushare、akshare、baostock 这几个库。免费、够用,个人研究完全没问题。

举个例子,用 akshare 拿日线数据,代码很简单:

import akshare as ak

# 获取平安银行日线数据
df = ak.stock_zh_a_hist(symbol="000001", period="daily", 
                         start_date="20200101", end_date="20231231")
print(df.head())

分钟线呢?我个人建议用 period="1"period="5" 参数。注意,分钟线数据量很大,一次别拉太久。我一般一次拉一个月,分批处理。

小提示: 分钟线数据,交易所只保留最近几年的。想回测2015年的分钟策略?抱歉,得找第三方数据商买。

二、数据清洗:处理缺失值与异常值

数据拿到手,第一件事不是算因子,而是清洗。我在项目中遇到过好几次,因为没清洗数据,回测曲线漂亮得像假的,实盘一跑就崩。

2.1 缺失值处理

缺失值常见原因:停牌、新股上市、数据源漏了。怎么处理?看情况:

  • 停牌导致的缺失:用前一天的收盘价填充。说白了,停牌期间价格不变。
  • 新股上市前:直接删除。没有数据,硬填没意义。
  • 数据源漏了:用前后两天的均值插值。我习惯用 df.interpolate()
# 用前向填充处理停牌
df['close'].fillna(method='ffill', inplace=True)

# 用线性插值处理小范围缺失
df['close'].interpolate(method='linear', inplace=True)
注意: 千万别用均值填充!股票价格不是平稳序列,用整体均值填充会引入巨大偏差。我曾经见过有人这么干,回测收益直接翻倍——假的。

2.2 异常值处理

异常值怎么判断?我一般用两种方法:

  1. 3σ 原则:超过均值±3倍标准差的值,视为异常。
  2. 百分位法:低于1%分位或高于99%分位的值,直接截断。

你想想看,如果某天某只股票涨了50%,但大盘没动,这大概率是数据错误。我习惯用百分位法,更稳健。

# 百分位截断
def winsorize_series(s, lower=0.01, upper=0.99):
    q_low = s.quantile(lower)
    q_high = s.quantile(upper)
    return s.clip(q_low, q_high)

df['pct_chg'] = winsorize_series(df['pct_chg'])

三、数据对齐:让不同股票站在同一起跑线

这一步很关键,但很多人会忽略。不同股票的交易日期不一样——有的停牌,有的刚上市。如果不做对齐,因子计算会出问题。

举个例子:你想算所有股票当天的收益率。但A股票停牌了,B股票正常交易。如果不处理,A的收益率就是NaN,后面算因子时整个截面就乱了。

我的做法是:先构建一个统一的交易日历,然后左连接所有股票数据。

# 构建交易日历(取所有股票交易日的并集)
trade_dates = pd.date_range(start='2020-01-01', end='2023-12-31', freq='B')
trade_calendar = pd.DataFrame(trade_dates, columns=['date'])

# 对齐:左连接
df_aligned = trade_calendar.merge(df, on='date', how='left')

# 缺失的交易日,用前一天的收盘价填充
df_aligned['close'].fillna(method='ffill', inplace=True)
核心要点: 数据对齐的本质是让所有股票在同一个时间截面上有值。做不到这一点,多因子模型就是空中楼阁。

四、知识体系总览

下面这张图,是我自己总结的数据准备流程。你看一眼,心里就有谱了。

数据准备流程 获取行情数据 日线 / 分钟线 数据清洗 缺失值 → 填充/删除 数据对齐 统一交易日历 异常值检测 3σ 原则 百分位法 缺失值处理 前向填充 线性插值 对齐方法 左连接 前向填充 输出:干净、对齐的行情数据

五、避坑指南

最后,分享几个我踩过的坑:

  • 复权问题:日线数据一定要用后复权。前复权会导致历史价格被修改,回测结果失真。我曾经用前复权跑回测,收益曲线漂亮得不行,一查发现是复权方式搞错了。
  • 分钟线的时间戳:不同数据源的时间格式不一样。有的用东八区,有的用UTC。对齐前先统一时区,不然数据会错位。
  • 停牌复牌:复牌当天,股价经常跳空。这时候用前向填充没问题,但要注意跳空带来的因子突变。我一般会在复牌后第一天,把因子值重新计算一遍。
我的习惯: 每次清洗完数据,我都会画一张缺失值热力图。一眼就能看出哪些股票、哪些时间段数据有问题。省时省力。

数据准备这块,说白了就是「脏活累活」。但你别嫌烦,这一步做扎实了,后面的因子合成、策略回测才能放心跑。嗯,今天就聊到这儿。


蓝海数据掘金营,专注资料整理