drkdev

몇가지 기술적 지표에 대한 수학적 직관

Aug 8, 2025  │  #ta-lib  

why detail matters?

ta_lib 를 살펴보면서 구체적인 지표의 구현을 확인해보려는 이유는 다음과 같다.

  1. 같은 raw data를 가공한 것임에도 불구하고 지표를 단순히 stacking하는 것의 회피
  2. 최대한 적은 숫자의 지표로 원하는 효과를 얻기 위해서
  3. 지표의 구체적 구현을 모른 채로 임의의 파라미터를 조정하는 문제1 에 대해서도 좀 더 숫자 감각을 기반으로 개인적인 확신을 가지기 위해서
  4. 내 트레이딩 시스템의 구현 중 특히 매매 트리거 부분을 외부 라이브러리에 의존성을 덜고 직접 구현하기 위해

구체적으로 함수의 convention 은 공식 문서 내 3.1 Direct call to a TA Function 를 먼저 참고하도록 한다. 내 매매 시스템에서도 동일한 시그니처로 사용할 듯?

개인적인 이야기

  1. 지표 = source data + 수학적 가공

  2. 시장이란 공간은 (가격 x 시간 x 거래량) 으로 구성됨. 해당 공간에서 ‘source data’가 파생됨.

    • 이 중 시간은 프랙탈을 형성하고 거래량은 (매도|매수) 방향성이 존재함
  3. 수학적인 직관으로 보자면 수학적 가공은

    • 빼는 건 거리, 곱하는 건 가중치, 나누는 건 정규화나 분배
    • 미분은 변화량(속도), 2차 미분은 변화량의 속도(가속도)
  4. 지표는 어떠한 ‘변곡점의 낌새’를 알려주는 것이고 베팅 하라고 알려주지는 않는다.

  5. 같은 데이터를 가지고 가공한 지표하면 너무 중첩하지 않는 것이 좋다. 손매매 하는 사람들이 인지적으로 처리 가능한 지표의 수량은 대략적으로 5개 안팍임. 주로 RSI, MA 계열, volume profile임.

    RSI = f(Price)
    MACD = f(Price) 
    Bollinger Bands = f(Price)
    Stochastic = f(Price, Volume)
    

tips

Microstructure에서 추출할 수 있는 내용들은 대개 알려진 지표에 없는 듯.
이건 시스템에 녹여내서 처리해야 하거나, 다른 지표를 통해 머리 속으로 굴려가며 매매해야 함

이동 평균 계열

SMA (Simple Moving Average)

SMA = (P1 + P2 + P3 + ... + Pn) / n

일단 SMA 계산의 대상이 무슨 가격인지에 따라 굉장히 의미가 달라진다 종가/시가/고가/저가/특정한 가격(vwap? twap? 니가 만든 가격?)
-> 그러니까 트뷰건 뭐건 켜자마자 SMA 눌렀다고 끝난게 아니라

  1. 무슨 값으로 계산할지
  2. 실제로 맞게 나오는지 손계산과 차트 간 크로스 체크 (생각보다 많은 곳들이 제대로 계산을 해서 보여주지 않는다)

단순 평균인데, 내 입장에선 이 지표가 제일 중요함

왜?
SMA가 계산한 가격이 평균에 닿았을 때가 베팅 지점이 되곤하기 때문임.

어떤 틱이나 캔들이 이동 평균을 건드렸다면 ‘갈림길’에서는 위 혹은 아래만 가능한 이중 선택 상황이기 때문이다.

하락 -> 상승에서는 반드시 평균을 건드릴 수밖에 없고
상승 -> 하락에서도 반드시 평균을 건드릴 수밖에 없다.

그리고 베팅을 결정했다면 눈 -> 손의 휴먼 latency인 600ms 보다 빨리 처리하는 것을 목표로 해야 한다

EMA (Exponential Moving Average)

5단위 EMA를 계산한다고 가정. 처음 첫 EMA는 SMA로 계산하고 그 이후부터 새 값이 들어오면 가중치 기반으로 업데이트한다.
가중치 α 는 hyper param이다. (보통 α = 2 / (period + 1) 인데 마음대로 조정할 수 있다)

그냥 SMA와 같이 1/n 기간 만큼 동일한 가중치가 아니라 좀 더 많은 가중치를 준 것에 불과함.

EMA_new = α × P_new + (1-α) × EMA_old

α = 0.1 → 새 데이터 10% 반영 (느린 반응)
α = 0.5 → 새 데이터 50% 반영 (빠른 반응)
α = 0.9 → 새 데이터 90% 반영 (극도로 민감)

MACD (Moving Average Convergence Divergence)

지표 이름 자체에서 이동평균이 ‘수렴’(Convergence)이냐, ‘발산’(Divergence)이냐를 판단하겠다는 의도가 보임
MACD의 극값을 찾아서 그곳에서 롱/숏을 하겠다는 의도가 있는 지표임
극값을 찾기 위해서 ‘차이의 평균’을 통해 미분(변화량) 개념을 근사적으로 활용한다.

1. EMA12 = 12일 EMA
2. EMA26 = 26일 EMA  
3. MACD Line = EMA12 - EMA26
4. Signal Line = MACD Line(EMA12 - EMA26)의 9일 EMA = 평활화
5. Histogram = MACD Line - Signal Line

종가를 source data로 놓고, 12, 26 EMA 기반으로 MACD 그리고, 시그널은 MACD의 9 EMA로 지표 조회하면 이렇게 나온다
주황이 시그널, 파랑이 MACD Line.
시그널이 MACD를 상향 돌파(signal > MACD), 하향 돌파(signal < MACD) 할 때를 추세 전환이라 보는 편이라
이를 좀 쉽게 보려면 histogram > 0 으로 전환 될 때 롱 치고, < 0 으로 전환될 때 숏치자는 것임

macd

왜 MACD의 극값을 찾으려고 하는가?

naive approach를 먼저 생각해보자
단기 EMA가 장기 EMA를 뚫으면 추세가 바뀌었으니까 롱을 치자()라는 전략이 너무 느리니까 MACD > 0 순간에 롱치면 이미 늦었다는 말

그러면 우리 단-장기 EMA의 차이가 극대화 되는 지점에서 조금 일찍 들어가서 좀 버티자 라는 의도를 가지고 지표를 만들기 시작함

차이가 극대화 되는 지점은 MACD’(t) = 0인 순간 (변화율이 0) 이고 이를 MACD-Signal 교차 ≈ MACD’(t) = 0로 근사한 것임

MACD > Signal: MACD'(t) > 0 (증가 중)
MACD = Signal: MACD'(t) ≈ 0 (변화 멈춤, 극값)
MACD < Signal: MACD'(t) < 0 (감소 중)

일반화

여기서 일반화하여 x의 평균이 x에 닿았다 (혹은 x가 x의 평균에 닿았다)는 것의 의미가 중요하다

x(t) = 어떤 시계열 함수
MA[x(t)] = x의 이동평균
라 한다면,

x = MA[x] ⟹ x’(t) ≈ 0 = 변화가 멈추는 순간 = 방향 전환 가능성이 높은 순간

volume

A/D Line

AD Line = Chaikin A/D Line = Accumulation/Distribution Line
방향성이 있는 거래량의 누적 합계

CLV (Close Location Value) = ((종가 - 저가) - (고가 - 종가)) / (고가 - 저가)  
                           = (2 × 종가 - 고가 - 저가) / (고가 - 저가)

AD Line = 이전 A/D Line + (CLV × 거래량)  
         = Σ(CLV × Volume)
         = Σ((-1 ~ +1) × 거래량)

결론적으로 CLV는
CLV = +1: 종가 = 고가 (완전한 강세 캔들)
CLV = 0: 종가가 캔들의 정중앙
CLV = -1: 종가 = 저가 (완전한 약세 캔들)

최종적으로 AD Line을 그리기 위해서는 CLV에 거래량을 곱해 거래량의 영향을 반영한다.

결국 AD line은 거래량 기반으로 +- 1 * 거래량을 꾸준히 누적한 값에 불과함

기계적으로 정리하자면 이렇게 해석할 수 있겠죠

거래량 많음 + 상승 → AD Line 크게 증가 (강한 매수)
거래량 적음 + 상승 → AD Line 조금 증가 (힘없는 상승)
거래량 많음 + 하락 → AD Line 크게 감소 (강한 매도)
거래량 적음 + 하락 → AD Line 조금 감소 (힘없는 하락)

그런데 AD Line은 이전 값에 근거하여 누적되는 지표이므로 타임 프레임이 짧은 환경에서는 오히려 노이즈라는 생각이 듦

volatility

BB(Bollinger Band)

타임프레임 n단위(기본 20)의 SMA 가 위치할 95% 신뢰 구간 내 표현.
당연히 타임프레임 내 가격의 움직임이 정규분포 움직인다는 가정 하에 짠 지표임.
그러나 가격은 일반적으로 fat tails, skewness, non-stationary 하다고 알려져 있다.

1. 상단 밴드 UB(t) = SMA20(t) + 2 × STD20(t) = 이동평균 + 2σ
2. 중간 밴드 MB(t) = SMA20(t)
3. 하단 밴드 LB(t) = SMA20(t) - 2 × STD20(t) = 이동평균 - 2σ

bb

ATR(Average True Range)

trend

momentum

RSI(Relative strength index)

그냥 최근 가격 변동의 방향성을 0-100으로 정규화한 것임. 매도/매수의 시그널로써 사용하면 안됨.

1. 상승폭(U) = 이번 종가 > 지난 종가 ? (이번 종가 - 저번 종가) : 0
2. 하락폭(D) = 이번 종가 < 지난 종가 ? (저번 종가 - 이번 종가) : 0
3. AU = U의 n개 평균 (보통 14)
4. AD = D의 n개 평균 (보통 14)
5. RS = AU / AD
6. RSI = 100 - (100 / (1 + RS)) -> 0 ~ 100 사이의 값으로 정규화 됨

50 기준선: 50 위/아래로 상승/하락 추세 판단

RSI > 70: 과매수 구간 (naive approach: 회귀에 베팅해서 매도 하라는 조언)
높은 RSI: 매수 주문량이 매도 주문량을 지속적으로 압도

RSI < 30: 과매도 구간 (naive approach: 회귀에 베팅해서 매수 하라는 조언)
낮은 RSI: 매도 주문량이 매수 주문량을 지속적으로 압도

다이버전스: 가격과 RSI가 반대 방향으로 움직일 때 추세 전환 신호

그러면 많이 상승했으면 당연히 RS가 클테고, RSI가 많이 나오겠네
RSI 70/30 단일 지표의 기계적 매매는 일종의 착시다

RSI가 말해주는 건 내가 계산하는 평균 기간내 가격이 많이 올랐다 혹은 내렸다 정도임

따라서 단순히 가격의 상대적인 움직임만으로 ‘과매도’, ‘과매수’란 표현을 쓰는 것 자체가 이상하다.

others


  1. 그 예로, 7일 이평을 6일 이평으로 보면 더 진입타점이 좋다는 등의 맥락이 없는 매매 방법론들 ↩︎