【Python】トレード戦略をバックテストして有効性を検証する

この記事は約11分で読めます。

 

前回までのあらすじ

 

前回はビットコインの価格データをCoingeckoからAPIを使って取得しました。

 

 

 

 

今回はこの価格データからトレードシュミレーションを行い、戦略の有効性をバックテストを引き続きPythonを使って行っていきたいと思います。

 

 

トレード戦略・バックテストとは何か?

 

システムトレードを行うにあたって、実際にプログラムを稼働させる前に、そのプログラムの過去のパフォーマンスを計算することを「バックテスト」と言います。

 

基本的にこのバックテストの成績で、トレード戦略の相場に対する有効性(パフォーマンス)を測り、実際に取引所で稼働させるかどうか検証します。

 

計算には基本的にプログラミング言語を使用します。要はデータ分析なので、言語はR・Pythonなんかで行われることが多いです。

 

 

Pythonでバックテストをやってみる

 

という訳で実際にPythonでのバックテストのコードを書いていきます。

 

・実行環境

    Windows10

    Python3.7

    Anaconda(jupyternotebook)

 

 

まずはバックテストで使うライブラリをインポートします。

 

 

# ライブラリの読み込み
import matplotlib.pyplot as plt
%matplotlib inline
import numpy as np
import pandas as pd
import time
import datetime
import requests
import json

#ビットコインの価格データを取得する
def get_btcprice(ticker,max): 
    url = ('https://api.coingecko.com/api/v3/coins/')+ticker+('/market_chart?vs_currency=jpy&days=')+max
    r = requests.get(url)
    r2 = json.loads(r.text) 
    return r2

# ビットコインの全期間の価格データを取得する
r2 = get_btcprice('bitcoin', 'max')


# 取得した価格データを整形する
# ライブラリの読み込み
from datetime import datetime
import pandas as pd

# jsonから価格データだけをPandasに変換して抽出する
def get_price(r2):
    s = pd.DataFrame(r2['prices'])
    s.columns = ['date','price']
    date = []
    for i in s['date']:
        tsdate = int(i/1000)
        loc = datetime.utcfromtimestamp(tsdate)
        date.append(loc)
    s.index = date
    del s['date']
    return s

btc = get_price(r2)
btc

 

 

<実行結果>

 

 

使用するのライブラリはPythonでデータ分析をする上でよく使うライブラリですし、前回の記事なので特に問題はないと思います。

 

 

データを可視化する

 

データが読み込めたら、まずは可視化してみましょう。

 

# データを可視化する
btc.plot()

 

 

すると↓のようなグラフが表示されます。

 

 

中々壮大なチャートになっています。。。

 

 

変化率から累積リターンを計算する

 

データの概要が掴めたところで次は変化率から累積リターンを計算します。基本的にトレードのリターンは変化率の合計で考えます。

 

変化率の計算は普通にfor文で計算することもできますが、Pythonであればpandasの関数pct_change()で一発で計算できます。

 

 

# 変化率を計算する
change = btc['price'].pct_change()
change

 

 

<実行結果>

 

 

そして、この変化率から累積変化率を計算します。累積変化率の計算には対数化などが必要ですが、pandasのcumprod()で一発で計算できます。Python超便利ですね。

 

 

# 変化率からトータルリターン(累積変化率)を計算する
trade_return = (change + 1).cumprod()
trade_return[0] = 1
trade_return = trade_return*10000
print(trade_return.head(), trade_return[-5:])

 

 

<実行結果>

 

 

 

 

この累積変化率が意味するものは、2013年4月28日から毎日ビットコインを1万円分購入して、次の日に売るということを繰り返していれば2019年6月23日には87万8,669円になっていたという計算になります。取らぬ狸の皮算用とはいえスゴイリターンですね。

 

ちなみにこのビットコインの価格データは毎日更新されていきますので、コードを実行する日によって累積リターンは変わります。

 

 

トレード戦略を考えバックテストで累積リターンを計算する

 

さてここからが本題なわけで次は適当なトレード戦略を考えて、その戦略に従って取引した場合の累積トレードリターンをPythonで計算してみます。

 

今回はとりあえず単純移動平均線を使ってみましょう。移動平均はtalibがなくてもPandasの関数.rolling().mean()で簡単に計算することができます。

 

 

#移動平均を計算する
EMA5 = btc['price'].rolling(5).mean()
EMA25 = btc['price'].rolling(25).mean()

 

 

このトレード戦略となる売買基準のことを一般的に『シグナル』といいます。トレード戦略のバックテストを行う際はまずこのシグナルの数値を計算し、そこからif文でシグナルに沿って『トレードシグナル』を計算します。

 

トレードシグナルとは、要は買いか、売りかのサインのことで、買いは1売りは-1とします。今回のシグナルは5日移動平均が25日移動平均より上ならば買い、下ならば売りとします。

 

この戦略によるトレードシグナルをPythonで計算する場合は↓のように記述します。

 

#トレード戦略から売買シグナルを計算する
signal = []
for i in range(len(btc['price'])): 
    #5日平均が25日平均より上なら買い=1とする 
    if EMA5[i] > EMA25[i]: 
        signal.append(1)
 
    # 5日平均が25日平均より下なら売り=-1とする 
    elif EMA5[i] < EMA25[i]: 
        signal.append(-1) 
    else: signal.append(0) 
signal

 

 

実行すると0(ノーポジ)と1(購入/ロング)と-1(売却/ショート)が格納されたsignalリストが生成されます。これがトレードシグナルです。

 

バックテストでトレード戦略の累積リターンの計算する方法は、『価格の変化率×トレードシグナル』が一般的です。

 

またn日のトレードシグナルから、n+1日目に 買い or ノーポジ or 売りを実行するので、シグナルと変化率はズラして計算する必要があります。そのまま計算すると、完璧な未来予知なのでトンデモリターンになります。

 

バックテストによる累積リターンの計算と計算結果の視覚化をPythonでは↓ように実装できます。

 

# プロット用ライブラリの読み込み
from pylab import rcParams
import matplotlib as mpl

# 日本語フォントの読み込み(エラーになる人はスルーしてください)
font = {"family":"Noto Sans CJK JP"}
mpl.rc('font', **font)

#キャンバスのサイズを大きくする
rcParams['figure.figsize'] = 10,5

# 日次変化率×トレードシグナルの累積変化率で
# トレード戦略に従ってトレードした累積リターンを算出する
backtest_return = ((change[1:-1] * signal[0:-2]) + 1).cumprod() 
x = btc.index[0:-2] 

# matplotlibでリターンの推移を可視化
plt.title('トレードリターンの比較') 
plt.plot(x, returns[0:-2], 'b', label='ホールドした場合のリターン', alpha=0.3, linewidth=0.5) 
plt.plot(x, backtest_return, 'orange', label='移動平均で取引した場合のリターン', alpha=1, linewidth=1.5) 
plt.grid(which='both') 
plt.legend()
plt.show()

 

 

<実行結果>

 

 

ちなみにMatplotlibに日本語入れたい場合は↓の記事を参照すれば簡単に日本語化が可能です。既にほかの方法で日本語化している人はフォントして云々くだりは無視して普通にプロットしてください。

 

参考記事:【python】Matplotlibで日本語化して文字化けを無くす

 

 

<おまけ>

# 出力した画像を保存する 
plt.savefig('backtest_return.png')

 

 

スポンサーリンク
スポンサーリンク

バックテストを有効性検証する指標の計算

 

バックテストでトレード戦略の有効性を検証する際は、累積リターン以外にも色々あり、ここではそのいくつか紹介していきたいと思います。

 

 

・最大ドローダウン

累積リターンが最大の時点からどれくらい減少したか、トレード戦略の安定性を測るもの最大ドローダウンが低いほどリターンが安定しているということを意味する

 

・勝率

計算方法・勝ちトレード数÷全トレード数

 

・ペイオフレシオ

計算方法:勝ちトレードの平均利益額÷負けトレードの平均損失額

 

・プロフィットファクター

計算方法:純利益÷純損失

 

 

これらのトレード戦略指標をPythonで実装するコードはここで記述すると、記事が長くなってしまうので、別の記事に書いています。

 

 

参考記事:【自動取引】トレード戦略のバックテスト①~MACDとモメンタムの併用

 

 

 

終わり

 

以上が簡単なトレードシュミーションを行った場合の累積トレードリターンの計算方法と有効性の検証方法です。こういう計算が簡単にできるのがプログラミング言語の強みですね。特にこういったデータ分析系の処理ではPythonがホント便利です。

 

また移動平均以外のテクニカル指標を計算する関数はPandasにはないので、自分で計算する必要がありますが、Pythonには『talib』というライブラリがあり、それをインストールすれば、関数1つで簡単に計算することができます。talibのインストールと使い方については↓の記事で解説しています。

 

 

 

次は実際にビットコイン取引所のAPIを使って残高の確認や注文の発注を行っていきます。これらの知識を合わせるとビットコインの自動取引botを作ることができます。

 

 

Pythonで自動売買Botを作る①~システムトレードの流れを把握する

 

ビットコインの「ブロックチェーン技術」を超わかりやすく説明してみる

 

大学生に超オススメな格安プログラミングスクール「クリプテックアカデミア」の評判・レビュー

 

 

コメント

タイトルとURLをコピーしました