Alpha Factor 탐색 > Momentum

2023. 7. 3. 20:18금융 데이터 분석

반응형

주가의 방향을 예측하는데 있어 Momentum을 나타내는 Factor들은 항상 많이 활용되어지고 있는 요인들중에 하나입니다.  이러한 Momentum이 어떻게 보면 군중들이 어디에 집중하고 있고 어디에 쏠리고 있는지를 판단할 수 있는 요소이기 때문입니다. 그리고 결국 주가는 군중들이 결정한다고 본다면 Momentum은 꼭 고려가 되어야할 지표임에는 틀림없습니다.

Momentum을 나타내는 지표가 많이 있게지만, 대표적인 지표를 몇개 선정하여 이를 활용해보도록 하겠습니다.

1. RSI(Relative strength index(RSI))

RSI는 0부터 100까지의 숫자를 가지며, 100에 가까울 수록 초과매수가 일어난 것으로 보고있습니다. 따라서 이를 활용하여 단순한 규칙을 만든다면 70이상일 때는 판매하고 30이하일때는 매수하라는 규칙을 만들어볼 수 있을 것입니다. 70이 넘었을 때 판매하라는 규칙은 상승폭이 너무 크고 이에 따라 차익실현 매물이 나올 것와 하락전환할 것이라는 예상으로 70이상에서 매도를 하라고 하는 것일 텐데, 정말 호재가 있거나 끝 없이 성장하는 주식이라면 이 규칙은 소용없어질 것입니다. 따라서 하나의 지표만 보지 않고 여러지표를 고려하는 것이 중요하고 그렇기 때문에 ML/DL 등 통계적 방법론을 활용하는 것도 하나의 주요 전략이 될 수 있을 것으로 생각됩니다.

다시 RSI로 돌아와 RSI 수식을 정리하면 다음과 같습니다.

 

$Avg_{gain}$은 n일 동안 전일대비 종가가 상승한날의 상승분 평균이고 $Avg_{loss}$는 n일 동안 전일대바 종가가 하락한 날의 하락분 평균입니다. 평균은 Exponential Moving Average을 활용해서 구하도록 하겠습니다. 지수가중평균은 최근 데이터에 좀 더 가중치를 줘서 구할 수 있기 때문에 최신성을 더 반영할 수 있습니다.

2022년 1월 1일부터 2023년 7월 3일까지의 카카오 주가 정보를 활용해서 RSI를 구해보도록 하겠습니다.

import FinanceDataReader as fdr
import pandas as pd
import numpy as np


## 주가 데이터
df = fdr.DataReader('035720','2022-01-01', '2023-07-03')

period = 14 ##RSI를 구하려는 기간(14거래일)
diff_close = df["Close"].diff() ## 종가의 가격차이
up, down = diff_close.copy(), diff_close.copy()

##상승한날의 상승분 저장
up[up < 0] = 0 ## 하락했을 때는 0으로 입력

##하락한날의 하락분 저장
down[down >=0] = 0 ## 상승했을 때는 0으로 입력

## 지수가중평균
avg_gain = up.ewm(com=(period-1), min_periods = period).mean()
avg_loss = down.abs().ewm(com=(period-1), min_periods = period).mean()

RS = avg_gain/avg_loss
RSI = 100-(100/(1+RS))

여기서 ewm은 pandas에서 제공하는 지수가중함수이고 이를 활용하여 지수가중평균을 구할 수 있습니다. com을 13(period가 14이기 때문에 period -1은 13)으로 입력하게 되면 지수가중평균에서 평활계수 $\alpha$는 1/(1+13)이 됩니다.

2. Price Momentum

RSI가 최근 14일, 30일 등 비교적 짧은기간의 모멘텀을 보는 지표라면 PRice momentum은 6개월, 12개월(해당월 제외)의 수익률을 Momentum을 판단하는데 활용합니다. 즉, 6개월/12개월 수익 규모가 높은 기업이 가격 동력성으로 인해 향후에도 오를 확률이 높다고 보는 관점입니다. 

수익규모로도 Momentum을 측정할 수 있지만, 수익률로도 Momentum을 표현할 수 있고 수익규모 및 수익률 모두 여기서도 Moving average 관점을 도입할 수 있습니다. Moving average를 활용하면 outlier에 대해서 좀 더 안정적인 결과를 줄 수 있을 것입니다. 여기서는 수익규모는 어떤 가격을 가친 기업을 선택했냐에 따라서 크게 변동할 수 있으므로 수익률를 활용해서 Momentum을 측정하도록 하겠습니다.

마찬가지로 22년 1월부터 23년 7월 3일까지의 카카오 주가정보를 바탕으로 수익률을 구한후, 제가 설정한 period(14거래일)로 지수가중평균을 이용해서 최종 수익률을 구하겠습니다.

### Price Momentum

price = df["Close"].reset_index()
price["initial_close"] = df["Close"].shift(180).values ##180일 거래일 전 기준으로 수익률 측정
price["diff"] = price["Close"] - price["initial_close"]
price["return"] = price["diff"]/price["initial_close"]

price["return_avg"] = price["return"].ewm(com=(period-1), min_periods = period).mean()

### final
price["RSI"] = RSI.values

마지막에 RSI까지 넣은 후 price 데이터를 봐보겠습니다. 

만약 Price momentum이 0이하이고 RSI가 70이상일 때 매도한다거나, Price momentum이 0이상이고 RSI가 30이하일 때 매도한다는 기준을 세웠다고 하면.. 데이터를 보니  23년 1월 16일과 23년  2월 9일에 매도하라는 신호를 받아볼 수 있었습니다.(매수하라는 신호는 없었습니다.) 

23년 1월 16일에 종가가 64,500원이고 2월 9일에 종가가 70,900원이고 현재 종가가 51,000원이니 저때 팔았으면 현재 기준으로는 손해를 안볼 수 있었을 것 같습니다. 다만 같은 신호더라도 언제 파냐에 따라서 수익률이 달라지기 때문에, 좀 더 최적의 타이밍을 잡기 위해서는 당연히 다른 지표들, 정보들도 활용해야 할 것 같습니다. (그리고 틀린 신호를 주는 경우도 분명히 많을 것입니다.)  다만 이런 것들도 하나의 기준으로 활용할 수 있다는 정도만 인지하는 정도만 해도 충분할 것 같습니다.

참고:

https://medium.com/codex/algorithmic-trading-with-relative-strength-index-in-python-d969cf22dd85 

https://hotorch.tistory.com/366

https://blog.naver.com/ben_rye/223028167000

https://moneyzine.com/investments/understanding-price-momentum/

반응형