backtesting.pyを活用してローソク足チャートを描画する

[backtesting.py](https://kernc.github.io/backtesting.py/)が出力するチャートはドラッグやスクロール操作が快適で、また様々なテクニカル指標を表示することができます。
バックテストの結果を可視化するのが主な使い方ですが、ただのローソク足チャートとして使うのもおすすめなので、やり方をメモしておきます。

まずStrategyを継承したクラスを作ります。initとnextメソッドを入れないと動かないので、以下のようにメソッドを作っておきます。メソッドの中身はとりあえずなくて構いません。

```python
from backtesting import Strategy

class MyStrategy(Strategy):
    
    def init(self):
        pass

    def next(self):
        pass
```

準備ができたので、Backtestクラスを走らせます。runメソッドのあとにplotメソッドを呼びます。

```python
from backtesting import Backtest
from backtesting.test import GOOG  # テスト用のグーグルの株価をプロットします。

bt = Backtest(GOOG, MyStrategy)
bt.run()
bt.plot(filename='google.html', superimpose=False)
```

superimposeをFalseにしているのは、日足のみ描画したかったからです。週足や月足を重ねて描画したい場合はFalseの代わりに'W'や'M'などをいれてください。

これで図のようなローソク足チャートが出力されます。

![bokeh_plot (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2591762/e15d06f4-72ac-6ccd-ad13-570853d718e3.png)
![bokeh_plot (5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2591762/c5411e5f-5878-8eff-671d-155f23556794.png)


テクニカル指標を追加したい場合は、MyStrategyクラスのinitメソッドに登録していきます。
様々なテクニカル指標を計算するライブラリ [TA-Lib](https://mrjbq7.github.io/ta-lib/)の関数も利用できます。
よくある移動平均 SMAだと以下の通りで、Iメソッドに計算したい関数と、関数の引数を指定します。dataをfloatに変換しているのは、データが整数だとTA-Libの関数が受け付けないことがあるためです。
オプションで、凡例名や色などを変えることができます。

```python
from backtesting import Strategy
from talib import SMA

class MyStrategy(Strategy):
    
    def init(self):
        # 終値の15日平均を描画する
        self.I(SMA, self.data.Close.astype('float'), 15, name='15日平均', color='tomato')

    def next(self):
        pass
```

適当なところを拡大すると図のようになります。ちゃんとできてそうですね。

![bokeh_plot (6).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2591762/f475c44c-b11a-7bcc-5c8e-be41bf4408f7.png)

TA-Libの関数に戻り値が複数ある場合でも同様です。

```python
from backtesting import Strategy
from talib import BBANDS, MA_Type

class MyStrategy(Strategy):
    
    def init(self):
        # ボリンジャーバンド
        self.I(BBANDS, self.data.Close.astype('float'), matype=MA_Type.T3, color='tomato')

    def next(self):
        pass
```

![bokeh_plot (9).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2591762/4f9f14f7-7909-4a74-ad8f-25226cb51f3a.png)

RSIみたいにローソク足に重ねにくいインジケーターは自動で新しいチャートを追加してくれます。すごいですね。

![bokeh_plot (12).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2591762/9985b86d-6b80-2fbd-ad02-9dbdfa7b9303.png)
![bokeh_plot (11).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2591762/e37074e7-be02-11ab-fc35-d2ef03b09e4f.png)

チャートを微調整したい場合は、bt.plot()がBokehのGridBoxのインスタンスを返すので、それを[Bokehのドキュメント](https://docs.bokeh.org/en/latest/)を見ながらゴニョゴニョします。
以下では、ローソク足チャートの高さを変えて、[この投稿](https://qiita.com/TKfumi/items/c3db5b460eda627ba01a)で説明したダブルタップで軸をリセットする機能を追加しています。

```python
from bokeh.io import save
from bokeh.events import DoubleTap
from bokeh.models import CustomJS

・・・

fig = bt.plot()
# figからメインの日足チャートを探す 参照渡しなので、一度新しい変数に格納するとよい
fig_ohlc = fig.children[0].chilren[0][0]
# 以下で高さの変更と機能追加を行う 詳しい説明はBokehのドキュメントを見る
fig_ohlc.height = 200
fig_ohlc.js_on_event(DoubleTap, CustomJS(args=dict(p=fig_ohlc), code='p.reset.emit()'))
save(fig, filename='google.html')
```

自分で一からつくるよりも楽に洗練されたプロットができますし、テクニカル分析もはかどると思います。