【第6回】mplfinanceを使用してテクニカルチャート表示

December 11, 2020

株価サーバーテクニカル分析python

無一物中Project記事一覧


はじめに

今では証券会社のサイトやアプリを使用すれば、手軽に望みの株価チャートが得られますから、自前で株価チャートを生成する必要性は殆どありません。自前チャートの用途をしいて探せば、自前で保持する株価データを確認のために可視化するくらいでしょうか。

pythonには株価チャートを表示するためのmplfinanceというパッケージが用意されていて、株価の時系列データのcsvファイルがあれば、手軽にチャート表示することができます。

本記事では、mplfinanceを使い、お馴染みのローソク足チャートだけでなく、各種オシレーター系チャートなども表示させてみます。

mplfinanceでチャート表示するための株価データのロード

mplfinanceでチャート表示させるためには、次の形式のpandasのDataFrameオブジェクトとして、csvファイルをロードする必要があります。

  • インデックスとしてDateTime型の’Date’列を持つ
  • 寄値として’Open’列を持つ
  • 高値として’High’列を持つ
  • 安値として’Low’列を持つ
  • 終値として’Close’列を持つ
  • 出来高として’Volume’列を持つ

DataFrame.png

本サイトで紹介した方法により、無尽蔵から取得した株価データで生成した時系列データは以下の形式をしています。

1301.csv
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)

candle0.png

基本のローソク足チャート

以下のコードでお馴染みのローソク足チャートと出来高を表示できます。

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)

candle1.png

移動平均線を追加

ローソク足チャートと重ねて移動平均線等の補助チャートを表示させたい場合、補助チャートのデータをを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)

candle2.png

今回はあえて移動平均線を自力計算させて、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)

結果はこれ。

candle3.png

ストキャスティクスは、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)

結果はこれ。

candle6.png

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)

candle4.png

通常の移動平均線による判断よりは有効。

さいごに、これまでの分、全部のせのチャートにまとめます。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)

candle7.png

まとめ

無一物中Project第6回では、mplfinanceを使用し、お馴染みのローソク足チャートだけでなく、ストキャスティクスチャート、rsiチャート、macdチャートを表示させる方法を紹介しました。


Written by questions6768 who lives in Uji, Kyoto.