【コードあり】mplfinanceで複数のチャートを描画する方法

python

この記事に書いてあること

結論から言えば、下図のようなチャートを描画するコードを書いています。

pythonで株式やfxのチャートを描画しようとすると、たいていmplfinanceに行きつきます。

しかしこの記事を書いている時点では情報がかなり少なく、意図したチャートを描くのは容易ではありません。

そこでこの記事では、複数のチャートを並列描画したり見た目をシンプルにしたりするコードについて書くことにしました。

コード

なにをおいてもまずはコードを書きます。

ポイントは以下の点です。

  • グラフの文字サイズや色を指定すること (52行めから)
  • 複数のチャートを描画するために枠組みを用意すること (61-69, 83-84, 126-127, 174-175行め)
  • x軸のメモリを月曜ごとにしたりするなど (72-80, 120-123, 164-171行め)
# 元となる日足チャートは↓のような形式で用意しておきます。
# mplfinanceでは四本値の大文字小文字はこの通りにする必要があります。
# date       Open    High    Low     Close   Volume
# 1990-01-04 38921.0 38950.0 38705.0 38712.0 4.720868e+08
# 1990-01-05 38717.0 38786.0 38090.0 38274.0 7.567594e+08
# 1990-01-08 38331.0 38564.0 38121.0 38294.0 5.200174e+08
# 1990-01-09 38281.0 38296.0 37729.0 37951.0 5.430759e+08
# 1990-01-10 37927.0 37927.0 37472.0 37696.0 5.538969e+08
# ..................
# 2021-07-09 27739.0 28000.0 27419.0 27940.0 1.425640e+09
# 2021-07-12 28412.0 28595.0 28405.0 28569.0 1.035770e+09
# 2021-07-13 28713.0 28852.0 28699.0 28718.0 9.575200e+08
# 2021-07-14 28517.0 28696.0 28482.0 28608.0 9.811800e+08
# 2021-07-15 28539.0 28571.0 28240.0 28279.0 9.711700e+08

# +-------------------+
# | ダウンサンプリング |
# +-------------------+

# サンプリングの仕方を指定する
d_ohlcv = {'Open': 'first', # 区間の最初の値 
           'High': 'max', # 区間の最大の値
           'Low': 'min', # 区間の最小の値
           'Close': 'last', # 区間の最後の値
           'Volume': 'sum'} # 区間の和

# 日足から週足をつくる
df_w = df_d.resample('W-MON', closed='left', label='left').agg(d_ohlcv)
# W-MON: Wは週ごとの集約。MONは月曜起点
# closed: 開始日時と終了日時のどちらを期間に含むかを指定
# closed='left'なら開始日時 ≦ 期間 < 終了日時となり、'right'なら開始日時 < 期間 ≦ 終了日時
# label: ラベルを開始日時にするか終了日時にするかを指定
# label='left'とすると開始日時、label='right'とすると終了日時がラベル

# 日足から月足をつくる
df_m = df_d.resample('MS').agg(d_ohlcv)


# +----------+
# | チャート |
# +----------+
# 日足も週足も月足も30本描くことにします
day = 30
week = 30
month = 30
df_d = df_d.tail(day)
df_w = df_w.tail(week)
df_m = df_m.tail(month)

fig = mpf.figure(figsize=(10, 5))

cs = mpf.make_mpf_style(gridcolor='black',
                        gridstyle='dotted',
                        facecolor='white',
                        edgecolor='#202426',
                        figcolor='white',
                        rc={'xtick.labelsize': 10, 
                            'ytick.labelsize': 10, 
                            'axes.labelsize': 10})

left = 0.07
left2 = 0.33 + left
left3 = 0.66 + left
width = 0.33 - left

under = 0.20
top = 0.05
height = (1 - under - top*2) / 2
under2 = under + height + top

# === 日足 ===
# 共通になるx軸の設定 (今回は月曜ごとのメモリにしたい)
dates = df_d.index.values
list_xtick = []
for date in dates:
    weekday = pd.to_datetime(date).weekday()
    if weekday == 0:
        list_xtick.append(date)
list_xlim = [df_d.index[0] - pd.tseries.offsets.Day(1),
             df_d.index[-1] + pd.tseries.offsets.Day(1)]

# ロウソク足と出来高を描画する枠を確保する
ax_price = fig.add_axes([left, under2, width, height], style=cs)
ax_volume = fig.add_axes([left, under, width, height], style=cs)

# ロウソク足の設定
ax_price.set_title('Daily', fontsize=10)
ax_price.tick_params(labelbottom=False,
                     labelleft=True,
                     labelright=True,
                     labeltop=False)
ax_price.set_xlim(list_xlim)
ax_price.set_xticks(list_xtick)
ax_price.yaxis.set_major_formatter(ScalarFormatter(useMathText=True))
ax_price.yaxis.get_major_formatter().set_powerlimits((0,1))

# 出来高の設定
ax_volume.set_xlim(list_xlim)
ax_volume.set_xticks(list_xtick)
ax_volume.set_xticklabels([pd.to_datetime(x).strftime('%Y/%m/%d') for x in list_xtick], rotation=90)
ax_volume.set_ylabel('Volume')
ax_volume.yaxis.set_major_formatter(ScalarFormatter(useMathText=True))
ax_volume.yaxis.get_major_formatter().set_powerlimits((0,1))

# 描画する
add_plot = [mpf.make_addplot(df_d['Volume'],
                             type='bar',
                             color='black',
                             ax=ax_volume,
                             secondary_y=False,
                             width=1)]
mpf.plot(df_d.loc[:, ['Open', 'High', 'Low', 'Close']],
         type='candle',
         ax=ax_price,
         addplot=add_plot,
         show_nontrading=True,
         xrotation=90)

# === 週足 ===
# 共通になるx軸の設定 (今回は月曜ごとのメモリにしたい)
dates = df_w.index.values
list_xtick = dates[::4]
list_xlim = [df_w.index[0] - pd.tseries.offsets.Week(1), df_w.index[-1] + pd.tseries.offsets.Week(1)]

# ロウソク足と出来高を描画する枠を確保する
ax_price = fig.add_axes([left2, under2, width, height], style=cs)
ax_volume = fig.add_axes([left2, under, width, height], style=cs)

# ロウソク足の設定
ax_price.tick_params(labelbottom=False,
                     labelleft=True,
                     labelright=True,
                     labeltop=False)
ax_price.set_title('Weekly', fontsize=10)
ax_price.set_xlim(list_xlim)
ax_price.set_xticks(list_xtick)
ax_price.yaxis.set_major_formatter(ScalarFormatter(useMathText=True))
ax_price.yaxis.get_major_formatter().set_powerlimits((0,1))

# 出来高の設定
ax_volume.set_xlim(list_xlim)
ax_volume.set_xticks(list_xtick)
ax_volume.set_xticklabels([pd.to_datetime(x).strftime('%Y/%m/%d') for x in list_xtick], rotation=90)
ax_volume.set_ylabel('Volume')
ax_volume.yaxis.set_major_formatter(ScalarFormatter(useMathText=True))
ax_volume.yaxis.get_major_formatter().set_powerlimits((0,1))

# 描画する
add_plot = [mpf.make_addplot(df_w['Volume'],
                             type='bar',
                             color='black',
                             ax=ax_volume,
                             secondary_y=False,
                             width=7)]
mpf.plot(df_w.loc[:, ['Open', 'High', 'Low', 'Close']],
         type='candle',
         ax=ax_price,
         addplot=add_plot,
         show_nontrading=True,
         style=cs,
         xrotation=90)

# === 月足 ===
# 共通になるx軸の設定 (今回は月曜ごとのメモリにしたい)
dates = df_m.index.values
list_xtick = []
for date in dates:
    month = pd.to_datetime(date).month
    if month in [4, 7, 10, 1]:
    list_xtick.append(date)
list_xlim = [df_m.index[0] - pd.tseries.offsets.MonthBegin(1), df_m.index[-1] + pd.tseries.offsets.MonthBegin(1)]

# ロウソク足と出来高を描画する枠を確保する
ax_price = fig.add_axes([left3, under2, width, height], style=cs)
ax_volume = fig.add_axes([left3, under, width, height], style=cs)

# ロウソク足の設定
ax_price.tick_params(labelbottom=False,
                     labelleft=True,
                     labelright=True,
                     labeltop=False)
ax_price.set_title('Monthly', fontsize=10)
ax_price.set_xlim(list_xlim)
ax_price.set_xticks(list_xtick)
ax_price.yaxis.set_major_formatter(ScalarFormatter(useMathText=True))
ax_price.yaxis.get_major_formatter().set_powerlimits((0,1))

# 出来高の設定
ax_volume.set_xlim(list_xlim)
ax_volume.set_xticks(list_xtick)
ax_volume.set_xticklabels([pd.to_datetime(x).strftime('%Y/%m/%d') for x in list_xtick], rotation=90)
ax_volume.set_ylabel('Volume')
ax_volume.yaxis.set_major_formatter(ScalarFormatter(useMathText=True))
ax_volume.yaxis.get_major_formatter().set_powerlimits((0,1))

# 描画する
add_plot = [mpf.make_addplot(df_m['Volume'],
                             type='bar',
                             color='black',
                             ax=ax_volume,
                             secondary_y=False,
                             width=31)]
mpf.plot(df_m.loc[:, ['Open', 'High', 'Low', 'Close']],
         type='candle',
         ax=ax_price,
         addplot=add_plot,
         show_nontrading=True,
         style=cs,
         xrotation=90)

fig.savefig('candlestick.png')

 

コメント

タイトルとURLをコピーしました