[Python]TA-Libとmplfinaneで、株価とテクニカル指標をグラフ化する

# はじめに

株価を見るのに、ローソク足に、線を入れたり、オシレータで見たりしたかったので、テクニカル分析ライブラリの[TA-Lib](https://mrjbq7.github.io/ta-lib/)と、ファイナンスグラフライブラリの[mplfinance](https://github.com/matplotlib/mplfinance)でグラフ表示する方法をまとめておきます。

# 環境
- Windows 10 home
- Python(3.7.3)
- JupyterLab(3.06)
- TA-Lib(0.4.17)
- investpy(1.0.3)
- mplfinance(0.12.7a0)

# 準備
mplfinanceはpipでインストールします。

```sh
pip install mplfinance 
```

テクニカルを計算するのに、TA-Libを利用します。pipでインストールします

```sh
pip install TA-Lib
```

それぞれimportしておきます。また、データ加工にpandasを利用するのでこれもimportします。

```Python
import mplfinance as mpf
import talib as ta
import pandas as pd
```



# サンプルデータ

以前に[investpyの記事](https://qiita.com/matsxxx/items/f7c50b88f0b6d1c9e4d5)を書いたので、investpyで入手したソニーの株価を表示します。

```Python
import investpy
stock_sony = investpy.get_stock_historical_data(stock='6758', country='japan', from_date='01/03/2021', to_date='30/04/2021')
```



# 株価を表示する

データは、columnsに`'Open', 'High', 'Low', 'Close', Volume'`を持っているデータを前提とします。

## デフォルトで表示する

`mpf.plot`で表示させます。デフォルトの設定だと, ohlcバーチャートが表示されます。

```Python
mpf.plot(stock_sony)
```
![ohlc_bar_chart.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/585573/b2c6c21d-b69d-23ad-7742-e4ea835d39aa.png)

## ローソク足で表示する

`mpf.plot`の引数に`type='candle'`を指定すると、ローソク足で表示することができます。

```Python
mpf.plot(stock_sony, type='candle')
```
![candle.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/585573/d67b41a2-9dd3-5a52-2de0-4356613e4ae0.png)

## 出来高を表示する

データに`'Volume'`列があれば、`mpf.plot`の引数に`volume=True`と指定すると、出来高を表示することができます。

```Python
mpf.plot(stock_sony, type='candle', volume=True)
```
![volume.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/585573/151b8330-668b-c575-3dd1-b3fd8879ca64.png)

## 表示スタイルを変更する

表示スタイルを変えるには、`mpf.plot`の引数に`style=`を与えます。[webページ](https://github.com/matplotlib/mplfinance/blob/master/examples/styles.ipynb)を参考に、好みのstyleを指定しましょう。利用可能なstyleは`mpf.available_styles()	`で出力できます。

```Python
mpf.plot(stock_sony, type='candle', style='mike')
```
![mike.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/585573/c7b4147f-cc25-2dd7-85de-48158b6c6b40.png)

# 線を表示させる

## 移動平均線を入れる

（単純）移動平均を追加するには、`mpf.plot`の引数に`mav`を指定します。 tupleかlistで与えれば、複数の期間の移動平均線を出力できます。例では、5と21期間の移動平均線を出力しています。

```Python
mpf.plot(stock_sony, type='candle', mav=(5,21))
```
![ma.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/585573/0f46245c-0e69-0dff-3f04-1081fc44715d.png)



## 水平線を入れる

`mpf.plot`の引数に`hlines=`を指定します。tupleで与えると、複数の線が引けます。各線の線種や色を変えたい場合は、dict形式で`linestyle`, `widths`, `colors`を記述します。

```Python
#hlinesにtupleで与える
mpf.plot(stock_sony, type='candle', hlines=(10600, 12500))
#hlinesにdictで与える
mpf.plot(stock_sony, type='candle', hlines={'hlines':[10600, 12500], 'linestyle':'dashdot', 'linewidths':[1,10], 'colors':['y', 'g']})
```
![hline.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/585573/c5a2297b-45f1-7935-31c9-af328f905324.png "hlinesにtupleで与える")
![hline2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/585573/053db9c2-edde-d97f-e6c5-df7dfa7fe4b8.png "hlinesにdictで与える")

## トレンドラインを入れる

`mpf.plot`引数の`tlines=`に、dict形式で与えます。`tlines`キーに、listの日付を与えると、各日付を結ぶ直線を引いてくれます。`tline_use`キーで指定日付のどの値（終値とか）を参照するかを指定します。`linestyle`, `widths`, `colors`キーを記載すると、線種、線幅、色を指定することができます。トレンドラインを延長したり、2点のうち一方は安値、もう一方の日は高値を結ぶといった細かなことはできないようです(2021/05時点）。

```Python
mpf.plot(stock_sony, type='candle', tlines={'tlines':[('2021/01/30', '2021/04/24')], 'tline_use':['open'], 'linestyle':'dotted', 'linewidths':0.5, 'colors':'c'})
```
![tline2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/585573/89fd2c69-f530-e9d4-35e6-a78a49a9fe68.png)

## 好きな線を入れる

`mpf.plot`に`alines=`を指定すると、tupleにした日付と株価ペアの2点を結ぶ直線を描くことができます。2点だけでなく3点以上のペアを与えると、各点をつなぐ折れ線を作成します。これもdict形式で与えると、線種、線幅、色を変更することができます。

```Python
#線種・線幅・色指定なし。2点のペア
mpf.plot(stock_sony, type='candle', alines=[('2021/02/15', 12800), ('2021/03/19',10500)])
#dictで線種・線幅・色指定し、3点のペアを与える
mpf.plot(stock_sony, type='candle', alines={'alines':[('2021/02/15', 12800), ('2021/03/19',10500), ('2021/04/01', 12400)], 'linestyle':'dashed', 'linewidths':1, 'colors':'k'})
```
![aline.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/585573/5185ade6-b684-2db6-e2c6-6f8923636f2c.png "線種・線幅・色指定なし。2点のペア")
![aline_multi.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/585573/8327ca2d-7e4f-b5d8-e77d-d0826a786936.png "dictで線種・線幅・色指定し、3点のペアを与える")

## ボリンジャーバンドを追加する

[ボリンジャーバンド](https://ja.wikipedia.org/wiki/%E3%83%86%E3%82%AF%E3%83%8B%E3%82%AB%E3%83%AB%E6%8C%87%E6%A8%99%E4%B8%80%E8%A6%A7#%E3%83%9C%E3%83%AA%E3%83%B3%E3%82%B8%E3%83%A3%E3%83%BC%E3%83%90%E3%83%B3%E3%83%89)の線を追加します。ボリンジャーバンドは、[talibで計算したもの](https://mrjbq7.github.io/ta-lib/func.html)を利用します。例で、追加するボリンジャーバンドは2σの線です。ボリンジャーバンドを追加するには、`mpf.make_addplot`で作成したオブジェクトを `mpf.plot`の引数に`addplot=`で与えます。

```Python
# TA-Libによるボリンジャーバンド計算
bb_2_upper, bb_2_mid, bb_2_lower = ta.BBANDS(stock_sony.Close, timeperiod=21, nbdevup=2, nbdevdn=2, matype=0)#period:移動平均線期間、nbdevup:上側バンド幅(デフォルト2σ)、nbdevdn:下側バンド幅(デフォルト2σ) matype:移動平均線の種類(0:単純移動平均線)
#ボリンジャーバンドの線をまとめる
bbands_2s = pd.concat([bb_2_upper, bb_2_mid, bb_2_lower], axis=1)
#プロット作成
addplot_2s = mpf.make_addplot(bbands_2s)
#株価に2σのボリンジャーバンドを表示
mpf.plot(stock_sony, type='candle', addplot=addplot_2s)
```
![bbands.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/585573/44702640-d3f2-54bd-28da-a36f2b0ee78f.png)

## ボリンジャーバンドの複数の線を追加して、線種・線幅・色を変える

複数の線を追加する場合は、`mpf.plot`の`addplot=`に、`mpf.make_addplot`で作成した複数のオブジェクトをlist化して与えます。この例では、2σに加えて3σのボリンジャーバンドを追加します。`mpf.make_addplot`では、線種は`linestyle=`、線幅は`width=`、色は`color=`で変更します。

```Python
#3σのバンドを計算する
bb_3_upper, bb_3_mid, bb_3_lower = ta.BBANDS(stock_sony.Close, timeperiod=21, nbdevup=3, nbdevdn=3, matype=0)
bbands_3s = pd.concat([bb_3_upper, bb_3_lower],axis=1)
#2σバンド
addplot_2s = mpf.make_addplot(bbands_2s, linestyle='dashed', width=0.4, color='b')
#3σバンド
addplot_3s = mpf.make_addplot(bbands_3s, linestyle='dashdot', width=1.0, color='m')
#センターライン 2σの計算時のものを利用
addplot_mid = mpf.make_addplot(bb_2_mid, linestyle='-', width=1.0, color='y')
#株価に2σと3σのボリンジャーバンド表示
mpf.plot(stock_sony, type='candle', addplot=[addplot_2s, addplot_3s, addplot_mid])
```
![line3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/585573/43bd513a-6c94-1da2-74f2-5b302ee2838f.png)

# 株価にオシレータを追加する

## MACDを表示する

代表的なオシレータである[MACD](https://en.wikipedia.org/wiki/MACD)を表示させます。TA-Libで計算します。期間は短期12、長期26、シグナル9と標準のものにしました。

`mpf.make_addplot`を使って、グラフを追加します。mplfinanceにグラフ領域を追加する場合は、`mpf.make_addplot`の引数に`panel=`を指定します。また、`secondary_y=`を指定して、左右どちらの軸をy軸にするかを指定します。（指定しないと線やヒストグラムがずれました）

```Python
#TA-LibによるMACD計算
macd, macdsignal, macdhist = ta.MACD(stock_sony.Close, fastperiod=12, slowperiod=26, signalperiod=9)
#ヒストグラムのプラス側とマイナス側の分離
macdhist_plus = macdhist.where(macdhist>=0, 0)
macdhist_minus = macdhist.where(macdhist<0, 0)
#MACDプロット設定
oscilator_macd = [
    mpf.make_addplot(macdsignal, color='c', width=1, panel=1, secondary_y=False),
    mpf.make_addplot(macd, color='m', width=1, panel=2, secondary_y=False),
    mpf.make_addplot(macdhist_plus, type='bar', color='r', panel=1, secondary_y=True),
    mpf.make_addplot(macdhist_minus, type='bar', color='b', panel=1, secondary_y=True),
                 ]
#株価とMACD表示
mpf.plot(stock_sony, type='candle', volume=True, addplot=oscilator_macd)
```
![macd.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/585573/c64b526c-5499-f34f-1c70-0d2f06c9f135.png)

## ストキャスティクスを表示する

買いすぎや売られすぎを判断する[ストキャスティクス](https://ja.wikipedia.org/wiki/%E3%82%B9%E3%83%88%E3%82%AD%E3%83%A3%E3%82%B9%E3%83%86%E3%82%A3%E3%82%AF%E3%82%B9)を表示させます。MACDと同様に、TA-Libで計算した数値を`mpf.make_addplot`を使って、グラフ化します。

```Python
#TA-Libでストキャスティクスを計算
slowk, slowd = ta.STOCH(stock_sony.High, stock_sony.Low, stock_sony.Close, fastk_period=5, slowk_period=3, slowk_matype=0, slowd_period=3, slowd_matype=0)
#買われすぎ、売られすぎを判断する80%と20%の基準線を作成
line_80 = pd.Series([80]*len(slowk), index=slowk.index)
line_20 = pd.Series([20]*len(slowk), index=slowk.index)
#ストキャスティクスのプロット作成
oscilator_stoch = [
    mpf.make_addplot(slowk, color='c', width=1, panel=1, ylim=(0,100)),
    mpf.make_addplot(slowd, color='m', width=1, panel=1, ylim=(0, 100)), 
    mpf.make_addplot(line_80, linestyle='dotted', color='r', width=1, panel=1),
    mpf.make_addplot(line_20, linestyle='dotted', color='r', width=1, panel=1)
                 ]
#株価とストキャスティクスを表示
mpf.plot(stock_sony, type='candle', addplot=oscilator_stoch)
```
![stoch_slow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/585573/8c13e72f-b3b0-f5d9-d5e2-45a897499f7d.png)



## 複数のオシレータを表示する

`mpf.make_addplot`の引数`panel=`を変更すると、表示グラフを増やすことができます。`mpf.plot`の`volume=True`にした場合、出来高が`panel=1`になるので、`mpf.make_addplot`で追加したい図は`panel=2`以降に指定します。

```Python
oscilator_mix = [
    #MACD
    mpf.make_addplot(macdsignal, color='c', width=1, panel=2, secondary_y=False),
    mpf.make_addplot(macd, color='m', width=1, panel=2, secondary_y=False),
    mpf.make_addplot(macdhist_plus, type='bar', color='r', panel=2, secondary_y=True),
    mpf.make_addplot(macdhist_minus, type='bar', color='b', panel=2, secondary_y=True),
    #ストキャスティクス   
    mpf.make_addplot(slowk, color='c', width=1, panel=3, ylim=(0, 100)),
    mpf.make_addplot(slowd, color='m', width=1, panel=3, ylim=(0, 100)), 
    mpf.make_addplot(line_80, linestyle='dotted', color='r', width=1, panel=3),
    mpf.make_addplot(line_20, linestyle='dotted', color='r', width=1, panel=3)
                 ]

mpf.plot(stock_sony, type='candle', volume=True, addplot=oscilator_mix)
```
![mix.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/585573/993caf54-8638-2980-9e4c-aa6bef661c4d.png)



# 作成した図を保存する

作成した図を保存した場合、`mpf.plot`の引数`savefig=`でファイル名を指定します。JupyterLab(or Jupyter Notebook)で表示する場合、`savefig=`を指定すると、JupyterLab上のグラフが消えますが、`closefig=False`をつけると、JupyterLab上に表示されたままになります。

```Python
graphs =[
    #ボリンジャーバンド
    mpf.make_addplot(bbands_2s, linestyle='dashed', width=0.4, color='b')
    mpf.make_addplot(bbands_3s, linestyle='dashdot', width=1.0, color='m')
    mpf.make_addplot(bb_2_mid, linestyle='-', width=1.0, color='y')
    #MACD
    mpf.make_addplot(macdsignal, color='c', width=1, panel=2, secondary_y=False),
    mpf.make_addplot(macd, color='m', width=1, panel=2, secondary_y=False),
    mpf.make_addplot(macdhist_plus, type='bar', color='r', panel=2, secondary_y=True),
    mpf.make_addplot(macdhist_minus, type='bar', color='b', panel=2, secondary_y=True),
    #ストキャスティクス
    mpf.make_addplot(slowk, color='c', width=1, panel=3, ylim=(0, 100)),
    mpf.make_addplot(slowd, color='m', width=1, panel=3, ylim=(0, 100)), 
    mpf.make_addplot(line_80, linestyle='dotted', color='r', width=1, panel=3),
    mpf.make_addplot(line_20, linestyle='dotted', color='r', width=1, panel=3)
]
#グラフ表示して、保存する。
mpf.plot(stock_sony, type='candle', volume=True, addplot=graphs, savefig='graph.png', closefig=False)
```
![graph.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/585573/483a5559-c08b-5a55-a3b5-ba71fed6bf4f.png)

# 参考

https://github.com/matplotlib/mplfinance#usage
https://mrjbq7.github.io/ta-lib/
https://saturday-in-the-park.netlify.app/TradingTools/06_PlotDailyChart/