如何将涨跌成交量计算函数适配到Pandas滚动窗口?
实现滚动50天涨跌成交量比率的方法
核心思路
通过向量化预处理配合滚动窗口求和,替代逐窗口调用自定义函数的方式,既能实现每日的历史比率计算,又能保证计算效率。具体步骤如下:
步骤1:预处理涨跌成交量列
先为DataFrame新增两列,分别标记当日上涨/下跌时的成交量(非涨跌日成交量记为0):
# 计算每日涨跌幅(首行Change为NaN,对应首日无涨跌数据) df['Change'] = df['Close'].pct_change() # 上涨日成交量:当日涨跌幅>0时取Volume,否则为0 df['Up_Volume'] = df.apply(lambda x: x['Volume'] if x['Change'] > 0 else 0, axis=1) # 下跌日成交量:当日涨跌幅<0时取Volume,否则为0 df['Down_Volume'] = df.apply(lambda x: x['Volume'] if x['Change'] < 0 else 0, axis=1)
步骤2:滚动计算50天窗口的成交量总和
使用rolling(50)窗口分别计算上涨、下跌成交量的滚动总和:
# 滚动50天上涨成交量总和 df['Rolling_Up_Vol'] = df['Up_Volume'].rolling(window=50).sum() # 滚动50天下跌成交量总和 df['Rolling_Down_Vol'] = df['Down_Volume'].rolling(window=50).sum()
步骤3:计算涨跌成交量比率
将两个滚动总和相除,同时处理下跌成交量总和为0的特殊情况(避免除以0错误):
# 计算比率,保留两位小数;若下跌总和为0,设为None(也可自定义其他值) df['Up_Down_Vol_Ratio'] = df.apply( lambda x: round(x['Rolling_Up_Vol'] / x['Rolling_Down_Vol'], 2) if x['Rolling_Down_Vol'] != 0 else None, axis=1 )
完整代码示例
# 假设你的DataFrame名为df,包含Close和Volume列 df['Change'] = df['Close'].pct_change() df['Up_Volume'] = df.apply(lambda x: x['Volume'] if x['Change'] > 0 else 0, axis=1) df['Down_Volume'] = df.apply(lambda x: x['Volume'] if x['Change'] < 0 else 0, axis=1) df['Rolling_Up_Vol'] = df['Up_Volume'].rolling(window=50).sum() df['Rolling_Down_Vol'] = df['Down_Volume'].rolling(window=50).sum() df['Up_Down_Vol_Ratio'] = df.apply( lambda x: round(x['Rolling_Up_Vol'] / x['Rolling_Down_Vol'], 2) if x['Rolling_Down_Vol'] != 0 else None, axis=1 ) # 查看最近20天的计算结果 print(df[['Close', 'Volume', 'Up_Down_Vol_Ratio']].tail(20))
效率说明
直接用rolling.apply调用原自定义函数虽然可行,但逐窗口处理的效率极低(数据量大时尤为明显)。上述向量化+滚动求和的方式利用Pandas内置优化,计算速度会提升数倍甚至数十倍。
内容的提问来源于stack exchange,提问作者RazzleDazzle
相关产品推荐
相关产品推荐

