본문 바로가기
가상화폐 퀀트 전략

트레이딩 전략 12 : 5일이동평균 & 5일 거래량 상승장 + 변동성 돌파 + 변동성 조절(MDD 5% 이하)

by TenMillionQuant 2022. 4. 11.

가상화폐 투자마법 공식 발췌 (전체코드는 아래 파일에 있습니다)

 

 

지금까지는 가격 데이터만 가지고 전략을 확인해보았다. 하지만, 기술적분석에는 가격데이터뿐만 아니라 거래량 데이터도 있다!

 

거래량으로 주가를 해석하는 방법은 주로 다음과 같다. 

 

가격 상승 거래량 증가 수요 축적 중 강세
가격 상승 거래량 감소 수요 감소 중 약세
가격 하락 거래량 증가 공급 상승 중 약세
가격 하락 거래량 감소 공급 소진 중 강세

 

잠잠했던 주식 또는 가상화폐의 가격이 오르고 거래량도 같이 오르면 상승장이 꺾이지 않고 지속될 가능성이 높다. 하지만, 가격이 오르는데 거래량이 많지 않으면 상승 추세가 곧 꺾이고 횡보할 가능성이 있다. 비슷하게, 가격은 떨어지는데 거래량이 증가하면 파는 사람이 많아지므로 급락장이 될 수 있다. 

 

위 논리를 가지고 백테스팅을 진행해보자. 

 

투자대상 : 비트코인(BTC), 라이트코인(LTC), 리플(XRP), 대시(DASH) 

투자기간 : 2017.06 ~ 2022.03

거래비용 : 0.2% 적용

투자전략

1. 각 화폐의 레인지 계산(전일 고가 - 전일 저가)

 

2. 조건 (둘 중 하나라도 낮을 경우 그날 투자 대상에서 제외)

    - 실시간 가격 > 당일 시가 + (레인지 x k) (여기서 K = 0.5 추천)

    - 전일 거래량 > 5일 거래량 이동평균

 

3. 매수 : 실시간 가격 > 당일 시가 + (레인지 x k) (여기서 K = 0.7 추천)

 

4. 돌파에 성공한 가상화폐는 가상화폐별 투입금액을 넣는다. (타깃 변동성 : 2%)

투입금액 : (타깃 변동성 / 전일 변동성) / 투자대상 가상화폐 수

 

5.  매도  : 다음날 시가

 

이제 해당 전략을 구현해보자. 

 

#필요한 데이터를 불러온다

import pybithumb
import pandas as pd
import numpy as np

 

BTC, LTC ETC, XRP중에서 시작일이 가장 최근인 가상화폐를 가지고 진행해보자.

 

# 비트코인, 라이트코인, 이더리움클래식, 리플을 가져오자
btc_df = pybithumb.get_ohlcv('BTC')
ltc_df = pybithumb.get_ohlcv('LTC')
etc_df = pybithumb.get_ohlcv('ETC')
xrp_df = pybithumb.get_ohlcv('XRP')

 

각 코인들의 5일이평선과 5일 가격 이평선 그리고 변동성을 구하자

 

# 각 코인들의 5일 가격 이평선을 구해보자
btc_df['ma_5'] = btc_df['close'].rolling(window=5).mean()
ltc_df['ma_5'] = ltc_df['close'].rolling(window=5).mean()
etc_df['ma_5'] = etc_df['close'].rolling(window=5).mean()
xrp_df['ma_5'] = xrp_df['close'].rolling(window=5).mean()

# 각 코인들의 5일 거래량 이동평균선을 구해보자
btc_df['ma_5_vol'] = btc_df['volume'].rolling(window=5).mean()
ltc_df['ma_5_vol'] = ltc_df['volume'].rolling(window=5).mean()
etc_df['ma_5_vol'] = etc_df['volume'].rolling(window=5).mean()
xrp_df['ma_5_vol'] = xrp_df['volume'].rolling(window=5).mean()

# 전날 거래량을 저장한다
btc_df['volume_shifted'] = btc_df['volume'].shift(1)
ltc_df['volume_shifted'] = ltc_df['volume'].shift(1)
etc_df['volume_shifted'] = etc_df['volume'].shift(1)
xrp_df['volume_shifted'] = xrp_df['volume'].shift(1)

# 변동성 구하기 = (전일 고가 - 전일 저가) / 전일 시가 x 100(백분율)
btc_df['high_shifted'] = btc_df['high'].shift(1)
btc_df['low_shifted'] = btc_df['low'].shift(1)
btc_df['open_shifted'] = btc_df['open'].shift(1)

btc_df['vol'] = ((btc_df['high_shifted'] - btc_df['low_shifted']) / btc_df['open_shifted']) * 100

# 변동성 구하기 = (전일 고가 - 전일 저가) / 전일 시가 x 100(백분율)
ltc_df['high_shifted'] = ltc_df['high'].shift(1)
ltc_df['low_shifted'] = ltc_df['low'].shift(1)
ltc_df['open_shifted'] = ltc_df['open'].shift(1)

ltc_df['vol'] = ((ltc_df['high_shifted'] - ltc_df['low_shifted']) / ltc_df['open_shifted']) * 100

# 변동성 구하기 = (전일 고가 - 전일 저가) / 전일 시가 x 100(백분율)
etc_df['high_shifted'] = etc_df['high'].shift(1)
etc_df['low_shifted'] = etc_df['low'].shift(1)
etc_df['open_shifted'] = etc_df['open'].shift(1)

etc_df['vol'] = ((etc_df['high_shifted'] - etc_df['low_shifted']) / etc_df['open_shifted']) * 100

# 변동성 구하기 = (전일 고가 - 전일 저가) / 전일 시가 x 100(백분율)
xrp_df['high_shifted'] = xrp_df['high'].shift(1)
xrp_df['low_shifted'] = xrp_df['low'].shift(1)
xrp_df['open_shifted'] = xrp_df['open'].shift(1)

xrp_df['vol'] = ((xrp_df['high_shifted'] - xrp_df['low_shifted']) / xrp_df['open_shifted']) * 100

 

시작일은 리플이 가장 최근이므로, 시작일의 기준은 리플로 한다. 

 

tickers_list = ['btc', 'ltc', 'etc', 'xrp']

start_date_list = [] # 데이터시작일 저장 리스트
end_date_list = [] # 마지막일 저장 리스트

for ticker in tickers_list:
    df = pybithumb.get_ohlcv(ticker)
    
    start_date_list.append(str(df.index[0]))
    end_date_list.append(str(df.index[-1]))
    
    print(ticker, start_date_list[-1], end_date_list[-1])
    
    # 리플 데이터가 가장 적으므로, 시작일을 리플로 기준을 잡자
ticker_df = pd.DataFrame({"tickers_list" : tickers_list, "start_date" : start_date_list, "end_date" : end_date_list})
ticker_df

 

데이터 클리닝을 진행한다. 데이터값이 NA인 행들은 삭제한다.

 

# 데이터가 없는 값들은 다 삭제한다

btc_df.dropna(inplace =  True)
ltc_df.dropna(inplace =  True)
etc_df.dropna(inplace =  True)
xrp_df.dropna(inplace =  True)

# 시작일은 리플 시작일로 설정하고, 다른 코인도 다 그날에 시작하게 바꾸자
start_date = xrp_df.index[0]

btc_df = btc_df[btc_df.index >= start_date]
ltc_df = ltc_df[ltc_df.index >= start_date]
etc_df = etc_df[etc_df.index >= start_date]
xrp_df = xrp_df[xrp_df.index >= start_date]

# 전일 고가를 shifted_high, 전일 저가를 shifted_low에 저장한다
btc_df['shifted_high'] = btc_df['high'].shift(1)
btc_df['shifted_low'] = btc_df['low'].shift(1)
btc_df['range'] = btc_df['shifted_high'] - btc_df['shifted_low']

ltc_df['shifted_high'] = ltc_df['high'].shift(1)
ltc_df['shifted_low'] = ltc_df['low'].shift(1)
ltc_df['range'] = ltc_df['shifted_high'] - ltc_df['shifted_low']

etc_df['shifted_high'] = etc_df['high'].shift(1)
etc_df['shifted_low'] = etc_df['low'].shift(1)
etc_df['range'] = etc_df['shifted_high'] - etc_df['shifted_low']

xrp_df['shifted_high'] = xrp_df['high'].shift(1)
xrp_df['shifted_low'] = xrp_df['low'].shift(1)
xrp_df['range'] = xrp_df['shifted_high'] - xrp_df['shifted_low']

# 데이터가 없는 값들은 다 삭제한다

btc_df.dropna(inplace =  True)
ltc_df.dropna(inplace =  True)
etc_df.dropna(inplace =  True)
xrp_df.dropna(inplace =  True)

# 데이터 수가 다 동일한지 확인한다
len(btc_df), len(ltc_df), len(etc_df), len(xrp_df)

 

이제 투자전략을 백테스팅해보자. 

 

total_capital = 100000000 # # 전체 투자금액, 처음 시드머니 1억
fee = 0.002 # 수수료 0.2%
k = 0.5

df_list = [btc_df, ltc_df, etc_df, xrp_df]
total_capital_list = []

n = 4

target_vol = 2 # 타겟변동성

for i in range(len(btc_df)):
    
    # 실시간 가격 > (당일 시가 + (레인지 x k)) 인지 확인한다 .
    # 확인하는 방법은 고가가 (당일 시가 + (레인지 x k))보다 크면 돌파, 작으면 돌파 실패를 의미한다
    # 가상화폐별로 확인을 한다
    
    buy_sell_price_list = [] # 돌파하게 되면, 매수/매도하는 가격 리스트
    
    vol_list = []
    
    for df in df_list:
        open_price = df.iloc[i]['open'] # 당일 시가
        high_price = df.iloc[i]['high'] # 당일 고가
        close_price = df.iloc[i]['close'] # 당일 종가 : 사실 당일 종가가 다음날 시가와 동일하므로 종가를 사용한다
        ma_5_price = df.iloc[i]['ma_5'] # 5일가격이평선
        ma_5_volume = df.iloc[i]['ma_5_vol'] # 5일거래량이평선
        volume = df.iloc[i]['volume_shifted'] # 전날 거래량
        
        # 타겟 가격 
        target_price = open_price + df.iloc[i]['range'] * k
        
        # 만약 시초가가 5일가격이평선보다 크고, 전날 거래량이 5일거래량이평선보다 크다면 
        if (open_price >= ma_5_price) and (volume >= ma_5_volume):

            # 만약 고가가 타겟 가격보다 크다면, 즉 장 중에 돌파 성공했다면, 
            if high_price >= target_price:
                
                 # 만약 타깃변동성 / 특정 화폐의 변동성이 1보다 크면 1로 세팅한다
                vol_invested = (target_vol / df.iloc[i]['vol'])

                if vol_invested >= 1:
                    vol_invested = 1
                
                vol_list.append(vol_invested / n)
                buy_sell_price_list.append([target_price, close_price])
    
                
    # 돌파에 성공한 가상화폐에 자산의 N분의 1 투입    
    vol_sum = sum(vol_list)

    # 임시 총자산 => 현금
    temp_total_capital = (1 - vol_sum) * total_capital

    for (buy_price, sell_price), vol_invested in zip(buy_sell_price_list, vol_list):

        # 자산의 N분의 1 투입
        coin_invested = total_capital * (vol_invested)

        # 매도금액을 매수금액으로 나누면 수익률이나오고, 거기에 수수료를 차감 후 투자금액을 곱하면 얻게 되는 금액이 나온다
        temp_total_capital += (sell_price / buy_price) * (1 - fee * 2) * coin_invested

    total_capital = temp_total_capital

    total_capital_list.append(total_capital)
    print(btc_df.index[i], total_capital, vol_sum)

 

이제 수익률 mdd를 확인해보자. 수익률은 -35%(.....)이고 mdd도 -35%이다.. 그래도 이전 전략보다는 방어를 해주었다. (이전 전략 : -45%)

 

 

트레이딩 전략 11 : 슈퍼상승장 + 변동성 돌파 + 변동성 조절(MDD 5% 이하)

가상화폐 투자마법 공식 발췌 (전체코드는 아래 파일에 있습니다) 이젠 지금까지 배워던 모든 조건들을 다 적용해보자. 변동성돌파, 변동성 조절, 슈퍼상승장 이 세가지 조건을 가지고 진행

tenmillionquant.tistory.com

 

ror_df = pd.DataFrame({ "total_capital" : total_capital_list}, index = btc_df.index)

ror_df['ror'] = ror_df['total_capital'].pct_change() + 1
ror_df['cum_ror'] = ror_df['ror'].cumprod()

ror_df

# 전 고점(HWM : High Water Mark)
ror_df['highwatermark'] =  ror_df['cum_ror'].cummax()
ror_df['drawdown'] = (ror_df['cum_ror'] / ror_df['highwatermark']) - 1

# mdd를 구한다
ror_df['max_drawdown'] = ror_df['drawdown'].cummin()

print(f"수익률 : ", (ror_df.iloc[-1]['cum_ror'] - 1) * 100 )
print("mdd : ", ror_df.iloc[-1]['max_drawdown'] * 100)

import matplotlib.pyplot as plt

plt.plot(ror_df['cum_ror'])
수익률 :  -34.00503793285642
mdd :  -34.045394113239624

 

댓글