ADX, DMI

게으른직장인·2022년 3월 23일
0

개념 정리

목록 보기
2/2
post-thumbnail

ADX는 추세의 강도를 확인하기 위한 아주 유용한 지표이다. DMI를 개선하여 나온 지표이며 ADX를 구하기 위해서는 우선 DMI를 계산하여야 한다.

DMI(Directional Movement Index)

DM(Directional Movement)

DM은 전 가격의 등락범위를 벗어난 현재 가격 등락을 의미한다. DM을 이용하여 PDM과 MDM을 아래와 같이 산출할 수 있다.

PDM=HtHt1PDM = H_t - H_{t-1}

NDM=LtLt1NDM = L_t - L_{t-1}

HtH_t 는 t일의 고가, LtL_t는 t일의 저가

단, 위 조건에서 추가로 PDM과 MDM은 한봉에 동시에 발생 할 수 없다.

TR(True Range)

TR=MAX(HtLt,HtCt1,LtCt1)TR = MAX(H_t - L_t, |H_t - C_{t-1}|, |L_t - C_{t-1}|)

CtC_t는 t일의 종가


DI(Directional Indicator)

DI는 TR값 중 DM이 차지하는 비중을 나탄낸다. 직관적으로 생각하면 가격 등락 변동폭중 심하게 튀어나간 범위의 비율을 나타내는 것이다.

DI=DMTRDI = \frac{DM}{TR}

DI를 통해서 아래와 같이 PDI와 MDI를 산출할 수 있다.

PDI=PDMTRPDI = \frac{|PDM|}{TR}

NDI=NDMTRNDI = \frac{|NDM|}{TR}

DMI 산출

PDIn=nPDMnTRPDI_n = \frac{\sum^n{PDM}}{\sum^n{TR}}

NDIn=nNDMnTRNDI_n = \frac{\sum^n{NDM}}{\sum^n{TR}}

위 N일 평균 PDI(Positive Directional Index)와 NDI(Negative Directional Index)를 함께 표기하는것을 DMI지표라 한다. PDI는 상승움직임 또는 매수 압력을 나타내며 NDI는 하락 움직임 또는 매도 압력을 의미한다.

ADX(Average Directional Index)

DX=PDIMDIPDI+MDI×100DX = \frac{|PDI - MDI|}{PDI + MDI} \times 100

ADX=i=1nDXinADX = \frac{\sum^n_{i=1}DX_i}{n}

구현

import time
import pymysql
import pandas as pd
import matplotlib.pyplot as plt
import mplfinance as mpf
import numpy as np

con = pymysql.connect(...)
cur = con.cursor()

sql = "SELECT * FROM CHART_BTCUSDT_3M WHERE DATETIME BETWEEN '20210101' AND '20220312'"
cur.execute(sql)
data = cur.fetchall()

df = pd.DataFrame(data, columns=
             [
                'datetime', 
                'open', 
                'high', 
                'low', 
                'close', 
                'volume', 
                'closeTime', 
                'QuoteAssetVolume', 
                'NumTrades',
                'TakerBuyBaseAssetVolume',
                'TakerBuyQuoteAssetVolume'  ,
                 'Ignore'
                ]
)
# df['datetime'] = pd.to_datetime(df['datetime'], unit='ms')
df.set_index('datetime', inplace=True)
df = df[['open', 'high', 'low', 'close', 'volume']]

# ADX DMI
# dm = pd.DataFrame()
pdm = df['high'].diff(1).abs()
ndm = df['low'].diff(1).abs()
cl = (df['close'] - df['close'].shift(1)).abs()

tr = pd.DataFrame()
tr['1'] = pdm
tr['2'] = ndm
tr['3'] = cl
tr = tr.sum(axis=1)

pdmn = pdm.ewm(14, adjust=False).mean()
ndmn = ndm.ewm(14, adjust=False).mean()
trn = tr.ewm(14, adjust=False).mean()

pdi = pdmn/trn
ndi = ndmn/trn

df['PDI'] = pdi
df['NDI'] = ndi
df['ADX'] = dx.ewm(14, adjust=False).mean()
df['ADX_signal'] = df['ADX'].ewm(14, adjust=False).mean()
df['ADX_OSC'] = df['ADX'] - df['ADX_signal']

df_draw = df[['PDI', 'NDI', 'ADX', 'ADX_signal', 'ADX_OSC']]

df_draw = df_draw.iloc[-500:]
df_test = df.iloc[-500:]

adps = []
adps.append(
    mpf.make_addplot(df_draw['ADX_OSC'], panel=2,type='bar',secondary_y=True, ylabel='ADX_OSC'))
adps.append(
    mpf.make_addplot(df_draw['ADX'], panel=2,type='line',secondary_y=False, ylabel='ADX'))
adps.append(
    mpf.make_addplot(df_draw['ADX_signal'], panel=2,type='line',secondary_y=False, ylabel='ADX'))
adps.append(
    mpf.make_addplot(df_draw['NDI'], panel=1,type='line',secondary_y=False, ylabel='DMI'))
adps.append(
    mpf.make_addplot(df_draw['PDI'], panel=1,type='line',secondary_y=False))

mpf.plot(df_test, style='charles', figratio=(8,5),figscale=3, addplot=adps, returnfig=True)

profile
취미로 퀀트 투자를 도전하는 직장인

0개의 댓글