기본 콘텐츠로 건너뛰기

[matplotlib]quiver()함수

[Stock] MACD(이동평균 컨버전스 다이버전스)와 APO(Absolute Price Oscillator)

MACD(이동평균 컨버전스 다이버전스)와 APO(Absolute Price Oscillator)

MACD

Macd(Moving Average Convergence/Divergence)는 시장의 잠재적 진입 및 청산 지점을 파악하기 위한 기술적 분석도구 입니다. MACD 는 가격의 두 이동평균 간의 관계를 측정하는 모멘텀 오실레이터입니다. MACD 라인과 신호 라인이라는 두 가지 주요 구성 요소로 구성됩니다. MACD 라인은 단기 지수 이동평균(EMA)과 장기 EMA의 차이이며, 신호 라인은 MACD 라인의 EMA입니다. 히스토그램은 MACD 라인과 신호 라인 사이의 차이를 나타내어 수렴인 컨버전스와 발산인 다이버전스를 시각적으로 표현합니다.

이동평균선 대순환 분석은 매매 타이밍을 명확히 나타내지만 신호가 늦게 나타납니다. 이러한 단점에 대응하기 위해 MACD 지표를 추가 합니다.

MACD는 이동평균 수렴/확산으로 번역되는 것으로 부터 알 수 있듯히 이평선의 일종이며 이들이 서로 붙거나 떨어짐을 의미한다. 즉, 두개의 이평선을 적용하는 것으로 다음과 같이 나타낼 수 있다.

MACD = 단기이평 - 장기이평 (식 1)

그러므로 기간이 다른 이평선의 차이를 의미한다. 이 지수의 고안자인 제럴드 아펠은 단기 이평선으로 일반적으로 12일 EMA(Exponential Moving Average), 장기 이평선으로 일반적으로 26일 EMA를 사용헸다.

  1. 12EMA > 26EMA → MACD는 양수이며 그 값은 커짐, 상승추세
  2. 위 양수 MACD의 최대점 즉, 정점 후 감소 (peak out): 12EMA 감소, 26EMA 증가
  3. 12EMA = 26EMA → MACD=0, 12EMA와 26EMA의 데드크로스 발생
  4. 12EMA < 26EMA → MACD는 음수이며 그 값의 절대치는 커짐, 하락추세
  5. 위 음수 MACD 절대값의 최대점 후 증가: 12EMA 증가, 26EMA 감소
  6. 12EMA = 26EMA → MACD=0, 12EMA와 26EMA의 골든크로스 발생

위 순서는 이평선 대순환 분석에서 이평선의 위치관계 추세와 같은 형태를 나타내며 MACD에 의한 신호가 앞서서 표시됩니다.

MACD는 식 1에서 나타낸 것과 같이 단기이평과 장기이평의 차이로 구성된다. 일반적으로 EMA12와 EMA26을 사용하는 것으로 이 차이에 대한 선의 위치를 명확하게 나타내기 위해 시그널(signal) 선을 추가 합니다. 일반적으로 EMA9를 적용합니다.

다음은 특정한 기간의 주가에 대해 MACD를 계산하기 위해 UDF calculate_macd()를 작성할 수 있습니다. 또는 pandas_ta.macd(close, fast=None, slow=None, signal=None, talib=None, offset=None, **kwargs) 함수를 적용할 수 있습니다. 함수 fast, slow, signal의 기본값은 각각 12, 26 그리고 9입니다. MACD, Hist(MACD-Signal), Signal(MACD의 지수이동평균)을 반환합니다.

#MACD  계산
def calculate_macd(data, type="Close", short=12, long=26, signal_window=9):
    da = data[type]
    df=pd.DataFrame()
    short_ema=da.ewm(span=short, adjust=False).mean()
    long_ema =da.ewm(span=long, adjust=False).mean()
    macd = short_ema - long_ema
    signal = macd.ewm(span = signal_window, adjust=False).mean()
    histogram = macd - signal
    df = pd.DataFrame({"MACD":macd, "Signal":signal, "Histogram":histogram})
    return df   

pandas_ta 함수 macd(data, fast=None, slow=None, signal=None, talib=None, offset=None, **kwargs)로 계산할 수 있습니다. 이 함수의 인수들은 help(ta.macd)로 확인할 수 있습니다.

import numpy as np
import pandas as pd
import yfinance as yf
import FinanceDataReader as fdr
import pandas_ta as ta
import matplotlib.pyplot as plt
import mplfinance as mpf

st=pd.Timestamp(2024,9, 1)
et=pd.Timestamp(2025, 5,2)
trgnme="000660.KS"
trg=yf.download(trgnme,  st, et)
trg.columns=[i[0] for i in trg.columns]

macd=calculate_macd(trg.Close)
macd.tail(3)
MACD_12_26_9 MACDh_12_26_9 MACDs_12_26_9
Date
2025-04-29 -3733.413104 1343.347202 -5076.760306
2025-04-30 -3668.584461 1126.540676 -4795.125137
2025-05-02 -2897.922881 1517.761805 -4415.684686
col=['r' if i > 0 else 'b' for i in macd.iloc[:, 1]]
adf=[mpf.make_addplot(ta.ema(trg.Close, 5), panel=0, color="brown", label="ema5"),
     mpf.make_addplot(ta.ema(trg.Close, 20), panel=0, color="navy", label="ema20"),
     mpf.make_addplot(macd.iloc[:,0], panel=1, color="brown", label="macd", title=""),
     mpf.make_addplot(macd.iloc[:,2], panel=1, color="navy", label="signal"), 
     mpf.make_addplot(macd.iloc[:, 1], type="bar", panel=1, color=col, alpha=0.6 )]
f, axs=mpf.plot(trg, type="candle", style="yahoo",volume=False, addplot=adf, returnfig=True, figsize=(12,8))
axs[0].legend(loc="upper left")
axs[3].legend(loc="upper left")
plt.show()

signal은 macd를 평활화한 것으로 기본적으로

  • macd > signal: 상승
  • macd < signal: 하락
  • macd의 기울기가 급할수록 추세의 강도가 강함
  • macd가 signal을 상향돌파는 상승 추세의 전환, 반대는 하락추세로의 전환을 암시

해석

  • MACD가 signal를 상향돌파: 골든크로스로 상승추세의 시작을 알리는 신호로 해석할 수 있음
  • MACD가 signal를 하향돌파: 데드크로스로 하향추세의 시작을 알리는 신호로 해석할 수 있음
  • 0선
    • 0선 위로 돌파: 단기이평 > 장기이평, 상승모멘텀 강화로 해석될 수 있음
    • 0선 아래로 돌파: 단기이평 < 장기이평, 하락모멘텀 강화로 해석될 수 있음
    • 오실레이터 막대길이가 짧아지는 것은 모멘텀 둔화를 의미
  • 다이버전스: 주가와 MACD의 움직임이 반대인 경우로 추세전환의 강력한 신호로 간주 할 수 있음
    • 주가는 저점을 낮추는데 MACD는 저점을 높이는 경우, 하락추세가 끝나고 상승추세로 전환될 가능성 시사
    • 주가는 고점을 높이는데 MACD는 고점을 낮추는 경우, 상승추세가 끝나고 하락추세로 전환될 가능성 시사

APO(Absolute Price Oscillator)

APO는 macd와 유사한 방식으로 단기이동평균과 장기이동평균의 차를 계산한 것입니다. 일반적으로 단기(fast)와 장기(slow)의 기간을 각각 12, 26을 사용합니다. 두 이동평균선의 차 또는 백분율로 나타낸 기술적 분석 지표입니다.

$$\begin{align}\text{APO} &= \text{단기이동평균} - \text{장기이동평균} \\ APO &= \frac{\text{단기이동평균} - \text{장기이동평균} }{\text{장기이동평균}}\cdot 100 \end{align}$$

pandas_ta.apo(close, fast=None, slow=None, mamode=None, talib=None, offset=None, **kwargs) 함수를 사용하여 계산할 수 있으며 mamode로 적용되는 이동평균의 계산방식을 지정할 수 있으며 기본값은 단순이동평균('sma')입니다. 결과는 단기와 장기 이평 차를 반환합니다. 위 macd에 사용된 데이터에 apo를 계산하여 그래프를 첨가합니다.

apo=ta.apo(trg.Close)
apo.tail(3)
Date
2025-04-29   -5975.000000
2025-04-30   -5026.923077
2025-05-02   -3500.000000
Name: APO_12_26, dtype: float64
macd=ta.macd(trg.Close)
col=['r' if i > 0 else 'b' for i in macd.iloc[:, 1]]
adf=[mpf.make_addplot(ta.ema(trg.Close, 5), panel=0, color="brown", label="ema5"),
     mpf.make_addplot(ta.ema(trg.Close, 20), panel=0, color="navy", label="ema20"),
     mpf.make_addplot(macd.iloc[:,0], panel=1, color="brown", label="macd", title=""),
     mpf.make_addplot(macd.iloc[:,2], panel=1, color="navy", label="signal"), 
     mpf.make_addplot(macd.iloc[:, 1], type="bar", panel=1, color=col, alpha=0.6 ),
     mpf.make_addplot(apo, panel=2, color="navy", label="apo")]
f, axs=mpf.plot(trg, type="candle", style="yahoo",volume=False, addplot=adf, returnfig=True, figsize=(12,8))
axs[0].legend(loc="upper left")
axs[2].legend(loc="upper left")
axs[4].legend(loc="upper left")
axs[4].axhline(0, color='skyblue', ls="dashed" )
plt.show()

sma를 적용한 APO는 macd 선과 거의 같습니다. 이 선은 0선을 기준으로 해석합니다.

  • APO > 0선: 단기추세가 장기 추세보다 강함을 의미
  • APO < 0선: 단기추세가 장기 추세보다 약함을 의미
  • APO가 상승 → 상승추세의 강화
  • APO가 하락 → 하락추세의 강화
  • APO가 0선을 상향돌파: 매수신호
  • APO가 0선을 하향돌파: 매도신호
  • 가격과 APO간에 다이버전스: 추세 전환 신호일 수 있음
    • 가격상승, APO 하락: 상승추세의 약화
    • 가격하락, APO 상승: 하락 추세의 약화

단기와 장기의 차로 계산하는 경우 APO는 MACD와 같습니다. 단지 MACD는 지수이동평균을 사용하는데 반해 APO는 단순이동평균을 사용합니다. EMA는 최근 가격에 더 큰 가중치를 부여하므로 MACD가 APO보다 가격변화에 더 민감하게 반응하는 경향이 있으므로 단기 추세변화를 더 잘 포착할 수 있지만 때로는 더 많은 가짜 신호를 발생시킬 수도 있습니다.

APO는 다양한 시간 프레임에 적용할 수 있으므로 단기, 장기 투자 스타일에 따라 이평선의 기간을 조정하여 사용할 수 있습니다. 일반적으로 단기는 12일, 장기는 26일 많이 사용합니다.

댓글

이 블로그의 인기 게시물

[Linear Algebra] 유사변환(Similarity transformation)

유사변환(Similarity transformation) n×n 차원의 정방 행렬 A, B 그리고 가역 행렬 P 사이에 식 1의 관계가 성립하면 행렬 A와 B는 유사행렬(similarity matrix)이 되며 행렬 A를 가역행렬 P와 B로 분해하는 것을 유사 변환(similarity transformation) 이라고 합니다. $$\tag{1} A = PBP^{-1} \Leftrightarrow P^{-1}AP = B $$ 식 2는 식 1의 양변에 B의 고유값을 고려한 것입니다. \begin{align}\tag{식 2} B - \lambda I &= P^{-1}AP – \lambda P^{-1}P\\ &= P^{-1}(AP – \lambda P)\\ &= P^{-1}(A - \lambda I)P \end{align} 식 2의 행렬식은 식 3과 같이 정리됩니다. \begin{align} &\begin{aligned}\textsf{det}(B - \lambda I ) & = \textsf{det}(P^{-1}(AP – \lambda P))\\ &= \textsf{det}(P^{-1}) \textsf{det}((A – \lambda I)) \textsf{det}(P)\\ &= \textsf{det}(P^{-1}) \textsf{det}(P) \textsf{det}((A – \lambda I))\\ &= \textsf{det}(A – \lambda I)\end{aligned}\\ &\begin{aligned}\because \; \textsf{det}(P^{-1}) \textsf{det}(P) &= \textsf{det}(P^{-1}P)\\ &= \textsf{det}(I)\end{aligned}\end{align} 유사행렬의 특성 유사행렬인 두 정방행렬 A와 B는 'A ~ B' 와 같...

[sympy] Sympy객체의 표현을 위한 함수들

Sympy객체의 표현을 위한 함수들 General simplify(x): 식 x(sympy 객체)를 간단히 정리 합니다. import numpy as np from sympy import * x=symbols("x") a=sin(x)**2+cos(x)**2 a $\sin^{2}{\left(x \right)} + \cos^{2}{\left(x \right)}$ simplify(a) 1 simplify(b) $\frac{x^{3} + x^{2} - x - 1}{x^{2} + 2 x + 1}$ simplify(b) x - 1 c=gamma(x)/gamma(x-2) c $\frac{\Gamma\left(x\right)}{\Gamma\left(x - 2\right)}$ simplify(c) $\displaystyle \left(x - 2\right) \left(x - 1\right)$ 위의 예들 중 객체 c의 감마함수(gamma(x))는 확률분포 등 여러 부분에서 사용되는 표현식으로 다음과 같이 정의 됩니다. 감마함수는 음이 아닌 정수를 제외한 모든 수에서 정의됩니다. 식 1과 같이 자연수에서 감마함수는 factorial(!), 부동소수(양의 실수)인 경우 적분을 적용하여 계산합니다. $$\tag{식 1}\Gamma(n) =\begin{cases}(n-1)!& n:\text{자연수}\\\int^\infty_0x^{n-1}e^{-x}\,dx& n:\text{부동소수}\end{cases}$$ x=symbols('x') gamma(x).subs(x,4) $\displaystyle 6$ factorial 계산은 math.factorial() 함수를 사용할 수 있습니다. import math math.factorial(3) 6 a=gamma(x).subs(x,4.5) a.evalf(3) 11.6 simpilfy() 함수의 알고리즘은 식에서 공통사항을 찾아 정리하...

sympy.solvers로 방정식해 구하기

sympy.solvers로 방정식해 구하기 대수 방정식을 해를 계산하기 위해 다음 함수를 사용합니다. sympy.solvers.solve(f, *symbols, **flags) f=0, 즉 동차방정식에 대해 지정한 변수의 해를 계산 f : 식 또는 함수 symbols: 식의 해를 계산하기 위한 변수, 변수가 하나인 경우는 생략가능(자동으로 인식) flags: 계산 또는 결과의 방식을 지정하기 위한 인수들 dict=True: {x:3, y:1}같이 사전형식, 기본값 = False set=True :{(x,3),(y,1)}같이 집합형식, 기본값 = False ratioal=True : 실수를 유리수로 반환, 기본값 = False positive=True: 해들 중에 양수만을 반환, 기본값 = False 예 $x^2=1$의 해를 결정합니다. solve() 함수에 적용하기 위해서는 다음과 같이 식의 한쪽이 0이 되는 형태인 동차식으로 구성되어야 합니다. $$x^2-1=0$$ import numpy as np from sympy import * x = symbols('x') solve(x**2-1, x) [-1, 1] 위 식은 계산 과정은 다음과 같습니다. $$\begin{aligned}x^2-1=0 \rightarrow (x+1)(x-1)=0 \\ x=1 \; \text{or}\; -1\end{aligned}$$ 예 $x^4=1$의 해를 결정합니다. solve() 함수의 인수 set=True를 지정하였으므로 결과는 집합(set)형으로 반환됩니다. eq=x**4-1 solve(eq, set=True) ([x], {(-1,), (-I,), (1,), (I,)}) 위의 경우 I는 복소수입니다.즉 위 결과의 과정은 다음과 같습니다. $$x^4-1=(x^2+1)(x+1)(x-1)=0 \rightarrow x=\pm \sqrt{-1}, \; \pm 1=\pm i,\; \pm1$$ 실수...