gry1994tistorycom

BitcoinBacktest / 파이썬비트코인백테스트

Mar 9th, 2020
76
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.20 KB | None | 0 0
  1. # -*- coding: utf-8 -*-
  2. """
  3. Created on Thu Mar  5 21:02:35 2020
  4.  
  5. @author: grw19
  6. """
  7.  
  8. import pandas as pd
  9. import talib
  10. import time
  11. """
  12. 1. 데이터 불러오기
  13. 2. 지표 설정하기 (talib)
  14. 3. 매수 시점 결정하기 (조건 + 매수안한 상태일때만)
  15. 4. 매도 시점 결정하기 (조건 + 매수한 상태일때만)
  16. 5. 백테스트하기
  17. 6. 결과출력하기 (csv로 출력해서 엑셀로 분석)
  18.  
  19. """
  20.  
  21. class CoinBacktest :
  22.     def __init__(self):
  23.         self.df = pd.read_csv("C:/coding/coin/data/BTCUSDT_1hour.csv")
  24.         self.df['buy'] = 0
  25.         self.df['sell'] = 0
  26.         self.df['signal'] = 0
  27.         self.indicator = pd.DataFrame()
  28.         self.indicator['date'] = self.df['TotalTime']
  29.        
  30.     def cal_indicator(self) :
  31.         print("지표를 계산합니다...")
  32.         start_time = time.time()
  33.         self.indicator['sma3'] = talib.SMA(self.df['priceClose'], timeperiod=3)
  34.         self.indicator['3dis'] =  self.df['priceClose'] - self.indicator['sma3'] # 3시간 이격도
  35.        
  36.         print(time.time() - start_time , "소요, 지표 계산 완료...")
  37.    
  38.     def buy_signal(self) : # 조건 만족 시 매수열을 만들어서 0 -> 1로 설정
  39.         print("매수 시점을 계산합니다...")
  40.         start_time = time.time()
  41.        
  42.         for i in range(0,len(self.indicator)) :
  43.             if self.indicator['3dis'][i] >=0 : # 이격도 위 + 미보유시 매수
  44.                 print(i, "매수")
  45.                 self.df['buy'][i] = 1 # 매수 조건 성립 시 1을 대입
  46.                
  47.        
  48.         print(time.time() - start_time , "소요, 매수 시점 완료...")
  49.     def sell_signal(self) : # 조건 만족 시  매도행을 만들어서 0 -> 1로, 매수행은 1 -> 0으로 설정
  50.         print("매도 시점을 계산합니다...")
  51.         start_time = time.time()
  52.        
  53.         for i in range(0,len(self.indicator)) :
  54.             if self.indicator['3dis'][i] < 0  : # 매수중인상태로 이격도 아래에 있으면 매도
  55.                 print(i, "매도")
  56.                 self.df['sell'][i] = 1 # 매수 조건 성립 시 1을 대입        
  57.                
  58.        
  59.         print(time.time() - start_time, "소요, 매도 시점 완료...")    
  60.        
  61.     def backtest(self,df) :    
  62.         print("백테스트를 시작합니다...")
  63.         start_time = time.time()
  64.         FEE = 0.1 / 100 # 수수료 0.06% + 슬리피 0.04%로 0.1%로 설정 (매수매도합 0.02%)
  65.         money = 1000   # 초기 원금 1000달러로 설정
  66.         slot = 0 # 미보유시 0, 보유시 1
  67.        
  68.         buy_date_list = []
  69.         buy_price_list = []
  70.         amount_list = []
  71.         sell_date_list = []
  72.         sell_price_list = []        
  73.         money_list = []
  74.         result_list = []
  75.         for i in range(0,len(self.df)-1) : # 한줄 한줄 해줌
  76.             if self.df['buy'][i] == 1 and slot == 0 : # 매수시그널이 나왔고, 미 보유 중일 경우
  77.                 print("매수 진입...")
  78.                 slot = 1 # 보유 상태로 바꿔줌
  79.    
  80.                 buy_date = df['TotalTime'][i+1]
  81.                 buy_price = df['priceOpen'][i+1] # 시그널이 뜬 다음 시가에 매수
  82.                 amount = (money / buy_price) / (1+FEE)  # 매수 수량 : 시가 / 보유수량에서 수수료 고려
  83.                 buy_date_list.append(buy_date) # 날짜
  84.                 buy_price_list.append(buy_price) # 가격
  85.                 amount_list.append(amount) # 수량
  86.                
  87.             if self.df['sell'][i] == 1 and slot == 1 : # 매도시그널이 나왔고, 보유 중일 경우
  88.                 print("매도 청산...")
  89.                 slot = 0 # 미보유 상태로 바꿔줌
  90.                 sell_price = df['priceOpen'][i+1] # 매도 시그널이 뜬 다음 시가에 매도
  91.                 sell_date = df['TotalTime'][i+1]
  92.                 result = (sell_price / buy_price)
  93.                 money = money * result / (1+FEE) # 수량 * 수익률 / 수수료
  94.                 sell_date_list.append(sell_date)
  95.                 sell_price_list.append(sell_price)
  96.                 money_list.append(money)
  97.                 result_list.append(result)
  98.         if len(buy_date_list) > len(sell_date_list) : # 마지막 매수는 아직 보유 중임. 이건 그냥 잘라줌
  99.             del buy_date_list[-1]
  100.             del buy_price_list[-1]
  101.             del amount_list[-1]
  102.            
  103.        
  104.         result_data = {'buy_date': buy_date_list, 'buy_price': buy_price_list, 'amount': amount_list,'sell_date' : sell_date_list,
  105.                          'sell_price' : sell_price_list,'money' : money_list,'result' :result_list }
  106.         result_df = pd.DataFrame(result_data,
  107.                           columns=['buy_date', 'buy_price', 'amount', 'sell_date', 'sell_price', 'money', 'result'])
  108.  
  109.         result_df.to_csv("C:/coding/coin/result/backtest.csv", header = True, index = False) # csv파일로 저장  
  110.        
  111.  
  112. if __name__ == "__main__":
  113.     start_time = time.time()
  114.     backtest = CoinBacktest()
  115.     backtest.cal_indicator()
  116.     backtest.buy_signal()
  117.     backtest.sell_signal()
  118.     backtest.backtest(backtest.df)
  119.     print(time.time() - start_time , "소요, 백테스트 완료...")
Add Comment
Please, Sign In to add comment