pandas, Matplotlib(mplfinance)でローソク足チャートを作成
pandasとMatplotlib(mplfinance, mpl_finance)を使ってローソク足チャート(Candlestick chart)を描画・作成する方法について、以下の内容を説明する。
- matplotlib.financeとmpl_finance, mplfinance
- mplfinanceでローソク足チャート(Candlestick chart)を作成
- データ準備
- グラフ作成・画像ファイル保存: 引数
savefig - 比率: 引数
figratio - プロットタイプ: 引数
type - 出来高(Volume): 引数
volume - 移動平均線: 引数
mav - 全体のスタイル: 引数
style - ダウンサンプリング(日足から週足に変換)
- [参考] mpl_financeでローソク足チャート(Candlestick chart)を作成
ローソク足チャートの元となるOHLCデータの算出やダウンサンプリングについての詳細は以下の記事を参照。
matplotlib.financeとmpl_finance, mplfinance
ローソク足チャートを含む金融関係のグラフ描画機能はもともとmatplotlib.financeとしてMatplotlibに含まれていたが、Matplotlibバージョン2.0からmpl_financeという別のパッケージとして切り出された。ドキュメントはMatplotlibの公式サイトに残されている。
さらにmplfinanceという新たなパッケージが作られ、2020年5月23日現在はmpl_financeはDEPRECATEDでmplfinanceの使用が推奨されている。
mplfinanceはMatplotlibとは別にインストールする必要がある。pip(環境によってはpip3)などを使う。
$ pip install mplfinance
mplfinanceでローソク足チャート(Candlestick chart)を作成
ここからはmplfinanceを使ってローソク足チャート(Candlestick chart)を作成する方法について説明する。
サンプルコードで使用したmplfinanceのバージョンは0.12.4a0。mplfinanceは活発に開発が進められているため、機能が変更・更新されている場合があるので注意。
公式の説明が充実しているのでそちらも参照されたい。
データ準備
ここではpandas-datareaderで取得して保存したApple(AAPL)の株価データを例とする。
pd.read_csv()でparse_dates=Trueとして時系列データのpandas.DataFrameとして読み込み、さらに['2017']で2017年のデータを抽出する。
parse_dates=Trueを省略すると行名indexが文字列として読み込まれmplfinanceのplot()では処理できなくなるので要注意。
import pandas as pd
import mplfinance as mpf
df = pd.read_csv('data/src/aapl_2015_2019.csv', index_col=0, parse_dates=True)['2017']
print(df)
# open high low close volume
# 2017-01-03 115.80 116.3300 114.760 116.15 28781865
# 2017-01-04 115.85 116.5100 115.750 116.02 21118116
# 2017-01-05 115.92 116.8642 115.810 116.61 22193587
# 2017-01-06 116.78 118.1600 116.470 117.91 31751900
# 2017-01-09 117.95 119.4300 117.940 118.99 33561948
# ... ... ... ... ... ...
# 2017-12-22 174.68 175.4240 174.500 175.01 16052615
# 2017-12-26 170.80 171.4700 169.679 170.57 32968167
# 2017-12-27 170.10 170.7800 169.710 170.60 21672062
# 2017-12-28 171.00 171.8500 170.480 171.08 15997739
# 2017-12-29 170.52 170.5900 169.220 169.23 25643711
#
# [251 rows x 5 columns]
mplfinanceのplot()の仕様に合わせて列名columnsを変更する。Open, Closeのように、大文字小文字も合っていないとダメ。
df.columns = ['Open', 'High', 'Low', 'Close', 'Volume']
pandas.DataFrameはどのように作成してもいいが、indexがDatetimeIndexである時系列データで、列名がOpen, Close...となっている必要がある。
グラフ作成・画像ファイル保存: 引数savefig
plot()の引数にpandas.DataFrameを指定する。
mpf.plot(df, savefig='data/dst/candlestick_mpf.png')

ここでは引数savefigにパスを指定して画像ファイルとして保存しているが、Jupyter Notebookではmpf.plot(df)とすると出力セルにグラフが表示される。
Jupyter Notebookの場合、引数savefigを指定してもグラフが表示される。入力セルの先頭にマジックコマンド%%captureをつけると表示されなくなる。
%%capture
mpf.plot(df, savefig='data/dst/candlestick_mpf.png')
便宜上、サンプルコードのpyファイルにも%%captureが記載されているが、pyファイルを実行する場合は削除する必要があるので注意。
mplfinanceの画像ファイル保存についての詳細は以下を参照。
比率: 引数figratio
引数figratioでグラフの縦横の比率(アスペクト比)を指定できる。
mpf.plot(df[50:100], figratio=(12,4),
savefig='data/dst/candlestick_mpf_figratio.png')

データ数が多いと見にくいので[50:100]で範囲を絞っている。適当に決めた値で特に意味はない。
プロットタイプ: 引数type
グラフのタイプを引数typeで指定できる。デフォルトは日本ではあまり見ないタイプだが、type='candle'とするとおなじみのローソク足になる。
mpf.plot(df[50:100], type='candle', figratio=(12,4),
savefig='data/dst/candlestick_mpf_candle.png')

そのほか'line'や'pnf'などもある。
色などの変更は後述の引数styleを使う。
出来高(Volume): 引数volume
引数volumeをTrueとすると、出来高(Volume)も描画される。
mpf.plot(df[50:100], type='candle', volume=True, figratio=(12,4),
savefig='data/dst/candlestick_mpf_volume.png')

当然ながら、元のpandas.DataFrameにVolume列が必要。
移動平均線: 引数mav
引数mavで移動平均線(Moving Average)を追加できる。整数intで単独の移動平均線を、整数intを要素とするタプルやリストで複数の移動平均線を追加できる。
mpf.plot(df[50:100], type='candle', volume=True, mav=(5, 25), figratio=(12,4),
savefig='data/dst/candlestick_mpf_mav.png')

例えば5と指定すると5点のデータの平均(日次データであれば5日移動平均線)となる。
全体のスタイル: 引数style
引数styleで全体のスタイルを変更できる。
mpf.plot(df[50:100], type='candle', figratio=(12,4),
volume=True, mav=(5, 25), style='yahoo',
savefig='data/dst/candlestick_mpf_style_yahoo.png')

様々なスタイルが選択可能。自分で作成することもできる。
ダウンサンプリング(日足から週足に変換)
日足から週足や月足、年足のチャートを作成したい場合は元のデータをダウンサンプリングする。
OHLCVデータのダウンサンプリングにはresample()メソッドを使う。
d_ohlcv = {'Open': 'first',
'High': 'max',
'Low': 'min',
'Close': 'last',
'Volume': 'sum'}
df_w = df.resample('W-MON', closed='left', label='left').agg(d_ohlcv)
print(df_w.head())
# Open High Low Close Volume
# 2017-01-02 115.80 118.16 114.76 117.91 103845468
# 2017-01-09 117.95 119.93 117.94 119.04 138810760
# 2017-01-16 118.34 120.50 118.22 120.00 116347987
# 2017-01-23 120.00 122.44 119.50 121.95 124748449
# 2017-01-30 120.93 130.49 120.62 129.08 249781248
ダウンサンプリングしたpandas.DataFrameをplot()の引数に指定すればよい。
mpf.plot(df_w, type='candle', figratio=(12,4),
volume=True, mav=(5, 25),
savefig='data/dst/candlestick_mpf_week.png')

歩み値(ティック)からOHLCを算出する方法や、resample()の詳細などは以下の記事を参照。
月足や年足を作成したい場合はresample()に指定する頻度コードをMSやYSなどにすればOK。
この例では元のデータが日足なのでそれより細かい時間足などを作成することはできないが、元のデータが分足であれば、resample()に指定する頻度コードによって30分足(30T)や4時間足(4H)なども作成可能。
[参考] mpl_financeでローソク足チャート(Candlestick chart)を作成
参考までに、以前書いたmpl_financeでローソク足チャート(Candlestick chart)を作成する方法についての説明も残しておく。
上述のようにmpl_financeはDEPRECATEDとなっているので、これから新しいコードを書くならmplfinanceの使用をおすすめする。
なお、バージョン0.12.4a0時点のmplfinanceでは、以下のようにmpl_financeの関数をインポートして使用することもできる。
from mplfinance.original_flavor import candlestick_ohlc
mpl_financeのローソク足チャート用関数
mpl_financeに用意されているローソク足チャート用関数は以下の4つ。
- candlestick_ohlc(ax, quotes, width=0.2, colorup='k', colordown='r', alpha=1.0)
- candlestick_ochl(ax, quotes, width=0.2, colorup='k', colordown='r', alpha=1.0)
- candlestick2_ohlc(ax, opens, highs, lows, closes, width=4, colorup='k', colordown='r', alpha=0.75)
- candlestick2_ochl(ax, opens, closes, highs, lows, width=4, colorup='k', colordown='r', alpha=0.75)
ohlcとochlはデータの順序が違い、candlestickとcandlestick2はデータの指定方法が違う。
candlestick- 引数
quotesにtime,open,high,low,closeが列(縦)に並んだ二次元配列を指定- 6列目以降はどんなデータが格納されていてもOK
timeはdate2num()で得られる数値(後述)
- 引数
candlestick2- 引数
opens,highs,lows,closesにそれぞれのデータの一次元配列を指定
- 引数
以下のサンプルコードではcandlestick_ohlc()を使う。
データ準備
mplfinanceの例と同じく、pandas-datareaderで取得して保存したApple(AAPL)の株価データを例とする。
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import mpl_finance
df_org = pd.read_csv('data/src/aapl_2015_2019.csv', index_col=0, parse_dates=True)['2017']
print(df_org)
# open high low close volume
# 2017-01-03 115.80 116.3300 114.760 116.15 28781865
# 2017-01-04 115.85 116.5100 115.750 116.02 21118116
# 2017-01-05 115.92 116.8642 115.810 116.61 22193587
# 2017-01-06 116.78 118.1600 116.470 117.91 31751900
# 2017-01-09 117.95 119.4300 117.940 118.99 33561948
# ... ... ... ... ... ...
# 2017-12-22 174.68 175.4240 174.500 175.01 16052615
# 2017-12-26 170.80 171.4700 169.679 170.57 32968167
# 2017-12-27 170.10 170.7800 169.710 170.60 21672062
# 2017-12-28 171.00 171.8500 170.480 171.08 15997739
# 2017-12-29 170.52 170.5900 169.220 169.23 25643711
#
# [251 rows x 5 columns]
このpandas.DataFrameから、candlestick_ohlc()の引数quotesに渡す二次元配列numpy.ndarrayを生成する。元データはこのあとも使うのでcopy()で生成したコピーを処理する。
df = df_org.copy()
df.index = mdates.date2num(df.index)
data = df.reset_index().values
matplotlib.dates(mdatesとしてインポート)のdate2num()関数でindexの日時データ(numpy.datetime64)を数値に変換する。ここで得られる数値は西暦1年1月1日からの経過日数で、Matplotlibで時系列データを扱う場合に使われるフォーマット。
reset_index()でindexを解除(データ列の一番左に移動)して、values属性でpandas.DataFrameからNumPy配列ndarrayを取得する。
- 関連記事: pandas.DataFrame, Seriesのインデックスを振り直すreset_index
- 関連記事: pandas.DataFrame, SeriesとNumPy配列ndarrayを相互に変換
以下のような二次元のnumpy.ndarrayが生成できる。
print(type(data))
# <class 'numpy.ndarray'>
print(data.shape)
# (251, 6)
print(data)
# [[7.3633200e+05 1.1580000e+02 1.1633000e+02 1.1476000e+02 1.1615000e+02
# 2.8781865e+07]
# [7.3633300e+05 1.1585000e+02 1.1651000e+02 1.1575000e+02 1.1602000e+02
# 2.1118116e+07]
# [7.3633400e+05 1.1592000e+02 1.1686420e+02 1.1581000e+02 1.1661000e+02
# 2.2193587e+07]
# ...
# [7.3669000e+05 1.7010000e+02 1.7078000e+02 1.6971000e+02 1.7060000e+02
# 2.1672062e+07]
# [7.3669100e+05 1.7100000e+02 1.7185000e+02 1.7048000e+02 1.7108000e+02
# 1.5997739e+07]
# [7.3669200e+05 1.7052000e+02 1.7059000e+02 1.6922000e+02 1.6923000e+02
# 2.5643711e+07]]
グラフ作成
生成した二次元配列numpy.ndarrayは左の列から日時、始値、高値、安値、終値、出来高の順にデータが格納されている。上述の通り、これをcandlestick_ohlc()の第二引数quotesに指定する。6列目の出来高の列は無視される。
fig = plt.figure(figsize=(12, 4))
ax = fig.add_subplot(1, 1, 1)
mpl_finance.candlestick_ohlc(ax, data, width=2, alpha=0.5, colorup='r', colordown='b')
ax.grid()
locator = mdates.AutoDateLocator()
ax.xaxis.set_major_locator(locator)
ax.xaxis.set_major_formatter(mdates.AutoDateFormatter(locator))
plt.savefig('data/dst/candlestick_day.png')
plt.close()
引数widthには各ローソクの幅、alphaには透過度、colorupには上昇時の色、colordownには下降時の色をそれぞれ指定する。色はアルファベット一文字や#FFFFFFのようなカラーコードで指定できる。
以下のローソク足チャートが生成される。

plt.savefig()ではなくplt.show()とするとグラフが表示される。
以下の3行はX軸の日時をフォーマットするための設定。
locator = mdates.AutoDateLocator()
ax.xaxis.set_major_locator(locator)
ax.xaxis.set_major_formatter(mdates.AutoDateFormatter(locator))
AutoDateLocator(), AutoDateFormatter()を使うと自動的に最適な間隔・フォーマットで描画される。MonthLocator()やWeekdayLocator()などで任意の間隔を指定したり、%Yや%mなどで任意の文字列にフォーマットすることもできる。
fig = plt.figure(figsize=(12, 4))
ax = fig.add_subplot(1, 1, 1)
mpl_finance.candlestick_ohlc(ax, data, width=2, alpha=0.5, colorup='r', colordown='b')
ax.grid()
ax.xaxis.set_major_locator(mdates.MonthLocator())
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y/%m'))
plt.savefig('data/dst/candlestick_day_format.png')
plt.close()

Matplotlibのバージョン2.0以降はデフォルトで軸の上限・下限に余白ができるようになった。これを変更する設定は以下の記事を参照。
ダウンサンプリング(日足から週足に変換)
週足や月足、年足のチャートを作成したい場合は元のデータをダウンサンプリングする。上述のmplfinanceの例の通り。
d_ohlcv = {'open': 'first',
'high': 'max',
'low': 'min',
'close': 'last',
'volume': 'sum'}
df_w = df_org.resample('W-MON', closed='left', label='left').agg(d_ohlcv)
あとの流れは日足の場合と同じ。
df_w.index = mdates.date2num(df_w.index)
data_w = df_w.reset_index().values
fig = plt.figure(figsize=(12, 4))
ax = fig.add_subplot(1, 1, 1)
mpl_finance.candlestick_ohlc(ax, data_w, width=4, alpha=0.75, colorup='r', colordown='b')
ax.grid()
locator = mdates.AutoDateLocator()
ax.xaxis.set_major_locator(locator)
ax.xaxis.set_major_formatter(mdates.AutoDateFormatter(locator))
plt.savefig('data/dst/candlestick_week.png')
plt.close()

移動平均線
ローソク足チャートと重ねて移動平均線を描画したい場合はrolling()メソッドを使う。
例えば、週次にダウンサンプリングしたpandas.DataFrameの終値(close)の列に対してrolling(n).mean()とするとn週移動平均が算出される。
これを同じaxにplot()していく。plot()の第一引数はX軸、第二引数はY軸に相当するデータ列を指定する。
fig = plt.figure(figsize=(12, 4))
ax = fig.add_subplot(1, 1, 1)
mpl_finance.candlestick_ohlc(ax, data_w, width=4, alpha=0.75, colorup='r', colordown='b')
ax.plot(df_w.index, df_w['close'].rolling(4).mean())
ax.plot(df_w.index, df_w['close'].rolling(13).mean())
ax.plot(df_w.index, df_w['close'].rolling(26).mean())
ax.grid()
locator = mdates.AutoDateLocator()
ax.xaxis.set_major_locator(locator)
ax.xaxis.set_major_formatter(mdates.AutoDateFormatter(locator))
plt.savefig('data/dst/candlestick_week_sma.png')
plt.close()

出来高グラフ(Volume)
OHLCVのV(Volume: 出来高)もあわせて可視化したい場合は、別のサブプロットに棒グラフで描画する。
plt.subplots()のnrows, ncolsでサブプロットの行数・列数を指定し、それぞれのaxにグラフを描画する。gridspec_kwで各サブプロットの大きさの比率を指定できる。sharex=TrueとするとX軸が共通化される。
出来高の棒グラフに対してもpandas.DataFrameのplot()ではなく、Matplotlibのplot()を使う。
fig, axes = plt.subplots(nrows=2, ncols=1, figsize=(12, 4), sharex=True,
gridspec_kw={'height_ratios': [3, 1]})
mpl_finance.candlestick_ohlc(axes[0], data_w, width=4, alpha=0.75, colorup='r', colordown='b')
axes[1].bar(df_w.index, df_w['volume'], width=4, color='navy')
axes[0].grid()
axes[1].grid()
locator = mdates.AutoDateLocator()
axes[0].xaxis.set_major_locator(locator)
axes[0].xaxis.set_major_formatter(mdates.AutoDateFormatter(locator))
plt.savefig('data/dst/candlestick_week_v.png')
plt.close()

移動平均線と出来高グラフの両方を追加する場合もやり方は同じ。
fig, axes = plt.subplots(nrows=2, ncols=1, figsize=(12, 4), sharex=True,
gridspec_kw={'height_ratios': [3, 1]})
mpl_finance.candlestick_ohlc(axes[0], data_w, width=4, alpha=0.75, colorup='r', colordown='b')
axes[0].plot(df_w.index, df_w['close'].rolling(4).mean())
axes[0].plot(df_w.index, df_w['close'].rolling(13).mean())
axes[0].plot(df_w.index, df_w['close'].rolling(26).mean())
axes[1].bar(df_w.index, df_w['volume'], width=4, color='navy')
axes[0].grid()
axes[1].grid()
locator = mdates.AutoDateLocator()
axes[0].xaxis.set_major_locator(locator)
axes[0].xaxis.set_major_formatter(mdates.AutoDateFormatter(locator))
plt.savefig('data/dst/candlestick_week_sma_v.png')
plt.close()
