파이썬 코인 자동매매 프로그램 만들기 : 스토캐스틱, 이동평균선, 일목균형표 구현하기
토이 프로젝트/암호화폐 자동거래 봇(Bot) 만들기

파이썬 코인 자동매매 프로그램 만들기 : 스토캐스틱, 이동평균선, 일목균형표 구현하기

by TechNyang 2024. 10. 22.
반응형

지난 시간에는 파이썬으로 기술적 분석을 통해 어떤 라이브러리를 설치해야 하는지 알아보았고, 볼린저 밴드와 MFI, RSI를 구현하는 법을 알아보았습니다.

이번에는 기술적 분석 방법 중 스토캐스틱, 이동평균선, 일목균형표를 구현하는 법을 알아보도록 하겠습니다.

 

이전 내용은 아래 링크를 확인해 주시면 감사하겠습니다.

 

코인 자동매매 프로그램 만들기 : 기술적 분석지표 만들기

지금까지 개발환경을 구축하고, 거래소 API를 통해 가격정보를 조회해 오는 것을 알아보았습니다. 이전 포스팅을 보시지 않으셨다면 아래 링크를 통해 보고 오시는 것을 추천드립니다. 코인 자

technyang.tistory.com

 

스토캐스틱(Stochastic) 구하기

다음 소개해드릴 지표는 스토캐스틱이라는 보조지표입니다.

스토캐스틱 지표는 1950년대 William Dunnigun이 소개하고 George Lane이 널리 보급하였습니다.

또한 이 지표는 우리나라의 고○○변호사가 실전에서 잘 맞는다고 하여 ‘마법의 지표’라고 부르기도 했습니다.

 

스토캐스틱은, 최근 N일간의 최고가와 최저가의 범위에서 현재의 가격이 어느 위치에 있는지 표시할 때 쓰이며,

매수세가 강할 때에는 위치가 높게 형성되고, 매도세가 강할 때에는 위치가 낮게 형성되는 것을 이용한 지표입니다.

 

스토캐스틱에는 2개의 선이 존재하는데요.

하나는 최근 n일간의 최고가와 최저가 그리고 현재의 종가를 이용해 현재 가격이 어느 위치에 있는지를 나타내는 %K선. 그 %K선의 이동평균선인 %D선입니다.

 

이 스토캐스틱도 위에 말씀드린 MACD와 같이 골든크로스와 데드크로스를 가지고 매수, 매도 타이밍을 판단합니다.

그리고 스토캐스틱은 Fast와 Slow로 구분됩니다.

 

Fast와 Slow모두 %K와 %D를 가지고 매매 타이밍을 잡는데요.

스토캐스틱 Fast는 가격에 민감하게 반응을 하여 시그널이 빈번하게 발생하고 그에 따라 거짓신호가 자주 발생하는 단점이 있습니다.

 

이를 보완하고 나온 것이 스토캐스틱 Slow입니다.

스토캐스틱 Slow의 %K는 스토캐스틱 Fast의 %D의 n일 이동평균이며, 스토캐스틱 Slowd의 %D는 스토캐스틱 Slow %K의 n일 이동평균입니다.

 

결론을 말씀드리자면 투자자들은 스토캐스틱 Slow를 자주 사용한다는 것입니다. 

스토캐스틱을 구하는 코드는 아래와 같습니다.

slowk, slowd = talib.STOCH(df['high'], df['low'], df['close'], fastk_period=12, slowk_period=5, slowd_period=5)

 

스토캐스틱 Slow의 설정값은 총 3개가 필요하며 일반적으로 (12, 5, 5) 혹은 (10, 6, 6)으로 설정되어 있습니다.

보통 (5, 3, 3), (10, 6, 6), (12, 5, 5), (20, 12, 12)를 많이 사용하며 숫자가 작을수록 단기 매매에 적합합니다.

위 코드를 수행한 결과는 아래 그림과 같이 트레이딩 뷰에서 보이는 값과 거의 일치함을 볼 수 있습니다.

트레이딩뷰-차트와-구현한-값이-일치하는-모습
스토캐스틱 트레이딩뷰 차트와 구현한 값이 일치하는-모습

 

스토캐스틱도 과매수, 과매도를 이용한 매매기법과 %K, %D의 교차를 이용한 매매기법이 존재하며, 이를 표로 정리해 보았습니다.

  스토캐스틱 슬로우(Slow)
매수 ① %K가 20%이하에서 상향돌파할 때 매수
② %K선이 %D선을 상향돌파할 때 매수
    (%K가 20%이하에서 골든 크로스일 경우 상승 가능성 높음)
매도 ① %K가 80%이상에서 하향돌파할 때 매도
② %K선이 %D선을 하향돌파할 때 매도
     (%K가 80%이상에서 데드 크로스일 경우 하락 가능성 높음)

 

위 표를 토대로 스토캐스틱 매매시그널을 포착하는 함수를 작성하면 다음과 같습니다.

 

스토캐스틱 매수, 매도 시그널

def getStochSignal(ticker):
    df = getCandleStick(ticker, '5m') # 5분봉

    slowk, slowd = talib.STOCH(df['high'], df['low'], df['close'], fastk_period=12, slowk_period=5, slowd_period=5)

    # 현재 K선이 20이하 이고, 과거에는 K선이 D선보다 아래에 있다가 현재 K선이 D선보다 맞닿아 있거나 위에 있으면.
    if slowk.iloc[-1] <= 20.0 and (slowk.iloc[-2] < slowd.iloc[-2]) and (slowk.iloc[-1] >= slowd.iloc[-1]):
        return 1 # 매수 시그널
    # 현재 K선이 80이상 이고, 과거에는 K선이 D선보다 위에 있다가 현재 K선이 D선보다 맞닿아 있거나 아래에 있으면.
    elif slowk.iloc[-1] >= 80 and (slowk.iloc[-2] > slowd.iloc[-2]) and (slowk.iloc[-1] <= slowd.iloc[-1]):
        return -1  # 매도 시그널
    else:
        return 0  # 관망

 

아래는 매수 시그널에 잡힌 펀디엑스의 스토캐스틱 화면입니다. 보시면 K선(푸른선)이 20 이하이면서 D선(붉은 선) 위에 위치하고 있으며, 전에는 K선이 D선보다 아래에 위치하고 있음을 알 수 있습니다.

스토캐스틱-매수시그널-차트
스토캐스틱 매수 시그널

 

또한 아래는 매도 시그널에 잡힌 비트토렌트의 스토캐스틱 화면입니다. 보시면 K선(푸른 선)이 80 이상이면서 D선(붉은 선) 밑에 위치하고 있으며, 전에는 K선이 D선보다 위에 위치하고 있음을 알 수 있습니다.

 

스토캐스틱-매도-시그널
스토캐스틱 매도 시그널

 

단순 이동평균선(SMA) 구하기

이동평균선은 추세를 판단하기 위한 간단하지만 아주 중요한 지표입니다.

이동평균선은 말 그대로 n일간의 기간동안의 주가의 평균을 나타내는데요. ta-lilb모듈을 이용하면 아래와 같이 아주 간단하게 구할 수 있습니다.

ma = talib.SMA(df[‘close’], period)

 

period에는 이동평균을 구하고자 하는 기간을 입력하시면 됩니다.

예를 들어 5일 이평선을 구하고 싶으시면 5를, 60일 이평선을 구하고 싶으시면 60을 넣으시면 됩니다.

def getSMA(ticker, period):
    df = getCandleStick(ticker, '1d') #일봉을 가져온다.
    ma5 = talib.SMA(df['close'], period) # n일선을 가져온다.
    return ma5.iloc[-1]

 

 

일목균형표 구하기

일목균형표는 1935년 ‘일목산인’(본명: 호소다 코이치)이 신문사에 재직하고 있을 때 증권시황란 작성을 위해 개발한 지표입니다.

 

대부분의 다른 지표는 후행성이거나 동행성을 보이지만, 일목균형표는 선행성까지 가지고 있어 미래를 예측하는 데에도 사용이 됩니다.

 

일목균형표는 여러가지의 지표들을 포괄적으로 내재가 되어있기 때문에 매수, 매도 전략이 아주 다양합니다. 또한 원래 일목균형표는 세상에 발표가 될 때 7권에 해당하였지만, 현재는 4권만이 발권되었다고 전해집니다.

 

그만큼 일목균형표를 이해하는 데에는 적지않은 공부가 필요합니다.  일목균형표는 구성은 5개의 선으로 구성되어 있습니다.

  • 전환선
    • (과거 9일간의 최고가 + 과거 9일간의 최저가) / 2
  • 기준선
    • (과거 26일간의 최고가 + 과거 26일간의 최저가) / 2
  • 후행스팬
    • 현재의 주가를 26일전 가격에 적용
  • 선행스팬 A
    • (현재 전환선 값 + 현재 기준선 값) / 2, 이 값을 26일 후 가격에 적용
  • 선행스팬 B
    • (과거 52일간의 최고가 + 과거 52일간의 최저가) / 2, 이 값을 26일 후 가격에 적용

추가로 구름대라는 것도 있는데요. 이것은 선행스팬 A와 선행스팬 B사이의 영역입니다.

일목균형표는 ta-lib모듈에서 지원을 하지 않아 직접 구현해 보겠습니다. 어렵지 않으니 걱정하실 필요는 없습니다.

 

전환선

df = getCandleStick(ticker, '5m')
period9_high = df['close'].rolling(window=9).max() # 과거 9일간 최고가
period9_low = df['close'].rolling(window=9).min() # 과거 9일간 최저가
tenkan_sen = (period9_high + period9_low) / 2

 

기준선

period26_high = df['close'].rolling(window=26).max() # 과거 26일간 최고가
period26_low = df['close'].rolling(window=26).min() # 과거 26일간 최저가
kijun_sen = (period26_high + period26_low) / 2

 

후행스팬

chikou_span = df.shift(-26) # shift 메서드는 원하는 수 만큼 이동시킴. 
                                                # -26이므로 뒤로(과거) 26만큼 이동시킴

 

선행스팬 A

senkou_span_a = ((tenkan_sen + kijun_sen) / 2).shift(26)

 

선행스팬 B

period52_high = df['close'].rolling(window=52).max() # 과거 52일간 최고가
period52_low = df['close'].rolling(window=52).min() # 과거 52일간 최저가
senkou_span_b = ((period52_high + period52_low) / 2).shift(26)

 

모든 구성을 작성하였습니다. 지금까지 작성한 표들을 한 곳에 모으면 일목균형표 메서드를 완성할 수 있습니다.

그 결과는 아래와 같습니다.

def getIchimoku(ticker):
    df = getCandleStick(ticker, '5m')
    
    period9_high = df['close'].rolling(window=9).max()
    period9_low = df['close'].rolling(window=9).min()
    tenkan_sen = (period9_high + period9_low) / 2
    
    period26_high = df['close'].rolling(window=26).max()
    period26_low = df['close'].rolling(window=26).min()
    kijun_sen = (period26_high + period26_low) / 2

    chikou_span = df.shift(-26)
    
    senkou_span_a = ((tenkan_sen + kijun_sen) / 2).shift(26)
    
    period52_high = df['close'].rolling(window=52).max()
    period52_low = df['close'].rolling(window=52).min()
    senkou_span_b = ((period52_high + period52_low) / 2).shift(26)

    return tenkan_sen, kijun_sen, chikou_span, senkou_span_a, senkou_span_b

 

그리고 일목균형표에는 구름대라는 영역이 존재하는데요. 이것은 선행스팬 A와 선행스팬 B사이의 영역을 가리킵니다.

일목균형표를 이용하여 매수와 매도 시그널을 얻는 메소드를 작성하려 하는데요.

앞에서도 말씀드렸듯이 일목균형표를 이용한 전략은 매우 다양하며, 지금 알려드리는 방법은 그중 1가지라는 점 꼭 기억해 주셨으면 좋겠습니다.

매수 매도
● 전환선이 기준선을 상향돌파
주가가 구름대를 상향 돌파
전환선이 기준선을 하향돌파
주가가 구름대를 하향 돌파

 

일목균형표  매수, 매도 시그널

def getIchimoku(ticker):
    df = getCandleStick(ticker, '5m')

    period9_high = df['close'].rolling(window=9).max()
    period9_low = df['close'].rolling(window=9).min()
    tenkan_sen = (period9_high + period9_low) / 2

    period26_high = df['close'].rolling(window=26).max()
    period26_low = df['close'].rolling(window=26).min()
    kijun_sen = (period26_high + period26_low) / 2

    chikou_span = df.shift(-26)

    senkou_span_a = ((tenkan_sen + kijun_sen) / 2).shift(26)

    period52_high = df['close'].rolling(window=52).max()
    period52_low = df['close'].rolling(window=52).min()
    senkou_span_b = ((period52_high + period52_low) / 2).shift(26)

    curPrice = getCurrPrice(ticker)

    if tenkan_sen.iloc[-1] > kijun_sen.iloc[-1] and tenkan_sen.iloc[-2] <= kijun_sen.iloc[-2]: #전환선이 기준선 상향돌파
        if curPrice > senkou_span_a.iloc[-1] and curPrice > senkou_span_b.iloc[-1]: # 주가가 구름대 상향돌파
            return 1
    elif tenkan_sen.iloc[-1] < kijun_sen.iloc[-1] and tenkan_sen.iloc[-2] >= kijun_sen.iloc[-2]: #전환선이 기준선 하향돌파
        return -1
    elif curPrice < senkou_span_a.iloc[-1] and curPrice < senkou_span_b.iloc[-1]: #주가가 구름대 하향돌파
        return -1
    else:
        return 0

 

 

다음 포스팅에는 청산기법과 거래소 API를 통해 매수와 매도하는 법을 알아보겠습니다.

감사합니다.

반응형

TOP

Designed by 티스토리

loading