가상화폐 투자마법 공식 발췌 (전체코드는 아래 파일에 있습니다)
지금까지는 가격 데이터만 가지고 전략을 확인해보았다. 하지만, 기술적분석에는 가격데이터뿐만 아니라 거래량 데이터도 있다!
거래량으로 주가를 해석하는 방법은 주로 다음과 같다.
가격 상승 | 거래량 증가 | 수요 축적 중 | 강세 |
가격 상승 | 거래량 감소 | 수요 감소 중 | 약세 |
가격 하락 | 거래량 증가 | 공급 상승 중 | 약세 |
가격 하락 | 거래량 감소 | 공급 소진 중 | 강세 |
잠잠했던 주식 또는 가상화폐의 가격이 오르고 거래량도 같이 오르면 상승장이 꺾이지 않고 지속될 가능성이 높다. 하지만, 가격이 오르는데 거래량이 많지 않으면 상승 추세가 곧 꺾이고 횡보할 가능성이 있다. 비슷하게, 가격은 떨어지는데 거래량이 증가하면 파는 사람이 많아지므로 급락장이 될 수 있다.
위 논리를 가지고 백테스팅을 진행해보자.
투자대상 : 비트코인(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
'가상화폐 퀀트 전략' 카테고리의 다른 글
트레이딩 전략 13 : 다자 가상화폐 + 평균 노이즈 비율 (0) | 2022.05.09 |
---|---|
트레이딩 전략 13 : 평균 노이즈 비율 + 마켓타이밍 + 변동성 돌파 (0) | 2022.04.13 |
트레이딩 전략 11 : 슈퍼상승장 + 변동성 돌파 + 변동성 조절(MDD 5% 이하) (0) | 2022.04.11 |
트레이딩 전략 10 : 상승장 + 변동성 돌파 + 변동성 조절(MDD 5% 이하) (0) | 2022.04.11 |
트레이딩 전략 9 : 다자 가상화폐 + 상승장 + 변동성 돌파 (1) | 2022.04.11 |
댓글