일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- binary search
- python Leetcode
- python sorted
- 코틀린기초
- 릿코드풀이
- python 알고리즘
- 알고리즘풀기
- python zip_longest
- leetcode풀이
- python 릿코드
- 잇츠디모
- 릿코드풀기
- 릿코드 파이썬
- 릿코드 풀기
- 파이썬릿코드
- 상가수익률계산기
- 파이썬릿코드풀기
- python xor
- 파이썬 알고리즘
- leetcode 풀기
- leetcode풀기
- 파이썬 알고리즘 풀기
- LeetCode
- 파이썬 릿코드
- 파이썬 프로그래머스
- 알고리즘풀이
- 릿코드
- 파이썬알고리즘
- 파이썬알고리즘풀기
- python priority queue
- Today
- Total
소프트웨어에 대한 모든 것
변동성 돌파 전략 - 코인 30종목 수익률 백테스트 본문
안녕하세요.
이전 글에서 변동성 돌파전략에 대해서 알아보고 간단한 코드를 통해서 변동성 돌파 전력의 수익률을 백테스팅 하였습니다. 이번에는 최근 거래대금 상위 30종목을 선정해서 변동성 돌파전략을 적용하고 기간수익률과 MDD가 어떻게 나오는지 살펴 보겠습니다.
그리고 이전 백테스트에서는 슬리피지와 업비트 수수료를 수수료에서 계산하지 않았는데요. 두 수수료를 수익률에서 반영하여 조금 더 정확한 기간수익률을 계산하도록 반영하였습니다.
변동성 돌파 전략을 전혀 모르신다면 이전 글을 먼저 참고해주세요.
2021.12.04 - [시스템 트레이딩/트레이딩 전략] - 변동성 돌파 전략 - 3초 만에 이해
2021.12.04 - [시스템 트레이딩/트레이딩 전략] - 변동성 돌파 전략 - 비트코인 수익률 백테스트
이제 시작하겠습니다!!!
원화거래 가능 종목 조회
먼저 티커명을 조회합니다.
fiat를 'KRW'로 지정해서 원화 거래 가능한 비트코인명만 얻어옵니다.
import pandas as pd
import numpy as np
import pyupbit
# 업비트 원화 거래 가능한 티커명 조회
ticker_names = pyupbit.get_tickers(fiat='KRW')
len(ticker_names)
2021년 12월 기준 109개의 원화 거래 가능한 코인이 업비트에서 조회가 됩니다.
109
일봉 데이터 다운로드
import time
# 일봉 데이터 다운로드
for ticker_name in ticker_names:
print(f'download {ticker_name}')
df = pyupbit.get_ohlcv(ticker_name)
df.to_csv(f'{ticker_name}.csv', encoding='cp949')
time.sleep(0.3)
거래대금 상위 30 종목만 리스트업
# 거래대금 정보 가져오기
tickers = []
for ticker_name in ticker_names:
filename = f'{ticker_name}.csv'
df = pd.read_csv(filename)
yesterday = df.iloc[-2]
tickers.append([ticker_name, yesterday['value']])
# 거래대금 상위 30개의 종목만 리스트업
top_k = 30
tickers = sorted(tickers, key=lambda x: x[1], reverse=True)
tickers = tickers[:top_k]
tickers
[['KRW-BORA', 686441955624.2686],
['KRW-BTC', 529378851668.7005],
['KRW-ETH', 335791783208.3432],
['KRW-SAND', 266026078543.17288],
['KRW-XRP', 250206084897.09152],
['KRW-GRS', 227633992828.0536],
['KRW-MATIC', 150205139780.61484],
['KRW-STORJ', 106420786942.7539],
['KRW-WAVES', 101661483238.50217],
['KRW-DOGE', 100092653125.45544],
['KRW-SOL', 94269121538.39432],
['KRW-WAXP', 90389281486.9285],
['KRW-BTT', 72999931536.37553],
['KRW-STX', 70909495522.37938],
['KRW-HUM', 68570786692.9694],
['KRW-TRX', 62625592958.028336],
['KRW-NEAR', 58010338203.62962],
['KRW-MLK', 55810862370.63876],
['KRW-PLA', 54179296169.85761],
['KRW-MANA', 54123033986.506966],
['KRW-BAT', 48252696848.42273],
['KRW-HIVE', 38179822649.9082],
['KRW-STPT', 37613986332.38828],
['KRW-EOS', 37255084666.01415],
['KRW-VET', 34780860400.33291],
['KRW-ARK', 31913767520.62695],
['KRW-AQT', 31867977831.11085],
['KRW-DOT', 30615446954.6888],
['KRW-ADA', 30451872572.78372],
['KRW-ETC', 27749565313.069084]]
코인 클래스 정의
코인별 정보를 저장하기 위한 클래스를 정의합니다.
class Coin:
def __init__(self, ticker_name):
# 티커명
self.ticker_name = ticker_name
# 단순 보율 수익률
self.simple_hpr = 0
self.k = 0
# 변동성 돌파 전략 적용한 기간수익률
self.hpr = 0
# 최대 낙폭
self.mdd = 0
# 승
self.win_count = 0
# 패
self.lose_count = 0
def get_winning_rate(self):
return self.win_count / (self.win_count+self.lose_count)
def __str__(self):
return f'{self.ticker_name}, k : {self.k:.2f}, 기간수익률 : {self.hpr:.2f}, MDD : {self.mdd:.2f}, 단순보유수익률 : {self.simple_hpr:.2f}'
변동성 돌파 전략 함수 구현
티커명(코인명)을 break_out()에 전달하면 일봉 데이터 파일을 읽어서 기간수익률이 가장 높게 나오는 최적의 k를 찾고 Coin을 리턴합니다. 수익률 계산시 슬리피지와 업비트 수수료를 반영하였습니다.
from math import inf
def break_out(ticker_name):
coin = Coin(ticker_name)
filename = f'{ticker_name}.csv'
df = pd.read_csv(filename)
best_k = 0
best_df = None
# 단순 보유 수익률
coin.simple_hpr = df.iloc[-1]['close'] / df.iloc[0]['close']
# 변동성 크기
df['range'] = (df['high'] - df['low']).shift(1)
for k in np.arange(0.1, 0.9, 0.01):
# 목표가
df['target_price'] = df['open'] + df['range'] * k
df['buy'] = np.where((df['high'] > df['target_price']), 1, 0)
# 슬리피지 + 업비트 매도/매수 수수료 (0.05% * 2)
fee = 0.002 + 0.001
# buy가 1이면, 수익률 = 종가/목표가 - 수수료
# buy가 0이면, 수익률 = 1
# ror = Rate of Return
df['ror'] = np.where(df['buy'] == 1,
df['close'] / df['target_price'] - fee, 1)
# hpr (Holding Period Return)
df['hpr'] = df['ror'].cumprod()
# MDD (MAximum Draw Down)
# MDD = (high - low) / high * 100
df['dd'] = (df['hpr'].cummax() - df['hpr']) / df['hpr'].cummax() * 100
# 승
df['win'] = np.where(df['ror'] > 1, 1, 0)
# 패
df['lose'] = np.where(df['ror'] < 1, 1, 0)
# 기간수익률
if coin.hpr < df.iloc[-1]['hpr']:
best_df = df.copy()
coin.k = k
coin.hpr = df.iloc[-1]['hpr']
coin.mdd = df['dd'].max()
coin.win_count = df['win'].sum()
coin.lose_count = df['lose'].sum()
new_filename = f'{ticker_name}_best.csv'
best_df.to_csv(new_filename)
return coin
30개 코인 종목에 대해서 변동성 돌파전략 적용
coins = []
for ticker in tickers:
coin = break_out(ticker[0])
coins.append(coin)
# 기간수익률 기준 내림차순 정렬
coins.sort(key=lambda x: x.hpr, reverse=True)
# 출력
for coin in coins:
print(coin)
기간수익률이 높은 순으로 오름차순 정렬하였습니다.
KRW-BORA, k : 0.10, 기간수익률 : 8.99, MDD : 60.25, 단순보유수익률 : 6.85
KRW-SAND, k : 0.10, 기간수익률 : 7.29, MDD : 43.99, 단순보유수익률 : 15.82
KRW-HIVE, k : 0.13, 기간수익률 : 7.07, MDD : 40.39, 단순보유수익률 : 3.56
KRW-STPT, k : 0.10, 기간수익률 : 4.56, MDD : 53.12, 단순보유수익률 : 2.20
KRW-HUM, k : 0.22, 기간수익률 : 4.06, MDD : 30.71, 단순보유수익률 : 3.92
KRW-ARK, k : 0.10, 기간수익률 : 2.99, MDD : 28.07, 단순보유수익률 : 1.03
KRW-MANA, k : 0.22, 기간수익률 : 2.81, MDD : 39.99, 단순보유수익률 : 3.89
KRW-WAXP, k : 0.15, 기간수익률 : 2.42, MDD : 50.35, 단순보유수익률 : 3.14
KRW-PLA, k : 0.26, 기간수익률 : 2.38, MDD : 58.15, 단순보유수익률 : 5.49
KRW-STORJ, k : 0.10, 기간수익률 : 1.75, MDD : 47.82, 단순보유수익률 : 1.56
KRW-STX, k : 0.41, 기간수익률 : 1.67, MDD : 25.84, 단순보유수익률 : 2.15
KRW-GRS, k : 0.10, 기간수익률 : 1.58, MDD : 39.79, 단순보유수익률 : 0.95
KRW-AQT, k : 0.38, 기간수익률 : 1.43, MDD : 42.12, 단순보유수익률 : 1.19
KRW-BAT, k : 0.10, 기간수익률 : 1.40, MDD : 37.41, 단순보유수익률 : 1.51
KRW-BTT, k : 0.71, 기간수익률 : 1.35, MDD : 24.23, 단순보유수익률 : 0.73
KRW-MATIC, k : 0.22, 기간수익률 : 1.35, MDD : 18.34, 단순보유수익률 : 1.28
KRW-BTC, k : 0.30, 기간수익률 : 1.30, MDD : 14.06, 단순보유수익률 : 1.31
KRW-VET, k : 0.60, 기간수익률 : 1.28, MDD : 16.63, 단순보유수익률 : 0.69
KRW-ETH, k : 0.27, 기간수익률 : 1.26, MDD : 18.95, 단순보유수익률 : 1.51
KRW-ADA, k : 0.48, 기간수익률 : 1.26, MDD : 19.02, 단순보유수익률 : 0.74
KRW-DOT, k : 0.67, 기간수익률 : 1.24, MDD : 14.77, 단순보유수익률 : 1.02
KRW-SOL, k : 0.59, 기간수익률 : 1.19, MDD : 7.89, 단순보유수익률 : 1.08
KRW-DOGE, k : 0.63, 기간수익률 : 1.11, MDD : 17.93, 단순보유수익률 : 0.43
KRW-MLK, k : 0.72, 기간수익률 : 1.10, MDD : 31.98, 단순보유수익률 : 1.03
KRW-XRP, k : 0.40, 기간수익률 : 1.03, MDD : 39.89, 단순보유수익률 : 0.84
KRW-WAVES, k : 0.12, 기간수익률 : 1.01, MDD : 53.68, 단순보유수익률 : 1.26
KRW-NEAR, k : 0.10, 기간수익률 : 1.00, MDD : 0.00, 단순보유수익률 : 0.82
KRW-EOS, k : 0.35, 기간수익률 : 0.98, MDD : 28.51, 단순보유수익률 : 0.53
KRW-ETC, k : 0.73, 기간수익률 : 0.97, MDD : 15.36, 단순보유수익률 : 0.54
KRW-TRX, k : 0.75, 기간수익률 : 0.92, MDD : 15.85, 단순보유수익률 : 1.09
오히려 단순보유수익률이 더 좋은 종목도 꽤 있네요.
어떻게 변동성 돌파 전략의 기간수익률을 더 높일 수 있을까요?
어떤 보조지표를 추가 할 수 있을까요?
다음 글에서는 추가적인 방법을 통해서 변동성 돌파 전략의 기간수익률을 높이는 방법에 대해서 글을 공유하겠습니다.