주식이나 코인 가격의 시계열 데이터로부터 과매수 상태인지, 과매도 상태인지, 강세인지, 약세인지를 알아낼 수 있는 지표 4개를 정리한 적이 있습니다. 각각 스토캐스틱 오실레이터, RSI, 현금흐름지수, 일중강도지수였는데요. 이번 포스팅에서는 여기에 스토캐스틱 RSI를 하나 더 추가해보겠습니다.
글의 순서
스토캐스틱 RSI
스토캐스틱 RSI 계산 방법
스토캐스틱 RSI로 과매수, 과매도 상태를 확인하는 법
스토캐스틱 RSI 장점
파이썬 코드 : 스토캐스틱 RSI
스토캐스틱 RSI
스토캐스틱 RSI (Stochastic RSI)는 주식이나 코인 등, 금융 자산의 기술적 분석에 사용되는 지표로, 상대강도지수(RSI)의 값을 스토캐스틱 오실레이터로 변환한 것입니다. RSI와 스토캐스틱 오실레이터의 특성을 결합한 만큼 보다 시장에 보다 민감하게 반응합니다.
스토캐스틱 RSI는 스토캐스틱 오실레이터나 RSI처럼 특정 기간 동안 자산의 과매수(overbought) 또는 과매도(oversold) 상태를 보여줍니다. 각각의 지표를 복습해보겠습니다.
(1) 스토캐스틱 오실레이터(Stochastic Oscillator)
스토캐스틱 오실레이터는 주어진 기간 동안의 최고가와 최저가 대비 현재 가격의 위치를 나타내는 지표입니다. %K와 %D 두 가지 선으로 구성되며, %K는 현재 가격의 상대적 위치를, %D는 %K의 이동평균을 나타냅니다.
(2) 상대강도지수 (RSI, Relative Strength Index)
RSI는 특정 기간 동안 주가가 전일 가격에 비해 상승했는지, 하락했는지의 추세를 0 ~ 100의 퍼센트 수치로 나타낸 지표입니다. RSI는 현재가 과매수 상태인지, 과매도 상태인지를 알려줍니다. 보통 RSI 퍼센트 수치로는 30이하면 과매도, 70 이상이면 과매수로 해석합니다.
스토캐스틱 RSI 계산 방법
스토캐스틱 RSI는 상대강도지수(RSI)의 값을 스토캐스틱 오실레이터를 이용하여 변환한 것입니다. 그러니까 스토캐스틱 오실레이터 공식에 현재가 대신 RSI를 대입하여 구합니다. 지금부터는 기간을 14일 동안으로 정하고 RSI를 구한다고 가정해보겠습니다.
RSI 값을 스토캐스틱 오실레이터에 적용합니다.
stochastic RSI = (RSI – RSI_min) / (RSI_max – RSI_min)
여기서, RSI_min은 14일이라는 기간 동안의 RSI 최소값이고 RSI_max는 14일이라는 기간 동안의 RSI 최대값입니다.
▶%K
m일 동안 stochastic RSI(%)의 평균
▶%D
t일 동안 %K의 평균
스토캐스틱 RSI로 과매수, 과매도 상태를 확인하는 법
▶과매수(overbought) 상태 : 스토캐스틱 RSI가 0.8 이상이면 자산이 과매수 상태에 있을 수 있음을 나타냅니다. 과매수로 자산이 과도하게 상승한 상태를 의미하며, 매도 신호로 해석될 수 있습니다.
▶과매도(oversold) 상태 : 스토캐스틱 RSI가 0.2 이하이면 자산이 과매도 상태에 있을 수 있음을 나타냅니다. 과매도로 자산이 과도하게 하락한 상태를 의미하며, 매수 신호로 해석될 수 있습니다.
▶중립 상태 : 스토캐스틱 RSI가 0.5 근처에 있으면 자산의 가격이 안정된 상태에 있음을 의미합니다. 중립 상태라고 표현할 수도 있습니다.
스토캐스틱 RSI 장점
스토캐스틱 RSI는 RSI보다 더 민감하게 반응하여 단기적인 저점과 고점을 판단할 때 유용합니다. 결과적으로 빠르게 매수 및 매도 신호를 포착할 수 있기 때문에 트레이더들도 많이 사용하고 있습니다.
파이썬 코드 : 스토캐스틱 RSI
스토캐스틱 RSI를 구하는 방법을 아래 코드의 calculate_stochastic_RSI 함수에 구현하였습니다. 스토캐스틱 RSI는 스토캐스틱 오실레이터에서 현재가 대신 RSI를 대입하여 구합니다. 그래서 가장 먼저 해야할 일이 RSI를 구하는 일입니다. calculate_stochastic_RSI 함수의 첫 번째 줄인 df[‘RSI’] = calculate_rsi(df, period)가 바로 RSI 계산 함수로부터 RSI를 구하는 루틴입니다.
판다스의 rolling 함수와 min, max 함수로 스토캐스틱 RSI를 간단하게 구할 수 있습니다. rolling 함수를 쓸 때, min_periods=1 이라고 지정하면, 1이라는 개수만 만족해도 연산을 수행합니다. 데이터 개수가 윈도우 크기보다 적더라도 연산을 수행하라는 의미입니다.
print(df.tail(5)) 부분을 유심히 봐주시기 바랍니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
import os import time import pandas as pd import numpy as np from binance.client import Client import datetime from datetime import datetime, timezone, timedelta import matplotlib.pyplot as plt import mplfinance as mpf #01) 바이낸스 계정 접속 api_key = os.getenv('Binan_API_KEY') api_secret = os.getenv('Binan_SECRET_KEY') client = Client(api_key, api_secret) print('\n','[ BINANCE ACCOUNT ACCESSED ]') #02) 입력 : 시계열 데이터 수집 구간(tstt~tend), 시간 간격(t_interval) tstt_utc = '2024-04-01 00:00:00' tend_utc = '2024-05-19 23:59:59' t_interval = '1d' #03) 파이썬 바이낸스 API로 비트코인 가격 데이터 가져오기 bars = client.get_historical_klines('BTCUSDT', t_interval, tstt_utc, tend_utc, limit=1000) #03-1) ohlcv 데이터만 추출 for i in bars: del i[6:] #04) 데이터프레임 열 이름 붙여주기 # mplfinance라는 패키지를 사용하기 위한 열 이름 : Date, Open, High, Low, Close, Volume df = pd.DataFrame(bars, columns=['Date','Open','High','Low','Close','Volume']) #05) 데이터프레임 열 type을 실수형으로 변환 df = df.astype({'Open' : 'float', 'High' : 'float', 'Low' : 'float', 'Close' : 'float', 'Volume' : 'float'}) #06) Date 열의 형태를 epoch에서 Pandas.Timestamp로 변경 : 세계 표준시에서 한국 표준시로 변환 df['Date'] = df['Date'].apply(lambda date: pd.Timestamp(time.ctime(date/1000.))) #06-1) 그래프 작성을 위해 시간의 시작과 끝 확인 nrows = df.shape[0] tstt_KST = df.at[0,'Date'].strftime('%Y-%m-%d %H:%M:%S') tend_KST = df.at[nrows-1,'Date'].strftime('%Y-%m-%d %H:%M:%S') print(df.tail(5)) #07) RSI 계산 함수 def calculate_rsi(df, n_rsi): # 변동폭 계산 : 현재 종가 - 지난 종가 delta = df['Close'].diff(1) #period = 1: 바로 이전 값과 비교, axis=0 : 행끼리 비교 # 상승(up), 하락(down) 구분 up = (delta.where(delta > 0, 0)).fillna(0) down = (delta.where(delta < 0, 0)).fillna(0) # n_rsi 기간 동안의 상승(up), 하락(down) 평균 avg_up = up.rolling(window=n_rsi, min_periods=1).mean() avg_down = down.rolling(window=n_rsi, min_periods=1).mean() # RS : 상대강도 rs = (avg_up/avg_down).abs() # RSI : 상대강도지수 rsi = rs/(1.0 + rs)*100 return rsi #08) Stochastic RSI 계산 함수 def calculate_stochastic_rsi(df, period, k_period, d_period): df['RSI'] = calculate_rsi(df, period) rsi_min = df['RSI'].rolling(window=period, min_periods=1).min() rsi_max = df['RSI'].rolling(window=period, min_periods=1).max() # 스토캐스틱 RSI는 스토캐스틱 오실레이터에서 현재가에 대응 df['Stochastic_RSI'] = (df['RSI'] - rsi_min) / (rsi_max - rsi_min) # %K : m일 동안의 Stochastic RSI (%로 변환 값) 평균 df['%K'] = df['Stochastic_RSI'].rolling(window=k_period, min_periods=1).mean() * 100 # %D : t일 동안의 %K 평균 df['%D'] = df['%K'].rolling(window=d_period, min_periods=1).mean() return df #09) 시계열 데이터로부터 스토캐스틱RSI 구하기 n_rsi = 14 m = 3 t = 3 df = calculate_stochastic_rsi(df, n_rsi, m, t) print(df.tail(5)) #10) 시계열 데이터 가시화 : 종가, RSI, Stochastic RSI의 %K, %D 표시 fig, axs = plt.subplots(3,1,figsize=(10,9)) axs[0].plot(df['Date'],df['Close'], label='close') axs[0].set_title('BTC Price') axs[0].set_xlim(np.datetime64(tstt_KST), np.datetime64(tend_KST)) axs[0].set_ylabel('Price (USDT)') axs[0].legend(loc='best') axs[0].tick_params(axis='x', rotation=15) axs[0].grid(True) # RSI axs[1].plot(df['Date'],df['RSI'], 'm', label='RSI') axs[1].set_xlim(np.datetime64(tstt_KST), np.datetime64(tend_KST)) major_yticks = [20, 30, 70, 80] axs[1].set_yticks(major_yticks) axs[1].legend(loc='best') axs[1].tick_params(axis='x', rotation=15) axs[1].grid(True) # Stochastic RSI %K, %D axs[2].plot(df['Date'],df['%K'], color='b', label='%K') axs[2].plot(df['Date'],df['%D'], color='m', label='%D') axs[2].set_xlim(np.datetime64(tstt_KST), np.datetime64(tend_KST)) major_yticks = [20, 30, 70, 80] axs[2].set_yticks(major_yticks) axs[2].legend(loc='best') axs[2].tick_params(axis='x', rotation=15) axs[2].grid(True) #09) 차트를 그림파일로 저장 file_path = 'C:/_python/pandas/backtesting/' plt.savefig(file_path +'Stochastic_RSI.png', dpi=200) plt.show() |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
[ BINANCE ACCOUNT ACCESSED ] Date Open High Low Close Volume 44 2024-05-15 09:00:00 61577.49 66444.16 61319.47 66206.50 43559.74719 45 2024-05-16 09:00:00 66206.51 66752.01 64602.77 65235.21 31106.36710 46 2024-05-17 09:00:00 65235.21 67451.20 65106.38 67024.00 26292.23409 47 2024-05-18 09:00:00 67024.00 67400.01 66600.00 66915.20 14441.25774 48 2024-05-19 09:00:00 66915.20 67700.00 66837.39 67294.80 7681.51373 Date Open High Low ... RSI Stochastic_RSI %K %D 44 2024-05-15 09:00:00 61577.49 66444.16 61319.47 ... 68.892804 1.000000 100.000000 86.750967 45 2024-05-16 09:00:00 66206.51 66752.01 64602.77 ... 64.681615 0.863017 95.433901 94.644337 46 2024-05-17 09:00:00 65235.21 67451.20 65106.38 ... 60.902424 0.740086 86.770106 94.068002 47 2024-05-18 09:00:00 67024.00 67400.01 66600.00 ... 58.353809 0.657184 75.342905 85.848971 48 2024-05-19 09:00:00 66915.20 67700.00 66837.39 ... 58.942941 0.676347 69.120587 77.077866 [5 rows x 10 columns] |
마치며 …
이번 포스팅에서는 시계열 데이터로부터 과매수 상태인지, 과매도 상태인지, 강세인지, 약세인지를 알아낼 수 있는 지표인 스토캐스틱 RSI에 대해 알아보았습니다. 이로써 과매수 상태인지, 과매도 상태인지, 강세인지, 약세인지를 알아낼 수 있는 시계열 데이터 분석 지표를 아래와 같이 하나 더 추가하였습니다.
(1) 스토캐스틱 오실레이터 (Stochastic Oscillator) : Slow %K, Slow %D
(2) 상대강도지수 (RSI, Relative Strength Index)
(3) 현금흐름지수 (MFI, Money Flow Index)
(4) 일중 강도 (Intraday Intensity, II)
(5) 스토캐스틱 RSI (Stochastic RSI) : Slow %K, Slow %D
스토캐스틱RSI는 상대강도지수(RSI) 값을 스토캐스틱 오실레이터로 변환한 것입니다. RSI와 스토캐스틱 오실레이터의 특성을 결합한 만큼 보다 시장에 보다 민감하게 반응합니다. 민감하게 반응하는 만큼 빠르게 매수 및 매도 신호를 포착할 수 있습니다.
함께 참고하면 좋은 글
▶ 파이썬 바이낸스 API로 시계열 데이터를 가져오는 파이썬 프로그래밍
▶ 시계열 데이터 분석 : 과매수, 과매도, 강세, 약세
▶ 시계열 데이터 분석 : 추세분석 지표 6가지
참고자료
▶ Investopedia, Stochastic RSI -StochRSI Definition