MACD(Moving Average Convergence Divergence、移動平均収束拡散)は、短期 EMA と長期 EMA の差をベースにしたトレンド系指標です。本記事では、計算式・pandas 実装・3 段グラフでの可視化・解釈のポイントを整理します。

目次

  1. MACD を構成する 3 本
  2. 計算式
  3. サンプルデータの準備
  4. MACD を計算する関数
  5. 可視化(価格 + MACD)
  6. 読み方のポイント
  7. クロスのフラグを立てる
  8. ヒストグラムの転換を取る

MACD を構成する 3 本

MACD は 3 つの値で表現されます。

  • MACD ライン: 短期 EMA から長期 EMA を引いた値
  • シグナル線: MACD ラインの EMA(さらに平滑化したもの)
  • ヒストグラム: MACD ラインからシグナル線を引いた値

慣例的に (短期, 長期, シグナル) = (12, 26, 9) が使われます。

計算式

短期期間を NsN_s、長期期間を NlN_l、シグナル期間を NgN_g とします。

MACDt=EMANs(P)tEMANl(P)t\mathrm{MACD}_t = \mathrm{EMA}_{N_s}(P)_t - \mathrm{EMA}_{N_l}(P)_t Signalt=EMANg(MACD)t\mathrm{Signal}_t = \mathrm{EMA}_{N_g}(\mathrm{MACD})_t Histt=MACDtSignalt\mathrm{Hist}_t = \mathrm{MACD}_t - \mathrm{Signal}_t

ヒストグラムが正の領域に大きく広がっていれば「買われている勢いが増している」、負の領域に大きく広がっていれば「売られている勢いが増している」と解釈されます。

サンプルデータの準備

import numpy as np
import pandas as pd
rng = np.random.default_rng(seed=37)
n = 260
returns = rng.normal(loc=0.0006, scale=0.013, size=n)
close = pd.Series(
2000 * np.exp(np.cumsum(returns)),
index=pd.date_range("2025-09-01", periods=n, freq="B"),
name="C",
)

MACD を計算する関数

def macd(
close: pd.Series,
short: int = 12,
long: int = 26,
signal: int = 9,
) -> pd.DataFrame:
"""MACD / Signal / Hist の 3 列を返す。"""
ema_short = close.ewm(span=short, adjust=False).mean()
ema_long = close.ewm(span=long, adjust=False).mean()
macd_line = ema_short - ema_long
signal_line = macd_line.ewm(span=signal, adjust=False).mean()
hist = macd_line - signal_line
return pd.DataFrame(
{"macd": macd_line, "signal": signal_line, "hist": hist}
)
m = macd(close)
print(m.tail())

adjust=False は EMA を再帰式の定義どおりに計算するオプションで、TA-Lib などの結果と整合しやすくなります。

可視化(価格 + MACD)

価格を上段、MACD を下段に並べる 2 段構成です。

import matplotlib.pyplot as plt
fig, (ax1, ax2) = plt.subplots(
nrows=2, sharex=True, figsize=(11, 6),
gridspec_kw={"height_ratios": [3, 2]},
)
ax1.plot(close.index, close.values, color="black", linewidth=0.8)
ax1.set_title("C & MACD(12, 26, 9)")
ax1.set_ylabel("Price")
ax1.grid(alpha=0.3)
ax2.plot(m.index, m["macd"], label="MACD", color="tab:blue")
ax2.plot(m.index, m["signal"], label="Signal", color="tab:orange")
colors = ["tab:red" if v < 0 else "tab:green" for v in m["hist"].fillna(0)]
ax2.bar(m.index, m["hist"], color=colors, width=1.0, alpha=0.5, label="Hist")
ax2.axhline(0, color="black", linewidth=0.6)
ax2.set_ylabel("MACD")
ax2.set_xlabel("Date")
ax2.legend(loc="upper left")
ax2.grid(alpha=0.3)
plt.tight_layout()
plt.savefig("macd_chart.png", dpi=120)
plt.close(fig)
価格と MACD ライン・シグナル線・ヒストグラムを描いた複合チャート

ヒストグラムは正で緑、負で赤の棒にすると、勢いの方向が一目で読めます。

読み方のポイント

観察ポイント一般的な解釈
MACD がシグナルを下から上抜け上昇への転換の兆し(MACD ゴールデンクロス)
MACD がシグナルを上から下抜け下落への転換の兆し(MACD デッドクロス)
MACD が 0 ラインを上抜け短期 EMA が長期 EMA を超える(中期トレンド転換)
ヒストグラムの拡大現在のトレンドが強まっている
ヒストグラムの縮小現在のトレンドが弱まっている

「MACD クロス」と「価格の SMA クロス」は別物である点に注意します。両者が同じ日付に出ることは少なく、組み合わせて使うことで遅行性をいくらか緩和できます。

クロスのフラグを立てる

MACD ラインがシグナル線を抜けた日を取り出します。

m["above"] = (m["macd"] > m["signal"]).astype(int)
m["cross"] = m["above"].diff()
gc = m.index[m["cross"] == 1].tolist()
dc = m.index[m["cross"] == -1].tolist()
print("MACD GC:", gc[:5])
print("MACD DC:", dc[:5])

ここでも、シグナル発生日の終値で約定 すると先読みになるため、実装上は position = above.shift(1) などで翌営業日に回します。

ヒストグラムの転換を取る

「ヒストグラムがマイナスからプラスに転じた日」を取りたい場合は次のとおりです。

m["hist_sign"] = np.sign(m["hist"]).fillna(0).astype(int)
m["hist_flip_up"] = (m["hist_sign"].diff() > 0) # -1 / 0 -> +1
m["hist_flip_dn"] = (m["hist_sign"].diff() < 0)

ヒストグラムの転換は MACD クロスより 1 〜 2 日早く出ることがあります。早出を取るか、確実性を取るかでルールを使い分けます。

注意点

  • 遅行指標: EMA を 3 段重ねているため、急騰急落直後はシグナルが間に合わないことがある
  • 横ばい相場で頻発する誤シグナル: ヒストグラムが小さい範囲で行ったり来たりする
  • 0 ラインの意味: 0 ラインはあくまで「短期 EMA = 長期 EMA」のライン。価格の絶対水準とは無関係
  • 絶対値での比較は不可: 銘柄ごとに価格水準が違うため、MACD の値そのものを銘柄横断で比較しても意味がない

生成AI へのプロンプト例

ロング形式の DataFrame に対し、Code ごとに MACD を計算する関数を依頼します。

入力 DataFrame:
- columns: Date (datetime64), Code (str), C (float)
Code ごとに MACD(12, 26, 9) を計算し、
- macd, macd_signal, macd_hist の 3 列を追加した DataFrame
を返す関数 add_macd(df, short=12, long=26, signal=9) を書いてください。
要件:
- pandas 2.2 系
- Code ごとに日付昇順に整列してから計算
- ewm(span=N, adjust=False) を使用
- 各 Code の冒頭は NaN を許容
- 関数の動作確認用サンプルコードを末尾に付ける

まとめ

  • MACD は EMA の差から作る トレンド系オシレーター
  • 構成要素は MACD ライン・シグナル線・ヒストグラムの 3 本
  • 標準パラメータは (12, 26, 9)。ewm(span=N, adjust=False) で再現できる
  • ゴールデンクロス・デッドクロスの判定は (macd > signal).astype(int).diff()
  • 遅行性・横ばい相場での誤シグナルは構造的な弱点。他指標と併用する前提で使う