金融数据基石:Pandas与NumPy在量化中的核心应用
做量化投资这些年,我越来越觉得一个道理:数据处理的功底,直接决定了策略的上限。你想想看,再漂亮的数学模型,如果数据预处理不到位,结果就是垃圾进垃圾出。今天我们就来聊聊量化分析的两大基石——Pandas和NumPy,看看它们在实际选股中到底怎么用。
为什么是这两个库?
说实话,我刚入行时也试过用纯Python列表处理行情数据。结果呢?一个简单的滚动均值计算,跑了半小时还没出结果。后来我才明白,NumPy的底层是用C写的,向量化操作比Python循环快几十倍。而Pandas,说白了就是给NumPy穿上了金融数据的外衣——时间索引、缺失值处理、分组聚合,这些都是为金融数据量身定做的。
核心认知:NumPy负责数学运算的底层加速,Pandas负责数据的结构化处理。两者配合,才能高效处理海量金融数据。
NumPy在量化中的三个高频场景
我个人习惯把NumPy的用法分成三类,你在实际项目中一定会遇到:
1. 数组运算替代循环
比如计算股票的日收益率。新手可能会写for循环,但用NumPy只需要一行:
import numpy as np
# 假设close_prices是收盘价数组
returns = np.diff(close_prices) / close_prices[:-1]
# 或者用更稳定的对数收益率
log_returns = np.diff(np.log(close_prices))
我在项目中遇到过一个问题:用普通方法计算5000只股票的收益率,耗时3分钟。换成向量化操作后,3秒搞定。这就是NumPy的价值。
2. 统计指标快速计算
选股时经常需要计算各种统计量。NumPy提供了现成的函数:
# 计算某只股票过去252天的年化波动率
daily_vol = np.std(returns) # 日波动率
annual_vol = daily_vol * np.sqrt(252) # 年化波动率
# 计算最大回撤
cum_returns = np.cumprod(1 + returns)
peak = np.maximum.accumulate(cum_returns)
drawdown = (cum_returns - peak) / peak
max_drawdown = np.min(drawdown)
避坑指南:我曾经直接用np.std计算波动率,结果发现它默认是总体标准差。金融数据通常用样本标准差,记得加上ddof=1参数。
3. 矩阵运算与因子合成
多因子选股时,经常需要做矩阵运算。比如计算因子之间的协方差矩阵:
# 假设factor_matrix是形状为(N, M)的矩阵,N为股票数,M为因子数
cov_matrix = np.cov(factor_matrix, rowvar=False)
# 计算因子相关性矩阵
corr_matrix = np.corrcoef(factor_matrix, rowvar=False)
Pandas:金融数据的瑞士军刀
如果说NumPy是发动机,那Pandas就是驾驶舱。它让数据处理变得直观。我个人觉得,Pandas最强大的地方在于时间序列处理。
1. 时间索引的魔法
金融数据天然带有时间标签。Pandas的DatetimeIndex让一切变得简单:
import pandas as pd
# 读取行情数据
df = pd.read_csv('stock_data.csv', parse_dates=['date'], index_col='date')
# 按月份重采样
monthly_returns = df['close'].resample('M').last().pct_change()
# 滚动计算20日均线
df['ma20'] = df['close'].rolling(window=20).mean()
你想想看,如果用纯Python实现这些功能,得写多少行代码?Pandas一行搞定。
2. 分组聚合与因子计算
选股时经常需要按行业分组计算指标。Pandas的groupby就是为此而生:
# 计算每个行业股票的市值占比
df['market_cap_weight'] = df.groupby('industry')['market_cap'].transform(
lambda x: x / x.sum()
)
# 计算行业内股票的排名
df['pe_rank'] = df.groupby('industry')['pe_ratio'].rank()
注意:groupby之后一定要记得用transform,而不是直接apply。transform会保持原始数据的形状,而apply会改变索引结构。这个坑我踩过好几次。
3. 缺失值处理的艺术
真实金融数据永远有缺失值。停牌、退市、数据错误……Pandas提供了灵活的处理方式:
# 向前填充缺失值(比如停牌期间用前一日数据)
df.fillna(method='ffill', inplace=True)
# 删除缺失值过多的股票
df = df.dropna(thresh=len(df.columns) * 0.7) # 保留至少70%数据完整的股票
# 用行业均值填充
df['pe_ratio'] = df.groupby('industry')['pe_ratio'].transform(
lambda x: x.fillna(x.mean())
)
实战:构建一个简单的选股因子
光说不练假把式。我们结合NumPy和Pandas,构建一个经典的动量因子:
import pandas as pd
import numpy as np
# 读取数据
df = pd.read_csv('daily_data.csv', parse_dates=['date'], index_col='date')
# 计算过去20个交易日的累计收益率(动量因子)
def calc_momentum(price_series):
return price_series.pct_change(periods=20)
# 对每只股票计算动量
momentum = df.groupby('stock_id')['close'].transform(calc_momentum)
# 对动量进行截面标准化(减去均值,除以标准差)
def standardize(series):
return (series - series.mean()) / series.std()
momentum_std = momentum.groupby(level='date').transform(standardize)
# 将结果添加到原数据框
df['momentum_factor'] = momentum_std
这段代码看起来简单,但背后包含了:分组计算、滚动窗口、截面标准化三个核心操作。嗯,这就是Pandas+NumPy的威力。
性能优化:别让数据拖慢你的策略
做量化最怕什么?策略跑得比乌龟还慢。我分享几个优化技巧:
| 优化方向 | 具体方法 | 效果 |
|---|---|---|
| 数据类型 | 用float32代替float64 | 内存减半,速度提升30% |
| 索引优化 | 使用分类索引(CategoricalIndex) | groupby速度提升5-10倍 |
| 避免循环 | 用向量化操作替代apply | 速度提升10-100倍 |
| 并行计算 | 使用numba或swifter库 | 多核并行,线性加速 |
我的经验:处理百万级数据时,先把数据按日期排序,然后设置MultiIndex(股票ID+日期),这样后续的切片和分组操作会快很多。
知识体系总览
下面这张图概括了本章的核心内容。我建议你把它当作学习地图:
这张图把本章的知识点串起来了。左边是NumPy,负责数学运算;右边是Pandas,负责数据处理。两者结合,才能构建出高效的量化策略。
写在最后
说实话,Pandas和NumPy的学习曲线并不陡峭。你只要掌握今天讲的这几个核心场景,就能应对90%的量化数据处理需求。剩下的10%,遇到问题再查文档也来得及。
记住一句话:好的数据预处理,是成功策略的一半。别急着跑模型,先把数据质量搞上去。
公众号:蓝海数据掘金营,微信deep3321