見出し画像

Backtesting.pyの使い方 その4

さて、今回はビットコインのやつをやります。
前回のコードのこの部分を

start = datetime.date(2018,1,1)
end = datetime.date.today()
data = web.DataReader('AAPL', 'yahoo', start, end)

以下のように変更してください。

periods = ["60", "300"]  # 60sec, 5min300
query = {"periods": ','.join(periods), "before": "", "after": "1596207600"}
rspJson = json.loads(requests.get("https://api.cryptowat.ch/markets/bitflyer/btcfxjpy/ohlc", params=query).text)
ohlcvs = rspJson["result"]

for period in periods:
    ohlcv_data = ohlcvs[period]
    ohlcv_ary = np.asarray(ohlcv_data)
    ohlcv_aryT = ohlcv_ary.T

    ts  = ohlcv_aryT[0]
    Open  = ohlcv_aryT[1]
    High  = ohlcv_aryT[2]
    Low = ohlcv_aryT[3]
    Close  = ohlcv_aryT[4]
    Volume = ohlcv_aryT[5]

data = pd.DataFrame(ohlcv_ary)
data.columns = ['ts','Open','High','Low','Close','Adj_Close','Volume']

これはOHLCVの値をクリプトウォッチからビットフライヤーのものを取得するようになっています。
以下の部分を

bt = Backtest(data, MDCross, cash=10_000, commission=.002)

以下のように変更してください。

bt = Backtest(data, MDCross, cash=100000000, margin=0.5, commission=.002)

これはBacktesting.pyが小数点以下のロットに対応していないためです。元本を1000万円にします。
それでは実行してみましょう。

相変わらずダメダメですね。
それでは最適化してみましょうか。
結果は以下。

うーんちょっとマシになりましたがこれではダメですね。
ここで私のお気に入りのADXを追加します。
以下の部分を

def MACD(values, m1, m2, ms):
    macd, macdsignal, macdhist = ta.MACD(data.Close, fastperiod=m1, slowperiod=m2, signalperiod=ms)
    return macd, macdsignal, macdhist

class MDCross(Strategy):
    n1 = 10
    n2 = 20
    m1 = 10
    m2 = 20
    ms = 5

    def init(self):
        self.sma1 = self.I(SMA, self.data.Close, self.n1)
        self.sma2 = self.I(SMA, self.data.Close, self.n2)
        self.macd, self.macdsignal, self.macdhist = self.I(MACD, self.data.Close, self.m1, self.m2, self.ms)

    def next(self):
        if crossover(self.macd, self.macdsignal):
            self.position.close()
            self.buy()

        elif crossover(self.macdsignal, self.macd):
            self.position.close()
            self.sell()

変更した実行結果はこちら。

Start                                     0.0
End                                    5999.0
Duration                               5999.0
Exposure Time [%]                       54.15
Equity Final [$]                161234102.968
Equity Peak [$]                 164798462.968
Return [%]                          61.234103
Buy & Hold Return [%]                6.021588
Return (Ann.) [%]                         0.0
Volatility (Ann.) [%]                     NaN
Sharpe Ratio                              NaN
Sortino Ratio                             NaN
Calmar Ratio                              0.0
Max. Drawdown [%]                   -7.599317
Avg. Drawdown [%]                   -1.549435
Max. Drawdown Duration                  883.0
Avg. Drawdown Duration              56.140351
# Trades                                  9.0
Win Rate [%]                        66.666667
Best Trade [%]                       5.285285
Worst Trade [%]                     -1.006603
Avg. Trade [%]                       2.774556
Max. Trade Duration                    1231.0
Avg. Trade Duration                360.888889
Profit Factor                       13.940548
Expectancy [%]                       2.805118
SQN                                  3.149682
_strategy                 MDCross(m1=5,m2=...
_equity_curve                         Equi...
_trades                      Size  EntryBa...

なかなかいい感じですね。パラメータはMACDは5,75,85。ADXはスパン45。
ADXの閾値は30以上40以下としているのがミソです。
コードは以下。
それではまた。

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
import talib as ta
import json
import requests
import numpy as np

periods = ["60", "300"]  # 60sec, 5min300
query = {"periods": ','.join(periods), "before": "", "after": "1596207600"}
rspJson = json.loads(requests.get("https://api.cryptowat.ch/markets/bitflyer/btcfxjpy/ohlc", params=query).text)
ohlcvs = rspJson["result"]

for period in periods:
    ohlcv_data = ohlcvs[period]
    ohlcv_ary = np.asarray(ohlcv_data)
    ohlcv_aryT = ohlcv_ary.T

    ts  = ohlcv_aryT[0]
    Open  = ohlcv_aryT[1]
    High  = ohlcv_aryT[2]
    Low = ohlcv_aryT[3]
    Close  = ohlcv_aryT[4]
    Volume = ohlcv_aryT[5]

data = pd.DataFrame(ohlcv_ary)
data.columns = ['ts','Open','High','Low','Close','Adj_Close','Volume']

def SMA(values, n):
    return pd.Series(values).rolling(n).mean()

def MACD(values, m1, m2, ms):
    macd, macdsignal, macdhist = ta.MACD(data.Close, fastperiod=m1, slowperiod=m2, signalperiod=ms)
    return macd, macdsignal, macdhist

def ADX(high, low, close, ls):
    real = ta.ADX(data.High, data.Low, data.Close, timeperiod=ls)
    return real

class MDCross(Strategy):
    n1 = 10
    n2 = 20
    m1 = 55
    m2 = 130
    ms = 5
    ls = 45

    def init(self):
        self.sma1 = self.I(SMA, self.data.Close, self.n1)
        self.sma2 = self.I(SMA, self.data.Close, self.n2)
        self.macd, self.macdsignal, self.macdhist = self.I(MACD, self.data.Close, self.m1, self.m2, self.ms)
        self.real = self.I(ADX, self.data.High, self.data.Low, self.data.Close, self.ls)

    def next(self):
        if crossover(self.macd, self.macdsignal) and self.real > 30 and self.real < 40:
            self.position.close()
            self.buy()

        elif crossover(self.macdsignal, self.macd) and self.real > 30 and self.real < 40:
            self.position.close()
            self.sell()

bt = Backtest(data, MDCross, cash=100000000, margin=0.5, commission=.002)
'''
stats = bt.run()
print(stats)
bt.plot()
'''
stats=bt.optimize(m1=range(5, 100, 10),m2=range(5, 100, 10),ms=range(5, 100, 10),maximize='Equity Final [$]', method='grid', constraint=lambda p: p.m1 < p.m2)
print(stats)
bt.plot()

いいなと思ったら応援しよう!