DMI(方向性指数)をPythonを使って計算してみた。DMIの使い方や計算方法などのまとめ。
こんにちは、新米データサイエンティスト(@algon_fx)です。今までやってきたPythonでテクニカル指標シリーズですが、今まではコーディングも含めて2〜3時間で書ける内容でした。
ところが!ところがですよ!今回のDMI(方向性指数 – Directional Movement Indesx)は、めっちゃ時間が掛かりました。昨日と今日の2日分の勉強時間を費やされました。DMI、計算がめっちゃややこしい。
ただ、テクニカル指標としては初心者から上級者まで人気が高いのも事実です。では、DMIの使い方や概要、さらにPythonを使って過去レートからDMIを計算してみましょう。
【人気記事】
DMI(方向性指数)とは?
DMI(方向性指数)ですが、英語ではDirectional Movement Indexで、考案されたのは1978年です。DMIの考案者ですが、ワイルダーさんという方で、実はこの方、他にも人気のテクニカル指標である「RSI」や「パラボリック」を考案された方です。
DMIの特徴として、一般的にトレンド相場が弱点なオシレーター系指標にも関わらず、その弱点を克服するために考案された指標なんです。(オシレーター系は一般的にレンジ相場のみでしか働かない)
下記のPythonコードを紐解くとより理解しやすいですが、DMIは前日の高値(または安値)と当日の高値(または安値)の変動幅を使っています。つまり、DMIはトレンドの方向性や、その強さを指標として表しているわけです。
DMI(方向性指数)の計算方法
次にDMIの計算方法ですが…これがマジで厄介です。単純移動平均(SMA)を用いるのが元々、ワイルダーさんが考案したものらしいのですが、現在では指数平滑移動平均(EMA)を使って処理をするのが一般的なようです。
DMIの細かい計算方法ですが、それを説明するだけで記事が膨大な量になるので、割愛します。詳しい計算方法は、下のPythonのコードを見て頂いた方が良いかと!
ここでは、DMIを計算する上で必要な指標の概要を説明します。個人的に後日にコードを見直した時に、これなんだってなりそうなんで…。
(1)DM – Directional Movement)
DMIの方向を決めるやつです。前日と当日の「上昇幅 or 下落幅」を比較地して、大きい方を採用する。不採用は0とする。
(2)TR – Truen Range
実質変動幅と訳されるのがTRです。これは(あ)当日の高値 – 当日の安値、(い)当日の高値 – 前日の終値、(う)前日の終値 – 当日の安値の3つを計算して、(あ)と(い)の比較、(あ)と(う)の比較をして、大きい方を採用します。(ややこしい!w)
(3)DI – Direction Inidicator
これはDMをTRで割ることで求めることが可能で、上昇または下落の強さを表します。。DIには「+DI」と「-DI」の二種類があり、求め方は下記の通りです。期間は一般的には14が使われます。
(4)DX – Directional Movement Index
「+DI」と「-DI」の差の絶対値を、適用された方向性の比率で割ります。いわば、トレンドの強弱をつけてくれるわけです。
(5)ADX – Average Directional Movement Index
そして、いよいよ最後にADXの計算です。こいつは、DXの指数平滑移動平均で求めます。
軽くDMIの計算方法をまとめようと心がけましたが、それぞれの触りしか触れていないのに、この量(笑)。Pythonがわかる方は、下のコードを見た方が、絶対にわかりやすいかと思います!
+DI -DI ADXの使い方(DMI)
さて、この計算がとても面倒なDMIですが、実際にトレードでどのような使い方をするのか、簡単に見ていきましょう。上の計算方法で説明した、「+DI」「-DI」「ADX」を使います。それぞれの、ざっくりとした意味は…
計算は死ぬほど面倒ですが、そういう指標に限って、使い方はシンプルで楽チン。こういうの大好きです。では、実際に下記のドル円の1分足、+DI=青色、-DI=黄色、ADX=赤色のチャートを見ながら使い方を紐解きましょう。
DMIですが、様々な使い方がありますが、まずはオーソドックスな+DI(青)と-DI(黄)のクロスから。下の赤丸のポイントで、+DI(青)が-DI(黄)を上抜けしてますが、これが買いのシグナルです。
逆のポイントで+DI(青)が-DI(黄)下抜けしているのが下のチャートでも確認できますが、その後は相場はレンジになっており、いわゆる「騙し」ですよね。DIのみを使ってトレードする人もいますが、騙しを見分けるためにADXと併せ使う人の方が一般的かと。
次はADXのみを表示させて見ました。また、わかりやすいようにADXの値が20のラインに赤線を引いています。ADXの使い方ですが、ADXが25未満の場合は「レンジ相場」で、ADXが25以上の場合は「トレンド相場」といった、トレンド指標として使えます。
実際に下のチャートを見ても、ADXが25未満の場所は、確かにレンジ相場になっているのが確認できますね。
このように、計算方法が本当に厄介なDMIですが、そのぶん、役に立つスーパーテクニカル指標なんです。(なにそれ)
DMI(方向性指数)をPythonを使って計算する
さて、いよいよPythonを使ってDMIを計算してみましょう。上の計算方法で示した通り、DMIをなす要素「DM」「TR」「DI(プラスとマイナス)」「DX」そして「ADX」の全てのロジックを処理する必要があります。
今回はビットコインの過去レートをスクレイピングして使います。詳しくは「ビットコインやらイーサリアムなど仮想通貨の過去レートをスクレイピングする方法」の記事をご参照ください。
では、まずは必要なライブラリーからインポートしましょう。
1 2 3 4 5 6 7 8 9 10 |
# DMI(方向性指数)を計算するのに必要なライブラリー import pandas as pd from datetime import datetime import matplotlib.pyplot as plt import time import numpy as np %matplotlib qt |
次にビットコインのレートを引っ張ってきて、Pandasのデータフレームへぶち込みます。こちら、1日ごとのレートです。
1 2 3 4 5 6 |
# コインマーケットキャップからデータをスクレイピング bit = pd.read_html("https://coinmarketcap.com/currencies/bitcoin/historical-data/?start=20180101&end="+time.strftime("%Y%m%d"))[0] bit = bit.assign(Date=pd.to_datetime(bit['Date'])) bit['Volume'] = bit['Volume'].astype('int64') |
これでビットコインのOHLCと日付&取引量が取れましたので、次は計算しやすいようにPadasのシリーズへ一つ一つ切り分けてあげましょう。
1 2 3 4 |
# レートをPandasのシリーズへ切り分け date, closep, highp, lowp, openp, volume = bit['Date'], bit['Close'], bit['High'], bit['Low'], bit['Open'], bit['Volume'] |
では、まず初めの処理として、TR(True Range)から描いてあげます。d=date、c=close、h=high、l=low、o=open、yc=yesterda close(前日の終値)です。
計算後、d(日付)とTR(True Range)を戻します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# TrueRangeの関数 def TR(d, c, h, l, o, yc): x = h-l y = abs(h-yc) z = abs(l-yc) if y <= x >= z: TR = x elif x <= y >= z: TR = y elif x <= z >= y: TR = z return d, TR |
次はDMを処理してあげましょう。各アーギュメントは、上の名付け例をご参考ください。yと付いているのは全て前日=Yesterdayの値です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
# DMの処理 def DM(d, o, h, l, c, yo, yh, yl, yc): moveUp = h - yh moveDown = yl - l if 0 < moveUp > moveDown: PDM = moveUp else: PDM = 0 if 0 < moveDown > moveUp: NDM = moveDown else: NDM = 0 return d, PDM, NDM |
今回は指数平滑移動平均(EMA)を使いますので、EMA関数も作っておきます。
1 2 3 4 5 6 7 8 9 |
# EMAの処理 def ExpMovingAverage(values, window): weights = np.exp(np.linspace(-1., 0., window)) weights /= weights.sum() a = np.convolve(values, weights, mode='full')[:len(values)] a[:window] = a[window] return a |
これで、チャートに表示する「+DI(ポジティブDI)」と「-DI(ネガティブDI」の計算が可能になりましたので、DIの計算を行います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# +DIと-DIの計算 def calcDIs(): x = 1 TRDates = [] TrueRanges = [] PosDMs = [] NegDMs = [] while x < len(date): TRDate, TrueRange = TR(date[x], closep[x], highp[x], lowp[x], openp[x], closep[x-1]) TRDates.append(TRDate) TrueRanges.append(TrueRange) #DM(d, o, h, l, c, yo, yh, yl, yc): DMdate, PosDM, NegDM = DM(date[x], openp[x], highp[x], lowp[x], closep[x], openp[x-1], highp[x-1], lowp[x-1], closep[x-1]) PosDMs.append(PosDM) NegDMs.append(NegDM) x += 1 expPosDM = ExpMovingAverage(PosDMs, 14) expNegDM = ExpMovingAverage(NegDMs, 14) ATR = ExpMovingAverage(TrueRanges, 14) xx = 0 PDIs = [] NDIs = [] while xx < len(ATR): PDI = 100 * (expPosDM[xx] / ATR[xx]) PDIs.append(PDI) NDI = 100 * (expNegDM[xx] / ATR[xx]) NDIs.append(NDI) xx += 1 return PDIs,NDIs |
最後に…トレンドを示す指標である「ADX」を計算してあげましょう!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
# ADXの処理 def ADX(): PositiveDI, NegativeDI = calcDIs() xxx = 0 DXs = [] while xxx < len(date[1:]): DX = 100*( (abs(PositiveDI[xxx] - NegativeDI[xxx]) /(PositiveDI[xxx] + NegativeDI[xxx])) ) DXs.append(DX) xxx += 1 ADX = ExpMovingAverage(DXs, 14) return ADX, PositiveDI, NegativeDI, date |
では、実際にADX()の関数を走らせて、ADX、PositiveDI(+DI)、NegativeDI(-DI)とdateを計算して見ましょう。
1 2 3 4 |
# DMIの処理を行う ADX, PositiveDI, NegativeDI, date = ADX() |
大丈夫そうですね!最後に、ビットコインの終値とDMI(+DI、-DI、ADX)をMatplotlibを使ってチャートにしてみましょう。DMIですが、前日の終値・高値・安値を使って算出するので、dateの一番初めのデータは落とします。
1 2 3 4 5 6 7 8 9 10 11 |
#DMIをプロッティング plotDate = date[1:] fig, (ax1, ax2) = plt.subplots(2,1, gridspec_kw = {'height_ratios':[3, 1]}) ax1.plot(plotDate, bit['Close'][1:]) ax2.plot(plotDate, ADX, 'b') ax2.plot(plotDate, PositiveDI, 'g') ax2.plot(plotDate, NegativeDI, 'r') plt.legend() plt.show() |
できてますね!これで、過去レートから必要な指標を処理して、DMIをチャートに乗せることができました。
まとめと次の課題
今回は、Pythonでテクニカル指標シリーズとして、トレンドの方向性と強弱を示す「DMI(方向性指数)」をPythonを使って計算をしてみました。DMIを成す「+DI」「-DI」「ADX」の指標を全て計算してMatplotlibでチャートを作ってみました。
本当に計算方法が複雑で、他のテクニカル指標の2倍以上の労力がかかりましたが、、DMIをトレードで利用している人も多いので、しっかりと出来て良かったです。
次の課題としては…本当に処理があっているのか不安ですので、その検証をしなくてはですね・・・。
長文でしたが、ブログ読んでいただきありがとうございます!Twitterでも色々と発信しているので、是非フォローお願いします!
ディスカッション
コメント一覧
まだ、コメントがありません