본문 바로가기
Python

파이썬을 이용한 주식, 가상 화폐 거래 전략 - Fibonacci & RSI

by 아짱이아빠 2022. 5. 14. 15:44
반응형

Fibonacci Retracement Level과 RSI 조건을 조합하여 가상 화폐나 주식에 적용할 수 있는 매매 전략에 대해 알아본다. 

파이썬 코드를 이용해서 Fibonacci Retracement Level과 RSI를 계산하고 가상 화폐 데이터를 불러와서 backtesting을 해본다.

 

Fibonacci Retracement Level은 주식이나 가상 화폐의 흐름을 분석할 때 사용되며 상승하는 흐름에서는 저항 수준을 예측하고 하향하는 흐름에서는 지지 수준을 예측할 수 있다.

이에 대한 내용은 아래의 링크에 좀 더 상세하게 나와있다. 

 

 

파이썬을 이용한 주식, 가상 화폐 분석 - Fibonacci Retracement

이번에는 Fibonacci 수열을 통해 주식을 분석하는 파이썬 코드에 대해 알아보겠다. Fibonacci 수열과 이를 통한 주식 분석에 대해 간단히 알아보면 다음과 같다. 먼저 Fibonacci 수열은 13세기 수학자 레

superhky.tistory.com

 

 

RSI(Relative Strength Index)는 가격의 상승 폭과 하락 폭을 계산하여 그 강도를 백분율로 계산해 현재 가격의 상태를 평가하고자 만든 지표이다.

RSI를 매매 전략으로 많이 이용하는 방법에는 과매수 상태와 과매도 상태를 판단하는 것이 있는데, RSI가 30 미만이면 과매도 상태로 곧 가격이 오를 가능성이 있다고 판단하며 RSI가 70을 넘어가면 과매수 상태로 조만간 가격이 떨어질 수 있을 가능성이 있다고 판단하다. 

 

[매매 전략]

이번에 얘기하는 전략은 Fibonacci Retracement Level과 RSI를 조합하는 방법이다.

매수의 조건은 RSI 값이 30 아래에 있다가 30을 넘어면서 Fibonacci의 각 저항 레벨을 뚫고 오를 때 매수를 한다.

매도의 조건은 RSI 값이 70을 넘은 후 상승이 하향으로 바뀔 때 매도를 한다.

매수 이후에 RSI가 70을 넘지 못하고 가격이 계속 하락하는 경우를 방지하기 위해서 매도의 조건은 한 가지를 더 추가한다.

지수이동평균을 계산하여 매도할 때의 가격이 이 보다 낮으면 RSI 기준 값을 60으로 낮추어 적용한다.

이 전략을 요약하면, RSI로 과매도 상태에서 가격이 상승할 것이란 가정하에 실제로 가격이 Fibonacci의 저항 레벨을 뚫고 올라가면 가격이 상승하고 있으니 매수를 하고 매도는 과매수 상태까지 되면 곧 가격이 하락할 것이란 예측으로 RSI가 하향할 때에 매도를 하는 것이다.

 

[파이썬 코드]

아래의 코드로 기본적인 라이브러리를 불러온다.

맨 처음에 있는 코드는 google colab에서 업비트 데이터를 불러오기 위해 관련 모듈을 설치하는 것이다.

!pip install pyupbit
import pyupbit
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

 

아래의 코드는 분석하고자 하는 가상 화폐를 입력하는 기능을 한다.

coin = input("코인 :")
df = pyupbit.get_ohlcv(coin,interval="minutes10", count=100)

 

입력은 ‘KRW-XXX’ 식으로 앞에 원화 표시를 하고 가상 화폐의 심볼을 넣으며, 10분 봉 데이터를 100개 불러온다.

 

다음은 RSI를 계산한다.

delta = df['close'].diff(1)
delta = delta.dropna()
up = delta.copy()
down = delta.copy()
up[ up < 0 ] = 0
down[ down > 0 ] = 0
time_period_10 = 10
AVG_Gain_10 = up.ewm(com=time_period_10-1, min_periods=time_period_10).mean()
AVG_Loss_10 = abs(down.ewm(com=time_period_10-1, min_periods=time_period_10).mean())
RS_10 = AVG_Gain_10 / AVG_Loss_10
RSI_10 = 100.0 - (100.0/(1.0 + RS_10))

 

여기서는 10개의 데이터를 기준으로 RSI를 계산했는데 가장 많이 적용하는 14개의 데이터를 통해 RSI를 계산하여 적용할 수도 있으나 조금 더 가격의 변화에 민감

 

아래는 Fibonacci Retracement Level과 분석하는 데이터 구간의 최댓값과 최솟값을 계산한다.

먼저 분석하려는 전체 데이터 구간의 최대값과 최솟값을 확인한 후 Fibonacci 비율을 적용하여 첫 번째부터 네 번째 레벨에 해당하는 가격을 계산하는 것이다.

max_price = df['close'].max()
min_price = df['close'].min()

difference = max_price - min_price
first_level = max_price - difference * 0.236
second_level = max_price - difference * 0.382
third_level = max_price - difference * 0.5
fourth_level = max_price - difference * 0.618

 

다음은 매도 조건에 사용할 지수이동평균을 구하며 여기서는 50개의 데이터에 대한 지수이동평균을 적용하였다. 

EMA_50 = df.close.ewm(span=50, adjust=False).mean()
df['EMA_50'] = EMA_50

 

아래는 앞에서 얘기한 매매 전략을 definition으로 구현한 부분이며 매매 전략의 핵심이 되는 부분이다. 

def buy_sell(data, case1, case2):
  BuySignal = []
  SellSignal = []
  buy_price=0
  flag = 1

  for i in range(0, len(data)):
    if (data['close'][i-1] < min_price) and (data['close'][i] > min_price) and flag==1 :
      for j in range(0,i):
        if (data[case1][i-j-1] < 30) and (data[case1][i-j] > 30) :
          BuySignal.append(data['close'][i])
          SellSignal.append(np.nan)
          flag = 0
          break
      if flag != 0:
        SellSignal.append(np.nan)
        BuySignal.append(np.nan)

    elif (data['close'][i-1] < fourth_level) and (data['close'][i] > fourth_level) and flag==1 :
      for j in range(0,i):
        if (data[case1][i-j-1] < 30) and (data[case1][i-j] > 30) :
          BuySignal.append(data['close'][i])
          SellSignal.append(np.nan)
          flag = 0
          break
      if flag != 0:
        SellSignal.append(np.nan)
        BuySignal.append(np.nan)

    elif (data['close'][i-1] < third_level) and (data['close'][i] > third_level) and flag==1 :
      for j in range(0,i):
        if (data[case1][i-j-1] < 30) and (data[case1][i-j] > 30) :
          BuySignal.append(data['close'][i])
          SellSignal.append(np.nan)
          flag = 0
          break
      if flag != 0:
        SellSignal.append(np.nan)
        BuySignal.append(np.nan)

    elif (data['close'][i-1] < second_level) and (data['close'][i] > second_level) and flag==1:
      for j in range(0,i):
        if (data[case1][i-j-1] < 30) and (data[case1][i-j] > 30) :
          BuySignal.append(data['close'][i])
          SellSignal.append(np.nan)
          flag = 0
          break
      if flag != 0:
        SellSignal.append(np.nan)
        BuySignal.append(np.nan)

    elif (data['close'][i-1] < first_level) and (data['close'][i] > first_level) and flag==1 :
      for j in range(0,i):
        if (data[case1][i-j-1] < 30) and (data[case1][i-j] > 30) :
          BuySignal.append(data['close'][i])
          SellSignal.append(np.nan)
          flag = 0
          break
      if flag != 0:
        SellSignal.append(np.nan)
        BuySignal.append(np.nan)

    elif (data['close'][i-1] < max_price) and (data['close'][i] > max_price) and flag==1:
      for j in range(0,i):
        if (data[case1][i-j-1] < 30) and (data[case1][i-j] > 30) :
          BuySignal.append(data['close'][i])
          SellSignal.append(np.nan)
          flag = 0
          break
      if flag != 0:
        SellSignal.append(np.nan)
        BuySignal.append(np.nan)

    elif (data['close'][i-2] > data[case2][i-2]) and (data[case1][i-1] > 70) and (data[case1][i-1] > data[case1][i]) and flag == 0:
      SellSignal.append(data['close'][i])
      BuySignal.append(np.nan)
      flag = 1

    elif (data['close'][i-2] < data[case2][i-2]) and (data[case1][i-1] > 60) and (data[case1][i-1] > data[case1][i]) and flag == 0:
      SellSignal.append(data['close'][i])
      BuySignal.append(np.nan)
      flag = 1

    else:
      SellSignal.append(np.nan)
      BuySignal.append(np.nan)

  return(BuySignal, SellSignal)

조금 복잡해 보이는데 이는 프로그램 전공자가 아니고 파이썬을 배워가는 입장에서 하고자 하는 내용을 효율적으로 구성하지 못했기 때문이며 로직은 앞에서 설명한 바와 같이 비교적 간단하다.

계산한 Fibonacci의 각 Level을 가격이 돌파할 때에 이전에 RSI가 30 미만에서 이상으로 올라왔었는지를 찾아 있었다면 매수를 하고 그렇지 않으면 매수를 하지 않는다.

매도는 지수이동평균 보다 가격이 높으면 RSI가 70을 넘었고 이후에 이전 RSI보다 현재의 RSI가 작아지면 매도를 하고 지수이동평균 보다 가격이 낮으면 RSI 기준을 60을 적용한다. 

 

이 definition은 아래의 코드로 실행하여 ‘df’에 그 결과를 저장한다.

x = buy_sell(df, 'RSI_10', 'EMA_50')
df['Buy_Signal_Price'] = x[0]
df['Sell_Signal_Price'] = x[1]

 

반응형

 

[Backtesting]

Fibonacci Retracement Level과 RSI를 조합한 매매 전략이 어느 정도의 수익이 가능한지 몇 가지 가상 화폐에 대해 backtesting을 해보겠다.

Backtesting 관련한 파이썬 코드는 아래의 링크에 자세히 나와있다.

 

 

SMA와 MACD 이용 Python 가상화폐 자동매매(2/2)-backtesting

지난번에 알아본 자동매매 프로그램을 backtesting 하는 방법과 그 결과에 대한 분석을 해보겠다. 먼저 backtesting 코드를 알아본 후 dp이다(ADA)와 이더리움클래식(ETC)에 대해 자동매매 프로그램의 누

superhky.tistory.com

 

(가상 화폐 : 리플(XRP))

리플(XRP)의 5월13일 새벽부터 저녁까지의 10분 봉 데이터 100개를 불러와서 지수이동평균과 Fibonacci Level, 그리고 RSI를 표현하면 아래와 같다.

리플(XRP)의 Fibonacci Level과 RSI 결과
(리플(XRP)의 Fibonacci Level과 RSI 결과)

위의 그림과 같은 흐름에서 거래 전략에 따른 결과를 예측해 보면, 06시가 넘었을 때쯤 RSI가 30 이하에서 30 이상으로 올라갔으며 이후 11시 부근에서 4번째 Fibonacci Level(파란색 선)을 넘어갈 때 매수가 이뤄졌을 것이다.

그리고 이 매수에 대한 매도는 지수이동평균보다 가격이 높기 때문에 RSI가 70 이상을 갔다가 내려오는 시점에서 첫 매도가 이뤄질 것이다.

그리고 12시 이전에 가격이 세 번째 Fibonacci Level(녹색 선)을 넘기 때문에 다시 매수가 이뤄지고 12시가 조금 넘은 시점 즈음 RSI가 하향하는 부분에서 두 번째 매도가 이뤄질 것으로 보인다.

 

backtesting의 결과는 아래와 같다.

리플(XRP) backtesting 결과
(리플(XRP) backtesting 결과)

앞에서 예측한 것 처럼 11시와 12 부근에서 거래가 이뤄졌고 이후에도 세 번의 거래가 더 발생했다.

총 5번의 거래에서 두 번은 손해를 봤고 최종 이 구간에서의 누적 수익률은 3.7%이다.

이 구간만 본다면 약 520원에서 600원 수준까지 올랐으므로 그냥 두었다면 수익은 약 15%였을 것이다.

 

(가상 화폐 : 트론(TRX))

같은 시간대에서 트론(TRX)의 경우는 가격의 흐름과 RSI, Fibonacci Level이 아래와 같다. 

트론(TRX)의 Fibonacci Level과 RSI 결과
(트론(TRX)의 Fibonacci Level과 RSI 결과)

12시 이전에 네 번째 Fibonacci Level을 넘으면서 첫 매수가 발생하고 13시 부근에서 첫 매도가 이뤄질 것이다.

14시 부근에서 첫 번째 Fibonacci Level(주황색 선)을 넘으면서 두 번째 매수가 발생하고 21시 부근에서 이에 대한 매도가 이뤄질 것으로 예측된다.

 

Backtesting 결과는 아래와 같다.

트론(TRX) backtesting 결과
(트론(TRX) backtesting 결과)

앞에서 예측한 것과 동일하게 두 번의 거래가 이뤄지고 총 누적 수익률은 약 5.1%이다.

아무 거래도 하지 않았다면 이 구간에서의 수익은 약 4.3%이다.

 

(가상 화폐 : 디센트럴랜드(MANA))

마지막 케이스는 디센트럴랜드(MANA)이다.

위에서와 같은 구간의 가격 흐름은 다음과 같다.

디센트럴랜드(MANA)의 Fibonacci Level과 RSI 결과
(디센트럴랜드(MANA)의 Fibonacci Level과 RSI 결과)

매수는 네 번째와 첫 번째 Fibonacci level을 넘을 때 발생할 것으로 보이고 12시 부근과 18시 부근에서 매수와 매도가 발생할 것으로 예측된다.

 

Backtesting 결과는 아래와 같다.

디센트럴랜드(MANA) backtesting 결과
(디센트럴랜드(MANA) backtesting 결과)

예측 대비 14시에서도 거래가 발생했다.

총 네 번의 거래 중 한 번의 손해가 있었고 누적 수익률은 약 19%이다.

이 구간은 약 1000원에서 시작하여 1400까지 올랐고 그냥 두었으면 수익률은 약 14%이다.

 

 

[결 론]

Fibonacci Retracement Level이라는 확률적인 지표를 가지고 RSI와 조합하여 매매 전략을 만들었고 backtesting으로 대략적인 결과도 확인했다.

Backtesting을 하는 날 거의 모든 가상 화폐가 상승장에 있었기 때문에 결과가 전체적으로 좋게 나왔다.

하락장에 있을 때 어떤 결과가 나오는지는 추가적으로 확인할 필요가 있겠다.

또한, 10분 봉 기준이 아닌 다른 기준의 데이터에서는 또 다른 결과가 나올 것이다. 

그러나 확실히 상승의 시점에서 매수 타이밍을 잡는 듯해 보인다.

문제는 역시 언제 매도를 할 것인가 인 것 같다.

 

반응형

댓글