はじめに
株価データの分析のために,複数銘柄のチャートを描きたいと思った
例えば,TOPIX Core30 だと30銘柄ある
1銘柄ずつループで回していると,チャートは表示されるものの,ワーニングが表示される
/usr/local/lib/python3.9/site-packages/mplfinance/_mplwraps.py:60:
RuntimeWarning: More than 20 figures have been opened.
Figures created through the pyplot interface
(`matplotlib.pyplot.figure`) are retained until explicitly closed
and may consume too much memory.
(To control this warning, see the rcParam `figure.max_open_warning`).
f = plt.figure(FigureClass=Mpf_Figure,*args,**kwargs)
※本記事中,見やすさのため,出力結果の一部に改行をいれているところがあります
20個より多くのグラフを描くとワーニングになるようで,
このワーニングがでなくなる方法を備忘録として残しておく
ワーニングが出たコード
こちらのデータ(SPY_20110701_20120630_Bollinger.csv)を使って同じチャートを30回描くコードだ
import pandas as pd
import mplfinance as mpf
df = pd.read_csv('SPY_20110701_20120630_Bollinger.csv',index_col=0,parse_dates=True)
# 30回チャートを描く
for index in range(30):
# チャート描画
fig = mpf.figure(figsize=(3, 3),style='yahoo')
ax1 = fig.add_subplot(1,1,1)
mpf.plot(df, ax=ax1, style='yahoo', type='candle', xrotation=30)
問題解決のため調査をはじめる
このワーニングの対処法を調査すると,matplotlib の解決策ばかりだった
plt.clf()
plo.close()
matplotlib では clf と close を呼べばいいらしい
しかし,mplfinance の場合は,closeやclfがない
試しに読んでみると
>>> mpl.close()
AttributeError: module 'mplfinance' has no attribute 'close'
>>> mpl.clf()
AttributeError: module 'mplfinance' has no attribute 'clf'
モジュール内の一覧を表示してみると
>>> import mplfinance as mpl
>>> dir(mpl)
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__',
'__package__', '__path__', '__spec__', '__version__', '_arg_validators', '_helpers',
'_mpf_warnings', '_mplwraps', '_panels', '_styledata', '_styles', '_utils', '_version',
'_widths', 'available_styles', 'figure', 'make_addplot', 'make_marketcolors',
'make_mpf_style', 'mplfinance', 'plot', 'plotting', 'show', 'write_style_file']
確かになさそうだ
fig を作った plt を得るしかなさそうである
mplfinance のソースを見てみる
mplfinance.figure が定義されている,_mplwraps.py を見ると plt がいた
def figure(*args,**kwargs):
style = _check_for_and_apply_style(kwargs)
f = plt.figure(FigureClass=Mpf_Figure,*args,**kwargs)
f.mpfstyle = style
return f
class Mpf_Figure(mplfigure.Figure):
…
matplotlib.pyplot.figure()
関数を呼び出している
引数FigureClass=Mpf_Figure
のMpf_Figureクラスは,_mplwraps.py 内で定義されているクラスだ
The wrapper function is the same as `matplotlib.pyplot.figure()`
except that it additionally accepts kwarg `style=` to set the mplfinance style.
_mplwraps.py のヘッダに書かれているが,mplfinance.figure()
関数は基本 matplotlib.pyplot.figure()
関数と同じだ
ただし,mplfinance の style を設定できるところだけが違う
style = _check_for_and_apply_style(kwargs)
_check_for_and_apply_style()
関数で matplotlib.pyplot.figure()
関数 に渡す kwargs から style を削除しているようだ
f.mpfstyle = style
そして,matplotlib.pyplot.figure()
関数でできた mplfinance.figure に後からスタイルを設定している
解決案
matplotlib.pyplot と,mplfinance._mplwraps.Mpf_Figure をインポート
import matplotlib.pyplot as plt
import mplfinance as mpf
from mplfinance._mplwraps import Mpf_Figure
figure の生成を,mplfinance.figure()
関数から,matplotlib.pyplot.figure()
関数に変更する
style は後から設定してあげる
# もともとの figure 生成
fig = mpf.figure(figsize=(3, 3),style='yahoo')
# 新しい figure の生成方法
fig = plt.figure(FigureClass=Mpf_Figure,figsize=(3, 3))
fig.mpfstyle = 'yahoo'
plot が終わったら,clf と close を呼んであげる
plt.show()
plt.clf()
plt.close()
まとめると以下のようだ
import pandas as pd
import matplotlib.pyplot as plt
import mplfinance as mpf
from mplfinance._mplwraps import Mpf_Figure
df = pd.read_csv('SPY_20110701_20120630_Bollinger.csv',index_col=0,parse_dates=True)
# 30回チャートを描く
for index in range(30):
# チャート描画
fig = plt.figure(FigureClass=Mpf_Figure,figsize=(3, 3))
fig.mpfstyle = 'yahoo'
ax1 = fig.add_subplot(1,1,1)
mpf.plot(df, ax=ax1, style='yahoo', type='candle', xrotation=30)
plt.show()
plt.clf()
plt.close()
めでたくワーニングが消えた
おわりに
matplotlib でのワーニングを消す方法を参考に mplfinance で行ってみた
うまいやり方,良い方法かどうかわからない…
これは違う,こうしたほうが良いなどあれば,コメントいただければと思う
追記
単にこれでよかったのかもしれない
インポートについて理解していなかったが,
Pythonのモジュールインポートのしくみを読むと,
モジュールオブジェクトはシングルトンなため,
自分で import した plt(matplotlib.pyplot)を使って clr,close を呼ぶだけ
# matplotlib.pyplot をインポート
import matplotlib.pyplot as plt
# plot,show の後に,pltのclf,closeを呼ぶ
plt.clf()
plt.close()
まとめると
import pandas as pd
import matplotlib.pyplot as plt
import mplfinance as mpf
df = pd.read_csv('SPY_20110701_20120630_Bollinger.csv',index_col=0,parse_dates=True)
# 30回チャートを描く
for index in range(30):
# チャート描画
fig = mpf.figure(figsize=(3, 3),style='yahoo')
ax1 = fig.add_subplot(1,1,1)
mpf.plot(df, ax=ax1, style='yahoo', type='candle', xrotation=30)
plt.show()
plt.clf()
plt.close()