Backtraderは本格的なバックテストが行えるPythonフレームワークです。複雑な戦略・複数銘柄・リスク管理まで対応しており、プロの個人投資家にも使われています。
Backtraderのインストール
pip install backtrader matplotlib
基本的なバックテストの構成
import backtrader as bt
import yfinance as yf
import pandas as pd
import datetime
# yfinanceからデータを取得してBacktrader用に変換
def get_data_for_bt(ticker, period="3y"):
df = yf.download(ticker, period=period, progress=False, auto_adjust=True)
df.index = pd.to_datetime(df.index)
data = bt.feeds.PandasData(dataname=df)
return data
シンプルな移動平均クロス戦略
class MACrossStrategy(bt.Strategy):
params = (
("short_period", 25),
("long_period", 75),
("stake", 100), # 取引単位(株数)
)
def __init__(self):
# 移動平均線を定義
self.ma_short = bt.ind.SMA(self.data.close, period=self.params.short_period)
self.ma_long = bt.ind.SMA(self.data.close, period=self.params.long_period)
# クロスシグナル
self.crossover = bt.ind.CrossOver(self.ma_short, self.ma_long)
def next(self):
if not self.position: # ポジションなし
if self.crossover > 0: # ゴールデンクロス
self.buy(size=self.params.stake)
print(f"BUY: {self.data.datetime.date(0)} @ {self.data.close[0]:.0f}")
else: # ポジションあり
if self.crossover < 0: # デッドクロス
self.sell(size=self.params.stake)
print(f"SELL: {self.data.datetime.date(0)} @ {self.data.close[0]:.0f}")
# バックテストを実行
def run_backtest(ticker, initial_cash=1_000_000):
cerebro = bt.Cerebro()
# データを追加
data = get_data_for_bt(ticker)
cerebro.adddata(data)
# 戦略を追加
cerebro.addstrategy(MACrossStrategy, short_period=25, long_period=75)
# 初期資金を設定
cerebro.broker.setcash(initial_cash)
# 手数料を設定(0.1%)
cerebro.broker.setcommission(commission=0.001)
# 分析ツールを追加
cerebro.addanalyzer(bt.analyzers.SharpeRatio, _name="sharpe", riskfreerate=0.01)
cerebro.addanalyzer(bt.analyzers.DrawDown, _name="drawdown")
cerebro.addanalyzer(bt.analyzers.Returns, _name="returns")
cerebro.addanalyzer(bt.analyzers.TradeAnalyzer, _name="trades")
print(f"初期資金: {cerebro.broker.getvalue():,.0f}円")
results = cerebro.run()
print(f"最終資金: {cerebro.broker.getvalue():,.0f}円")
# 結果を表示
strat = results[0]
sharpe = strat.analyzers.sharpe.get_analysis().get("sharperatio", 0)
mdd = strat.analyzers.drawdown.get_analysis()["max"]["drawdown"]
total_return = strat.analyzers.returns.get_analysis()["rtot"] * 100
trades = strat.analyzers.trades.get_analysis()
print(f"\n=== バックテスト結果 ===")
print(f"総リターン: {total_return:.1f}%")
print(f"シャープレシオ: {sharpe:.2f}" if sharpe else "シャープレシオ: N/A")
print(f"最大ドローダウン: {mdd:.1f}%")
if trades.get("total"):
total = trades["total"]["total"]
won = trades.get("won", {}).get("total", 0)
print(f"取引回数: {total}, 勝率: {won/total:.1%}" if total > 0 else "")
cerebro.plot(style="candlestick", volume=False)
return results
run_backtest("7203.T")
RSI戦略の実装
class RSIStrategy(bt.Strategy):
params = (
("rsi_period", 14),
("rsi_overbought", 70),
("rsi_oversold", 30),
("stake_pct", 0.95), # 資金の95%を使用
)
def __init__(self):
self.rsi = bt.ind.RSI(self.data.close, period=self.params.rsi_period)
def next(self):
cash = self.broker.getcash()
price = self.data.close[0]
size = int((cash * self.params.stake_pct) / price)
if not self.position:
if self.rsi[0] < self.params.rsi_oversold:
if size > 0:
self.buy(size=size)
else:
if self.rsi[0] > self.params.rsi_overbought:
self.close()
def compare_strategies(ticker):
"""複数戦略を比較"""
strategies = [
("MA Cross", MACrossStrategy, {}),
("RSI", RSIStrategy, {}),
]
for name, strategy, params in strategies:
cerebro = bt.Cerebro()
cerebro.adddata(get_data_for_bt(ticker))
cerebro.addstrategy(strategy, **params)
cerebro.broker.setcash(1_000_000)
cerebro.broker.setcommission(0.001)
cerebro.addanalyzer(bt.analyzers.Returns, _name="returns")
results = cerebro.run()
ret = results[0].analyzers.returns.get_analysis()["rtot"] * 100
print(f"{name}: {ret:.1f}%")
compare_strategies("7203.T")
パラメーター最適化
def optimize_strategy(ticker):
"""パラメーターを最適化"""
cerebro = bt.Cerebro()
cerebro.adddata(get_data_for_bt(ticker))
# 最適化:short_periodとlong_periodの全組み合わせをテスト
cerebro.optstrategy(
MACrossStrategy,
short_period=range(10, 50, 10),
long_period=range(50, 200, 25)
)
cerebro.broker.setcash(1_000_000)
cerebro.broker.setcommission(0.001)
cerebro.addanalyzer(bt.analyzers.Returns, _name="returns")
results = cerebro.run()
# 結果をDataFrameに整理
opt_results = []
for run in results:
strat = run[0]
ret = strat.analyzers.returns.get_analysis()["rtot"] * 100
opt_results.append({
"short": strat.params.short_period,
"long": strat.params.long_period,
"return(%)": round(ret, 1)
})
df = pd.DataFrame(opt_results).sort_values("return(%)", ascending=False)
print("Top10パラメーター:")
print(df.head(10))
return df
optimized = optimize_strategy("7203.T")
まとめ
Backtraderは手数料・ポジション管理・複数銘柄に対応した本格的なバックテストフレームワークです。パラメーター最適化機能も充実しており、プロフェッショナルな戦略検証が可能です。

