Pythonによるバックテスト1
Pythonによるバックテスト
Pythonでバックテストを行うためのライブラリです。MQLが苦手だけど、Pythonは少しできるといった方は、こちらを使うのが良いのではないでしょうか?機械学習を用いたトレード検証を行うのに有益なツールの1つです。
概要
ウェブサイトからの文言を抜粋します。
Does it seem like you had missed getting rich during the recent crypto craze? Fret not, the international financial markets continue their move rightwards every day. You still have your chance. But successful traders all agree emotions have no place in trading — if you are ever to enjoy a fortune attained by your trading, better first make sure your strategy or system is well-tested and working reliably to consistent profit. Mechanical or algorithmic trading, they call it. They’ll usually recommend signing up with a broker and trading on a demo account for a few months … But you know better. You know some programming.
最近の暗号ブームで一攫千金を逃したように思われますか?ご心配なく、国際金融市場は日々右肩上がりの動きを続けています。以前としてチャンスはあります。しかし、成功しているトレーダーは皆、トレーディングに感情は関係ないことに同意しています。もし、これまでトレーディングによって得た富を享受したことがあるなら、まず最初にした方が良いのは、あなたの戦略やシステムが十分にテストされ、安心して安定した利益が得られるかどうかです。機械的取引、もしくはアルゴリズム取引、人々をそう呼んでいます。普通はブローカーと契約し、数ヶ月間デモ口座で取引することを勧めます… しかし、あなたはもっと分別があります。プログラミングを知っています。
It is far better to foresee even without certainty than not to foresee at all.
確信がなくても予見することは、まったく予見しないよりはるかに良い。
— Henri Poincare
Backtesting.py is a Python framework for inferring viability of trading strategies on historical (past) data. Of course, past performance is not indicative of future results, but a strategy that proves itself resilient in a multitude of market conditions can, with a little luck, remain just as reliable in the future. Improved upon the vision of Backtrader, and by all means surpassingly comparable to other accessible alternatives, Backtesting.py is lightweight, fast, user-friendly, intuitive, interactive, intelligent and, hopefully, future-proof. It is also documented well, including a handful of tutorials.
Backtesting.pyは、過去のデータから取引戦略の実行可能性を推測するためのPythonフレームワークです。もちろん、過去のパフォーマンスは将来の結果を示すものではありませんが、多くの市場環境においてそれ自体が回復力を持つことを証明した戦略は、少しの運があれば、将来も同様に信頼性を保つことができます。Backtraderの構想に基づいて改良されたBacktesting.pyは、軽量で、高速で、ユーザーフレンドリーで、直感的で、インタラクティブで、インテリジェントで、うまくいけば、将来性もあります。また、チュートリアルを含め、ドキュメントも充実しています。
インストール
以下を実行するだけです。Windowsでも問題なく動きます。
pip install backtesting
使い方
基本的な使い方を解説します。以下のような単純な戦略を考えてみましょう。
期間の異なる単純移動平均(SMA)を考えます。Fast SMAは10日間移動平均、Slow SMAは20日間移動平均とします。
- ゴールデンクロス: Fast SMAがSlow SMAをクロスしたらロング
- デッドクロス:Slow SMAがFast SMAをクロスしたらショート
SMAの計算はライブラリで用意されていますが、カスタムインジケータを利用する場合を想定してpandasで計算を行います。
import pandas as pd
def SMA(data, period):
return pd.Series(data).rolling(window=period).mean()
次に、backtestingライブラリから必要なモジュールを読み込みます。
from backtesting import Backtest, Strategy
from backtesting.lib import crossover
class SmaCross(Strategy):
n1 = 10
n2 = 20
def init(self):
close = self.data.Close
self.fast_sma = self.I(SMA, close, self.n1)
self.slow_sma = self.I(SMA, close, self.n2)
def next(self):
if crossover(self.fast_sma, self.slow_sma):
self.buy()
elif crossover(self.slow_sma, self.fast_sma):
self.sell()
戦略を作るときにStrategyクラスを継承したクラスを作成します。次にinit()で必要な機能を最初に定義します。StrategyのメソッドにI(インジケータ)があります。これは単なる値の配列ですが、next()で次の値が呼ばれるようになっています。
corssover関数によって2つSMAの値の大小関係をチェックすることができます。Fast SMAがslow SMAをクロスしたらself.buy()で実際にロングします。このメソッドはOrderを返します。これによって、移動平均による取引戦略を実装することができます。
なお、MQLだと以下のような形で結構長くなります。
#include <Trade\Trade.mqh>
#include <Trade\SymbolInfo.mqh>
input int ShortTerm_MA_Period = 10;
input int LongTerm_MA_Period = 20;
input ENUM_TIMEFRAMES Timeframe = PERIOD_H1;
input ENUM_MA_METHOD ma_method=MODE_SMA;
input ENUM_APPLIED_PRICE applied_price=PRICE_CLOSE;
input double Lots = 1.0;
int Slow_MA_Handle;
int Fast_MA_Handle;
double Short_MA_Array[];
double Long_MA_Array[];
CTrade m_trade;
CSymbolInfo m_symbol;
void OnInit()
{
Fast_MA_Handle = iMA(m_symbol.Name(), Timeframe, ShortTerm_MA_Period, 0, ma_method, applied_price);
Slow_MA_Handle = iMA(m_symbol.Name(), Timeframe, LongTerm_MA_Period, 0, ma_method, applied_price);
}
void OnTick()
{
int bar = Bars(Symbol(), Timeframe);
ArrayResize(Short_MA_Array, bar);
ArrayResize(Long_MA_Array, bar);
CopyBuffer(Short_MA_Handle, 0, 0, bar, Fast_MA_Handle);
CopyBuffer(Long_MA_Handle, 0, 0, bar, Slow_MA_Handle);
// 新しいバーが開始したら取引戦略を実行する
if (Volume[0] == 1)
{
if (Short_MA_Array[1] < Long_MA_Array[1] && Short_MA_Array[0] > Long_MA_Array[0])
{
// ゴールデンクロスが発生したら、BUY注文を出す
m_trade.Buy(Lots, m_symbol.Name(), m_symbol.Ask(), 0, 0);
}
else if (Short_MA_Array[1] > Long_MA_Array[1] && Short_MA_Array[0] < Long_MA_Array[0])
{
// デッドクロスが発生したら、SELL注文を出す
m_trade.Buy(Lots, m_symbol.Name(), m_symbol.Bid(), 0, 0);
}
}
}
※ 実際には#include <Expert> からCExpert ExtExpert;を使った方が良いと思います。とはいえ、PythonよりもMQLの方がトレードに特化した機能があるので、どちらが良いかは一概には言えません。特に、機械学習を利用する場合はPythonの方が圧倒的に楽です(MQLの記事を見ると機械学習はできそうですが、結構面倒そうでした)。
上記のように定義した戦略クラスを利用して、バックテストを実行します。ここではGoogleのデータを利用します。
from backtesting.test import GOOG
GOOG
| Date | Open | High | Low | Close | Volume |
|---|---|---|---|---|---|
| 2004-08-19 | 100.00 | 104.06 | 95.96 | 100.34 | 22351900 |
| 2004-08-20 | 101.01 | 109.08 | 100.50 | 108.31 | 11428600 |
| 2004-08-23 | 110.75 | 113.48 | 109.05 | 109.40 | 9137200 |
| 2004-08-24 | 111.24 | 111.60 | 103.57 | 104.87 | 7631300 |
| 2004-08-25 | 104.96 | 108.00 | 103.88 | 106.00 | 4598900 |
| … | … | … | … | … | … |
| 2013-02-25 | 802.30 | 808.41 | 790.49 | 790.77 | 2303900 |
| 2013-02-26 | 795.00 | 795.95 | 784.40 | 790.13 | 2202500 |
| 2013-02-27 | 794.80 | 804.75 | 791.11 | 799.78 | 2026100 |
| 2013-02-28 | 801.10 | 806.99 | 801.03 | 801.20 | 2265800 |
| 2013-03-01 | 797.80 | 807.14 | 796.15 | 806.19 | 2175400 |
bt = Backtest(GOOG, SmaCross, cash=10000, commission=.002, exclusive_orders=True)
output = bt.run()
bt.plot()
結果
チャート
バックテストの結果
| Start | 2004-08-19 00:00:00 |
| End | 2013-03-01 00:00:00 |
| Duration | 3116 days 00:00:00 |
| Exposure Time [%] | 97.067039 |
| Equity Final [$] | 68221.96986 |
| Equity Peak [$] | 68991.21986 |
| Return [%] | 582.219699 |
| Buy & Hold Return [%] | 703.458242 |
| Return (Ann.) [%] | 25.266427 |
| Volatility (Ann.) [%] | 38.383008 |
| Sharpe Ratio | 0.658271 |
| Sortino Ratio | 1.288779 |
| Calmar Ratio | 0.763748 |
| Max. Drawdown [%] | -33.082172 |
| Avg. Drawdown [%] | -5.581506 |
| Max. Drawdown Duration | 688 days 00:00:00 |
| Avg. Drawdown Duration | 41 days 00:00:00 |
| # Trades | 94 |
| Win Rate [%] | 54.255319 |
| Best Trade [%] | 57.11931 |
| Worst Trade [%] | -16.629898 |
| Avg. Trade [%] | 2.074326 |
| Max. Trade Duration | 121 days 00:00:00 |
| Avg. Trade Duration | 33 days 00:00:00 |
| Profit Factor | 2.190805 |
| Expectancy [%] | 2.606294 |
| SQN | 1.990216 |
| _strategy | SmaCross |
| _equity_curve | Equity DrawdownPct DrawdownD… |
| _trades | Size EntryBar ExitBar EntryPrice ExitP.. |
Googleの株価に対しては移動平均を使った取引戦略はバイアンドホールドよりも悪いことから良い戦略とは言えないことがわかります。とはいえ、シャープレシオが0.658271とプラスで、マイナスになっていないことから一部の期間ではワークするのかもしれません。
他にも様々な機能があるようなので、サンプルコードを実行した結果などを載せていけたらと思います。








