当前位置: 首页 > 图灵资讯 > 行业资讯> 如何利用Python实现滑动窗口计算以分析股票市场的移动平均线?

如何利用Python实现滑动窗口计算以分析股票市场的移动平均线?

来源:图灵python
时间: 2026-08-20 11:25:14
pandas.DataFrame.rolling 为时间序列设计,自动处理索引对齐、缺失值和边界行为,是滑动窗口最安全的计算方法,默认按顺序滑动,window=20 表示 20 交易日,需要 resample 按自然日计算填充;min_periods=1 当数据不足时,可以返回部分平均值;rolling().mean() 快速稳定,必须使用复杂的逻辑 rolling().apply(),但不支持 min_periods 而且性能低。

计算滑动窗 pandas.DataFrame.rolling 最直接

直接调用 rolling 这是最安全的方法,专门为时间序列设计,自动处理索引对齐、缺失值和边界行为。不要自己写 for 循环或用 numpy.convolve 手动实现-容易错位,不兼容 NaN、原始时间戳不能保留。

  • rolling 默认情况下,如果数据已按日期上升顺序排列(df.indexDatetimeIndex),结果自然对齐
  • 窗口大小用 window=20 表示 20 交易日不是日历日;如果需要自然日(如 20 必须先用日历日) resample('D').first() 填充再计算
  • 遇到停牌或缺价时,min_periods=1 可使窗户不足 20 条数据仍返回部分平均值,否则返回 NaN)
rolling().mean()rolling().apply() 的关键区别

rolling().mean() 快速稳定,适用于标准移动平均;但是,如果需要计算加权平均、中位数或自定义逻辑(如排除最高和最低平均值),则必须使用 rolling().apply(),但要注意性能和边界。

  • apply 默认传入 Series,函数不能依赖全局变量或外部变量 DataFrame —— 否则,多进程或 chunk 情况下会出错
  • 例如计算「去极值后的 20 日均值」:lambda x: x.clip(lower=x.quantile(0.1), upper=x.quantile(0.9)).mean(),但每次都要重算分位数,慢;建议在使用之前预计计算阈值 rolling().agg()
  • apply 不支持 min_periods 参数需要在函数中手动判断 len(x) 并返回 <code>np.nan
常见错误:收盘价直接没有排序 rolling

从接口拉下股票数据往往是倒序(最新在前),而 rolling 按索引顺序滑动。如果没有排序,20 日均线实际上是“未来” 20 天”的平均值完全逆转。

Python 3.14.2

Python 3.14.2是Python编程语言于2025年12月5日发布的稳定版本,属于3.14系列的第二次维护更新。该版本包含18个修复项目,重点解决多过程、数据和正则表达模块的回归问题,修复CVE-2025-12084等安全漏洞。这个版本标志着Python发展的一个重要里程碑,即自由线程模式(删除GIL)正式得到官方支持。

下载

  • 检查顺序:df.index.is_monotonic_increasing,不满意就先执行 df = df.sort_index()
  • 更安全的方法:无论原始顺序如何,统一使用 df.sort_values('date').set_index('date') 构建索引
  • 一些市场界面(例如 akshare)返回的 DataFrame 默认无索引,必须设置显式设置 set_index('date'),否则 rolling 按整数位置滑动,与日期无关
MA5/MA10/MA20 同时计算不要重复调用 rolling

连续三次 df['close'].rolling(5).mean().rolling(10).mean().rolling(20).mean() 三次独立窗口扫描会触发,IO 和 CPU 浪费明显。

立即学习“Python免费学习笔记(深入);

  • agg 一次完成:df['close'].rolling(20).agg(['mean', lambda x: x.rolling(10).mean().iloc[-1], lambda x: x.rolling(5).mean().iloc[-1]]) —— 但嵌套 rolling 不推荐
  • 正确做法:分别定义三个窗口,但重用同一列:df[MA5] = df['close'].rolling(5).mean()df[MA10] = df['close'].rolling(10).mean(),底层 pandas 多次优化单列 rolling
  • 若要批量生成,用字典推导:{f'MA{n}': df['close'].rolling(n).mean() for n in [5, 10, 20]},再 pd.concat(..., axis=1)
时间序列对齐和窗口方向比公式本身更容易出错。特别是当数据与非交易日、复权调整或分钟高频数据混合时,rolling 默认行为可能不符合商业语义——你必须看清楚「到今天为止 N 天均值」,还是「包括今天 N 天中心均值」,后者得用 center=True