class RLTrading: def __init__(self): self.agent = Agent(hist_ws=hist_ws, forward_ws=forward_ws) self.trader = Trader(record=True) self.fee_rate = 0.0001 def Train(self, epochs=100, train_files=['/running/2019-05-22/ni8888.csv'], target_profit=2, stoploss=2, fee=0.5, learn_step=2000): for _ in range(epochs): for f in train_files: wallet = 0 count = 1 hist, forward = self._gen_sample(f) state = np.hstack( (hist[0], [[wallet]] * len(hist[0]))) # state defination for i, hs in enumerate(hist): h, f = hist[i], forward[i] action = int( self.agent.choose_action(np.expand_dims(state, 0))) print('choose action %d' % (action)) reward, wallet = self._cal_reward(h, f, action, wallet) s_ = np.hstack( (h, [[wallet]] * len(h))) # state defination self.agent.store_memory(state, action, reward, s_) if count % learn_step == 0: self.agent.learn() state = s_ count += 1 def Plot(self, f): df = pd.read_csv(f) df.columns = shot.get_columns() df['mid'] = (df['asks[0]'] + df['bids[0]']) / 2 plt.title(f) plt.plot(df['mid']) plt.show() def Test(self, test_file=[ '/running/2019-05-22/ni8888.csv', '/running/2019-05-23/ni8888.csv', '/running/2019-05-24/ni8888.csv', '/running/2019-05-27/ni8888.csv', ]): for f in test_file: #self.Plot(f) wallet = 0 count = 1 hist, forward = self._gen_sample(f) for i, hs in enumerate(hist): h, f = hist[i], forward[i] state = np.hstack((h, [[wallet]] * len(h))) # state defination shot, action = self.agent.real_act(np.expand_dims(state, 0)) shot = shot.flatten() reward, wallet = self._cal_reward(h, f, action, wallet) if reward > 0: print(self.agent.print_qeval(np.expand_dims(state, 0))) if action == 1: # buy self.trader.RegisterOneTrade("ticker", 1, shot[col_dict['asks[0]']]) elif action == 2: # sell self.trader.RegisterOneTrade("ticker", 1, shot[col_dict['bids[0]']]) print('in %d actionspace' % (len(hist))) self.trader.Summary() # gen_sample: generate sample, one by one, hist_sample->[i, i+hist_ws], forward_sample->[i, i+forward_ws] def _gen_sample(self, file_name, hist_ws=hist_ws, forward_ws=forward_ws): print('running read_csv') df = pd.read_csv(file_name) df.columns = shot.get_columns() del df['ticker'] print('read over') hist_sample, forward_sample = [], [] for i in range(hist_ws, len(df) - forward_ws): hist_sample.append(df.iloc[i - hist_ws:i].values) forward_sample.append(df.iloc[i:i + forward_ws].values) print('gen_sample over') return hist_sample, forward_sample # cal_reward: reward based on action,forward and wallet, consider the best situation def _cal_reward(self, hist, forward, action, wallet): reward = 0.0 fee = hist[-1][col_dict['asks[0]']] * self.fee_rate if action == 1: # buy action buy_price = hist[-1][col_dict['asks[0]']] # ask price if wallet == 0: # best sitution's pnl as reward close_price = forward[:, col_dict['bids[0]']].max() wallet = 1 return close_price - buy_price - fee, wallet elif wallet == -1: # close sell, using buy wallet = 0 avg_close_price_buy = forward[:, col_dict['asks[0]']].mean() return avg_close_price_buy - buy_price, wallet else: return -fee / forward_ws, wallet elif action == 2: # sell action sell_price = hist[-1][col_dict['bids[0]']] # bid price if wallet == 0: # best sitution's pnl as reward close_price = forward[:, col_dict['asks[0]']].min() wallet -= 1 return sell_price - close_price - fee, wallet elif wallet == 1: # close buy, using sell, reward are price-avgprice wallet = 0 avg_close_price_sell = forward[:, col_dict['bids[0]']].mean() return sell_price - avg_close_price_sell, wallet else: return -fee / forward_ws, wallet else: # sit if wallet == 0: return 0.0, wallet else: #return -fee/forward_ws, wallet return 0.0, wallet
class BaseFactor: def __init__(self): self.f_value = [] self.tr = Trader() def run(self, start_date, end_date, ticker): self.m = self.LoadData(start_date, end_date, ticker) self.CalFactor() self.PlotFactor() self.TestPnl() self.PlotSignal() def PlotSignal(self): df_list = [i[1] for i in sorted(self.m.items(), key=lambda x: x[0])] if len(df_list) < 1: print('empty df') return df = df_list[0] start = time.time() for i in range(1, len(df_list)): df = pd.merge(df, df_list[i], how='outer') print('finished merge used %lfs' % (time.time() - start)) plt.plot(df['mid'], label='mid', alpha=0.3) buy_x = df[df['money'] < 0].index.tolist() buy = df[df['money'] < -0.1] plt.scatter(x=buy.index.tolist(), y=buy['mid'].tolist(), marker='.', s=[4] * len(buy), c='red', label='buy') sell = df[df['money'] > 0.1] plt.scatter(x=sell.index.tolist(), y=sell['mid'].tolist(), marker='.', s=[4] * len(sell), c='green', label='sell') plt.title('factor percentile signal') plt.legend() plt.grid() plt.show() def TestPnl(self): for k in self.m: df = self.m[k] up = df['factor'].quantile(0.999) down = df['factor'].quantile(0.001) df['money'] = np.where(df['factor'] > up, df['mid'], 0.0) df['money'] = np.where(df['factor'] < down, -df['mid'], df['money']) for i in df['money'].tolist(): if abs(i) > 1: self.tr.RegisterOneTrade('ni8888', 1 if i > 0 else -1, abs(i)) self.tr.Summary() self.tr.PlotStratRawPnl(show=True) self.tr.PlotStratPnl(show=True) def PlotFactor(self): plt.plot(self.f_value, label='factor value') plt.title('factor value curve') plt.legend() plt.grid() plt.show() def CalFactor(self): for k in sorted(self.m.keys()): df = self.m[k] df['factor'] = self.cal(df) self.f_value += df['factor'].tolist() @abstractmethod def cal(self, df): pass def LoadData(self, start_date, end_date, ticker): dl = dateRange(start_date, end_date) m = {} for date in dl: path = '/root/' + date + '/' + ticker + '.csv' if os.path.exists(path): m[date] = self.ReadData(date, ticker) else: print("%s not existed!" % (path)) return m def ReadData(self, date, ticker): path = '/root/' + date + '/' + ticker + '.csv' df = pd.read_csv(path, header=None) df.columns = shot.get_columns() df['mid'] = (df['asks[0]'] + df['bids[0]']) / 2 df['return1'] = df['mid'].diff(1).fillna(0.0) / df['mid'] return df
class BackTester: def __init__(self): self.reader = Reader() self.order_file_size = 0 self.shot_file_size = 0 self.pos= {} self.net_pnl = {} self.gross_pnl = {} self.ticker_strat_map = {} self.avgcost = {} self.gross_time_allpnl_map = {} self.net_time_allpnl_map = {} self.strat_data_map = {} self.gross_strat_pnl_map = {} self.net_strat_pnl_map = {} self.pnl_contract = set([]) self.Caler = CALER(contract_config_path) self.trader = Trader() def GetStratPair(self, s): exec('temp=' + s) return temp def GetStratPnlKey(self): return self.net_strat_pnl_map.keys() def load_binary_order(self, file_path): self.reader.load_order_file(file_path) self.order_file_size = self.reader.get_ordersize() def load_binary_shot(self, file_path): self.reader.load_shot_file(file_path) self.shot_file_size = self.reader.get_shotsize() def load_binary_strat(self, file_path): start_sec = time.time() self.reader.load_strat_file(file_path) self.strat_file_size = self.reader.get_stratsize() for i in range(self.strat_file_size): strat = self.reader.read_bstrat(i) self.pnl_contract.add(self.GetStratPair(strat.ticker)[-1]) for c in self.GetStratPair(strat.ticker): self.ticker_strat_map[c] = strat.ticker if not self.strat_data_map.has_key(strat.ticker): self.strat_data_map[strat.ticker] = {} self.strat_data_map[strat.ticker][strat.time] = strat.last_trade print('load start cost ' + str(time.time()-start_sec)) #sys.exit(1) def load_csv_data(self, file_path): pass def clear(self): self.reader = Reader() self.order_file_size = 0 self.shot_file_size = 0 self.pos= {} self.net_pnl = {} self.gross_pnl = {} self.ticker_strat_map = {} self.avgcost = {} self.gross_time_allpnl_map = {} self.net_time_allpnl_map = {} self.strat_data_map = {} self.gross_strat_pnl_map = {} self.net_strat_pnl_map = {} self.pnl_contract = set([]) self.Caler = CALER(contract_config_path) def RunShot(self): for i in range(self.shot_file_size): shot = self.reader.read_bshot(i) ''' def RunStrat(self): for i in range(self.strat_file_size): strat = self.reader.read_bstrat(i) for c in GetStratPair(strat.contract): self.ticker_strat_map[c] = strat.contract self.strat_map[strat.contract] = strat.last_trade ''' def RunOrder(self): for i in range(self.order_file_size): o = self.reader.read_border(i) o.Show() if o.action == 4: print('passing order %s' %(o.order_ref)) continue if o.shot_time < 156549195 or o.send_time < 1565491959: print('passing order %s' %(o.order_ref)) continue self.trader.RegisterOneTrade(o.contract, o.size, o.price) continue true_size = (o.size if o.side == 1 else -o.size) if not self.pos.has_key(o.contract): self.pos[o.contract] = 0 self.avgcost[o.contract] = 0.0 self.net_pnl[o.contract] = 0 self.gross_pnl[o.contract] = 0 pre_pos = self.pos[o.contract] self.pos[o.contract] += true_size is_close = (self.pos[o.contract]*true_size <= 0) if is_close == True: print('close order hit') this_net_pnl = self.Caler.CalNetPnl(o.contract, self.avgcost[o.contract], abs(pre_pos), o.price, o.size, OrderSide.Buy if o.side==1 else OrderSide.Sell) this_gross_pnl = self.Caler.CalPnl(o.contract, self.avgcost[o.contract], abs(pre_pos), o.price, o.size, OrderSide.Buy if o.side==1 else OrderSide.Sell) #print("%s %f %i %f %i %i " %(o.contract, self.avgcost[o.contract], abs(pre_pos), o.price, o.size, o.side)) self.net_pnl[o.contract] += this_net_pnl self.gross_pnl[o.contract] += this_gross_pnl if self.pos[o.contract] == 0: self.avgcost[o.contract] = 0.0 if o.contract in self.pnl_contract: # close contract #self.time_allpnl_map[o.shot_time] = (np.sum(self.pnl.values()), o.contract) strat_id = self.ticker_strat_map[o.contract] strat_pair = self.GetStratPair(strat_id) if not self.net_strat_pnl_map.has_key(strat_id): self.net_strat_pnl_map[strat_id] = {} self.net_strat_pnl_map[strat_id][o.shot_time] = np.sum([self.net_pnl[sp] for sp in strat_pair]) if not self.gross_strat_pnl_map.has_key(strat_id): self.gross_strat_pnl_map[strat_id] = {} self.gross_strat_pnl_map[strat_id][o.shot_time] = np.sum([self.gross_pnl[sp] for sp in strat_pair]) else: self.avgcost[o.contract] = abs((self.avgcost[o.contract] * (self.pos[o.contract] - true_size) + o.price * true_size) / self.pos[o.contract]) def Plot(self): keys = self.GetStratPnlKey() print keys ksize = len(keys) ncol, nrow = 2, 3 width = int(math.sqrt(ksize)) + 1 height = int(math.sqrt(ksize)) +1 fig,ax = plt.subplots(nrows=nrow,ncols=ncol,figsize=(15,8)) count = 0 for i in range(ksize): key = keys[i] if count % (ncol*nrow) == 0 and count > 0: fig.savefig('pnl@i' %(count)) fig.tight_layout() plt.show() fig,ax = plt.subplots(nrows=nrow,ncols=ncol,figsize=(15,8)) this_ax = ax[int(count/ncol)%nrow, count%ncol] this_ax.set_title(key) data_keys = sorted(self.strat_data_map[key].keys()) self.net_strat_pnl_map[key][np.min(data_keys)-10] = 0.0 self.gross_strat_pnl_map[key][np.min(data_keys)-10] = 0.0 net_pnl_keys = sorted(self.net_strat_pnl_map[key].keys()) gross_pnl_keys = sorted(self.gross_strat_pnl_map[key].keys()) print(net_pnl_keys) this_ax.plot(net_pnl_keys, [self.net_strat_pnl_map[key][k] for k in net_pnl_keys], label='net_pnl', color='red') this_ax.plot(gross_pnl_keys, [self.gross_strat_pnl_map[key][k] for k in gross_pnl_keys], label='gross_pnl', color='black') twin_ax = this_ax.twinx() #twin_ax.plot(data_keys, [self.strat_data_map[key][k] for k in data_keys], label='strat_data', color='blue', alpha=0.3) this_ax.legend() twin_ax.legend() count += 1 fig.savefig('pnl@%i' %(count)) fig.tight_layout() plt.show() def Report(self): self.trader.Summary() def Run(self): if self.order_file_size != 0: self.RunOrder() if self.shot_file_size != 0: self.RunShot()