현명한 투자자라면 자신의 알고리즘을 무작정 전투에 내보내기전에 과거데이터를 이용해 수익률을 확인할 것이다. 물론 과거 데이터에 대한 수익이 무조건 보장되진않는다.
✏️ 과거데이터 추출
get_ohlcv
pastPrice = pyupbit.get_ohlcv(ticker,interval='minutes30', count=1000)
코드를 실행시키는 시간부터 1000분전까지의 30분간격의 데이터를 불러와 pastPrice변수에 저장한다.
1분봉, 3분봉, 5분, 15분 등의 데이터는 minutes1, minutes3, minutes5 이런식으로 바꿔주면 된다.
pastPrice를 출력때려보면 이런게 나온다.
필요한걸 뽑아내려면 어떻게 다듬어야할까? 우선 저게 뭔지 보자. print(type(pastPrice))
'pandas.core.frame.DataFrame'
판다스 데이터프레임이다. 난 복잡한 데이터가 필요한 것도 아니고 판다스에 익숙하지 않아서 저걸 그냥 리스트로 바꿔서 필요한 것만 뽑아쓰려한다.
판다스를 리스트로 만글기위해서는 values 속성을 이용해서 DataFrame을 ndarray로 변환하고 tolist()로 리스트변환하면 된다.
pastPrice = pyupbit.get_ohlcv(ticker,interval='minutes30', count=1000)
pastPrice_to_list=pastPrice.values.tolist()
요런 느낌으로. 이제 알아서 손질해서 필요한 데이터를 만들면 된다.
✏️ 업비트 만들기?
데이터는 준비됐는데 백테스팅을 위해서 실제 업비트를 쓸수는 없다. 업비트의 계좌 형식과 필요한 주요메서드를 구현했다.
class Upbit:
def __init__(self, ticker: str):
self.balances=[
{
'currency':'KRW',
'balance': 1000000.0,
'avg_buy_price': 0.,
},
{
'currency': ticker,
'balance': 0.,
'avg_buy_price': 0.,
},
] # 보유 현금과 코인 정보
self.fee = 0.0005 # 거래 수수료
def get_balances(self): # 잔고호출
return self.balances
# def get_avg_buy_price(self, ticker):
# return self.balances[ticker]['avg_buy_price']
def buy_market_order(self, ticker: str, price: float, nowPrice: float) -> bool:
# price는 매수가가 아니라 매수할 총금액
if price <=5000:
print('KRW 5000 이상부터 매수가 가능합니다.')
return False
# 수수료 고려
total_price = price*(1+self.fee)
# 잔고
balance = self.get_balances()[0]["balance"]
# 잔고부족
if balance < total_price:
print(f'잔고가 부족합니다. 현재 KRW잔고: {balance}원, 필요금액: {total_price}원')
return False
# 거래액만큼 현금잔고감소
self.get_balances()[0]["balance"] -= total_price
#volume: price로 살수 있는 코인의 수
volume = price/nowPrice
# 거래한 코인의 평단가 계산, 추매량 만큼 잔고 증가
method = self.get_balances()
method[1]['avg_buy_price'] = method[1]['balance'] * method[1]['avg_buy_price'] + price
method[1]['balance'] += volume
method[1]['avg_buy_price'] /= method[1]['balance']
return True
def sell_market_order(self, ticker: str, volume: float, nowPrice: float) -> bool:
# 수수료 고려
total_price = nowPrice*volume*(1-self.fee)
# 코인수 부족
method = self.get_balances()
if method[1]['balance'] < volume:
return False
# 잔고변화
method[0]['balance'] += total_price
method[1]['balance'] -= volume
return True
buy_market_order()는 원래 ticker와 price를 매개변수로 가지지만 여기선 현재가 계산을 위해서 nowPrice를 변수로 넣어주았다. 과거 nowPrice데이터를 리스트로 받아온 후 반복문으로 로직을 돌릴 것이다.
✏️ 백테스트
나는 10분봉을 이용해 계산을 했다. 10000개의 데이터를 가지고 테스트 했으니 대략 69일정도 테스트를 했다고 계산. 69일간 약 6.62 %의 수익(POR)을 얻었다. 104일간 테스트했을때는 약 13%의 수익을, 내 남은 군생활인 500일간 테스트했을때는 64%의 수익을 얻었다.
POR 계산은 다음과 같이 했다.
def POR(self, value, initial):
ROI = (value-initial)/initial
POR = ROI*100
return POR
다음 포스트에서는 계속 매매가 진행될 수 있도록 AWS 서버를 생성하고 프로그램을 작동시켜보도록하겠다. 이틀 후면 부대복귀다.
✏️ 백테스트 주의점
백테스트를 진행하면서 분명 수익률을 높히고자 변수를 이것저것 바꿔본다던가 조정을 가할 것이다. 하지만 과한 조정은 과적합 (overfitting)이 될 수 있다. 과거 데이터에 대한 시뮬레이션 결과를 좋게하고자 과한 튜닝을 한다해서 실제결과에도 같은 결과를 가져올 것이란 보장이 없다는 것을 인지해야한다. 지금 하고 있는 튜닝이 과거 데이터에 대한 튜닝인지 인지해라.
'주식 > 자동매매' 카테고리의 다른 글
[2] 파이썬으로 업비트 거래하기 (0) | 2022.03.02 |
---|---|
[1] 파이썬으로 코인 자동매매하기 (0) | 2022.03.02 |