def backTest(self): ''' Function that used to do back-testing based on the strategy you give Params: None Notes: this back-test function will move on minute bar and generate your strategy detail dataframe by using the position vectors your strategy gives each minute ''' format1 = h5py.File(self.data_format1_path, mode='r') format2 = h5py.File(self.data_format2_path, mode='r') assets = list(format1.keys()) keys = list(format2.keys()) for i in range(len(keys)): data_cur_min = format2[keys[i]][:] # 1. initialization if i == 0: total_balance = self.init_cash average_price_old = np.mean(data_cur_min[:, :4], axis=1) position_old = np.repeat(0., 4) position_new = np.repeat(0., 4) details = list() stop_signal = False # 2. calculate position & cash/crypto/total balance & transaction cost etc. position_change = position_new - position_old mask = np.abs(position_change) > .25 * data_cur_min[:, 4] position_change[mask] = (.25 * data_cur_min[:, 4] * np.sign(position_change))[mask] position_new = position_old + position_change average_price = np.mean(data_cur_min[:, :4], axis=1) transaction_cost = np.sum( np.abs(position_change) * average_price * self.commissionRatio) revenue = np.sum( position_old * (average_price - average_price_old)) - transaction_cost crypto_balance = np.sum(np.abs(position_new * average_price)) total_balance = total_balance + revenue cash_balance = total_balance - crypto_balance detail = np.append( position_new, list(average_price) + [ cash_balance, crypto_balance, revenue, total_balance, transaction_cost ]) details.append(copy.deepcopy(detail)) position_old = copy.deepcopy(position_new) average_price_old = copy.deepcopy(average_price) # 3. check special cases # if cash balance is less than lower limit, the program will stop all trading actions in the future if (cash_balance < self.cash_balance_lower_limit) and (stop_signal == False): stop_signal = True print("Current cash balance is lower than", self.cash_balance_lower_limit) print("Your strategy is forced to stop") print( "System will soon close all your positions (long and short) on crypto currencies" ) if stop_signal: position_new = np.repeat(0., 4) if '09:30:00' in keys[i]: print(keys[i][:10]) continue # Update position and memory [position_new, self.memory ] = handle_bar(i, keys[i], data_cur_min, self.init_cash, self.commissionRatio, cash_balance, crypto_balance, total_balance, position_new, self.memory) # Update position and timer if '09:30:00' in keys[i]: print(keys[i][:10]) detailCol = assets + [s + '_price' for s in assets] + [ "cash_balance", "crypto_balance", "revenue", "total_balance", "transaction_cost" ] detailsDF = pd.DataFrame(details, index=pd.to_datetime(keys), columns=detailCol) format1.close() format2.close() return detailsDF
def backTest(self): ''' Function that used to do back-test based on the strategy you give Params: None Notes: this back-test function will move on minute bar and generate your strategy detail dataframe by using the position matrix your strategy gives each minute Data: 1. Load futures information matrix and trading data during backtesting period 2. You can load different .h5 file by changing the path down below to paths like self.train_data_path or self.test_data_path so that you can test and train your own strategy on different periods 3. Try to make your strategy profitable and achieve stable return ''' info = pd.read_csv(self.info_path, encoding='utf-8') btData = h5py.File(self.data_format2_path, mode='r') keys = list(btData.keys()) # PnL initialization timer = 0 pnl = self.init_cash details = list() detail = [np.repeat(0.,13), self.init_cash, 0., 0., self.init_cash, 0.] lastPosition = np.repeat(0, 13) for i in range(len(keys)-1): # Data of current minute and next minute data_cur_min = btData[keys[i]][:] exe_cur_min = np.mean(data_cur_min[:,:4], axis=1) exe_next_min = np.mean(btData[keys[i+1]][:,:4], axis=1) # Update position and parameter [curPosition, self.memory] = handle_bar(timer, data_cur_min, info, self.init_cash, self.commissionRatio, detail, self.memory) # Calculate margin required and commission charged marginRequired = np.matmul(np.abs(curPosition), (exe_next_min * info.unit_per_lot * info.margin_rate)) transactionVolume = np.matmul(np.abs(curPosition-lastPosition), (exe_next_min * info.unit_per_lot)) commission = transactionVolume * self.commissionRatio # Check and update pnl dataChange = exe_next_min - exe_cur_min revenue_min = np.matmul(lastPosition, dataChange * info.unit_per_lot) pnl = pnl + revenue_min - commission # Check if strategy losses too much assert pnl > self.margin_threshold, "Too much loss, strategy failed" # Check if margin requirement is satisfied assert marginRequired <= pnl, "You don't have enough margin" # Keep record detail = [curPosition, pnl-marginRequired, marginRequired, revenue_min, pnl, commission] details.append(copy.deepcopy(detail)) # Update position and timer lastPosition = copy.deepcopy(curPosition) timer+=1 if '09:30:00' in keys[i]: print(keys[i][:10]) detailCol = ["postion","cash_balance", "margin_balance", "revenue", "total_balance", "transaction_cost"] detailsDF = pd.DataFrame(details,index=pd.to_datetime(keys[:-1]),columns=detailCol) btData.close() return detailsDF