akatak blog

プログラム初心者の50代ビジネスマンがセカンドキャリアを目指して働きながらPythonを中心に独学していましたが、昨年IT系企業に転職。新規事業開発の仕事をすることになりました。自らの覚え書きや成果物、感じたことなどを脈絡もなく書き連ねるブログです。

PlotlyとTA-libでテクニカル分析チャートを描く

前回はPythonを利用して株価のローソク足チャートを描くのに、PlotlyとCufflinksを使いました。Cufflinksを使うと、ローソク足チャートもテクニカル分析用のチャートもすごく簡単にきれいに描けました。

それはそれで良いのですが、今後、アルゴリズムトレードなどを研究していくにあたり、テクニカル分析のチャートだけでなく、データを利用できるといいですよね。

いろいろと調べていくと、テクニカル分析にはTA-Libというモジュールが良いようです。早速利用してみましょう。

TA-Libのインストール

これがうまくいかないですよね〜。私はMacを使っているのですが、conda install ta-lib, pip install ta-libもうまくいかない。ネットで調べると、困っている方がそれなりにいて、それぞれ解決策が異なっているようです。私の環境ではうまくいかず、どこかのサイトにPythonのバージョンを下げたらインストールできたという記事が載っていたので、試してみました。

新たにPython 3.5の仮想環境を作ったら、なんと今回はインストールできました。環境は個々に異なりますので、うまくいかない方はPythonのダウングレードを試してみると良いかもしれません。

TA-Libを使ってみる

TA-Lib
こちらのサイトに、簡単な使い方が書かれています。
かなりのテクニカル分析が網羅されているようで、人気があるのもわかる気がします。

さて、必要なライブラリをインポートしておきます。

# TA-Libをインポート
import talib as ta

# 株価を取得するためにpandas_datareaderもインポート
import pandas_datareader.data as web

# numpyとpandasは必須
import numpy as np
import pandas as pd

# チャートを描くのにPlotlyを利用します
import plotly.offline as pyo
import chart_studio.plotly as py
import plotly.graph_objs as go

Jupyter Notebookを利用してPlotlyのグラフを作成するには、以下のコマンドを実行しておきます。

pyo.init_notebook_mode()

さて、前回同様、pandas_datareaderを利用して、Yahooから日経225の株価データを入手します。

df = web.DataReader('^N225', 'yahoo', '2018-01-01')

これで2018/1/1以降、直近までの株価が入手できます。

さて、データの最後の5行を見ておきます。 f:id:akatak:20191123211237p:plain

問題ないですね。もし、最後の1行にデータがない(ゼロ)の場合には、以下の通り、最終行を除いておきます。

df = df.iloc[:-1]

さあ、それでは、テクニカル分析用にデータを作成していきます。TA-Libはnumpyのarray形式でしか入力を受け付けないようですので、高値・安値・終値をDataFrame, Series形式からnumpy.array形式に変換します。始値は使いません。

h = np.array(df['High'])
l = np.array(df['Low'])
c = np.array(df.loc[:, 'Close']) #このようにしても同じです。

単純移動平均 (Simple Moving Average)

sma20 = ta.SMA(c, timeperiod=20)
sma50 = ta.SMA(c, timeperiod=50)
sma200 = ta.SMA(c, timeperiod=200)

# PlotlyではDataFrameを使うので、以下の通り、dfに追加しておきます。
df['SMA20'] = sma20
df['SMA50'] = sma50
df['SMA200'] = sma200

指数平滑化移動平均(Exponential Moving Average)

ema20 = ta.EMA(c, timeperiod=20)
ema50 = ta.EMA(c, timeperiod=50)
ema200 = ta.EMA(c, timeperiod=200)

df['EMA20'] = ema20
df['EMA50'] = ema50
df['EMA200'] = ema200

MACD (Moving Average Convergence/Divergence)¶

macd, macd_sig, macd_hist = ta.MACD(c, fastperiod=12, 
                                        slowperiod=26,
                                        signalperiod=9)

df['MACD'] = macd
df['MACD_SIG'] = macd_sig
df['MACD_HIST'] = macd_hist

RSI (Relative Strength Index)¶

rsi_long = ta.RSI(c, timeperiod=14)
rsi_short = ta.RSI(c, timeperiod=7)

df['RSI_LONG'] = rsi_long
df['RSI_SHORT'] = rsi_short

WILLR (Williams' %R)¶

willr = ta.WILLR(h, l, c, timeperiod=14)

df['WILLR'] = willr

Stochastic (STOCH)

slowk, slowd = ta.STOCH(h, l, c, fastk_period=5, slowk_period=3,
                        slowk_matype=0, slowd_period=3, slowd_matype=0)

df['SLOWK'] = slowk
df['SLOWD'] = slowd

Bolinger Bands (BBANDS)

u_band, m_band, l_band = ta.BBANDS(c, timeperiod=5,
                                   nbdevup=2, nbdevdn=2, matype=0)

df['BBAND_U'] = u_band
df['BBAND_M'] = m_band
df['BBAND_L'] = l_band

ADX, DI+ and DI-

adx = ta.ADX(h,l,c,timeperiod=14)
df['ADX'] = adx

DI_plus = ta.PLUS_DI(h, l, c, timeperiod=14)
DI_minus = ta.MINUS_DI(h, l, c, timeperiod=14)
df['DI_plus'] = DI_plus
df['DI_minus'] = DI_minus

Plotlyでチャート化してみる

さて、テクニカル分析データを作成しましたので、チャート化してみましょう。

Plotlyではdatalayoutをそれぞれ作成してから、グラフ化します。 まずはlayoutから。

layout = {
    'height':1000,
    'title' : {'text':'日経225推移', 'x':0.5},
    'titlefont': {'size':25},
    'xaxis': {'title': "", 'rangeslider':{'visible':False}},
    'yaxis' : {'domain': [.55, 1], 'title': "価格(円)" ,'side':"left", 'tickformat':',' },
    'yaxis2': {'domain': [.45, .55], 'title': "RSI", 'side':"right"},
    'yaxis3': {'domain': [.35, .45], 'title': "MACD", 'side':"right"},
    'yaxis4': {'domain': [.25, .35], 'title': "Will%R", 'side':"right"},
    'yaxis5': {'domain': [.15, .25], 'title': "STOCHASTIC", 'side':"right"},
    'yaxis6': {'domain': [.05, .15], 'title': "ADX&DI", 'side':"right"},
}

heightで全体の高さを指定しておいて、各yaxisdomainにて、全体を1.0としたときの、各チャートのy軸に占める位置を[.05, .15]のように指定します。

まずは、ローソク足チャートを作成します。plotlyにはローソク足用のメソッドが用意されています。

trace = go.Candlestick(
    x     = df.index,
    open  = df['Open'],
    high  = df['High'],
    low   = df['Low'],
    close = df['Close'],
    yaxis = 'y1',
    name  = '日経225'
)

そして、以下の通り、datalayoutを指定します。

fig = {'data':[trace] ,'layout':layout}

ここで一旦チャートを描いてみましょう。

f:id:akatak:20191123215152p:plain

ここにテクニカル分析チャートを追加します。一度に追加してしまいましょう。

fig['data'].extend([
    go.Scatter(yaxis="y1" ,x=df.index ,y=df["EMA20"], name= 'EMA20', 
               line=dict(color='lightblue' ,width=1)),
    
    go.Scatter(yaxis="y1" ,x=df.index ,y=df["EMA50"] ,name= 'EMA50',
               line=dict(color='cyan' ,width=1)),

    go.Scatter(yaxis="y1" ,x=df.index ,y=df["EMA200"] ,name= 'EMA200',
               line=dict(color='darkblue' ,width=1)),
    
    go.Scatter(yaxis="y2" ,x=df.index ,y=df["RSI_LONG"] ,name= 'RSI Long',
               line=dict(color='yellowgreen' ,width=1)),

    go.Scatter(yaxis="y2" ,x=df.index ,y=df["RSI_SHORT"] ,name= 'RSI Short',
               line=dict(color='orange' ,width=1)),
    
    go.Scatter(yaxis="y3" ,x=df.index ,y=df["MACD"] ,name= 'MACD',
               line=dict(color='cornflowerblue' ,width=1)),
    
    go.Scatter(yaxis="y3" ,x=df.index ,y=df["MACD_SIG"] ,name= 'MACD(SIG)',
               line=dict(color='red' ,width=1)),
    
    go.Scatter(yaxis="y4" ,x=df.index ,y=df["WILLR"] ,name= 'WILL%R',
               line=dict(color='blue' ,width=1)),  
    
    go.Scatter(yaxis="y5" ,x=df.index ,y=df["SLOWK"] ,name= 'STOCHASTIC %K',
               line=dict(color='blue' ,width=1)), 

    go.Scatter(yaxis="y5" ,x=df.index ,y=df["SLOWD"] ,name= 'STOCHASTIC %D',
               line=dict(color='red' ,width=1)), 

    go.Scatter(yaxis="y6" ,x=df.index ,y=df["ADX"] ,name= 'ADX',
               line=dict(color='darkgreen' ,width=2)), 
    
    go.Scatter(yaxis="y6" ,x=df.index ,y=df["DI_plus"] ,name= 'D+',
               line=dict(color='orange' ,width=2)), 
    
    go.Scatter(yaxis="y6" ,x=df.index ,y=df["DI_minus"] ,name= 'D-',
               line=dict(color='lightgreen' ,width=2)), 
])

pyo.iplot(fig)

こんな感じで、うまく描けました!Plotlyはカーソルをグラフの上に持っていくと、数値が表示されるし、一部を拡大・縮小したりできるので、便利ですよね。そして、Plotlyに利用者として登録しておくと、上記のように動くグラフをブログに貼り付けたりできますので、おすすめです。

[2020/7/8 追記]

前回のブログにも記載した通り、今回のグラフも、よくみるとx軸には土日祝日もプロットされています。すなわち、プロットがなくギャップがあいているグラフとなっています。これを解消する方法を偶然知りましたので、追加情報として共有いたします。実は、layoutのxaxisに'xaxis': {'type': 'category'}を追加すると、土日祝日がx軸から除外されるようになります。ご確認いただけると幸いです。