이전 글 - 코인 종목 선정 하기

 

1. 백테스팅 전 기본 세팅

먼저, 투자 과정과 최종 결과를 알아보기 위해 아래의 내용을 세팅한다.

  • 시작 금액
  • 종료 금액
  • 수익이 발생한 날들의 수
  • 손실이 발생한 날들의 수
  • 최대 수익 비율 (%)
  • 최대 손실 비율 (%)
  • 코인 별 투자 이력

이를 코드로 작성해보자

class Back_Testing:
    def __init__(self, seed, duration):
        self.duration = [] # 테스트 기간
		
        # 시작과 종료 금액
        self.start_seed = seed
        self.end_seed = seed

		# 수익과 손실 기간
        self.revenu_count = 0
        self.loss_count = 0

		# 최대 수익과 손실 비율
        self.max_revenu_ratio = -math.inf
        self.max_loss_ratio = math.inf

        self.coin_history = {}
        self.error = 0
        self.start_date = datetime.datetime.now()

        for day in range(duration, 0, -1):
            self.duration.append(self.start_date - datetime.timedelta(days=day) - datetime.timedelta(days=1))

투자 시작 금액과 투자 기간을 받아서 181일 전 부터 전일 까지 테스트를 시작하도록 self.duration 에 리스트로 받는다.

 

2. 시뮬레이션 설명과 코드

텍스트 기간을 순회하며 이전 글에서 작성했던 함수를 통해 투자할 코인 종목을 최대  n개 반환한다.

1. 투자 대상의 코인의 예상 저가와 저가를 비교한다 이때, 실제 저가가 예상 저가보다 낮거나 같으면

해당 일에 투자를 진행한 것으로 간주한다.

2. 실제 고가가 예상 고가보다 높게 기록된 경우, 예상 고가에 판 것으로 간주하고 수익을 계산한다.

3. 실제 고가가 예상 보가보다 낮게 기록된 경우, 종가에 판 것으로 간주하고 수익을 계산한다.

def simulate(self):
        for day in self.duration:
            coin_list = check_bull_market(day, 5) # 투자 코인 5개 설정
            check_win = self.end_seed

            if len(coin_list) == 0:
                print("오늘은 투자 할 대상이 없습니다.")
            
            for coin in coin_list:
                coin_seed = int(self.end_seed / len(coin_list))
                after_coin_seed = 0

                pre_high, pre_low = coin_list[coin]["high"], coin_list[coin]["low"]

                self.end_seed -= coin_seed

                if coin not in self.coin_history:
                    self.coin_history[coin] = 0

                time.sleep(0.5)
                chart = pyupbit.get_ohlcv_from(ticker = coin, fromDatetime = day - datetime.timedelta(days=1), to = day)
                
                invest_status = False
                
                if chart is None:
                    self.error += 1
                    self.end_seed += coin_seed
                    continue
                
                high_price = chart["high"].iloc[-1]
                low_price = chart["low"].iloc[-1]
                close_price = chart["close"].iloc[-1]

                if low_price <= pre_low:
                    invest_status = True
                    
                    if high_price >= pre_high:
                        variance =  (pre_high - pre_low) / pre_low
                        
                    else:
                        variance =  (close_price - pre_low) / pre_low
                    
                    after_coin_seed = coin_seed + coin_seed * variance * 0.9995
                    
                self.end_seed += after_coin_seed if invest_status else coin_seed
                self.coin_history[coin]  += after_coin_seed - coin_seed if invest_status else after_coin_seed
                
            total_variance = round((self.end_seed - check_win) / check_win * 100, 2)
            self.max_revenu_ratio = max(self.max_revenu_ratio, total_variance)
            self.max_loss_ratio = min(self.max_loss_ratio, total_variance)

            if check_win < self.end_seed:
                self.revenu_count += 1
            
            elif check_win > self.end_seed :
                self.loss_count += 1

 

3. 유의 해야할 사항

위의 시나리오 2번 (실제 고가가 예상 고가보다 높은 경우)의 경우 실제 투자 시 다르게 작용 할 수 있다.

장 시작 (오전 9시) → 저가 → 고가 → 종가 순으로 가격이 움직이는 경우 2번 시나리오와 거의 유사하게 수익을 발생시키지만

다른 경우, 장 시작 → 고가 → 저가 → 종가 순으로 가격이 움직이는 경우 실제 수익은 백테스팅 수익과 다를 수 있다.

 

해당 편차를 해소하기 위해서는 해당 일자에 시간 단위로 데이터를 재 호출 한 다음 고가와 저가 순서를 파악한 후 계산해야 한다.

따라서 아래의 테스트 결과에는 해당 부분이 반영되지 않은 결과인 점을 감안해야 한다.

더 정확한 테스트를 원한다면 해당 방법을 사용해보길 권장한다.

 

4. 백테스팅 결과

테스트 기간: 180일
수익 기간: 89일
손실 기간: 31일

최대 수익률: 4.14%
최저 수익률: -4.92%

시작 금액 : 100,000
마감 금액 : 162,544
수익률: 62.54%

 

다음 글 - 코인 가격 비동기로 불러오기