移動平均線(Moving Average)は、テクニカル分析でもっとも基本的な指標の 1 つです。本記事では、単純移動平均(SMA)と指数移動平均(EMA)の違い、Python での計算方法、グラフへの描き方を順に整理します。

目次

  1. 移動平均線が何を示すか
  2. SMA の計算式
  3. EMA の計算式
  4. サンプルデータの準備
  5. SMA を計算する
  6. EMA を計算する
  7. まとめて DataFrame にする
  8. チャートにする
  9. SMA と EMA の使い分け
  10. よくある誤用

移動平均線が何を示すか

移動平均線は、ある期間の終値を平均して並べた折れ線です。

  • ノイズの多い日次終値を 滑らかな線 に変換する
  • トレンドの方向(上昇 / 下降 / 横ばい)を視覚的に把握しやすくする
  • 短期の線と長期の線の 交差(クロス) から売買シグナルを作る試みもある

「将来の株価を予測する」ものではない点には常に注意が必要です。あくまで 過去のトレンドを要約する道具 です。

SMA の計算式

単純移動平均(Simple Moving Average)は、指定した日数 N の終値の 算術平均 です。

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

たとえば 5 日 SMA は「直近 5 日の終値の平均」です。日が進むたびに、もっとも古い 1 日が抜け、新しい 1 日が加わります。

EMA の計算式

指数移動平均(Exponential Moving Average)は、新しい値ほど重みが大きくなる 平均です。

EMAt=αPt+(1α)EMAt1\mathrm{EMA}_t = \alpha \cdot P_t + (1 - \alpha) \cdot \mathrm{EMA}_{t-1}

α\alpha は平滑化係数で、慣例的に α=2/(N+1)\alpha = 2 / (N + 1) と設定されます(N は日数指定)。値が新しいほど効きが強く、結果として「反応が速い が、ノイズに敏感」な線になります。

サンプルデータの準備

サンプルとしてランダムウォークで生成した終値を使います。

import numpy as np
import pandas as pd
rng = np.random.default_rng(seed=42)
n_days = 200
returns = 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 を指定すると、内部で α=2/(N+1)\alpha = 2 / (N + 1) が使われます。

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)
終値に SMA(25) と SMA(75) と EMA(25) を重ねた折れ線チャート

figsize・線の太さ・色は好みで調整できます。EMA の線を破線で描くと、SMA と区別しやすくなります。

SMA と EMA の使い分け

観点SMAEMA
反応速度遅い(平等な平均)速い(直近重視)
ノイズ耐性強い(滑らか)弱い(細かく動く)
解釈の容易さ直感的やや不直感
実装の手軽さどちらも 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 は反応速度が速い
  • 営業日ベースで計算する。窓の長さは過剰最適化に注意