[기술적 분석] 지표/전략 : MACD(Moving Average Convergence Divergence)

반응형

 

  MACD(이동 평균 수렴 확산, Moving Average Convergence Divergence)은 이동평균을 이용한 지표와 매매 전략 중 골든 크로스, 데드 크로스(Golden Cross, Dead Cross) 다음으로 유명한 지표가 아닌가 싶다. 말 그대로 이동 평균선이 벌어지고 언젠가는 모이는 가격 흐름을 이용하여 매매하는 방식인데 기본적인 개념은 골든 크로스, 데드 크로스 혹은 APO(Absolute Price Oscillator)와 유사하다. 우선 단기, 장기 이동 평균선 두 개를 이용해 이 차이를 MACD라고 한다. 여기까지는 APO와 다를 바가 없는데, MACD를 이동 평균하여 시그널(Signal)이라는 선을 하나 더 만든다. 이로서 오실레이터가 되며, MACD와 시그널의 차이를 히스토그램 형태로 표시한다. 결론적으로 APO를 이동 평균하여 오실레이터를 만들고 이 차이를 또 수치화한다. APO에 비해 2개 더, 3배 더 많은 정보를 가지고 투자에 임하는 것이다.

 

  MACD를 처음 만든 사람은 제럴드 아펠(Gerald Appel). 제럴드가 70년대에 MACD를 처음 만들었을 때에는 이동평균의 차이인 MACD와 이것의 이동평균인 시그널만 존재하는 오실레이터 지표였다. 이후 80년대에 들어 톰 애스프레이(Tom Aspray)에 의해 MACD와 시그널의 차이인 히스토그램이 추가되어 현재 우리가 알고 있는 MACD의 형태가 완성되었다. 일반적으로 이동평균은 EMA(지수 이동 평균, Exponential Moving Average)를 사용하며, 단기 이동 평균은 12일, 장기 이동 평균은 26일을 사용한다. MACD를 이동평균할 때에는 통상 9일을 사용하며 이 역시 지수 이동 평균을 사용한다.

 

MACD(Moving Average Convergence Divergence) 보조 지표

반응형

 

  매매 전략은 골든/데드 크로스와 동일하게 MACD라인이 양수, 음수로 전환될 때 거래를 하는 방식. MACD에서 MACD라인은 APO와 마찬가지로 단기 이동 평균이 장기 이동 평균보다 높은 가격을 형성하고 위쪽에 있는 경우이다. 이때는 상승 추세로 보고 MACD가 기준선(0)을 상향 돌파하면 상승 추세 전환으로 보고 매수(골든 크로스), MACD가 기준선(0)을 하향 돌파하면 하락 추세 전환으로 보고 매도(데드 크로스)한다. 이 기본적인 골든/데드 크로스 전략을 무시하면 안 되는 게 실제로 지표들을 만져보면 알겠으나 수익률이 결코 낮은 전략이 아니다. 사이클이 존재하거나(석유, 화학, 원자재, 반도체 등) 매일매일 예측 불가로 날뛰지 않는 시가총액 높은 종목들에 이 전략을 적용하면 엥간한 액티브 펀드보다 수익률이 좋게 나오는 경우가 많다.

 

  다음으로는 오실레이터다 보니 MACD와 시그널 라인이 교차하는 경우에 거래하는 방식. MACD 라인이 시그널 라인을 상향 돌파하면(히스토그램이 양수이면) 매수, MACD 라인이 시그널 라인을 하향 돌파하면(히스토그램이 음수이면) 매도하는 방식이다. 앞서 말했듯이 지표의 이름이 이동 평균의 '수렴과 발산'인 이유는 이 지표의 기본적인 사상이 주가가 오르락 내리락 하면서 '장/단기 이동평균선이 지속적으로 수렴과 발산을 반복한다.'라는 믿음에서 시작했기 때문이다. 근데 이동평균선이 최대로 수렴하면 MACD가 0인 것은 알겠는데, 최대로 발산했을 지점은 어디인가? 그래야 언제부터 수렴할지(추세 전환이 발생할지)를 파악할 수 있는데, 이 지점을 포착할 목적으로 만든 것이 시그널 라인이다. 따라서 이 전략은 매매 시그널이 앞선 골든/데드 크로스 전략에 비해 빠르게 나오며 이 때문에 허위 시그널도 자주 발생해 매매가 빈번해질 수 있다.

 

  추가로, 주가와 MACD 및 시그널의 방향이 다른 경우를 다이버전스라 하여 추세 전환을 예측하는 용도로 사용되기도 한다. 즉, 주가는 상승 중인데 MACD와 시그널은 고점을 갱신하지 못하고 하락하는 경우나 주가는 하락 중인데 MACD와 시그널은 저점을 갱신하지 못하고 상승하는 경우(이동평균 간의 간격이 좁아지는 경우, 수렴하는 경우)에는 조만간 추세전환이 발생할 것으로 예측할 수 있다. 단, 다이버전스의 경우에는 시스템에 적용하여 매매 전략을 만드는데 어려움이 있을 수 있다.

 

  MACD는 추세와 추세의 강도를 파악하기에는 강력한 지표 중 하나이고 유명한 데에는 이유가 있는 법. 대충 적용하여도 꽤 좋은 수익률을 보여주는 지표이자 전략이다. 다만, 이 역시 APO와 마찬가지로 수치화하여 표현할 때, 기본적으로 주당 가격이 높은 종목은 그 수치가 크게 나오고 주당 가격이 낮은 종목은 수치가 낮게 나오는 단점이 있어 종목 간 비교를 어렵게 한다. 이런 단점을 보완한 게 MACD를 만든 제럴드 아펠 본인이 다시 만든 PPO(Percentage Price Oscillator)인데, 이는 다음에 이어서 설명한다.

2024.05.18 - [주가 분석/기술적 분석] - [기술적 분석] 지표/전략 : PPO(Percentage Price Oscillator)

 

[기술적 분석] 지표/전략 : PPO(Percentage Price Oscillator)

MACD(Moving Average Convergence Divergence)를 만든 제럴드 아펠(Gerald Appel)이 만든 PPO(Percentage Price Oscillator)를 소개한다. PPO는 MACD와 거의 유사하다. 다만, MACD의 특성상 장/단기 이동 평균선의 차이를 그대

antsinvest.tistory.com

 

 

  마지막으로 트레이딩 뷰 파인 스크립트 소스와 pandas-ta 소스를 공유하며 마친다.

 

 

  • MACD(Moving Average Convergence Divergence) 트레이딩 뷰 파인 스크립트 지표 소스
//@version=5
indicator(title="Moving Average Convergence Divergence", shorttitle="MACD", format=format.price, precision=2, timeframe="", timeframe_gaps=true)
import TradingView/ta/7 as ta7
import blackcat1402/pandas_ta/7 as pta

ma(source, length, _type) =>
    switch _type
        "SMA" => ta.sma(source, length)
        "EMA" => ta.ema(source, length)
        "DEMA" => ta7.dema(source,length)
        "TEMA" => ta7.tema(source,length)
        "FRAMA" => ta7.frama(source,length)
        "T3" => ta7.t3(source,length)
        "TRIMA" => ta7.trima(source,length)
        "RMA" => ta.rma(source, length)
        "WMA" => ta.wma(source, length)
        "HMA" => ta.hma(source, length)
        "VWMA" => ta.vwma(source * volume, length)
        "ALMA" => pta.alma(source, length)
        "JMA" => pta.jma(source, length)
        "SINWMA" => pta.sinwma(source, length)
        "FWMA" => pta.fwma(source, length)
        "LINREG" => pta.linreg(source, length)
        "SWMA" => pta.swma(source)
        "YIDYA" => pta.vidya(source, length)
        "VWAP" => pta.vwap(source)
        "ZLMA" => pta.zlma(source, length)

srcInput = input(close, "Source")
shortLengthInput = input.int(12, title="Short Length", group="Short", minval=1)
shortmaTypeInput = input.string("EMA", title="Short MA Type", options = ["SMA", "EMA", "DEMA", "TEMA", "FRAMA", "T3", "TRIMA", "RMA", "WMA", "HMA", "VWMA", "ALMA", "JMA", "SINWMA", "FWMA", "LINREG", "SWMA", "VIDYA", "VWAP", "ZLMA"], group="Short", display = display.data_window)
longLengthInput = input.int(26, title="Long Length", group="Long", minval=1)
longmaTypeInput = input.string("EMA", title="Short MA Type", options = ["SMA", "EMA", "DEMA", "TEMA", "FRAMA", "T3", "TRIMA", "RMA", "WMA", "HMA", "VWMA", "ALMA", "JMA", "SINWMA", "FWMA", "LINREG", "SWMA", "VIDYA", "VWAP", "ZLMA"], group="Long", display = display.data_window)
signalLengthInput = input.int(9, title="Long Length", group="Signal", minval=1)
signalmaTypeInput = input.string("EMA", title="Short MA Type", options = ["SMA", "EMA", "DEMA", "TEMA", "FRAMA", "T3", "TRIMA", "RMA", "WMA", "HMA", "VWMA", "ALMA", "JMA", "SINWMA", "FWMA", "LINREG", "SWMA", "VIDYA", "VWAP", "ZLMA"], group="Signal", display = display.data_window)

shortMA = ma(srcInput, shortLengthInput, shortmaTypeInput)
longMA = ma(srcInput, longLengthInput, longmaTypeInput)

MACD = shortMA - longMA
signal = ma(MACD, signalLengthInput, signalmaTypeInput)
histogram = MACD - signal

plot(MACD, title="MACD", color=color.blue)
plot(signal, title="Signal", color=color.red)
hline(0, "Middle Band", linestyle=hline.style_dotted, color=color.gray)
plot(histogram, title = "Histogram", style = plot.style_columns, color = (histogram >= 0 ? (histogram[1] < histogram ? #26A69A : #B2DFDB) : (histogram[1] < histogram ? #FFCDD2 : #FF5252)))

 

 

  • MACD(Moving Average Convergence Divergence) 트레이딩 뷰 파인 스크립트 전략 소스
//@version=5
strategy(title="Moving Average Convergence Divergence", shorttitle="MACD", margin_long=100, margin_short=100, default_qty_type=strategy.percent_of_equity, default_qty_value=50, commission_type=strategy.commission.percent, commission_value=0.2, pyramiding=0)
import TradingView/ta/7 as ta7
import blackcat1402/pandas_ta/7 as pta

ma(source, length, _type) =>
    switch _type
        "SMA" => ta.sma(source, length)
        "EMA" => ta.ema(source, length)
        "DEMA" => ta7.dema(source,length)
        "TEMA" => ta7.tema(source,length)
        "FRAMA" => ta7.frama(source,length)
        "T3" => ta7.t3(source,length)
        "TRIMA" => ta7.trima(source,length)
        "RMA" => ta.rma(source, length)
        "WMA" => ta.wma(source, length)
        "HMA" => ta.hma(source, length)
        "VWMA" => ta.vwma(source * volume, length)
        "ALMA" => pta.alma(source, length)
        "JMA" => pta.jma(source, length)
        "SINWMA" => pta.sinwma(source, length)
        "FWMA" => pta.fwma(source, length)
        "LINREG" => pta.linreg(source, length)
        "SWMA" => pta.swma(source)
        "YIDYA" => pta.vidya(source, length)
        "VWAP" => pta.vwap(source)
        "ZLMA" => pta.zlma(source, length)

srcInput = input(close, "Source")
shortLengthInput = input.int(12, title="Short Length", group="Short", minval=1)
shortmaTypeInput = input.string("EMA", title="Short MA Type", options = ["SMA", "EMA", "DEMA", "TEMA", "FRAMA", "T3", "TRIMA", "RMA", "WMA", "HMA", "VWMA", "ALMA", "JMA", "SINWMA", "FWMA", "LINREG", "SWMA", "VIDYA", "VWAP", "ZLMA"], group="Short", display = display.data_window)
longLengthInput = input.int(26, title="Long Length", group="Long", minval=1)
longmaTypeInput = input.string("EMA", title="Short MA Type", options = ["SMA", "EMA", "DEMA", "TEMA", "FRAMA", "T3", "TRIMA", "RMA", "WMA", "HMA", "VWMA", "ALMA", "JMA", "SINWMA", "FWMA", "LINREG", "SWMA", "VIDYA", "VWAP", "ZLMA"], group="Long", display = display.data_window)
signalLengthInput = input.int(9, title="Long Length", group="Signal", minval=1)
signalmaTypeInput = input.string("EMA", title="Short MA Type", options = ["SMA", "EMA", "DEMA", "TEMA", "FRAMA", "T3", "TRIMA", "RMA", "WMA", "HMA", "VWMA", "ALMA", "JMA", "SINWMA", "FWMA", "LINREG", "SWMA", "VIDYA", "VWAP", "ZLMA"], group="Signal", display = display.data_window)
indi = input.string("Golden/Dead Cross(MACD)", title="Strategy Indicator", options = ["Golden/Dead Cross(MACD)", "Golden/Dead Cross(Signal)", "MACD-Signal"])

shortMA = ma(srcInput, shortLengthInput, shortmaTypeInput)
longMA = ma(srcInput, longLengthInput, longmaTypeInput)

MACD = shortMA - longMA
signal = ma(MACD, signalLengthInput, signalmaTypeInput)
histogram = MACD - signal

plot(MACD, title="MACD", color=color.blue)
plot(signal, title="Signal", color=color.red)
hline(0, "Middle Band", linestyle=hline.style_dotted, color=color.gray)
plot(histogram, title = "Histogram", style = plot.style_columns, color = (histogram >= 0 ? (histogram[1] < histogram ? #26A69A : #B2DFDB) : (histogram[1] < histogram ? #FFCDD2 : #FF5252)))

startDate = input.time(defval=timestamp("01 Jan 1970 00:00 +0000"), group = "Test Range")
finishDate = input.time(defval=timestamp("31 Dec 2025 24:00 +0000"), group = "Test Range")
time_condition = time >= startDate and time <= finishDate
 
if(time_condition)
	if (indi == "Golden/Dead Cross(MACD)")
		if ta.crossover(MACD, 0)
			strategy.entry("매수", strategy.long, oca_type=strategy.oca.cancel, comment="매수")
		if ta.crossunder(MACD, 0)
			strategy.close_all('매도')
	if (indi == "Golden/Dead Cross(Signal)")
		if ta.crossover(signal, 0)
			strategy.entry("매수", strategy.long, oca_type=strategy.oca.cancel, comment="매수")
		if ta.crossunder(signal, 0)
			strategy.close_all('매도')
    if (indi == "MACD-Signal")
		if ta.crossover(MACD, signal)
			strategy.entry("매수", strategy.long, oca_type=strategy.oca.cancel, comment="매수")
		if ta.crossunder(MACD, signal)
			strategy.close_all('매도')
	
bgcolor(strategy.position_size > 0 ? color.new(color.yellow,90) : na)

 

 

  • MACD(Moving Average Convergence Divergence) pandas-ta 소스
import pandas as pd
import pandas_ta as ta
import FinanceDataReader as fdr

data = fdr.DataReader('005930')
macd = ta.macd(close=data['Close'], fast=12, slow=26, signal=9)
data = pd.concat([data, macd], axis=1)
data.dropna(inplace=True)
반응형