본문 바로가기
파이썬/가상화폐

Python으로 비트코인 승률 67% 전략, 역추세 전략 , RSI(2) 백테스팅 구현 - 2

by 행복론자 2020. 5. 20.

지난글에 이어

RSI(2)를 이용한 역추세 전략을 보완할 수 있는 일종의 장치를 조금 넣어보고 수정한 코드입니다.

무엇을 추가할까 생각할 때 제일 먼저 생각난게 

 

1. 손절라인 

지난 전략은 당일 종가가 5일 이평선을 넘을 때만 매도하므로 매수한 이후 지구 멘틀까지 떨어져도 절대 팔지 않습니다. 그러니 매도 조건에 해당할 때까지(물려 있는 기간) 다른데 투자하지 못하므로 이또한 다른 투자기회를 잃어버리는 손실입니다.

또 전략의 원리 자체가 큰 폭락 이후 반등을 기대하는 방식입니다.

반대로 말하면 반등이 없다면 끝없는 하락이 이어질 수도 있기에 나와야된다고 생각해 손절라인을 넣었습니다.

너무 길지도, 짧지도 않게 매수후 1.5% 떨어질 때 무조건 청산 합니다.

사실 그 수치가 1.5이어야 한다하는 특별한 이유는 없습니다. 

제가 진짜 매매를 한다고 했을 때 견딜 수 있는 수치라고 생각한 것도 있고 결과만 놓고 봐서 괜찮은 수치라 선택했습니다. 

 

 

2. 과매수 구간 매도 RSI(2) > 70 or 80

14일 Base에 RSI 전략에는 과매수 구간에 파는 것이 좋다라고 하듯이 RSI(2)의 값이 너무 높아지면 매도하는 조건을 넣었는데, 이 조건은 사용해보니 큰 효과가 있지는 않지만 승률 및 손익비를 높이는데 효과가 아예 없지는 않았습니다.

 

아래는 위에 개선된 조건을 넣은 코드입니다.

import pybithumb
import pandas as pd
import numpy as np
from matplotlib import pyplot as plt

# 비트코인 BTC
df = pybithumb.get_ohlcv("BTC")

period = 2
date_index = df.index.astype('str')

U = np.where(df.diff(1)['close'] > 0, df.diff(1)['close'],0)  # df.diff를 통해 (기준일 종가 - 기준일 전일 종가)를 계산하여 0보다 크면 증가분을 감소했으면 0을 넣어줌
D = np.where(df.diff(1)['close'] < 0, df.diff(1)['close'] * (-1),0)  # df.diff를 통해 (기준일 종가 - 기준일 전일 종가)를 계산하여 0보다 작으면 감소분을 증가했으면 0을 넣어줌
AU = pd.DataFrame(U, index=date_index).rolling(window=period).mean()  # AU, period=2일 동안의 U의 평균
AD = pd.DataFrame(D, index=date_index).rolling(window=period).mean()  # AD, period=2일 동안의 D의 평균
RSI = AU / (AD + AU) * 100  # 0부터 1로 표현되는 RSI에 100을 곱함
df['U'] = U
df['D'] = D
df['AU'] = AU
df['AD'] = AD
df['RSI2'] = RSI
df['ma3'] = df['close'].rolling(window=3, min_periods=1).mean()
df['ma5'] = df['close'].rolling(window=5, min_periods=1).mean()
df['ma20'] = df['close'].rolling(window=20, min_periods=1).mean()
df['ma50'] = df['close'].rolling(window=50, min_periods=1).mean()
df['ma200'] = df['close'].rolling(window=200, min_periods=1).mean()

bid_price = 0
ask_signal = False
accum_profit = 0
accum_loss = 0
win_count = 0
lose_count = 0
profit = 0
start_cash = 1000000
cash = start_cash
daily_cash =[]

for i, row in df.iterrows():
    ma3, ma5, ma20, ma50, ma200 = row['ma3'], row['ma5'], row['ma20'], row['ma50'], row['ma200']
    open, close, rsi2 = row['open'], row['close'], row['RSI2']

    # 청산시점 확인
    if ask_signal:
        # print('3. sell at', i, end="\n \n")
        profit = (open - bid_price) / bid_price * 100

    # 매수조건 확인
    elif not bid_price and ma200 < close < ma3 and rsi2 < 20:
        # print('1. buy at', i)
        df.at[i, 'bid_price'] = close
        bid_price = close

    # 매도조건 확인
    elif bid_price:
        diff = (bid_price - close) / bid_price
        diff *= 100

        # 손절 선
        if diff > 1.5:
            profit = (close - bid_price) / bid_price * 100

        elif close > ma5:
            # print('2.1 sell signal at', i)
            ask_signal = True

        elif rsi2 > 80:
            # print('2.2 sell signal at', i)        
            profit = (close - bid_price) / bid_price * 100

    if profit:
        df.at[i, 'profit'] = profit
        bid_price = 0
        ask_signal = False

        # 수익거래
        if profit > 0:
            win_count += 1
            accum_profit += profit

        # 손실거래
        else:
            lose_count += 1
            accum_loss += profit

        cash *= 1 + profit / 100
        print(profit)

        profit = None

    daily_cash.append(cash)

df.to_csv('excel.csv')
trading_count = win_count + lose_count

CAGR = ((daily_cash[-1] / start_cash ) ** (1 / float( len(daily_cash) / 365)) - 1) * 100  # CAGR = (최종잔액/최초잔액) ^ (1/거래기간) - 1

print('1. 승리거래', win_count)
print('2. 패배거래', lose_count)
print('3. 매매승률', win_count / trading_count)
print('4. 수익총합', accum_profit)
print('5. 손실총합', accum_loss)
print('6. 전체합', accum_profit + accum_loss)
print('7. 수익평균', accum_profit / win_count)
print('8. 손실평균', accum_loss / lose_count)
print('9. CAGR', CAGR)
print('10. balance', cash)

 

 

다음은 최종 결과 및 수익률 그래프입니다.

 

 

 

 

눈여겨 볼 부분은 막상 전략을 수행해도 거래하지 않는 날이 정말 많습니다.

백테스트 기간인 2247일 동안 200번 가량 매매하고 사는 것은 고작 100번을 겨우 넘기니 시스템 트레이딩을 돌려서 사는 날이 눈에 띄게 적을 것입니다. 매수조건인 RSI(2)값을 더 작게 잡으면 더욱 낮은 거래빈도를 보입니다. 

이전 코드와 다르게 저는 RSI(2)값이 20보다 작은 경우로 조건을 잡아 그나마 더 매수의 기회가 있었습니다.

 

 

최종 잔액만 놓고 보면 나쁜 매매는 아니었다고 보지만 어디까지나 백테스팅이기도 하고 제일 문제는 아무것도 하지 않는 2년 가량의 세월이 미래에는 얼마나 더 길지 모르겠지만 확실히 나쁜 전략은 아닌 것 같습니다. 


같이 읽어보면 좋은 글

2022.12.27 - [파이썬/가상화폐] - [전자책] 바이낸스 코인선물자동매매 시스템 개발 방법을 담은 책이 출시되었습니다.

 

[전자책] 바이낸스 코인선물자동매매 시스템 개발 방법을 담은 책이 출시되었습니다.

🎁 바이낸스 자동매매 시스템 개발 방법을 담은 책이 출시되었습니다. "나 대신 일해주는 코인선물자동매매 프로그램 개발, 노하우 및 소스를 모두 공개합니다" ✔️ Q: 무슨 내용인가요? Python

jsp-dev.tistory.com

 

2022.11.05 - [파이썬/가상화폐] - [공지] 코인거래소별 프리미엄 체크봇 개발 가이드와 풀소스 전자책 | binance bybit | 업비트 김치프리미엄

 

[공지] 코인거래소별 프리미엄 체크봇 개발 가이드와 풀소스 전자책 | binance bybit | 업비트 김치프

https://kmong.com/gig/417785 거래소별 코인 프리미엄 알림봇 개발 가이드를 드립니다 | 36000원부터 시작 가능한 총 평점 5점의 3개 총 작업 개수 완료한 총 평점 5점인 JSDEV의 전자책, 투잡·재테크 전자

jsp-dev.tistory.com

 

 

반응형
이 포스팅은 쿠팡파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

댓글