BacktraderでRSI+MACDを組み合わせた日本株バックテスト【製造メーカー株で検証】

Python実装・コード

先日、backtraderで作ったBOTを初めて動かしてみたんですが、バックテストでは勝率65%だったのに実運用2週間でマイナスになりました。。。「なんで?」ってなって色々調べたら、RSIとMACDの組み合わせ方に問題があったことがわかって、改めてちゃんと整理しようと思って記事にします。

なぜRSI+MACDの組み合わせを試したか

日本株、特に製造メーカー系の銘柄(トヨタや日立など)を見ていると、トレンドが出るとしばらく続く傾向があると感じていました。「トレンドフォローにMACDを使って、エントリーのタイミングをRSIで絞れれば精度が上がるんじゃないか」というシンプルな仮説からスタートしました。backtraderはPythonのバックテストライブラリとして日本語情報も増えてきたので、これを使って検証してみます。

環境準備

まず必要なライブラリをインストールします。

pip install backtrader yfinance pandas matplotlib

RSI+MACD戦略の実装

戦略のロジックはシンプルです。MACDがシグナル線を上抜け、かつRSIが50以下のときに買い。MACDがシグナル線を下抜けたら売り。というルールにします。

import backtrader as bt
import yfinance as yf
import pandas as pd

class RSIMACDStrategy(bt.Strategy):
    params = (
        ('rsi_period', 14),
        ('macd1', 12),
        ('macd2', 26),
        ('macdsig', 9),
        ('rsi_entry', 50),
    )

    def __init__(self):
        self.macd = bt.indicators.MACD(
            self.data.close,
            period1=self.params.macd1,
            period2=self.params.macd2,
            period_signal=self.params.macdsig
        )
        self.rsi = bt.indicators.RSI(
            self.data.close,
            period=self.params.rsi_period
        )
        self.crossover = bt.indicators.CrossOver(
            self.macd.macd, self.macd.signal
        )

    def next(self):
        if not self.position:
            # MACDがシグナルを上抜け、かつRSIが50以下
            if self.crossover > 0 and self.rsi < self.params.rsi_entry:
                self.buy()
        else:
            # MACDがシグナルを下抜けたら売り
            if self.crossover < 0:
                self.sell()

# トヨタ自動車(7203.T)のデータを取得
ticker = '7203.T'
df = yf.download(ticker, start='2022-01-01', end='2025-12-31')
df.columns = [c[0].lower() for c in df.columns]

# backtrader用にデータを変換
data = bt.feeds.PandasData(dataname=df)

# セレブロ(実行エンジン)を設定
cerebro = bt.Cerebro()
cerebro.addstrategy(RSIMACDStrategy)
cerebro.adddata(data)
cerebro.broker.setcash(1000000)  # 100万円スタート
cerebro.broker.setcommission(commission=0.001)  # 0.1%手数料

print(f'開始資金: {cerebro.broker.getvalue():.0f}円')
results = cerebro.run()
print(f'最終資金: {cerebro.broker.getvalue():.0f}円')

# 結果を可視化
cerebro.plot(style='candlestick')

パラメータのポイント

RSIの閾値を50にしているのがこの戦略のミソです。一般的にRSI30以下を「売られすぎ」と使う人が多いですが、トレンドフォロー前提なのでMACDがクロスした時点ですでに「勢い」が出始めています。そこにRSI30以下を要求すると、エントリーできるチャンスが減りすぎてしまいます。50以下という緩めの条件で「まだ過熱していない」を確認する程度に使うのがいいと思います。

バックテスト結果の読み方

backtraderのplotで出力されるチャートには、売買タイミングが矢印で表示されます。ただし僕が最初に失敗したのが、バックテストの期間設定です。2020年のコロナショックを含む期間でテストすると、急落時の損失も含まれるので本来の戦略性能が見えにくくなります。まずは直近2〜3年のデータで検証して、そのあと過去の荒れた相場でも耐えられるか確認する順番がおすすめです。

注意点:バックテストと実運用の乖離

僕が最初に痛い目を見たのが、スリッページと約定タイミングの問題です。バックテストでは終値で約定する設定になっていますが、実際には翌営業日の始値に近い価格で約定することが多いです。製造メーカー株は出来高が多いので影響は小さいですが、それでも設定に組み込むのが安全です。

# スリッページを考慮した設定
cerebro.broker.set_slippage_perc(0.001)  # 0.1%のスリッページ

まとめ

RSI+MACDの組み合わせは、単体で使うより確実にエントリー精度が上がります。ただしパラメータは銘柄ごとに最適値が違うので、まずトヨタで動かして感触をつかんでから他の銘柄に広げるのがいいと思います。次は僕も日立(6501.T)とパナソニック(6752.T)でも同じ戦略を検証してみるつもりです。同じ製造業でも業種が違うとパラメータのベスト値が変わるのかどうか、気になっています。

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