如何在Python中实现无循环的14日条件平滑移动平均列?
无循环实现仅包含delta正值的14日平滑移动平均
嘿,我懂你这种困扰——用Python循环处理股票数据,一旦数据集大起来速度简直没法忍。你之前尝试用ewm但结果不对,其实是没抓准你要的平滑公式和ewm参数的对应关系,咱们来搞定它。
先拆解你的需求公式
你要计算的avg_gain本质是个带条件的指数加权移动平均,核心公式是:
Avg_Gain(t) = (Avg_Gain(t-1) * 13 + max(delta(t), 0)) / 14
换个写法就是:
Avg_Gain(t) = (1/14)*max(delta(t),0) + (13/14)*Avg_Gain(t-1)
这完全符合递推式EWMA的结构,只是需要先把delta的负值替换为0,再用特定的权重计算。
为什么之前的ewm尝试不对?
默认的ewm(span=14).mean()用的是alpha=2/(span+1)(也就是2/15≈0.133),和你需要的alpha=1/14≈0.071不匹配。而且默认的adjust=True会计算累积加权平均,不是你要的递推式逐步更新,所以结果自然对不上。
正确的无循环实现方案
直接用Pandas的向量化操作,效率拉满:
import numpy as np import pandas as pd # 读取数据 df = pd.read_csv('stock_price.csv', delimiter=',') # 计算每日涨跌幅delta df['delta'] = df['PX_LAST'].pct_change() # 生成gain列:仅保留delta的正值,负值替换为0(用clip比apply高效) df['gain'] = df['delta'].clip(lower=0) # 计算符合需求的平滑平均 # alpha=1/14对应公式里的权重,adjust=False强制递推式计算 df['avg_gain'] = df['gain'].ewm(alpha=1/14, adjust=False, min_periods=1).mean() # 和原循环逻辑对齐,设置第一个值为0 df.loc[df.index[0], 'avg_gain'] = 0 # 查看结果 print(df[['Dates', 'PX_LAST', 'delta', 'avg_gain']])
关键参数解释
clip(lower=0):这是Pandas内置的向量化方法,比lambda x: x if x>0 else 0快得多,专门用来把数值限制在指定范围内。alpha=1/14:对应你公式里的新值权重,1/14的新gain加上13/14的历史平均值,完美匹配你的循环逻辑。adjust=False:这个参数一定要加!它会强制EWMA用递推的方式计算,和你手动循环的每一步完全一致,而不是用累积加权的方式。
效率对比
这个方法完全是底层优化过的向量化操作,时间复杂度是O(n),但执行速度比Python循环快几十甚至上百倍——尤其是当你的股票数据有几万条的时候,差别会特别明显。
内容的提问来源于stack exchange,提问作者pythonlearner13
相关产品推荐
相关产品推荐

