4
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Python Backtraderで米国株/ETFのバックテストをはじめてみる

Last updated at Posted at 2022-05-01

Backtrader 』というバックテスト/システムトレード向けのPythonフレームワークが気になったので触れてみることに。
本記事では、環境構築~簡易サンプルコード実行までを(備忘録用に)まとめました。

私の環境は下記の通りです。

Windows 10
Python 3.10.0
Jupyter Notebook

準備

本記事のサンプルコードを動かすためのライブラリをインストールしていきます。

Backtrader DocumentationのQuickstart Guideのサンプルコードを一通り動かす場合は、backtrader githubページ記載の手順に従えばOKです。
Download ZIPで『datas』フォルダのデータをローカルに持ってくることもお忘れなく。

backtrader

このフレームワークを利用することによって、バックテスト/トレーディングのためのインフラ構築を簡単に行うことができます。
端末で下記いずれかのコマンドを実行し、インストールします。

pip install backtrader
pip install backtrader[plotting] # matplotlib 未インストールの場合

plotするには matplotlib のバージョンは最低 1.4.1 は必要みたいです。`

yfinance

Yahoo!Financeからマーケット情報をダウンロードするために使用します。
yfinance githubページにも記載されている通り、Yahoo, Inc.公認のAPIではないため、注意して扱う必要がありそうです。

pip install yfinance

yfinence を使用するためには、他に Pandas , Numpy , requests , lxml が必要になります。
各ライブラリの必要なバージョン等については、上記リンクよりご確認ください。

動作確認

今回はできるだけシンプルに、コードが機能するかを確かめます。
従って、取引戦略を凝ったり、手数料を考慮する等、細かいロジックは実装しません。

データ取得

まずは yfinance を使ってデータを取りに行きましょう。
今回の対象は米国ETFの VTI とします。

import yfinance as yf
data = yf.download('VTI', start='2022-04-01', end='2022-05-01')
data

''' 実行結果 -> '''
	Open	High	Low	Close	Adj Close	Volume
Date						
2022-03-31	230.679993	231.320007	227.610001	227.669998	227.669998	4087000
2022-04-01	228.660004	228.750000	226.630005	228.580002	228.580002	3455900
2022-04-04	228.860001	230.539993	228.380005	230.520004	230.520004	3241100
...	...	...	...	...	...	...
2022-04-27	209.850006	212.399994	208.550003	209.660004	209.660004	4955900
2022-04-28	211.880005	215.750000	209.449997	214.770004	214.770004	3767700
2022-04-29	212.899994	214.309998	206.710007	206.880005	206.880005	7326200

日毎の始値や終値などの情報が入っていますね。
ちなみに、データの型はDataFrameです。

type(data)

''' 実行結果 -> '''
pandas.core.frame.DataFrame

Backtraderについて

サンプル全体を動かす前に、backtraderの基礎を一度おさえておきます。
基本的な構成は以下のようになります。

1. Strategyの構築
調整するパラメータを決定したうえで、マーケットへのEntry/Exitのロジックを記述します。 必要となる指標があればStrategy内でインスタンス化します。
2. Cerebro Engineの作成
データ入力やStrategyの実行、データ監視をまとめて行ってくれます。バックテスト/データ供給/トレーディングの核を担う部分になります。
3. Cerebro Engineの実行
データのロードと入力を行い(cerebro.adddata)、実行(cerebro.run())します。cerebro.plot()で結果を図示できます。
基本構成
import backtrader as bt

# Strategyの構築
class MyStrategy(bt.Strategy):
   ''' 処理を記載 '''

# Cerebro Engineの作成
cerebro = bt.Cerebro()

# データロード/入力
data = ''' データを取ってくる '''
cerebro.adddata(data)

# 実行
cerebro.run()

自作したMyStrategyクラスはbt.Strategyクラスを継承しているため、特定のメソッドを記述するだけで、Cerebro Engineの方で良い感じに実行してくれます。

サンプルコードの実行

それでは、VTI のData FeedをCerebro Engineに渡して、動かしてみましょう。

サンプルコード
サンプルコード全体
import backtrader as bt
import yfinance as yf

class MyStrategy(bt.Strategy):

    # 実行記録
    def log(self, txt, dt=None):
        dt = dt or self.datas[0].datetime.date(0)
        print('%s, %s' % (dt.isoformat(), txt))

    # コンストラクタ
    def __init__(self):
        
        self.dataclose = self.datas[0].close

        self.order = None

    # 処理通知部
    def notify_order(self, order):
        if order.status in [order.Submitted, order.Accepted]:
            return

        # 取引内容を通知
        if order.status in [order.Completed]:
            if order.isbuy():
                self.log('BUY EXECUTED, %.2f' % order.executed.price)
            elif order.issell():
                self.log('SELL EXECUTED, %.2f' % order.executed.price)

            self.bar_executed = len(self)

        elif order.status in [order.Canceled, order.Margin, order.Rejected]:
            self.log('Order Canceled/Margin/Rejected')

        self.order = None

    # 売買処理部
    def next(self):
        
        self.log('Close, %.2f' % self.dataclose[0])

        if self.order:
            return

        # マーケットにいるかチェック
        if not self.position:

            # 3セクション連続下落で購入
            if self.dataclose[0] < self.dataclose[-1]:
                if self.dataclose[-1] < self.dataclose[-2]:
                    
                    self.log('BUY CREATE, %.2f' % self.dataclose[0])
                    self.order = self.buy()

        else:

            # 5セクション経過で良かれ悪かれ売却
            if len(self) >= (self.bar_executed + 5):
                
                self.log('SELL CREATE, %.2f' % self.dataclose[0])
                self.order = self.sell()
                

# ETF:VTIのデータをダウンロード
yf_data = yf.download('VTI', start='2022-04-01', end='2022-05-01')
# データをCerebro Engine用のフォーマットに変換
data = bt.feeds.PandasData(dataname=yf_data)

# Cerebro Engineの作成
cerebro = bt.Cerebro()
# Strategyの読み込み
cerebro.addstrategy(MyStrategy)
# データ入力
cerebro.adddata(data)

# ターゲット資産の設定
cerebro.broker.setcash(400)

# 実行
cerebro.run()

# 最終結果を表示
print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
実行結果
実行結果
[*********************100%***********************]  1 of 1 completed
2022-03-31, Close, 227.67
2022-04-01, Close, 228.58
2022-04-04, Close, 230.52
2022-04-05, Close, 227.15
2022-04-06, Close, 224.54
2022-04-06, BUY CREATE, 224.54
2022-04-07, BUY EXECUTED, 224.20
2022-04-07, Close, 225.39
2022-04-08, Close, 224.69
2022-04-11, Close, 221.18
2022-04-12, Close, 220.50
2022-04-13, Close, 223.39
2022-04-14, Close, 220.67
2022-04-14, SELL CREATE, 220.67
2022-04-18, SELL EXECUTED, 220.41
2022-04-18, Close, 220.29
2022-04-18, BUY CREATE, 220.29
2022-04-19, BUY EXECUTED, 220.23
2022-04-19, Close, 224.17
2022-04-20, Close, 223.88
2022-04-21, Close, 220.22
2022-04-22, Close, 214.22
2022-04-25, Close, 215.39
2022-04-26, Close, 209.25
2022-04-26, SELL CREATE, 209.25
2022-04-27, SELL EXECUTED, 209.85
2022-04-27, Close, 209.66
2022-04-28, Close, 214.77
2022-04-29, Close, 206.88
Final Portfolio Value: 385.83

Strategyの売買ロジックとしては、
3セクション連続で基準価格(終値)が下落した場合に買い注文(成行)を実施し、
5セクション経過で売り注文を実施しています。
ただし、まだマーケットに出ていない場合は、買い注文のみの実行となっています。
注意点として、売買の判断材料は対象銘柄の終値となっているため、売買が実行されるのは 翌営業日 になっています。

一例
2022-04-26, SELL CREATE, 209.25
2022-04-27, SELL EXECUTED, 209.85

ターゲット資産400.00 [dol] に対し、このStrategyを適用すると、資産が385.83 [dol] まで減ってしまいました。
利益を上げるには、Strategyをしっかり練る必要がありそうです。

今回の目的である「 backtrader の動作確認」は達成しましたので、本記事の内容としては以上になります。

4
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?