본문 바로가기

파이썬으로 퀀트 프로그램 만들기 project/백테스팅

[백테스팅] 하이킨아시 캔들 이용하여 매매하기

728x90

하이킨아시 캔들을 이용하여 매매 백테스팅을 진행해 보도록 하겠습니다.

기본적인 매매 아이디어는 유튜버 코비딕 님의 "한 달 만에 10만원 → 6000만원 만든 매매법 분석" 에서 따왔습니다.

매매 아이디어는 다음과 같습니다.

 

 

매수조건:

1. 200일 이평선 위에 하이킨아시 캔들들이 있음

2. stochastic rsi에서 k가 d를 상향돌파 -> 과매도로 판단

3. 2번째 조건 발생 5봉 이내에, 이전 양봉보다 몸통이 길고 아랫꼬리가 없는 양봉이 나오면 매수!

손익비는 익절 3퍼, 손절 1.5퍼로 맞춰줍니다.

 

 

이제 본격적인 코드를 소개해드리겠습니다.

import pyupbit

access = "abc123"          # 본인 값으로 변경
secret = "abc123"          # 본인 값으로 변경
upbit = pyupbit.Upbit(access, secret)

print(upbit.get_balance("KRW-BTC"))     # KRW-BTC 조회
print(upbit.get_balance("KRW"))         # 보유 현금 조회

pyupbit 라이브러리를 이용하기 위한 access 값과 secret값을 입력해 줍니다. 

get_balance를 통해 잘 로그인 되었는지 확인합니다.

 

## 하이킨아시 차트로 변환 ##

import pandas as pd
count = 10000
df = pyupbit.get_ohlcv("KRW-BTC", interval='minute60',count = count)


heikin = pd.DataFrame()
#heikin['open'] = [0 for i in range(count)]

heikin['close'] = (df['open'] + df['close'] + df['high'] + df['low'])/4
heikin['open'] = 0
heikin.iloc[0,1] = df['open'].iloc[0]

for i in range(count - 1):
    heikin.iloc[i+1, 1] = (heikin.iloc[i, 1] + heikin.iloc[i, 0])/2

heikin = heikin[['open', 'close']]


heikin['high'] = 0
for i in range(count):
    heikin.iloc[i,2] = max(df['high'].iloc[i], heikin['open'].iloc[i], heikin['close'].iloc[i])

heikin['low'] = 0
for i in range(count):
    heikin.iloc[i,3] = min(df['low'].iloc[i], heikin['open'].iloc[i], heikin['close'].iloc[i])

heikin['pm'] = 0
for i in range(count):
    if heikin.iloc[i,0] <= heikin.iloc[i,1] :
        heikin.iloc[i,4] = 1
    else:
        heikin.iloc[i,4] = -1

비트코인 1시간봉 데이터 1만 개를 내려받습니다. 이제 이것을 하이킨아시 캔들로 변환해 줍니다.

제가 하이킨아시 캔들 변환해 주는 외부 라이브러리를 찾아봤는데 없더라고요.

그래서 제가 하이킨아신 캔들 변환식을 직접 코드로 구현해 봤습니다.

 

제대로 변환되었는지 한번 확인해 볼게요.

300개 봉 데이터만 비교해 보겠습니다.

좌측이 하이킨아시 캔들이고, 우측이 기존 일반적인 캔들입니다. 

잘 변환된 것 같네요.

 

추가로 heikin 데이터프레임에 필요한 열들을 추가해 줍니다.

import talib

heikin['EMA_200'] = talib.EMA(heikin['close'], 200)
heikin['buy'] = False
heikin['hpr'] = 1
heikin['ror'] = 1
heikin['buy_price'] = 0 # 평단가
heikin['condtion_happen'] = 0
heikin['dr'] = 1
heikin["trading_number"] = 0
heikin["win"] = 0
heikin["lose"] = 0

k, d = talib.STOCHRSI(df['close'])

 

 

위에서 정한 매매 조건으로 백테스팅을 진행합니다.

stop_profit = 1.03
stop_loss = 0.985

for i in range(1,count):
    if heikin.iloc[i-1,6] == False: # buy == false
       
        # 첫번째 조건 # 200일 이평선 위에 있음
        if heikin.iloc[i,1] > heikin.iloc[i,5]: 
            
            if heikin.iloc[i-1,10] == 0: # 두번째 조건 발생한 적 없으면

                # 두번째 조건 # k 가 d를 상향돌파, 과매도
                if (k[i-1] - d[i-1] <= 0 and k[i] - d[i] >= 0)  and k[i]<=20: 
                    heikin.iloc[i,10] = 1

                    # 세번째 조건 # 이후 5일 이내에 이전 양봉보다 몸통이 길고 아랫꼬리가 없는 양봉이 나오면 매수
                    if heikin.iloc[i-1,4] == 1 and heikin.iloc[i,4] == 1 and (heikin.iloc[i-1,1] - heikin.iloc[i-1,0]) < (heikin.iloc[i,1] - heikin.iloc[i,0]):
                        heikin.iloc[i,6] = True # 매수
                        heikin.iloc[i,9] = df.iloc[i,3]
        
            elif heikin.iloc[i-1,10] > 0 and heikin.iloc[i-1,10] < 6: # 두번째 조건 발생한 적 있음
                
                #세번째 조건 # 이후 5일 이내에 이전 양봉보다 몸통이 길고 아랫꼬리가 없는 양봉이 나오면 매수
                if heikin.iloc[i-1,4] == 1 and heikin.iloc[i,4] == 1 and (heikin.iloc[i-1,1] - heikin.iloc[i-1,0]) < (heikin.iloc[i,1] - heikin.iloc[i,0]):
                    heikin.iloc[i,6] = True # 매수
                    heikin.iloc[i,9] = df.iloc[i,3] # 금일 종가로 매수
                else:
                    heikin.iloc[i,10] = heikin.iloc[i-1,10] + 1

            else:
                heikin.iloc[i,10] = 0          

                    
    else: # buy == true
        if(heikin.iloc[i-1,8] < stop_profit and heikin.iloc[i-1,8] > stop_loss): # 기준 손익비
            heikin.iloc[i,6] = True
            heikin.iloc[i,9] = heikin.iloc[i-1,9] # 평단가
            heikin.iloc[i,8] = df.iloc[i,3]/heikin.iloc[i,9] # ror 현재 갖고 있는 포지션에 대한 수익률
            heikin.iloc[i,11] =  df.iloc[i,3] / df.iloc[i,0] # 금일 수익률 # 금일 종가/시가
           
        else: # 매도
            heikin.iloc[i,6] = False
            # heikin.iloc[i,8] = 1 # ror 최신화
            # heikin.iloc[i,9] = 0 # 평단가 초기화
            # heikin.iloc[i,11] = 1 # 금일 수익률


heikin['hpr'] = heikin['dr'].cumprod()   

     
for i in range(1,count):
    if heikin.iloc[i-1,6] == False and heikin.iloc[i,6] == True:
        heikin.iloc[i,12] = heikin.iloc[i-1,12] + 1
    else:
        heikin.iloc[i,12] = heikin.iloc[i-1, 12]

    if heikin.iloc[i-1,8] >= stop_profit: # 이겼을때
        heikin.iloc[i,13] = heikin.iloc[i-1,13]+1
        heikin.iloc[i,14] = heikin.iloc[i-1,14]
        
    elif heikin.iloc[i-1,8] <= stop_loss: #졌을때
        heikin.iloc[i,13] = heikin.iloc[i-1,13]
        heikin.iloc[i,14] = heikin.iloc[i-1,14]+1
    
    else:
        heikin.iloc[i,13] = heikin.iloc[i-1,13]
        heikin.iloc[i,14] = heikin.iloc[i-1,14]

 

 

결과를 plot 해줍니다.

import matplotlib.pyplot as plt
#heikin[['close', 'EMA_200']].plot()
plt.figure(figsize=(10,8))
plt.plot(range(count), heikin['hpr']*df.iloc[200,0], label="hpr")
plt.plot(range(count), df['close'], label='index')
plt.plot(range(count), heikin['EMA_200'], label='ema200')
plt.xlim(200,count)
plt.legend()

 

hpr 파란 선이 누적 수익률이 됩니다. 결과가 매우 처참하네요.. 

유튜브 영상에서는 10만원이 6000만원이 된다고 했지만 백테스팅 결과는 정반대의 모습입니다.

제가 코드 속 오류를 범했을 수 도 있습니다. 댓글로 피드백해주시면 감사하겠습니다.

다음에 더 좋은 코드로 찾아뵙겠습니다.