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
Exemple #2
0
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
Exemple #3
0
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()