Ejemplo n.º 1
0
class GDAXOrderBookBacktest:
    """
    """

    def __init__(self):
        self.data = None
        self.strategies = []
        self.broker = Broker()


    def add_strategy(self, strategy):
        strategy.add_broker(self.broker)
        self.strategies.append(strategy)


    def load_csv_directory(self, directory):
        """
        """

        logger.info('Loading CSV data from {}...'.format(directory))

        directory_enc = os.fsencode(directory)

        csv_names = ('datetime', 'type', 'price', 'size', 'num-orders')

        filenames = sorted(os.listdir(directory_enc))

        data_list = []

        for filename in filenames:
            file_path_enc = os.path.join(directory_enc, filename)
            file_path = os.fsdecode(file_path_enc)

            data = pd.read_csv(file_path, header=None, names=csv_names)
            data_list.append(data)

            logger.info('Read {}'.format(filename))

        self.data = pd.concat(data_list, ignore_index=True)


    def run(self):
        """
        """

        # Group data so strategies see the full order book in a give moment
        grouped_data = self.data.groupby('datetime')

        logger.info('Running strategies...')

        # Run strategies on data
        for key, item in grouped_data:
            data = grouped_data.get_group(key)

            self.broker.next(key, data)

            for strategy in self.strategies:
                strategy.next(key, data)

        logger.info('Calculating metrics...')

        # Calculate strategy metrics
        for strategy in self.strategies:
            strategy.metrics()


    def plot(self):
        """
        """

        data_plot = self.data

        data_plot_b = data_plot.loc[data_plot['type'] == 'b']
        data_plot_b = data_plot_b.groupby('datetime')['price'].max()
        data_plot_b = data_plot_b.to_frame('Best Bid')

        data_plot = data_plot_b

        account_df = pd.DataFrame.from_records(
            self.broker.account_value,
            index='datetime',
            columns=['datetime', 'Account Value']
        )

        data_plot = data_plot.join(account_df, how='left')
        data_plot = data_plot.interpolate(method='time')

        fig, axes = plt.subplots(nrows=2)

        data_plot['Best Bid'].plot(ax=axes[0])
        data_plot['Account Value'].plot(ax=axes[1])

        first_best_bid = data_plot['Best Bid'].head(1)
        first_best_bid_xy = (first_best_bid.index[0], first_best_bid[0],)
        axes[0].annotate('{}'.format(first_best_bid[0]), first_best_bid_xy)

        last_best_bid = data_plot['Best Bid'].tail(1)
        last_best_bid_xy = (last_best_bid.index[0], last_best_bid[0],)
        axes[0].annotate('{}'.format(last_best_bid[0]), last_best_bid_xy)

        first_account = data_plot['Account Value'].head(1)
        first_account_xy = (first_account.index[0], first_account[0],)
        axes[1].annotate('{}'.format(first_account[0]), first_account_xy)

        last_account = data_plot['Account Value'].tail(1)
        last_account_xy = (last_account.index[0], last_account[0],)
        axes[1].annotate('{}'.format(last_account[0]), last_account_xy)

        plt.show()
Ejemplo n.º 2
0
class SAMGameGym(gym.Env):
    metadata = {'render.modes': ['human']}

    def __init__(self, env_config):
        account = Account(000000, env_config['initial_cash'], 0,
                          env_config['initial_cash'],
                          env_config['initial_cash'], dict(), False)
        max_limit = env_config['window']
        self.resized_image_width = 100
        self.resized_image_height = 100
        image_channel = 4
        self.log_every = env_config['log_every']
        self.broker = Broker(account, max_limit=max_limit)
        self.all_tickers = self.broker.all_tickers
        self.n_symbols = env_config['n_symbols']
        self.tech_indicators = env_config['tech_indicators']
        length = OHCLVV + len(self.tech_indicators.split())
        self.use_image = env_config['use_image']

        if self.use_image:
            self.observation_space = gym.spaces.Dict({
                'data':
                gym.spaces.Box(-np.inf, np.inf,
                               (self.n_symbols, max_limit, length)),
                'images':
                gym.spaces.Box(-np.inf, np.inf,
                               (self.n_symbols, self.resized_image_height,
                                self.resized_image_width, image_channel)),
                'privates':
                gym.spaces.Box(-np.inf, np.inf, (5 + self.n_symbols * 2, ))
            })
        else:
            self.observation_space = gym.spaces.Dict({
                'data':
                gym.spaces.Box(-np.inf, np.inf,
                               (self.n_symbols, max_limit, length)),
                'privates':
                gym.spaces.Box(-np.inf, np.inf, (5 + self.n_symbols * 2, ))
            })

        self.action_space = gym.spaces.MultiDiscrete([env_config['bins']] *
                                                     self.n_symbols)
        self.current_tickers = None
        self.qty_val = np.linspace(-env_config['max_shares'],
                                   env_config['max_shares'],
                                   env_config['bins'])
        self.images = None
        self.refresh_data = True

    def extract_data(self, df_dict, t, statuses, images=None):
        columns = ['open', 'high', 'low', 'close', 'volume', 'vwap']
        columns.extend(self.tech_indicators.split())
        dfs = [df_dict[tick][columns] for tick in t]
        frame = np.array(dfs)
        privates = self.broker.account.flat()  # fix
        privates.extend(statuses)

        # if images is not None:
        #     images = np.array(list(
        #         self.broker.get_view(frame=df_dict,
        #                              resize=(self.resized_image_width, self.resized_image_height)).values()))
        #
        #     self.images = images[0, :, :, :3]
        #     return frame, images, privates
        # else:
        return frame, privates

    def render(self, mode='rgb_array'):
        if self.use_image:
            assert self.images is not None
            plt.imshow(self.images)
            # plt.pause(0.1)
            plt.show(block=False)

    def reset(self):
        if self.refresh_data:
            t = np.random.choice(self.all_tickers, self.n_symbols)
            self.current_tickers = t
            self.broker.account.stocks_owned = {tick: 0 for tick in t}
            df_dict = self.broker.start(t, self.use_image,
                                        self.tech_indicators)
            self.refresh_data = False
        else:
            df_dict = self.broker.next(use_image=False)[0]

        # if self.use_image:
        #     frame, images, privates = self.extract_data(df_dict, t, [1] * self.n_symbols)
        #     return {'data': frame, 'images': images, 'privates': np.array(privates, dtype=np.float)}
        # else:
        frame, privates = self.extract_data(df_dict, self.current_tickers,
                                            [1] * self.n_symbols)
        return {'data': frame, 'privates': np.array(privates, dtype=np.float)}

    def step(self, action):
        res = self.broker.next(self.use_image)
        orders = make_orders(self.current_tickers, action, res[0],
                             self.qty_val)
        statuses = self.broker.place_orders(orders)

        reward = self.broker.equity - self.broker.last_equity
        done = self.broker.done()
        self.refresh_data = done

        # print(res[-1], flush=True, end='\r')
        if res[2]:  # 2 - new week
            #todo: bug here
            print(ERASELINE,
                  self.broker.account,
                  '\norders:',
                  orders,
                  '\nstatuses:',
                  statuses,
                  flush=True)
            weekly_df = pd.DataFrame(
                self.broker.daily_account_balances).set_index('timestamp')
            weekly_perf = bt.weekly_backtest_with(
                weekly_df,
                [bt.BTMetrics.SHARPE_RATIO, bt.BTMetrics.MAX_DRAWDOWN])
            reward += sum(weekly_perf.values())
            done = True

        if self.use_image:
            next_frame, next_images, next_privates = self.extract_data(
                res[0], self.current_tickers, statuses)
            # todo: add order statuses to observation private variables
            return dict(data=next_frame, images=next_images, privates=np.array(next_privates, dtype=np.float)), \
                   reward, done, {}
        else:
            next_frame, next_privates = self.extract_data(
                res[0], self.current_tickers, statuses)
            # todo: add order statuses to observation private variables

            return dict(data=next_frame, privates=np.array(next_privates, dtype=np.float)), \
                   reward, done, {}