본문 바로가기
데이터과학/데이터 분석 실습

스토캐스틱 지표를 이용한 알고리즘 투자전략 (feat. 파이썬)

by 경성현 2020. 12. 30.

스토캐스틱(Stochastic Oscillator)를 이용하여 투자전략을 세우는 방법에 대해서 설명드리겠습니다. 시장 움직임에 대한 스토캐스틱 지표의 민감도는 지표 생성 기간을 조정하거나 결과의 이동 평균을 취함으로써 줄일 수 있습니다. 스토캐스틱 지표는 0–100 범위의 값을 사용하여 과매 수 및 과매도 거래 신호를 생성하는 데 사용됩니다.

스토캐스틱 지표는 주로 차트의 추세를 파악하는 방법으로 최근 N일간의 최고가와 최저가의 범위 내에서 현재 가격의 위치를 백분율로 표시한 지표입니다.

스토캐스틱 지표는 Fast와 Slow 두가지가 있고, 각각의 %K, %D를 구합니다. Fast 지표는 주가에 너무 민감하게 반응하기 때문에 아주 짧은 주기의 단타를 하시는 활용하시면 좋고, 보통은 Slow 지표를 매매에 활용하게 됩니다.

## Stochastic Fast  
Fast %K = {(현재가 - N기간 중 최저가) / (N기간 중 최고가 - N기간 중 최저가)} * 100
Fast %D = Fast %K를 M기간 (지수)이동평균

## Stochastic Slow
Slow %K = Fast %D
Slow %D = Slow %K를 T기간 이동평균

스토캐스틱 지표의 사용 방법

스토캐스틱 지표는 대부분의 HTS 또는 MTS 프로그램에 포함되어 있으며 쉽게 사용할 수 있습니다. 사용되는 표준 기간은 14일이지만 특정 분석한 상황을 반영할 수 있도록 조정할 수 있습니다. 스토캐스틱 지표는 현재 종가에서 해당 기간의 최저값을 빼서 해당 기간의 최고값과 최저값의 차이로 나눈 다음 100을 곱하여 계산됩니다. 예컨데, 14일 최고가가 15,000원, 최저값이 12,500원, 현재 종가는 14,500원이라면, 스토캐스틱 지표는 (14,500-12,500) / (15,000-12,500) * 100으로 이를 계산하면 80이 됩니다.

현재 가격을 표준 기간의 범위와 비교함으로써 스토캐스틱 지표는 가격이 최근 고가 또는 저가 근처에서서 마감되는 일관성을 갖습니다. 값이 80이면 자산이 과매수 직전에 있음을 의미합니다.

상대적 강도 지수(Relative Strength Index)와 스토캐스틱 지표의 차이점

상대적 강도 지수(Relative Strength Index, RSI)와 스토캐스틱 지표는 모두 기술 분석에 널리 사용되는 가격 모멘텀 지표입니다. 종종 함께 사용되지만 각각 다른 이론적 배경이 있으며, 계산방법도 다릅니다.

스토캐스틱 지표는 종가가 현재 추세와 같은 방향에 가깝게 마감되어야한다는 가정에 근거합니다. 한편, RSI는 가격 움직임의 속도를 측정하여 과매수 및 과매도 수준을 추적합니다. 일반적으로 RSI는 추세 시장에서 더 유용하고 횡보 또는 고르지 않은 시장에서는 스토캐스틱 지표가 유용합니다.

스토캐스틱 지표를 이용한 트레이딩 기법

  1. 과매수, 과매도 이용 기법
    - 일반적으로 (20%, 80%)를 기준으로, %K가 20% 이하면 과매도 구간으로 보고 매수 포지션을 잡고, %K가 80% 이상이면 과매수 구간으로 보고 매도 포지션을 잡는다.
  2. %K와 %D 교차를 이용한 매매기법
    - %K선이 %D선을 상향 돌파 (골든 크로스) 하면 매수

    - 과매도 구간(%K 20% 이하)에서 골든 크로스면 확률 상승
    - %K선이 %D선을 하향 돌파 (데드 크로스) 하면 매도
    - 과매수 구간 (%K 80% 이상) 에서 데드 크로스면 확률 상승
  3. 기준선 활용
    - %K선과 %D선이 기준선(보통 50%)을 상향 돌파하면 매수, 하향 돌파하면 매도

스토캐스틱 지표 한계

스토캐스틱 지표의 주요 한계는 잘못된 신호를 생성할 수 있다는 것입니다. 지표에 의해서 거래를 했지만, 실제로 가격이 뒤따르지 않아 결국 거래 손실로 이어질 수 있다는 의미입니다. 불안정한 시장 상황에서 이것은 매우 빈번하게 발생할 수 있습니다. 이를 보완할 수 있는 한 가지 방법은 가격 추세를 필터로 사용하는 것입니다. 이런 경우, 매도 또는 매수 신호가 추세와 같은 방향 일 때만 트레이딩 신호로 활용하는 것입니다. 

파이썬을 이용한 스토캐스틱 지표 계산

파이썬을 이용해서 위에서 설명한 스토캐스틱 지표를 계산해 보겠습니다. 우선 분석이 필요한 라이브러리를 Import 하겠습니

import pandas as pd
import matplotlib.pyplot as plt
plt.style.use('fivethirtyeight')

주식 데이터 로드

야후 파이낸스(yfinance) 라이브러리를 이용해서 나그닥의 한 종목 데이터를 가져오겠습니다. 야후 파이낸스 라이브러리가 없다면, '!pip install yfinance'를 통해서 설치해 주시면 됩니다. 예시로 위해서 클린 에너지 퓨엘(Clean Energy Fuels, NYSE: CLNE) 데이터를 사용하겠습니다. 

import yfinance as yf

df = yf.download('CLNE', start="2020-01-01", end="2020-12-31")
df['Date'] = df.index

df.head()

스토캐스틱 지표 계산 함수

일자(n, m, t)에 따른 Stochastic Fast와 Stochastic Slow를 계산하는 함수를 만들어 보겠습니다.

# 일자(n,m,t)에 따른 Stochastic(KDJ)의 값을 구하기 위해 함수형태로 만듬
def Stochastic(df, n=14, m=5, t=5):
    # 입력받은 값이 dataframe이라는 것을 정의해줌
    df = pd.DataFrame(df)

    # n일중 최고가
    ndays_high = df.High.rolling(window=n, min_periods=1).max()
    
    # n일중 최저가
    ndays_low = df.Low.rolling(window=n, min_periods=1).min()

    # Fast%K 계산
    fast_k = ((df.Close - ndays_low) / (ndays_high - ndays_low)) * 100

    # Fast%D (=Slow%K) 계산
    slow_k = fast_k.ewm(span=m).mean()

    # Slow%D 계산
    slow_d = slow_k.ewm(span=t).mean()

    # dataframe에 컬럼 추가
    df = df.assign(fast_k=fast_k, fast_d=slow_k, slow_k=slow_k, slow_d=slow_d)

    return df

상대적 강도 지수(RSI) 계산

비교를 위해서 상대적 강도지수도 함께 계산해 보겠습니다. 상대적 강도 지수에 대한 설명은 주식 시장의 기술 지표 분석(feat. 파이썬)을 참고해 주세요. 이번 예시에서는 상대적 강도 지수의 계산 window를 14일로 하겠습니다.

# 단순 이동 평균(Simple Moving Average, SMA)
def SMA(data, period=30, column='Close'):
  return data[column].rolling(window=period).mean()

# 상대적 강도 지수(RSI) 계산 함수
def RSI(data, period = 14, column = 'Close'):
  delta = data[column].diff(1) #Use diff() function to find the discrete difference over the column axis with period value equal to 1
  delta = delta.dropna() # or delta[1:]
  up =  delta.copy()  # delta 값 복사
  down = delta.copy() # delta 값 복사
  up[up < 0] = 0 
  down[down > 0] = 0 
  data['up'] = up
  data['down'] = down
  AVG_Gain = SMA(data, period, column='up')#up.rolling(window=period).mean()
  AVG_Loss = abs(SMA(data, period, column='down'))#abs(down.rolling(window=period).mean())
  RS = AVG_Gain / AVG_Loss
  RSI = 100.0 - (100.0/ (1.0 + RS))
  
  data['RSI'] = RSI
  return data

기술 지표를 계산해서 DataFrame에 추가

df = Stochastic(df, 14, 5, 5)
df = RSI(df, 14)
df.tail()

주가 데이터 시각화

# 시각화 할 변수 정의
column_list = ['Close']

# 2020년 10월 부터 시각화
cut = df.Date>='2020-10-01'
df[column_list].loc[cut,:].plot(figsize=(12.2,6.4)) #Plot the data
plt.title('Price for Clean Energy Fuels')
plt.ylabel('USD($)')

스토캐스틱 FAST와 RSI 시각화

# 시각화 할 변수 정의
column_list = ['fast_k','fast_d','RSI']

# 2020년 10월 부터 시각화
cut = df.Date>='2020-10-01'
df[column_list].loc[cut,:].plot(figsize=(12.2,6.4)) #Plot the data
plt.title('Stochastic Oscillator and RSI')
plt.ylabel('Percent')

스토캐스틱 SLOW와 RSI 시각화

# 시각화 할 변수 정의
column_list = ['slow_k','slow_d','RSI']

# 2020년 10월 부터 시각화
cut = df.Date>='2020-10-01'
df[column_list].loc[cut,:].plot(figsize=(12.2,6.4)) #Plot the data
plt.title('Stochastic Oscillator and RSI')
plt.ylabel('Percent')

 

지금은 매도 타이밍?

스토캐스틱 Fast와 Slow 모두 값이 높게 나오네요. RSI도 거의 80에 가까운 수치니, 기술 지표 상으로 지금은 Clean Energy Fuels을 매수하기에 적절하지 않은 상황이긴 합니다. 저는 며칠전 거의 상투일때 매수를 했네요ㅠㅠ 하지만, 클린 에너지는 바이든 정부의 정책 기조 이기 때문에 2년 정도 묵혀둔다면 충분히 상승하지 않을까... 기대하며 매수 타이밍을 기다려보겠습니다.