3、数据获取与准备:数据源选择(A股/美股)、Pandas基础、数据清洗与对齐、复权价格处理

做量化投资,有一句老话叫「垃圾进,垃圾出」。你策略再牛,模型再炫,数据源出了问题,一切都是白搭。我个人习惯把数据获取和清洗看作整个因子投资流程的「地基工程」——地基没打牢,后面盖的楼越高,塌得越快。

这一章,我们就来聊聊这个地基怎么打。我会从数据源的选择讲起,然后带你过一遍 Pandas 的基础操作,最后重点说说数据清洗、对齐和复权处理。嗯,这些都是我踩过无数坑之后总结出来的经验。

3.1 数据源选择:A股 vs 美股

选数据源,说白了就是选「食材」。你要做川菜,得买辣椒;你要做粤菜,得买鲜虾。A股和美股的数据特点完全不同,我分别说说。

A股数据源

  • Wind(万得):国内机构标配,数据全,但贵。个人用户基本用不起。
  • 聚宽(JoinQuant):回测平台自带数据,免费版够用,但导出有限制。
  • Tushare:开源社区维护,免费但需要积分,数据质量参差不齐。
  • AKShare:完全免费,接口丰富,适合个人研究。我最近比较喜欢用这个。
注意:A股数据有个坑——停牌、涨跌停、ST 股票的处理。我曾经因为没过滤 ST 股票,回测结果漂亮得不行,实盘直接被打脸。一定要在数据清洗阶段把这些股票剔除掉。

美股数据源

  • Yahoo Finance(yfinance):免费,接口简单,适合快速获取。但数据有时会缺失,尤其是分红、拆股信息。
  • Alpha Vantage:免费但有调用次数限制,一天500次,个人够用。
  • Quandl:数据质量高,但很多数据集要付费。
  • IB(盈透证券)API:实时数据,适合高频交易。我一般用这个做实盘。

你想想看,选数据源其实就是在「成本」和「质量」之间做权衡。我个人建议:初期研究用免费源(AKShare 或 yfinance),等策略成熟了再上付费数据。

3.2 Pandas 基础:你每天都要用的工具

Pandas 是 Python 量化投资的「瑞士军刀」。你几乎所有的数据操作都离不开它。我不打算讲全部 API,只挑几个最常用的说。

核心数据结构

  • Series:一维数组,带标签。可以理解为 Excel 里的一列。
  • DataFrame:二维表格,带行索引和列索引。这就是你每天打交道的「数据表」。

常用操作

import pandas as pd
import numpy as np

# 读取 CSV 文件
df = pd.read_csv('stock_data.csv', parse_dates=['date'], index_col='date')

# 查看前5行
print(df.head())

# 查看数据基本信息
print(df.info())

# 缺失值处理
df = df.dropna()  # 删除缺失行
# 或者用前向填充
df = df.fillna(method='ffill')

# 选择列
close = df['close']

# 条件筛选
high_volume = df[df['volume'] > 1e7]

# 分组操作
grouped = df.groupby('stock_code').apply(lambda x: x.sort_index())
小技巧:我习惯在读取数据时就把日期列设为索引,这样后续的时间序列操作会方便很多。另外,df.info() 是我最常用的调试命令——一眼就能看出数据有没有缺失、类型对不对。

3.3 数据清洗与对齐:别让脏数据毁了你的策略

数据清洗,说白了就是「去伪存真」。我从多个数据源拿到的数据,格式、频率、时间范围都不一样,必须对齐才能用。

常见的数据问题

  1. 缺失值:停牌日、节假日、数据源本身缺失。
  2. 异常值:价格突然跳变、成交量异常放大。
  3. 重复值:同一时间戳出现多条记录。
  4. 时间戳不对齐:A股和美股交易时间不同,跨市场策略尤其要注意。

清洗流程

# 1. 删除重复行
df = df.drop_duplicates()

# 2. 处理缺失值
# 对于价格数据,我一般用前向填充
df['close'] = df['close'].fillna(method='ffill')
# 对于成交量,如果缺失就填0
df['volume'] = df['volume'].fillna(0)

# 3. 检测异常值(3-sigma 方法)
mean = df['close'].mean()
std = df['close'].std()
df = df[(df['close'] > mean - 3*std) & (df['close'] < mean + 3*std)]

# 4. 对齐多个股票的时间索引
# 假设我们有两只股票的数据
stock_a = pd.read_csv('stock_a.csv', index_col='date', parse_dates=True)
stock_b = pd.read_csv('stock_b.csv', index_col='date', parse_dates=True)

# 取两个时间索引的交集
common_dates = stock_a.index.intersection(stock_b.index)
stock_a_aligned = stock_a.loc[common_dates]
stock_b_aligned = stock_b.loc[common_dates]
避坑指南:我曾经在做一个多因子模型时,发现回测收益高得离谱。查了半天,原来是某只股票的数据有重复行,导致收益率计算翻倍了。从那以后,我每次清洗数据都会先跑一遍 df.duplicated().sum() 检查重复值。

3.4 复权价格处理:还原真实的收益率

复权价格,是量化投资里最容易出错的地方之一。为什么?因为股票会分红、送股、拆股,这些事件会导致价格出现「虚假」的跳变。如果你直接用原始价格计算收益率,结果会严重失真。

三种价格类型

类型 说明 适用场景
不复权 原始交易价格 技术分析、K线形态识别
前复权 调整历史价格,使当前价格不变 回测、因子计算(最常用)
后复权 调整当前价格,使历史价格不变 长期趋势分析

我个人习惯用前复权数据做因子计算。为什么呢?因为前复权保证了「当前价格是真实的」,而历史价格被调整后,计算出来的收益率才是真实的。

复权计算逻辑

# 假设我们有一只股票的分红和拆股信息
# 复权因子 = (1 + 分红率) * 拆股比例
# 前复权价格 = 原始价格 * 复权因子

def calculate_forward_adjusted_price(price, dividend, split_ratio):
    """
    计算前复权价格
    price: 原始价格序列
    dividend: 每股分红
    split_ratio: 拆股比例(如 1:2 拆股,split_ratio=2)
    """
    # 计算复权因子
    adj_factor = (1 + dividend / price.shift(1)) * split_ratio
    adj_factor = adj_factor.fillna(1)
    
    # 累积复权因子
    cum_adj_factor = adj_factor.cumprod()
    
    # 前复权价格
    forward_adj_price = price * cum_adj_factor
    
    return forward_adj_price

# 使用示例
price = pd.Series([100, 102, 98, 105, 110])
dividend = pd.Series([0, 0, 2, 0, 0])  # 第3天分红2元
split_ratio = pd.Series([1, 1, 1, 2, 1])  # 第4天1:2拆股

adj_price = calculate_forward_adjusted_price(price, dividend, split_ratio)
print(adj_price)
经验之谈:如果你用的是聚宽、Tushare 这些平台,它们一般会直接提供复权价格,省去了自己计算的麻烦。但如果你从 Yahoo Finance 拿数据,记得用 yfinance.download(..., auto_adjust=True) 参数,它会自动返回调整后的价格。

3.5 本章知识体系

下面这张图,是我梳理的本章核心逻辑。你可以把它当作一个「数据准备路线图」。

数据获取与准备:核心流程 数据源选择 A股:Wind/聚宽/Tushare 美股:Yahoo/Alpha Vantage Pandas基础 DataFrame/Series 读取/筛选/分组 数据清洗与对齐 缺失值/异常值 时间对齐/去重 复权价格处理 前复权 / 后复权 / 不复权 干净、对齐、复权的面板数据 可用于因子计算和回测

这张图展示了从数据源选择到最终生成可用数据的完整流程。每一步都有坑,但只要你按照这个路线图走,基本不会出大问题。

核心要点:
  • 数据源选择要权衡成本和需求,初期用免费源,后期上付费数据。
  • Pandas 是数据操作的基础,重点掌握 DataFrame 的读取、筛选、分组和对齐。
  • 数据清洗要处理缺失值、异常值、重复值和时间对齐。
  • 复权价格处理是计算真实收益率的关键,前复权最常用。

好了,这一章的内容就到这里。数据准备好了,下一章我们就可以开始真正地计算因子了。记住,数据质量决定了你的策略能走多远——别在这个环节偷懒。

专注资料整理