소프트웨어에 대한 모든 것

변동성 돌파 전략 - 코인 30종목 수익률 백테스트 본문

카테고리 없음

변동성 돌파 전략 - 코인 30종목 수익률 백테스트

앤테바 2021. 12. 18. 22:56
반응형

안녕하세요. 

이전 글에서 변동성 돌파전략에 대해서 알아보고 간단한 코드를 통해서 변동성 돌파 전력의 수익률을 백테스팅 하였습니다. 이번에는 최근 거래대금 상위 30종목을 선정해서 변동성 돌파전략을 적용하고 기간수익률과 MDD가 어떻게 나오는지 살펴 보겠습니다.

 

그리고 이전 백테스트에서는 슬리피지와 업비트 수수료를 수수료에서 계산하지 않았는데요. 두 수수료를 수익률에서 반영하여 조금 더 정확한 기간수익률을 계산하도록 반영하였습니다.

 

변동성 돌파 전략을 전혀 모르신다면 이전 글을 먼저 참고해주세요.

 

2021.12.04 - [시스템 트레이딩/트레이딩 전략] - 변동성 돌파 전략 - 3초 만에 이해

 

변동성 돌파 전략 - 3초 만에 이해

변동성 돌파 전략 기본 래리 윌리암스 (Larry Williams)에 의해 고안됨 트렌드 추종을 기본으로 함. 상승하는 놈이 계속 상승한다!!! 전략이 굉장히 심플하지만 강력함 변동성 돌파 전략 핵심 돌파 가

wellsw.tistory.com

 

2021.12.04 - [시스템 트레이딩/트레이딩 전략] - 변동성 돌파 전략 - 비트코인 수익률 백테스트

 

변동성 돌파 전략 - 비트코인 수익률 백테스트

이전 글에서 변동성 돌파 전략에 대해서 기본적인 이론 지식을 습득하였습니다. 2021.12.04 - [시스템 트레이딩/트레이딩 전략] - 변동성 돌파 전략 - 3초 만에 이해 변동성 돌파 전략 - 3초 만에 이해

wellsw.tistory.com

 

 

이제 시작하겠습니다!!!

 

원화거래 가능 종목 조회

먼저 티커명을 조회합니다.

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

 

오히려 단순보유수익률이 더 좋은 종목도 꽤 있네요.

어떻게 변동성 돌파 전략의 기간수익률을 더 높일 수 있을까요?

어떤 보조지표를 추가 할 수 있을까요?

 

다음 글에서는 추가적인 방법을 통해서 변동성 돌파 전략의 기간수익률을 높이는 방법에 대해서 글을 공유하겠습니다.

반응형
Comments