ADX(Average Directional movement indeX)、ADXR(Average Directional movement indeX Rating)

 

概要
図1 ADXとADXR、DMI

ADXはJ・ウェイルズ・ワイルダーが考案したディレクショナルムーブメントシステム(Directional Movement System)という相場解析手法の一部であるDMI(Directional Moment Indicator)から指数DX(Directional movement indeX)を計算し、さらに移動平均を取ったもので、一定方向の価格変動幅を測定し、トレンドの強さを数値化して使用するオシレーター系テクニカル指標です。図1のようにDMIと併用されることが多い指標です。

DM(方向性)からDX(方向性指数)を計算します。このDXのSMAを取ったものがADXとなります。ADXの数値が上昇し続けている時はトレンドの継続を意味しており、数値が下がっている時(水準例ADX25以下)は方向感がない状態であるとします。水準を超えた場合は買いか売りどちらかのトレンドが発生したします。数値数値が上昇し50を超えたときはトレンドが最終局面にあるとします。

このようにADXは値動きからトレンド成分を取り出して数値化したものですが、更にADXを平滑化し変動を減らして、トレンド成分を読みやすくしたものにADXR(Average Directional movement indeX Rating)があります。

計算方法

まず方向性指数を計算します。DMIで使った+DMと-DMを使って計算します。DMIの計算についてはこちらをご覧ください。DXの定義は下の通りになります。

$$ \rm{} DX = |(+DI)-(-DI)|/\{(+DI)+(-DI)\} \times 100 (\%) $$

次にn区間の場合のDXを計算し、DXのSMAを使ってADXを計算します。

$$ \rm{} DX(n) = |(+DI(n))-(-DI(n))|/\{(+DI(n))+(-DI(n))\} \times 100 (\%) \\ ADX(n) = SMA(DX(n), n) // $$

実際に計算してみたものが以下になります。計算では簡単のためnとして2を使用します。

日数終値 安値 高値 +DI(2)  -DI(2)  DX(2)  ADX(2)  
1日目10009971057
2日目10501040107412.70100
3日目10701035107317.55.254.577.3
4日目10601056108218.410.228.641.6
5日目10801078110141.8010064.3
6日目11001095115562.90100100
7日目11501112115842.90100100
8日目1120111311323.20100100
9日目113010941134024.7100100
10日目(最新)1100 10401112056.2100100

上の例ではnを2として計算していますが、日足の場合には慣用的にnに14日が使われます。

Pythonによる実装

必要なライブラリを読み込みます

!pip install mpl_finance #Collaboratoryに入っていないライブラリを読み込みます
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import pandas as pd
import mpl_finance
import sys
import numpy as np
from datetime import datetime
from matplotlib.offsetbox import OffsetImage, AnnotationBbox
import requests
import io

用意したcsvファイルからデータを読み込みます

#ファイルの読み込み
URL = "https://neulab.co.jp/wp-content/uploads/pseudo_data.csv" #csvファイルのURL

datafile = requests.get(URL)#ファイルの読み込み

#データフレームの作成
df_temp = pd.read_csv(io.BytesIO(datafile.content), header=0, index_col=0, parse_dates=True, encoding="UTF-8")

df = df_temp.loc[:,['Open','High','Low','Close']]
df.head()

DMとDIを先に計算し、ADX、ADXRを計算します

#DMIの計算
df_pDM = (df['High'] - df['High'].shift(1))
df_mDM = (df['Low'].shift(1) - df['Low'])

df_pDM.loc[df_pDM<0] = 0
df_pDM.loc[df_pDM-df_mDM < 0] = 0

df_mDM.loc[df_mDM<0] = 0
df_mDM.loc[df_mDM-df_pDM < 0] = 0

#trの計算
a = (df['High'] - df['Low']).abs()
b = (df['High'] - df['Close'].shift(1)).abs()
c = (df['Low'] - df['Close'].shift(1)).abs()

df_tr = pd.concat([a, b, c], axis=1).max(axis=1)

df_pDI = df_pDM.rolling(14).sum()/df_tr.rolling(14).sum() * 100
df_mDI = df_mDM.rolling(14).sum()/df_tr.rolling(14).sum() * 100

df_DX = (df_pDI-df_mDI).abs()/(df_pDI+df_mDI) * 100
df_DX = df_DX.fillna(0)
df_ADX = df_DX.rolling(14).mean()
df_ADXR = df_ADX.rolling(14).mean()

matplotを使ったチャートの表示と保存例です

canvas_color = '#fffafa'
line_color = '#c8ced1'
font_color = '#171510'
colorup = '#bf0000'
colordown = '#006fbf'

n_data = -100
data = df[n_data:]
ohlc = np.vstack((range(len(data)), data.T)).T

fig, (ax1, ax2) = plt.subplots(2, 1, gridspec_kw={'height_ratios': [10, 6]}, sharex=True, figsize=(12,9))
fig.patch.set_facecolor(canvas_color)
ax1.patch.set_facecolor(canvas_color)
mpl_finance.candlestick_ohlc(ax1, ohlc, width=0.5, alpha=1, colorup=colorup, colordown=colordown)
ax2.patch.set_facecolor(canvas_color)
ax2.plot(range(len(data)), df_pDI.values[n_data:], color='red', ls='-', label='+DI')
ax2.plot(range(len(data)), df_mDI.values[n_data:], color='blue', ls='-', label='-DI')
ax2.plot(range(len(data)), df_ADX.values[n_data:], color='darkorange', ls='-', label='ADX')
ax2.plot(range(len(data)), df_ADXR.values[n_data:], color='darkgrey', ls='-', label='ADXR')
ax1.grid()
ax2.grid()

l1,l2 = ax2.get_legend_handles_labels()
ax2.legend(l1,l2, fontsize=14, edgecolor='none', facecolor=canvas_color)

ax1.add_artist(im_sabo)
ax1.set_ylabel("Price of Something", fontsize=22)
ax1.set_ylim(9000., 10000.)
ax1.set_xlim(-5., 105.)
ax1.yaxis.tick_right()
ax1.yaxis.set_label_coords(0, 0.5)
ax1.tick_params(labelsize=24, labelcolor=font_color, color=line_color)

ax1.spines['left'].set_linewidth(0)
ax1.spines['right'].set_linewidth(0)
ax1.spines['top'].set_linewidth(0)
ax1.spines['bottom'].set_linewidth(0)

ax2.yaxis.tick_right()
ax2.set_ylim([0,100])
ax2.tick_params(labelsize=22, labelcolor=font_color, color=line_color)

ax2.spines['left'].set_color(line_color)
ax2.spines['right'].set_color(line_color)
ax2.spines['top'].set_color(line_color)
ax2.spines['bottom'].set_color(line_color)

xtick0 = 2
plt.xticks(range(xtick0,len(data),12), [x.strftime('%m/%d') for x in df_pDI.index][xtick0::12])

plt.subplots_adjust(left=0.05, right=0.89, bottom=0.1, top=0.99)
plt.grid(which='major',color=line_color,linestyle='-')
plt.grid(which='minor',color=line_color,linestyle='-')

ax2.grid(linestyle='--', lw=1)
ax1.set_axisbelow(True)

#バンド描画
bandx = [-5,-5,105,105]
banddown = [25,0,0,25]
ax2.fill(bandx,banddown,color="b",alpha=0.1)

fig.savefig('ADX.png', facecolor=fig.get_facecolor(), edgecolor='none')

以上のコードをGoogle社の提供しているColaboratory上で公開しており、実際に動作させることができます。

リンクはこちら

ADX、ADXRの使い方

図2のようにADXだけではトレンドの方向までは分からないので、DMIと組み合わせて予想を行います。以下はトレンドフォローの場合です。図3のように売買の方向をDMIで売買タイミングをADXで予想します。

図2 ADXによるトレンド発生判断
図3 ADXとDMIを組み合わせた使い方

ADXRの使い方はADXと同様です。

注意点

繰り返しますが、ADXが100近くに上昇している場合はトレンドが継続していることを意味していますが、 絶対値を計算に使っているので、その方向までは分かりません。トレンドの方向は別な指標を使って知る必要があります。


※このHPページで紹介しているテクニカル指標を使った取引ルールや売買シグナルの見方は一般的な考え方に基づくものであり、利益の増加や損失の減少を保証するものではありません。ご自身の判断にてお取引いただきますようお願いいたします。


現在、ニューラボでは人工知能による取引アルゴリズムを開発中です。11月にリリース予定。乞うご期待!
自動取引にご興味を持たれましたら お問い合わせページよりお気軽にお問合せください。