Backtesting.pyの使い方 その2
前回は公式ドキュメントのサンプルコードを実行して、グーグルの株価でドテン売買した場合どうなるかを確認しました。
今回はpandas-datareaderというのを使って任意の株価、為替レートを取得してみます。
まずはpipでインストール。
pip install pandas-datareader
そして前回のコードを変更したものが以下のコードになります。
pandas_datareaderをインポートし、datetimeでデータの始まりの日付と終わりの日付を指定しています。
コピペして実行してみて下さい。
from backtesting import Strategy
from backtesting.lib import crossover
from backtesting import Backtest
import pandas as pd
import pandas_datareader.data as web
import datetime
start = datetime.date(2018,1,1)
end = datetime.date.today()
data = web.DataReader('AAPL', 'yahoo', start, end)
def SMA(values, n):
return pd.Series(values).rolling(n).mean()
class SmaCross(Strategy):
n1 = 10
n2 = 20
def init(self):
self.sma1 = self.I(SMA, self.data.Close, self.n1)
self.sma2 = self.I(SMA, self.data.Close, self.n2)
def next(self):
if crossover(self.sma1, self.sma2):
self.position.close()
self.buy()
elif crossover(self.sma2, self.sma1):
self.position.close()
self.sell()
bt = Backtest(data, SmaCross, cash=10_000, commission=.002)
stats = bt.run()
print(stats)
bt.plot()
2018年からのアップルの株価の日足で売買するようになっています。
以下のような結果が出ると思います。
Start 2018-01-02 00:00:00
End 2022-06-06 00:00:00
Duration 1616 days 00:00:00
Exposure Time [%] 96.7713
Equity Final [$] 22629.029394
Equity Peak [$] 31905.479855
Return [%] 126.290294
Buy & Hold Return [%] 239.347507
Return (Ann.) [%] 20.270102
Volatility (Ann.) [%] 38.434394
Sharpe Ratio 0.527395
Sortino Ratio 0.95409
Calmar Ratio 0.55462
Max. Drawdown [%] -36.547718
Avg. Drawdown [%] -5.14563
Max. Drawdown Duration 482 days 00:00:00
Avg. Drawdown Duration 35 days 00:00:00
# Trades 40
Win Rate [%] 42.5
Best Trade [%] 79.788108
Worst Trade [%] -13.977958
Avg. Trade [%] 2.091649
Max. Trade Duration 188 days 00:00:00
Avg. Trade Duration 40 days 00:00:00
Profit Factor 1.980521
Expectancy [%] 3.094839
SQN 0.790003
_strategy SmaCross
_equity_curve ...
_trades Size EntryB...
Return [%] 126.290294
Buy & Hold Return [%] 239.347507
うーん、これもバイ&ホールドのほうが良い結果ですね。
それでは最適化というのをやってみましょうか。
移動平均線の短期n1と長期n2の値を変化させ、最終的な利益Equity Final [$]が最大になるようにします。
コードの以下の部分を
stats = bt.run()
print(stats)
bt.plot()
下のように変更してください。
stats=bt.optimize(n1=range(5, 100, 10),n2=range(5, 100, 10),maximize='Equity Final [$]', method='grid', constraint=lambda p: p.n1 < p.n2)
print(stats)
bt.plot()
こうするとn1とn2の値を5から100まで10刻みで変化させて、Equity Final [$]の値が最大になるパターンを見つけ出してくれます。
それでは実行してみましょう。
Start 2018-01-02 00:00:00
End 2022-06-06 00:00:00
Duration 1616 days 00:00:00
Exposure Time [%] 98.475336
Equity Final [$] 45727.273419
Equity Peak [$] 49863.126632
Return [%] 357.272734
Buy & Hold Return [%] 239.347507
Return (Ann.) [%] 40.995594
Volatility (Ann.) [%] 44.049393
Sharpe Ratio 0.930673
Sortino Ratio 2.032229
Calmar Ratio 1.656755
Max. Drawdown [%] -24.744512
Avg. Drawdown [%] -4.07038
Max. Drawdown Duration 456 days 00:00:00
Avg. Drawdown Duration 24 days 00:00:00
# Trades 60
Win Rate [%] 46.666667
Best Trade [%] 51.761384
Worst Trade [%] -15.693983
Avg. Trade [%] 2.57146
Max. Trade Duration 117 days 00:00:00
Avg. Trade Duration 27 days 00:00:00
Profit Factor 2.857283
Expectancy [%] 3.048345
SQN 1.898985
_strategy SmaCross(n1=5,n2...
_equity_curve ...
_trades Size EntryB...
Return [%] 357.272734
Buy & Hold Return [%] 239.347507
うおぉ!バイ&ホールドの利益を超えました!最適な値はn1は5でn2は15だそうです。コンピューターって賢いなぁ。4年間で10000$が45000$になる計算です。
今回は単純移動平均を使いましたがTa-libを導入するとさらに高度なテクニカル解析が出来るようになります。
それは後ほど。
それでは。