なぜ「Backtesting.py」が個人投資家の定番になっているのか
Pythonで自作の売買ルールを検証したいとき、最も手軽で実用的なライブラリがBacktesting.pyです。pandasのDataFrameをそのまま渡せ、ルールをinit()とnext()の2メソッドで書くだけで、損益曲線・シャープレシオ・最大ドローダウンまで一気に算出してくれます。インストールもpip install backtestingだけで完了するため、業務でも学習でも導入コストが極めて低いのが魅力です。
2026年に入っても、Backtesting.pyはアルゴ取引の検証における「最初の一手」として広く使われています。インジケータライブラリ(ta、pandas-ta、TA-Lib)との相性も良く、検証から実運用ロジック化までスムーズに繋げられます。
戦略例:ゴールデンクロス/デッドクロス
今回は基本中の基本であるSMA(短期20日 / 長期50日)のクロス戦略を日経平均(^N225)で検証します。短期線が長期線を上抜けたら買い、下抜けたら全決済というシンプルなルールです。シンプルゆえにロバストネスを見極めやすく、機械学習モデルのベースラインとしても優秀です。
Python実装:データ取得からバックテストまで
import yfinance as yf
import pandas as pd
from backtesting import Backtest, Strategy
from backtesting.lib import crossover
def SMA(values, n):
return pd.Series(values).rolling(n).mean()
class SmaCross(Strategy):
n1 = 20
n2 = 50
def init(self):
close = self.data.Close
self.sma1 = self.I(SMA, close, self.n1)
self.sma2 = self.I(SMA, close, self.n2)
def next(self):
if crossover(self.sma1, self.sma2):
self.buy()
elif crossover(self.sma2, self.sma1):
self.position.close()
df = yf.download('^N225', start='2018-01-01', end='2026-05-01', auto_adjust=True)
df = df[['Open','High','Low','Close','Volume']].dropna()
bt = Backtest(df, SmaCross, cash=1_000_000, commission=0.001)
stats = bt.run()
print(stats[['Return [%]','Sharpe Ratio','Max. Drawdown [%]','# Trades']])
bt.plot(filename='sma_cross_n225.html', open_browser=False)
結果の読み方
出力のReturn [%]は累計リターン、Sharpe Ratioはリスク調整後リターンの定番指標です。Max. Drawdown [%]は精神的な耐久度を示す重要指標で、SMAクロスは上昇相場では機能しても、レンジ相場ではドローダウンが膨らみがちです。bt.plot()で生成されるHTMLには売買ポイントと損益曲線が描画されるため、シグナルの質を視覚的に確認できます。
パラメータ最適化と過剰最適化への注意
stats_opt = bt.optimize(
n1=range(5, 40, 5),
n2=range(40, 120, 10),
maximize='Sharpe Ratio',
constraint=lambda p: p.n1 < p.n2,
)
print(stats_opt._strategy)
最適化は強力ですが、サンプル外(アウトオブサンプル)で同じ性能が出るとは限りません。必ず期間を分割してウォークフォワードテストを行い、最適化したパラメータが「過去にだけ効いた数字」になっていないかを確認しましょう。
まとめと次のステップ
Backtesting.pyを使えば、戦略の良し悪しを感覚ではなく数値で議論できるようになります。次の一手としては、(1) スリッページやスプレッドをcommissionに織り込む、(2) 個別株でユニバースを広げて分散効果を測る、(3) RSIやATR等を組み合わせてエッジを上乗せする、がおすすめです。まずは上のコードをそのまま実行し、自分の感覚と数字のズレを確かめてみてください。

