【第6回】mplfinanceを使用してテクニカルチャート表示
December 11, 2020
株価サーバー テクニカル分析 python無一物中Project記事一覧
- 【第1回】株価サーバーの構築の概要
- 【第2回】無尽蔵から株価データの一括取得
- 【第3回】無尽蔵株価データから銘柄毎の時系列データを生成
- 【第4回】無尽蔵から自動で株価データを取得し株価データベースを更新
- 【第5回】出来ず株価の補填と株式分割を自動調整してチャート表示
- 【第6回】mplfinanceを使用してテクニカルチャート表示(本記事)
- 【第7回】テクニカル指標による銘柄スクリーニング
- 【第8回】株価チャート配信サーバー
- 【第9回】チャート形状の認識
はじめに
今では証券会社のサイトやアプリを使用すれば、手軽に望みの株価チャートが得られますから、自前で株価チャートを生成する必要性は殆どありません。自前チャートの用途をしいて探せば、自前で保持する株価データを確認のために可視化するくらいでしょうか。
pythonには株価チャートを表示するためのmplfinanceというパッケージが用意されていて、株価の時系列データのcsvファイルがあれば、手軽にチャート表示することができます。
本記事では、mplfinanceを使い、お馴染みのローソク足チャートだけでなく、各種オシレーター系チャートなども表示させてみます。
mplfinanceでチャート表示するための株価データのロード
mplfinanceでチャート表示させるためには、次の形式のpandasのDataFrameオブジェクトとして、csvファイルをロードする必要があります。
- インデックスとしてDateTime型の’Date’列を持つ
- 寄値として’Open’列を持つ
- 高値として’High’列を持つ
- 安値として’Low’列を持つ
- 終値として’Close’列を持つ
- 出来高として’Volume’列を持つ
本サイトで紹介した方法により、無尽蔵から取得した株価データで生成した時系列データは以下の形式をしています。
2020/07/01,2716,2732,2673,2680,22600000
2020/07/02,2699,2710,2666,2697,16600000
2020/07/03,2764,2764,2689,2731,22400000
2020/07/06,2734,2740,2715,2740,16800000
2020/07/07,2750,2750,2720,2739,12200000
2020/07/08,2717,2764,2717,2733,15100000
よって、csvファイルをDataFrameとしてロードしたのち、所定の列名を付加し、日付列をインデックス指定する必要があります。
import pandas as pd
path = '/path/of/nnnn.csv' # csvファイルのパス
df = pd.read_csv(path, header=None, names=['Date','Open','High','Low','Close','Volume'], encoding='UTF-8')
df['Date'] = pd.to_datetime(df['Date'])
df = df.set_index("Date")
term = 100 # ロード期間
df = df.tail(term)
別記事で、時系列データをロードし、株式分割の調整を行った上で、mplfinanceが読み込める形式のDataFrameオブジェクトを返す関数をパッケージで用意しています。これを使用すると、時系列データのロードを簡潔に記述できます。サンプルコードでは、ロード後、チャートを表示しています。
import mplfinance as mpf
import muzinzo.adjust_close_value as mz
code = '1301' # 証券コード
df = mz.load_stock_price_timeslice(code, adjust=True, term=100)
mpf.plot(df)
基本のローソク足チャート
以下のコードでお馴染みのローソク足チャートと出来高を表示できます。
import mplfinance as mpf
import muzinzo.adjust_close_value as mz
code = '1301' # 証券コード
df = mz.load_stock_price_timeslice(code, adjust=True, term=100)
mpf.plot(df, type='candle', volume=True)
移動平均線を追加
ローソク足チャートと重ねて移動平均線等の補助チャートを表示させたい場合、補助チャートのデータををDataFrameオブジェクトとして用意し、make_addplot()でチャートに追加します。
移動平均線の算出。
def calc_mav(df, s, m, l):
# 移動平均
mav = pd.DataFrame()
mav["mav_s"] = df["Close"].rolling(s).mean()
mav["mav_m"] = df["Close"].rolling(m).mean()
mav["mav_l"] = df["Close"].rolling(l).mean()
return mav
...
df = mz.load_stock_price_timeslice('1301', adjust=True, term=100)
mav = calc_mav(df, 5, 25, 75)
addplot = mpf.make_addplot(mav[['mav_s', 'mav_m', 'mav_l']])
mpf.plot(df, type='candle', volume=True, addplot=addplot)
今回はあえて移動平均線を自力計算させて、addplotで追加しましたが、実は、期間だけ設定すれば、移動平均線を描いてくれる機能がplot()には備わっています。
df = mz.load_stock_price_timeslice('1301', adjust=True, term=100)
mpf.plot(df, type='candle', volume=True, mav=[5, 25, 75])
ストキャスティクスチャートを追加
まずは、ストキャスティクスを算出し、DataFrameに保持します。いっしょに、買われすぎ/売られすぎの目安となる80%, 20%ラインも入れておきます。
def calc_stochastic(df, term):
stochastic = pd.DataFrame()
stochastic['%K'] = ((df['Close'] - df['Low'].rolling(term).min()) \
/ (df['High'].rolling(term).max() - df['Low'].rolling(term).min())) * 100
stochastic['%D'] = stochastic['%K'].rolling(3).mean()
stochastic['%SD'] = stochastic['%D'].rolling(3).mean()
stochastic['UL'] = 80
stochastic['DL'] = 20
return stochastic
ストキャスティクスなどのオシレーター系チャートは、通常ローソク足チャートとは別パネルに表示します。make_addplot()のpanel引数を設定することにより、別パネルに表示できるようになります。
ローソク足チャートがpanel=0, 出来高を表示する場合は、出来高のパネルはpanel=1となりますから、panel=2にストキャスティクスチャートを表示させるとよいです。
df = mz.load_stock_price_timeslice('1301', adjust=True, term=100)
stochastic = calc_stochastic(df, 14)
apd_oscilator = [
mpf.make_addplot((stochastic[['%K', '%D', '%SD', 'UL', 'DL']]),
ylim=[0, 100], panel=2),
]
mpf.plot(df, type='candle', volume=True, addplot=apd_oscilator)
結果はこれ。
ストキャスティクスは、80%以上で買われすぎ、20%以下で売られすぎのサインと思っていたのですが。。。
ダマしが多く、サインの遅延もあるし、あまり当たらないな~、と思っていたら、有益な記事を見つけました。
https://www.universalpage.org/stochastic.html
ストキャスティクスでチャートの呼吸を読む。「買われすぎ、売られすぎの指標」は間違い?!
が言いえているように思えます。
この記事によれば、%K, %Dの交点(ゴールデンクロス、デッドクロス)に着目するということのようです。
rsiチャートを追加
rsiもストキャスティクス同様、買われすぎ、売られすぎをあらわすオシレーターです。
ここの研究記事には、「市場の過熱感を知りたいときはストキャスティクスよりRSIを使うべき」とあるように、ストキャスティクスよりも高性能な場合もあるようです。ただ、rsiはボックス相場の時のみ有効という知見もあります。
rsi算出コードは以下のとおり。
def calc_rsi(df, term):
rsi = pd.DataFrame()
rsi['diff'] = df['Close'].diff()
f_plus = lambda x: x if x > 0 else 0
f_minus = lambda x: x if x < 0 else 0
rsi['diff+'] = rsi['diff'].map(f_plus)
rsi['diff-'] = rsi['diff'].map(f_minus)
rsi['rs'] = rsi['diff+'].rolling(window=term, center=False).mean()\
/ rsi['diff-'].abs().rolling(window=term, center=False).mean()
rsi['rsi'] = 100.0 - (100.0 / (1.0 + rsi['rs']))
rsi['UL'] = 80
rsi['DL'] = 20
return rsi
ストキャスティクスのかわりにrsiをチャートに追加してみます。
df = mz.load_stock_price_timeslice('1301', adjust=True, term=100)
rsi = calc_rsi(df, 14)
apd_oscilator = [
mpf.make_addplot((rsi[['rsi', 'UL', 'DL']]),
ylim=[0, 100], panel=2),
]
mpf.plot(df, type='candle', volume=True, addplot=apd_oscilator)
結果はこれ。
macdチャートを追加
次に、より洗練された移動平均線であるmacdチャートを追加してみます。 まずは、macdを計算。
macdとsignalの交点(ゴールデンクロス、デッドクロス)が重要なので、これを強調する棒グラフを描くためのデータも用意します。
def calc_macd(df, es, el, sg):
macd = pd.DataFrame()
macd['ema_s'] = df['Close'].ewm(span=es).mean()
macd['ema_l'] = df['Close'].ewm(span=el).mean()
macd['macd'] = macd['ema_s'] - macd['ema_l']
macd['signal'] = macd['macd'].ewm(span=sg).mean()
macd['diff'] = macd['macd'] - macd['signal']
f_plus = lambda x: x if x > 0 else 0
f_minus = lambda x: x if x < 0 else 0
macd['diff+'] = macd['diff'].map(f_plus)
macd['diff-'] = macd['diff'].map(f_minus)
return macd
プロットした結果。
df = mz.load_stock_price_timeslice('1301', adjust=True, term=100)
macd = calc_macd(df, 12, 26, 9)
apd_oscilator = [
mpf.make_addplot((macd[['macd', 'signal']]), panel=2),
mpf.make_addplot((macd['diff+']), type='bar', color='r', panel=2),
mpf.make_addplot((macd['diff-']), type='bar', color='b', panel=2),
]
mpf.plot(df, type='candle', volume=True, addplot=apd_oscilator)
通常の移動平均線による判断よりは有効。
さいごに、これまでの分、全部のせのチャートにまとめます。panelは複数段重ねることができるのです。
df = mz.load_stock_price_timeslice('1301', adjust=True, term=100)
mav = calc_mav(df, 5, 25, 75)
stochastic = calc_stochastic(df, 14)
rsi = calc_rsi(df, 14)
macd = calc_macd(df, 12, 26, 9)
apd_oscilator = [
mpf.make_addplot((stochastic[['%D', '%SD', 'UL', 'DL']]),
ylim=[0, 100], panel=2),
mpf.make_addplot((rsi[['rsi', 'UL', 'DL']]),
ylim=[0, 100], panel=3),
mpf.make_addplot((macd[['macd', 'signal']]), panel=4),
mpf.make_addplot((macd['diff+']), type='bar', color='r', panel=4),
mpf.make_addplot((macd['diff-']), type='bar', color='b', panel=4),
mpf.make_addplot(mav[['mav_s', 'mav_m', 'mav_l']])
]
mpf.plot(df, type='candle', volume=True, addplot=apd_oscilator)
まとめ
無一物中Project第6回では、mplfinanceを使用し、お馴染みのローソク足チャートだけでなく、ストキャスティクスチャート、rsiチャート、macdチャートを表示させる方法を紹介しました。