【MT5 API シストレ開発②】シンプルな戦略をバックテストする方法
この記事は、システムトレードを自身のPCで実装するためのシリーズ第2回です。
今回は、「Backtrader」を用いたルールベース戦略のバックテストの方法を紹介します。
バックテスト方法
まずは、過去データを使ってどのようにバックテストを行うのか、そのイメージをつかみましょう。
実際の取引では、新規注文と決済注文の価格差から損益が算出され、そこから手数料やスプレッド、スリッページといった取引コストが差し引かれた分が最終的な損益となります。
新規注文を出す時点では決済注文を出す時点の価格はわからない、つまり未来の情報は常にわからないのですが、この状況を過去データで再現する必要があります。

時間経過とともに新たな価格(4本値)が生成されて、「定義された戦略ロジックの条件」を満たすと注文を出してポジションを保有します。
ポジションを保有しているときも、新たな価格(4本値)が生成されたときに決済条件を満たしているかどうかの判定が入り、条件を満たしていればポジションを解消して損益結果を計算します。
このようなループを過去データで実現するためのプログラムを作成し、バックテストを実施します。

Backtrader
Backtraderは過去データを時系列に沿って1つずつ読み取り、実際のトレードを擬似的に再現するPythonのバックテスト用ライブラリです。
Pythonのバックテストツールはいくつか存在しますが、この記事ではBacktraderを扱います。
事前に以下のコマンドでインストールします。
pip install backtrader
Backtraderにはさまざまな機能がありますが、ここではバックテストに必要な①DataFeed、②Strategy、③Broker、④Analyzer、⑤Cerebroの5つを説明します。
➀ DataFeed
DataFeedはバックテストに用いる過去データを取り扱う役割を持っています。
データは基本的に4本値が含まれる時系列の表データを使います。
この表データの一行が1期間(日足であれば1日、1時間足であれば1時間)を示し、一行ずつデータを渡して時間経過を再現します。
➁ Strategy
Strategyは、ユーザーが定義した売買ルールに従って取引シグナルを出す役割を担います。
DataFeedから新たなデータを受け取ったときプログラムを実行して、必要に応じてシグナルを出します。
➂ Broker
バックテスト内で適用する証拠金や取引コスト、スリッページなどを定義して、損益額を計算します。
④ Analyzer
バックテストのパフォーマンス分析を行う役割です。
バックテスト後にトレード統計を取得します。
⑤ Cerebro
Cerebroはそれぞれの機能をコントロールする役割です。
この後説明するバックテストの各操作はCerebroによって行っていきます。
簡単な戦略のバックテスト
まずは単純な戦略として、2本の単純移動平均線(SMA)のクロスで取引する戦略を作ってみましょう。
1.戦略を作成する
まずは戦略を定義します。
Backtraderでの戦略の作り方の例は以下の通りです。
import backtrader as bt
class SmaCross(bt.Strategy):
params = dict(
fast=20,
slow=60,
size=100,
)
def __init__(self):
close = self.data.close
self.fast_ma = bt.ind.SMA(close, period=self.p.fast)
self.slow_ma = bt.ind.SMA(close, period=self.p.slow)
self.crossover = bt.ind.CrossOver(self.fast_ma, self.slow_ma)
def next(self):
if not self.position:
if self.crossover > 0:
self.buy(size=self.p.size)
else:
if self.crossover < 0:
self.close()
上記のコードのように戦略クラスを作成します。
クラス名は何の戦略かわかりやすい名前を付けたいので「SmaCross」としています。
SmaCrossクラスの冒頭で、「params」に示す箇所に設定値を作成します。
この例では、2本のSMAを使うためSMAの期間を2つと、取引の枚数を設定します。
次に「__init__」ですが、ここにはバックテストの開始時に一度だけ実行する処理を記述します。
このコードでは以下の3つの内容を記述しています。- ●終値の設定
- ●短期SMAと長期SMAの設定
- ●クロスを数値化するインジケーターの設定
最後に「next」ですが、これは時間経過のたび(新たな4本値が呼ばれるたび)に実行する処理を記述します。
今回はゴールデンクロスが出たら買い、デッドクロスが出たら決済するだけの戦略を書いています。
2本のSMAのクロスを観測するインジケーター(crossover)を定義済みなので、その状況に応じて条件分岐を作成しています。
2.データを設定する
戦略を作成したら、Backtraderで利用する時系列データを設定します。

このような4本値を含むデータ(rates_df)を持っているとして、このデータをBacktraderに認識させるコードを記載します。
data = bt.feeds.PandasData(
dataname=rates_df,
open='open',
high='high',
low='low',
close='close',
volume='tick_volume',
openinterest=None
)
「4本値の過去データが入っているデータフレームを教える」「open, high, low, close, volume, openinterestを示す列名を教える」というような意味を含んでいます。
これでBacktraderが扱うデータを指定することができました。
3.バックテストを実行する
戦略の定義とデータの設定が終われば、いよいよバックテストを実行できます。
Cerebroを使って各種操作を行っていきます。
cerebro = bt.Cerebro()
# データ投入
cerebro.adddata(data)
# 戦略投入
cerebro.addstrategy(SmaCross)
# 初期資金
cerebro.broker.setcash(100_000)
# 手数料(例:往復0.01%)
cerebro.broker.setcommission(commission=0.0001)
# バックテスト実行
results = cerebro.run()
まず「cerebro = bt.Cerebro()」でバックテスト全体を制御する「Cerebroクラスのインスタンス(オブジェクト)」を1つ生成します。
これは、これからcerebroを使ってバックテストを行うための準備のようなイメージです。
# データ投入
cerebro.adddata(data)
# 戦略投入
cerebro.addstrategy(SmaCross)
ここでは事前に作成したデータと戦略を投入しています。
# 初期資金
cerebro.broker.setcash(100_000)
# 手数料(例:往復0.01%)
cerebro.broker.setcommission(commission=0.0001)
続いて「broker」にて、バックテストの初期証拠金と手数料を設定します。
今回は簡易的な設定に留めています。
# バックテスト実行
results = cerebro.run()
ここまでの設定が終わったら最後にバックテストを実行します。
バックテストを実行したあとは、以下のコードで簡易的な可視化ができます。
cerebro.plot(iplot=False, volume=False)

意図したタイミングで売買が行われているかが視覚的に確認できます。
バックテスト結果の詳しい評価方法については、次回以降の記事で解説します。
次回について
今回の記事ではBacktraderを用いたルールベースの戦略をバックテストする方法を解説しました。
次回は、戦略の最適化とアウトオブサンプルテストを解説します。
【MT5 API シストレ開発】
本記事の執筆者:藍崎@システムトレーダー
| 本記事の執筆者:藍崎@システムトレーダー | 経歴 |
|---|---|
![]() |
個人投資家としてEA開発&システムトレード。 トレードに活かすためのデータサイエンス / 統計学 / 数理ファイナンス / 客観的なデータに基づくテクニカル分析 / 機械学習 / MQL5 / Python |
EA(自動売買)を学びたい方へオススメコンテンツ

OANDAではEA(自動売買)を稼働するプラットフォームMT4/MT5の基本的な使い方について、画像や動画付きで詳しく解説しています。MT4/MT5のインストールからEAの設定方法までを詳しく解説しているので、初心者の方でもスムーズにEA運用を始めることが可能です。またOANDAの口座をお持ちであれば、独自開発したオリジナルインジケーターを無料で利用することもできます。EA運用をお考えであれば、ぜひ口座開設をご検討ください。
本ホームページに掲載されている事項は、投資判断の参考となる情報の提供を目的としたものであり、投資の勧誘を目的としたものではありません。投資方針、投資タイミング等は、ご自身の責任において判断してください。本サービスの情報に基づいて行った取引のいかなる損失についても、当社は一切の責を負いかねますのでご了承ください。また、当社は、当該情報の正確性および完全性を保証または約束するものでなく、今後、予告なしに内容を変更または廃止する場合があります。なお、当該情報の欠落・誤謬等につきましてもその責を負いかねますのでご了承ください。
