如何用Python高效计算价格动量?基于n日滚动均值实现
高效实现价格动量计算的方案
嘿,我太懂你这种用循环处理大数据集卡到崩溃的感受了!你的循环写法在小数据集上没问题,但面对5000+行数据时,逐行切片、赋值的操作会让Python慢到离谱——毕竟Python的循环本身就不是为这种批量计算设计的。咱们直接用向量化操作来解决,速度能提升好几个数量级!
先理清楚你的需求
你定义的规则是:
- 当日涨跌幅>0时,动量标记为1;否则为-1
- 计算过去3日动量的平均值,前2天数据不足3个窗口,返回NaN
第一步:高效生成动量列
你原来用apply的方法虽然能工作,但np.where的向量化写法会更快(尤其是大数据集):
import numpy as np import pandas as pd # 模拟你的涨跌幅数据 df = pd.DataFrame({'close in percent': np.array([0.27772152, 1.05468772, 0.124156 , -0.39298394, 0.56415267, 1.67812005])}) # 向量化生成动量列,比apply快得多 df['momentum'] = np.where(df['close in percent'] > 0, 1, -1)
执行后df['momentum']就是你想要的[1,1,1,-1,1,1]。
第二步:用滚动窗口计算平均动量
Pandas内置的rolling函数专门用来处理这类滑动窗口计算,完全是向量化实现,速度超快:
# 窗口大小3,min_periods=3表示必须凑齐3个数据才计算均值,否则返回NaN df['3_day_momentum'] = df['momentum'].rolling(window=3, min_periods=3).mean()
运行后你会得到完全符合预期的结果:
| close in percent | momentum | 3_day_momentum |
|---|---|---|
| 0.27772152 | 1 | NaN |
| 1.05468772 | 1 | NaN |
| 0.124156 | 1 | 1.0 |
| -0.39298394 | -1 | 0.333333 |
| 0.56415267 | 1 | 0.333333 |
| 1.67812005 | 1 | 0.333333 |
备选方案:用Numpy卷积实现
如果你更习惯纯数组操作,Numpy的convolve函数也能高效完成计算:
window_size = 3 mom_array = df['momentum'].values # 用卷积计算窗口内的总和(窗口是全1的数组),mode='valid'只保留完全覆盖的窗口 window_sums = np.convolve(mom_array, np.ones(window_size), mode='valid') # 前面补window_size-1个NaN,再除以窗口大小得到平均值 price_momentum = np.concatenate([[np.nan]*(window_size-1), window_sums / window_size]) df['3_day_momentum'] = price_momentum
这个方法的速度和Pandas的rolling差不多,适合不需要DataFrame,直接操作数组的场景。
为什么这些方法更快?
原来的循环是在Python层面逐行处理,每一步都要做切片、数组转换、赋值等开销极大的操作;而向量化操作是调用底层的C语言实现,一次性处理整个数据集,效率提升至少几百倍——5000行数据用这两种方法,绝对能在毫秒级完成,再也不用等10分钟啦!
内容的提问来源于stack exchange,提问作者GRS
相关产品推荐
相关产品推荐

