지난글에 이어
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 - [파이썬/가상화폐] - [전자책] 바이낸스 코인선물자동매매 시스템 개발 방법을 담은 책이 출시되었습니다.
2022.11.05 - [파이썬/가상화폐] - [공지] 코인거래소별 프리미엄 체크봇 개발 가이드와 풀소스 전자책 | binance bybit | 업비트 김치프리미엄
'파이썬 > 가상화폐' 카테고리의 다른 글
업비트 API 특정IP에서만 실행 설정방법 (GCP에서 사용) (2) | 2021.05.19 |
---|---|
가상화폐거래소 업비트 Open API Key 발급 받는법 (1) | 2021.02.23 |
Python으로 비트코인 승률 67% 전략, 역추세 전략 , RSI(2) 백테스팅 구현 - 1 (1) | 2020.05.17 |
Python으로 Larry Williams의 변동성 돌파 전략 백테스팅 - 4 / 비트코인 / 가상화폐 자동매매 / 변동성 조절 / pybithumb / 빗썸 / noise / 노이즈 (9) | 2020.03.10 |
Python으로 Larry Williams의 변동성 돌파 전략 백테스팅 - 3 / 비트코인 / 가상화폐 자동매매 / 변동성 조절 / pybithumb / 빗썸 (3) | 2020.03.09 |
댓글