跳到主要内容

移动平均:SMA 与 EMA

直觉

移动平均是「把噪声熨平」,露出价格的趋势。最简单的 简单移动平均(SMA) 把过去 NN 天一视同仁地平均;指数移动平均(EMA) 则给最近的价格更高权重,反应更快。它们是几乎所有技术指标和趋势策略的地基。

数学原理

SMA(过去 NN 期等权平均):

SMAt=1Ni=0N1Pti\text{SMA}_t = \frac{1}{N}\sum_{i=0}^{N-1} P_{t-i}

EMA(指数衰减加权,越近权重越大):

EMAt=αPt+(1α)EMAt1,α=2N+1\text{EMA}_t = \alpha\, P_t + (1-\alpha)\,\text{EMA}_{t-1}, \qquad \alpha = \frac{2}{N+1}
「人话」解释:SMA 和 EMA 的差别在哪?
  • SMANN 天等量看待——10 天前的价格和今天一样重要。它平滑、滞后,转势慢。
  • EMA 让最近的价格权重更大,所以对最新走势更敏感、转向更快,但也更容易被噪声「骗」。
  • α=2N+1\alpha=\frac{2}{N+1} 是把「窗口长度 NN」转成「衰减速度」的常用换算;α\alpha 越大,越看重当下。

可运行案例:叠加 SMA 与 EMA

读取 spy_daily.csv,画出 20 日 SMA、20 日 EMA 与原始收盘价,直观对比两者的「平滑度」与「滞后性」。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

df = pd.read_csv('/data/spy_daily.csv', parse_dates=['date']).set_index('date')
close = df['close']

N = 20
sma = close.rolling(N).mean()
ema = close.ewm(span=N, adjust=False).mean()      # span=N ⇔ alpha=2/(N+1)

# 取最近一年看清楚
recent_start = close.index.max() - pd.Timedelta(days=365)
recent = close.loc[recent_start:]
sma_r = sma.loc[recent_start:]
ema_r = ema.loc[recent_start:]

plt.figure(figsize=(9, 3.8))
plt.plot(recent, color="#94a3b8", lw=1, label="收盘价")
plt.plot(sma_r, color="#2563eb", lw=1.6, label=f"SMA{N}")
plt.plot(ema_r, color="crimson", lw=1.6, label=f"EMA{N}")
plt.title(f"SMA{N} vs EMA{N}:EMA 更贴近价格、转势更快")
plt.xlabel("日期"); plt.ylabel("价格"); plt.legend()
plt.tight_layout(); plt.show()

动手改一改

把窗口 N 从 20 改成 60,再改成 5——观察:窗口越大均线越平滑、越滞后;窗口越小越贴价格、越抖。

小结

  • SMA:等权平均,平滑、滞后;
  • EMA:指数加权,α=2/(N+1)\alpha=2/(N+1),更敏感、转向快;
  • 均线是趋势策略(模块 4 双均线)和很多指标(MACD)的基础。