見出し画像

仮想通貨自動売買botのバックテスト環境の作り方

はじめに

仮想通貨の売買手法の一つに自動売買botがあります。自動売買botとは、あらかじめプログラムしておいた戦略に従って、コンピュータに自動で売買させるもののことを言います。
botを構築・運用するフローは下記が一般的かと思います。各フローは一回実施して終わり、というものではなく、より良い戦略を求めて何度も繰り返されます。なかでも1と2のフローは、実市場投入前のテストとなるため、ここで良い戦略を見つけ出すことが重要となります。

  1. 取引戦略の立案

  2. 過去データを用いたバックテストによる戦略の妥当性評価

  3. 実市場に投入し、運用

しかしながら2のバックテストには、バックテストを行う環境整備に加えて、過去データの取得や整形の処理が必要になり、意外と手間がかかります。そこで本記事では、バックテスト環境構築方法の紹介およびプログラムの販売を行います。

バックテスト環境構築方法の紹介

バックテストには、PythonのライブラリであるBacktesting.pyを利用します。Backtesting.pyに対して、①過去データ(OHLCV)と、②バックテストしたい戦略を与えることで、バックテストが行えます。
①過去データは、GMOコインで提供されているヒストリカルデータを利用します。ヒストリカルデータは取引履歴のデータであり、そのままではbacktesting.pyに与えることができず、OHLCV形式に変換する必要があります。OHLCVは、Open(始値), High(高値), Low(安値), Close(終値), Volume(出来高)を表したローソク足表現に必要なデータです。
②バックテストしたい戦略はbotの肝となる部分です。今回はバックテスト環境を構築することが目的であるため、単純に移動平均線のゴールデンクロスで買い注文、デッドクロスで売り注文を出すものとします。

このような前提を踏まえ、下記のようなプログラムを作成しました。プログラミング言語にはPython 3を用いています。

  1. 前準備

    1. GMOコインより過去の取引履歴を取得し、データベースに保存

    2. 取引履歴から1秒間隔のOHLCVデータを作成し、データベースに保存

  2. バックテスト

    1. 1秒間隔のOHLCVデータから、任意時間軸のOHLCVに変換(ダウンサンプリング)

    2. 任意時間軸のOHLCVデータとバックテストしたい戦略を用いてバックテスト

    3. 結果出力

このようなプログラムを実行することで以下のような結果が得られます。今回は簡単な例として2021年12月中の10日間について、1時間足でバックテストを行った結果を載せています。

可視化したバックテスト結果
Start                     2021-12-09 21:00:00
End                       2021-12-20 20:00:00
Duration                     10 days 23:00:00
Exposure Time [%]                   90.530303
Equity Final [$]                    9227410.0
Equity Peak [$]                    10980166.0
Return [%]                            -7.7259
Buy & Hold Return [%]               -1.902373
Return (Ann.) [%]                  -91.333486
Volatility (Ann.) [%]               10.856734
Sharpe Ratio                              0.0
Sortino Ratio                             0.0
Calmar Ratio                              0.0
Max. Drawdown [%]                  -18.341854
Avg. Drawdown [%]                   -6.223474
Max. Drawdown Duration        5 days 12:00:00
Avg. Drawdown Duration        1 days 15:00:00
# Trades                                   11
Win Rate [%]                        36.363636
Best Trade [%]                       3.392896
Worst Trade [%]                     -5.351754
Avg. Trade [%]                      -0.486244
Max. Trade Duration           1 days 21:00:00
Avg. Trade Duration           0 days 22:00:00
Profit Factor                        0.631329
Expectancy [%]                      -0.457763
SQN                                 -0.573955

これらの結果より、Returnは-7.72%と、この戦略ではマイナスリターンになることがわかります。
この戦略の変数としては、2つの移動平均線それぞれの平均を取る期間となります。期間の取り方にはいろいろなパターンが考えられますが、backtesting.pyでは様々なパターンを総当たりで試して、最も良いものを見つけ出す、といったことが可能です。そのような方法により改善した結果が下記となります。

パラメータ変更後のバックテスト結果
Start                     2021-12-09 21:00:00
End                       2021-12-20 20:00:00
Duration                     10 days 23:00:00
Exposure Time [%]                   89.772727
Equity Final [$]                   11067294.0
Equity Peak [$]                    11473294.0
Return [%]                           10.67294
Buy & Hold Return [%]               -1.902373
Return (Ann.) [%]                 2085.717421
Volatility (Ann.) [%]             1564.244004
Sharpe Ratio                         1.333371
Sortino Ratio                       55.102496
Calmar Ratio                       258.189702
Max. Drawdown [%]                   -8.078236
Avg. Drawdown [%]                   -4.532622
Max. Drawdown Duration        3 days 05:00:00
Avg. Drawdown Duration        1 days 02:00:00
# Trades                                   11
Win Rate [%]                        63.636364
Best Trade [%]                       5.492743
Worst Trade [%]                     -2.955451
Avg. Trade [%]                       0.643194
Max. Trade Duration           2 days 00:00:00
Avg. Trade Duration           0 days 22:00:00
Profit Factor                        2.099845
Expectancy [%]                       0.672754
SQN                                   0.72316

Returnは+10.67%とプラスになりました。
このようにバックテストを行うことで、売買戦略の事前検証が可能となります。(今回の例は期間をとても短くしているため、過去データの期間でしか有用でない可能性があります。この点も踏まえて、様々な戦略を様々な期間で検討、テストする必要があります。)

有料記事部分に含まれる内容

上記のようなプログラムを、有料記事部分で配布しています。Python3の環境が整っている場合は、zipファイルをダウンロードし、すぐに実行することが可能です。

プログラムの実行方法

前提条件として、Python 3をインストールしておいてください。PowerShell等のコンソールで下記を実行して、Pythonのバージョンとpipのバージョンがそれぞれ表示されていれば大丈夫です。(本記事ではPython 3.10.1で動作検証しています。)

C:\Users\Administrator>python --version
Python 3.10.1

C:\Users\Administrator>pip --version
pip 21.2.4 from C:\Users\Administrator\AppData\Local\Programs\Python\Python310\lib\site-packages\pip (python 3.10)

添付されている適当なフォルダに展開(下記例ではC:\note)し、フォルダのトップで下記コマンドを実行してください。その結果、バックテスト結果がコンソールに表示されるとともに、可視化されたhtmlファイルが生成されます。生成されたhtmlファイルはブラウザで開くことで、売買のタイミングや資金推移を確認できます。

C:\note>pip install -r requirements.txt
# ライブラリのインストール処理が行われます

C:\note>python main.py
# プログラムが実行され、下記処理が行われます。
# - 過去データをダウンロード
# - OHLCVデータへの変換
# - バックテスト
# - バックテスト結果の表示

zipファイル内に含まれるファイルの解説

zipファイル内には下記ファイルが含まれています。

  • main.py

    • メインのプログラムです。このプログラムから他のプログラムを呼び出すことで、上記で述べた前準備およびバックテストを行います。

  • DatabaseAccessor.py

    • データベースにはsqliteを用いていますが、それに対する操作を行うプログラムです。

  • InitializeDatabase.py

    • データベースの初期化に用いるプログラムです。

  • GetTradeHistory.py

    • GMOコインから過去データを取得し、データベースに格納するプログラムです。

  • requirements.txt

    • プログラムの実行に必要な依存ライブラリが定義されているファイルです

  • data(空フォルダ)

    • GMOコインから取得した過去データを格納するフォルダです

プログラム中の変更可能なパラメータ

main.pyの下記部分を変更することで、様々な条件でのバックテストが可能です。

バックテストを行う銘柄の変更

32行目の下記BTCの部分を変更することで対象銘柄の変更が可能です。利用可能な銘柄は、GMOコインのヒストリカルデータページに記載されているものとなります。レバレッジ取引のデータを使いたい場合は、スラッシュをアンダーバーに変更してください。(例:"BTC/JPY"の場合、"BTC_JPY"と指定)

symbol = "BTC"

バックテストを行う期間の変更

37,38行目の下記日時指定部分を変更することで、対象期間の変更が可能です。1つめのdateから、2つめのdateまでのデータを取得し、バックテストに用います。

    GetTradeHistory.getTradeHistory(
        dbName, symbol, date(2021, 12, 10), date(2021, 12, 21))

ダウンサンプリングの期間変更

42行目の下記freq指定部分を変更することで、ダウンサンプリングの期間の変更が可能です。"1H"は1時間間隔、"2H"は2時間間隔といったように指定でき、"1T"は1分間隔、"30T"は30分間隔といったような形になります。"H"は時間間隔、"T"は分間隔、"S"は秒間隔を表します。詳細についてはpandasのドキュメントを参照してください。

    freq = "1H"

戦略の変更

12-26行目の下記部分がバックテストする戦略となります。今回は移動平均線のゴールデンクロスで買い、デッドクロスで売りという戦略で、短期間の移動平均線で利用するローソク足の数が10、長期間の移動平均線で利用するローソク足の数が20、としています。戦略の記述方法については、backtesting.pyのドキュメントを参照してください。

# バックテストする戦略
class SmaCross(Strategy):
    n1 = 10
    n2 = 20

    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.sell()

バックテスト実行時条件の変更

55-64行目の下記部分でバックテストを行う際のパラメータを指定しています。各パラメータについてはコメントおよびbacktesting.pyのドキュメントを参照してください

    # バックテストの設定
    bt = Backtest(
        down_sampled_df_trades,  # 時系列データ
        SmaCross,                # テストする戦略
        cash=10000000,           # 最初の余力
        commission=0,            # 取引手数料
        margin=0.5,              # レバレッジ倍率の逆数(0.5で2倍レバレッジ)
        trade_on_close=False,    # True: 現在の終値で取引, False: 次の始値で取引
        exclusive_orders=True    # True:自動でポジションをクローズ, False: 手動でポジションをクローズ
    )

戦略の最適化条件の変更

71-76行目の下記部分で戦略の最適化を行っています。戦略定義時は移動平均線の計算で用いるローソク足の数は固定でしたが、このようなプログラムにより、計算で用いるローソク足の数を5~30の間を5刻みで変更した際に、最も収益が最大となるパラメータを探索することが出来ます。

    output2 = bt.optimize(
        n1=range(5, 30, 5),     # n1について、5~30の間を5刻みで探索
        n2=range(5, 30, 5),     # n2について、5~30の間を5刻みで探索
        maximize='Equity Final [$]',        # Equity Finalを最大化
        constraint=lambda p: p.n1 < p.n2)   # n1<n2となるように制約


以下有料記事部分でプログラムを格納したzipファイルを添付しています

ここから先は

0字 / 1ファイル

¥ 1,000

この記事が気に入ったらサポートをしてみませんか?