移動平均線(Moving Average)は、テクニカル分析でもっとも基本的な指標の 1 つです。本記事では、単純移動平均(SMA)と指数移動平均(EMA)の違い、Python での計算方法、グラフへの描き方を順に整理します。
目次
- 移動平均線が何を示すか
- SMA の計算式
- EMA の計算式
- サンプルデータの準備
- SMA を計算する
- EMA を計算する
- まとめて DataFrame にする
- チャートにする
- SMA と EMA の使い分け
- よくある誤用
移動平均線が何を示すか
移動平均線は、ある期間の終値を平均して並べた折れ線です。
- ノイズの多い日次終値を 滑らかな線 に変換する
- トレンドの方向(上昇 / 下降 / 横ばい)を視覚的に把握しやすくする
- 短期の線と長期の線の 交差(クロス) から売買シグナルを作る試みもある
「将来の株価を予測する」ものではない点には常に注意が必要です。あくまで 過去のトレンドを要約する道具 です。
SMA の計算式
単純移動平均(Simple Moving Average)は、指定した日数 N の終値の 算術平均 です。
たとえば 5 日 SMA は「直近 5 日の終値の平均」です。日が進むたびに、もっとも古い 1 日が抜け、新しい 1 日が加わります。
EMA の計算式
指数移動平均(Exponential Moving Average)は、新しい値ほど重みが大きくなる 平均です。
は平滑化係数で、慣例的に と設定されます(N は日数指定)。値が新しいほど効きが強く、結果として「反応が速い が、ノイズに敏感」な線になります。
サンプルデータの準備
サンプルとしてランダムウォークで生成した終値を使います。
import numpy as npimport pandas as pd
rng = np.random.default_rng(seed=42)n_days = 200returns = rng.normal(loc=0.0005, scale=0.015, size=n_days)close = pd.Series( 100 * np.exp(np.cumsum(returns)), index=pd.date_range("2026-01-01", periods=n_days, freq="B"), name="C",)print(close.head())pd.date_range(..., freq="B") で営業日(土日除く)の日付列を作っています。
SMA を計算する
pandas の rolling を使います。
sma_5 = close.rolling(window=5).mean()sma_25 = close.rolling(window=25).mean()sma_75 = close.rolling(window=75).mean()window=N は「過去 N 日」を意味します。先頭の N-1 日は値が足りないため NaN になります。
rolling には min_periods という引数もあり、データが少ない冒頭でも計算したい場合に使います。
sma_25_fill = close.rolling(window=25, min_periods=10).mean()ただし、デフォルトで NaN を返すほうが「データ不足を可視化できる」ため、初学者には標準動作のほうが安全です。
EMA を計算する
pandas の ewm を使います。
ema_5 = close.ewm(span=5, adjust=False).mean()ema_25 = close.ewm(span=25, adjust=False).mean()ema_75 = close.ewm(span=75, adjust=False).mean()span=N を指定すると、内部で が使われます。
adjust=False は再帰的な定義(上の数式そのまま)で計算するオプションです。adjust=True(既定)はやや異なる加重平均で計算します。本記事では再帰定義のほうを使います。
まとめて DataFrame にする
df = pd.concat( { "C": close, "SMA(5)": sma_5, "SMA(25)": sma_25, "SMA(75)": sma_75, "EMA(5)": ema_5, "EMA(25)": ema_25, "EMA(75)": ema_75, }, axis=1,)print(df.tail())チャートにする
matplotlib で「終値 + 移動平均」を 1 枚に描きます。
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(10, 5))ax.plot(df.index, df["C"], label="C", color="black", linewidth=1.0)ax.plot(df.index, df["SMA(25)"], label="SMA(25)", color="tab:blue")ax.plot(df.index, df["SMA(75)"], label="SMA(75)", color="tab:orange")ax.plot(df.index, df["EMA(25)"], label="EMA(25)", color="tab:green", linestyle="--")ax.set_title("C & Moving Averages")ax.set_xlabel("Date")ax.set_ylabel("Price")ax.legend()ax.grid(alpha=0.3)plt.tight_layout()plt.savefig("moving_average.png", dpi=120)plt.close(fig)
figsize・線の太さ・色は好みで調整できます。EMA の線を破線で描くと、SMA と区別しやすくなります。
SMA と EMA の使い分け
| 観点 | SMA | EMA |
|---|---|---|
| 反応速度 | 遅い(平等な平均) | 速い(直近重視) |
| ノイズ耐性 | 強い(滑らか) | 弱い(細かく動く) |
| 解釈の容易さ | 直感的 | やや不直感 |
| 実装の手軽さ | どちらも 1 行で書ける | どちらも 1 行で書ける |
「滑らかさ重視なら SMA、反応速度重視なら EMA」 が大まかな指針です。MACD のような他のテクニカル指標は EMA を内部で使うので、両方の存在を知っておくと連携しやすくなります。
よくある誤用
- 窓の長さを最適化しすぎる: パラメータを過去データに合わせて選ぶと、未来データに対しては機能しないことが多い(過剰適合)
- 絶対水準で売買を決める: 移動平均はあくまでトレンドの可視化。「移動平均を超えたら買い」は単独では弱い指標
- 休日を含めて計算してしまう: 営業日ベース(freq=“B”)で揃えること。休日を含むと窓の意味が崩れる
生成AI へのプロンプト例
複数銘柄に対して移動平均をまとめて計算したい場合の例です。
入力 DataFrame は次の構造です:- columns: Date (datetime64), Code (str), C (float)- 1 行 1 (銘柄, 日付) のロング形式
Code ごとに 5 日 / 25 日 / 75 日 の SMA と EMA を計算し、元の列に sma_5, sma_25, sma_75, ema_5, ema_25, ema_75 を追加したDataFrame を返す関数 add_moving_averages(df) を書いてください。
要件:- pandas 2.2 系- Code ごとに日付昇順に整列してから計算- 各 Code の冒頭は NaN を許容(その方が誤検知が減る)- 関数だけでなく、簡単な動作確認用のサンプルコードも併記まとめ
- 移動平均はトレンドを滑らかに見せる道具。予測ではなく要約 と理解する
- SMA は
rolling(window=N).mean()、EMA はewm(span=N, adjust=False).mean()で計算できる - SMA は滑らか、EMA は反応速度が速い
- 営業日ベースで計算する。窓の長さは過剰最適化に注意