PythonでRSI+MACDを組み合わせた売買シグナル自動生成【テクニカル分析入門】

Uncategorized

RSIとMACDを組み合わせる理由

テクニカル分析の世界では「単一の指標だけに頼るな」とよく言われます。RSI(相対力指数)は売られすぎ・買われすぎを判断するのに優れていますが、トレンドが強い相場では誤シグナルを出しやすいという弱点があります。一方MACD(移動平均収束発散)はトレンドの方向と強さを捉えるのが得意ですが、横ばい相場ではダマシが多くなります。

この2つを組み合わせることで互いの弱点を補い合い、より精度の高い売買シグナルを生成できます。本記事では、PythonとTA-Libを使ってRSI+MACDの複合シグナルシステムをゼロから構築する方法を解説します。

RSIとMACDの基礎をおさらい

RSI(Relative Strength Index)は一定期間における値上がり幅と値下がり幅を比較し、相場の過熱感を0〜100の数値で表します。一般的に30以下が売られすぎ(買いシグナル)70以上が買われすぎ(売りシグナル)とされます。

MACD(Moving Average Convergence Divergence)は短期EMA(12日)から長期EMA(26日)を引いた値です。この値がシグナルライン(MACDの9日EMA)を上抜けたら買い、下抜けたら売りというのが基本的な使い方です。

環境のセットアップ

pip install yfinance pandas numpy matplotlib ta

株価データの取得とRSI・MACDの計算

import yfinance as yf
import pandas as pd
import numpy as np
import ta
import matplotlib.pyplot as plt

ticker = '9432.T'
df = yf.download(ticker, start='2024-01-01', end='2026-05-01', auto_adjust=True)
df = df[['Open', 'High', 'Low', 'Close', 'Volume']].copy()

# RSIの計算(期間14日)
df['RSI'] = ta.momentum.RSIIndicator(close=df['Close'], window=14).rsi()

# MACDの計算
macd = ta.trend.MACD(close=df['Close'], window_slow=26, window_fast=12, window_sign=9)
df['MACD'] = macd.macd()
df['MACD_Signal'] = macd.macd_signal()
df['MACD_Hist'] = macd.macd_diff()

print(df[['Close', 'RSI', 'MACD', 'MACD_Signal']].tail(10))

複合シグナルの生成ロジック

買いシグナル:RSIが30以下(売られすぎ)かつMACDがシグナルラインを上抜けた場合

売りシグナル:RSIが70以上(買われすぎ)かつMACDがシグナルラインを下抜けた場合

def generate_signals(df):
    signals = pd.DataFrame(index=df.index)
    signals['Close'] = df['Close']
    signals['Signal'] = 0

    macd_cross_up = (df['MACD'] > df['MACD_Signal']) & (df['MACD'].shift(1) <= df['MACD_Signal'].shift(1))
    macd_cross_down = (df['MACD'] < df['MACD_Signal']) & (df['MACD'].shift(1) >= df['MACD_Signal'].shift(1))

    buy_condition = (df['RSI'] < 35) & macd_cross_up
    sell_condition = (df['RSI'] > 65) & macd_cross_down

    signals.loc[buy_condition, 'Signal'] = 1
    signals.loc[sell_condition, 'Signal'] = -1
    return signals

signals = generate_signals(df)
print(f"買いシグナル発生回数: {len(signals[signals['Signal']==1])}")
print(f"売りシグナル発生回数: {len(signals[signals['Signal']==-1])}")

シグナルをチャートで可視化する

fig, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(14, 10), sharex=True)

# 株価 + シグナル
ax1.plot(df.index, df['Close'], color='#333333', linewidth=1.5, label='終値')
buy_sig = signals[signals['Signal']==1]
sell_sig = signals[signals['Signal']==-1]
ax1.scatter(buy_sig.index, buy_sig['Close'], marker='^', color='#00aa44', s=100, label='買い', zorder=5)
ax1.scatter(sell_sig.index, sell_sig['Close'], marker='v', color='#dd2222', s=100, label='売り', zorder=5)
ax1.legend(); ax1.grid(True, alpha=0.3)

# RSI
ax2.plot(df.index, df['RSI'], color='#7c3aed', linewidth=1.5)
ax2.axhline(y=70, color='red', linestyle='--', alpha=0.7)
ax2.axhline(y=30, color='green', linestyle='--', alpha=0.7)
ax2.set_ylim(0, 100); ax2.grid(True, alpha=0.3)

# MACD
ax3.plot(df.index, df['MACD'], color='#2563eb', linewidth=1.5, label='MACD')
ax3.plot(df.index, df['MACD_Signal'], color='#ef4444', linewidth=1.5, label='シグナル')
ax3.bar(df.index, df['MACD_Hist'],
        color=['#22c55e' if v >= 0 else '#ef4444' for v in df['MACD_Hist']], alpha=0.6)
ax3.legend(); ax3.grid(True, alpha=0.3)
plt.tight_layout(); plt.show()

シグナルの勝率を簡易検証

results = []
for date in buy_sig.index:
    entry_price = df.loc[date, 'Close']
    future_dates = df.index[df.index > date][:5]
    if len(future_dates) >= 5:
        exit_price = df.loc[future_dates[-1], 'Close']
        results.append((exit_price - entry_price) / entry_price * 100)

if results:
    win_rate = sum(1 for r in results if r > 0) / len(results) * 100
    print(f"シグナル後5日の勝率: {win_rate:.1f}%")
    print(f"平均リターン: {np.mean(results):.2f}%")

まとめと実践のヒント

RSIとMACDの組み合わせは汎用性が高い手法です。ただし、銘柄・期間によって最適なパラメータは異なります。RSIの閾値(今回は35/65)やMACDの期間は、対象銘柄の特性に合わせてバックテストで最適化しましょう。また、手数料とスリッページを必ず考慮してください。次のステップとして、今回のシグナルをBacktesting.pyに組み込んで、より精密なバックテストを実施してみてください。

タイトルとURLをコピーしました