Пример #1
0
    def __init__(self,
                 instruments,
                 frequency=Frequency.MINUTE,
                 table_name='bins',
                 file_name='sqlite'):
        self.__engine = create_engine(f'sqlite:///{file_name}')
        self.__DBSession = sessionmaker(bind=self.__engine)
        self.__logger = get_logger(SQLiteFeed.LOGGER_NAME)
        if table_name in table_names.keys():
            self.__bar_model = table_names[table_name]
        else:
            self.__bar_model = make_bar_model(table_name)
            table_names[table_name] = self.__bar_model

        def before_cursor_execute(conn, cursor, statement, parameters, context,
                                  executemany):
            conn.info.setdefault('query_start_time', []).append(time.time())

            self.__logger.debug(
                f'Start Query: {statement} with params: {parameters}')

        def after_cursor_execute(conn, cursor, statement, parameters, context,
                                 executemany):
            total = time.time() - conn.info['query_start_time'].pop(-1)
            self.__logger.debug("Query Complete!")
            self.__logger.debug("Total Time: %f", total)

        event.listens_for(self.__engine,
                          "before_cursor_execute")(before_cursor_execute)
        event.listens_for(self.__engine,
                          "after_cursor_execute")(after_cursor_execute)

        super(SQLiteFeed, self).__init__(frequency, instruments, None, None)

        self.bars = []
Пример #2
0
    def __init__(self, broker: BaseBroker, series_max_len=None):
        self.__broker = broker
        self.__activePositions = set()
        self.__orderToPosition = {}
        self.__barsProcessedEvent = Event()
        self.__analyzers = []
        self.__namedAnalyzers = {}
        self.__resampledBarFeeds = []
        self.__dispatcher = Dispatcher()
        self.__broker.order_events.subscribe(self.__onOrderEvent)
        self.bar_feed.bar_events.subscribe(self.__onBars)
        self.bar_feed.feed_reset_event.subscribe(self.reset)

        # onStart will be called once all subjects are started.
        self.__dispatcher.getStartEvent().subscribe(self.onStart)
        self.__dispatcher.getIdleEvent().subscribe(self.__onIdle)

        # It is important to dispatch broker events before feed events, specially if we're backtesting.
        self.__dispatcher.addSubject(self.broker)
        self.__dispatcher.addSubject(self.bar_feed)

        # Initialize logging.
        self.__logger = logger.get_logger(BaseStrategy.LOGGER_NAME)

        self.use_event_datetime_logs = True

        self.__onEnterOkEvent = Event()
        self.__onEnterCanceledEvent = Event()
        self.__onExitOkEvent = Event()
        self.__onExitCanceledEvent = Event()

        self.__onEnterOkEvent.subscribe(self.onEnterOk)
        self.__onEnterCanceledEvent.subscribe(self.onEnterCanceled)
        self.__onExitOkEvent.subscribe(self.onExitOk)
        self.__onExitCanceledEvent.subscribe(self.onExitCanceled)
        self.__onEnterStartEvent = Event()
        self.__onExitStartEvent = Event()
        """
            我们尝试把数据序列记在策略中
            TODO: 对于离线的回测,这个过程可以利用本来的数据
        """

        instruments = broker.instruments

        self.bar_series = dict()
        self.max_series_length = series_max_len

        for instrument in instruments:
            self.bar_series[instrument] = BarDataSeries(max_len=series_max_len)
        """
            反正都要用,为何不把所有Positions管理起来呢
        """
        self.__positions = []
        self.__onEnterStartEvent.subscribe(self.__on_enter_start)
Пример #3
0
    def __init__(self,
                 path,
                 instruments,
                 frequency=Frequency.MINUTE,
                 maxLen=None):

        super(DataFrameFeed, self).__init__(frequency, instruments, None,
                                            maxLen)

        self.store = pd.HDFStore(path)

        self.__logger = get_logger("DATAFrameFeed Logger")
Пример #4
0
    def __init__(self,
                 table_name='bars',
                 db_name='database',
                 db_username='******',
                 db_password='******',
                 connector='mysqldb',
                 db_host='127.0.0.1',
                 db_port=3306):
        self.__engine = create_engine(
            f'mysql+{connector}://{db_username}:{db_password}@{db_host}:{db_port}/{db_name}'
        )
        self.__DBSession = sessionmaker(bind=self.__engine)
        self.__logger = get_logger(MySQLFeed.LOGGER_NAME)
        self.__bar_model = make_bar_model(table_name)

        def before_cursor_execute(conn, cursor, statement, parameters, context,
                                  executemany):
            conn.info.setdefault('query_start_time', []).append(time.time())

            self.__logger.debug(
                f'Start Query: {statement} with params: {parameters}')

        def after_cursor_execute(conn, cursor, statement, parameters, context,
                                 executemany):
            total = time.time() - conn.info['query_start_time'].pop(-1)
            self.__logger.debug("Query Complete!")
            self.__logger.debug("Total Time: %f", total)

        event.listens_for(self.__engine,
                          "before_cursor_execute")(before_cursor_execute)
        event.listens_for(self.__engine,
                          "after_cursor_execute")(after_cursor_execute)

        super(MySQLFeed, self).__init__()

        self.bars = []
Пример #5
0
"""
想法:
对于每个需要被操作的Indicator,我们把它传入到这里,然后再将它attach上去。
每笔交易之前我们都可以记录Indicator的数值,然后记录下来。

然后当交易结束后,则得到一个交易与其之前的Indicator的一一对应

当然,有四个时间点,分别是:

入场前、入场后、出场前、出场后

每个时间点都对应有一堆indicator的数值

"""

logger = get_logger('indicator_analyz')


class Indicators(stratanalyzer.StrategyAnalyzer):
    """
        indicators:
            你所打算处理的Indicator的一个字典.
            注意需要传入一个Generator,而不是实例,因为Indicator将会在attach之前被给上priceDS

        instrument:
            标的
            这里用来分析具体针对某种策略的indicator
    """
    def __init__(self, indicators: dict, instrument):
        super(Indicators, self).__init__()
        self.__priceDS = None
Пример #6
0
class OrderBook(stratanalyzer.StrategyAnalyzer):
    l = get_logger('OrderBook')

    def to_df(self):

        self.l.debug('Converting The Order Book...')

        positions = []
        for position in self.strat.positions:
            dict = {
                "instrument": None,
                "return": None,
                "PnL": None,
                "entry_state": None,
                "entry_type": None,
                "entry_fill_price": None,
                "entry_amounts": None,
                "entry_filled": None,
                "entry_submitted_at": None,
                "entry_accepted_at": None,
                "entry_finished_at": None,
                "entry_canceled_at": None,
                "exit_state": None,
                "exit_type": None,
                "exit_fill_price": None,
                "exit_submitted_at": None,
                "exit_accepted_at": None,
                "exit_finished_at": None,
                "exit_canceled_at": None,
                "exit_amounts": None,
                "exit_filled": None,
                "not_filled": None,
            }
            entry_order: Order = position.getEntryOrder()
            dict["instrument"] = position.getInstrument()
            dict["entry_state"] = entry_order.state
            dict["amounts"] = position.getAmounts()
            dict["entry_submitted_at"] = entry_order.submitted_at
            dict["entry_accepted_at"] = entry_order.accepted_at
            dict["entry_finished_at"] = entry_order.finish_datetime
            dict["entry_canceled_at"] = entry_order.canceled_at
            dict["entry_type"] = entry_order.type
            dict["entry_amounts"] = entry_order.quantity
            dict["entry_filled"] = entry_order.filled
            if entry_order.is_filled:
                dict["entry_fill_price"] = position.getEntryOrder(
                ).avg_fill_price

            exit_order: Order = position.getExitOrder()

            if exit_order is not None:
                dict["exit_submitted_at"] = exit_order.submitted_at
                dict["exit_accepted_at"] = exit_order.accepted_at
                dict["exit_canceled_at"] = exit_order.canceled_at
                dict["exit_finished_at"] = exit_order.finish_datetime
                dict["exit_type"] = exit_order.type
                dict["exit_state"] = exit_order.state
                dict["exit_amounts"] = exit_order.quantity
                dict["exit_filled"] = exit_order.filled
                if exit_order.is_filled:
                    dict["exit_fill_price"] = exit_order.avg_fill_price

            dict["not_filled"] = position.getAmounts()
            dict["PnL"] = position.getPnL()
            dict["return"] = position.getReturn()

            positions.append(dict)

        dict = {
            "instrument": None,
            "return": None,
            "PnL": None,
            "entry_state": None,
            "entry_type": None,
            "entry_fill_price": None,
            "entry_amounts": None,
            "entry_filled": None,
            "entry_submitted_at": None,
            "entry_accepted_at": None,
            "entry_finished_at": None,
            "entry_canceled_at": None,
            "exit_state": None,
            "exit_type": None,
            "exit_fill_price": None,
            "exit_submitted_at": None,
            "exit_accepted_at": None,
            "exit_finished_at": None,
            "exit_canceled_at": None,
            "exit_amounts": None,
            "exit_filled": None,
            "not_filled": None,
        }

        df = pd.DataFrame(positions, columns=dict.keys())

        return df

    def save_csv(self, filename):

        return self.to_df().to_csv(filename)
Пример #7
0
class ResultDrawer:
    logger = get_logger('Drawer Logger')

    def __init__(self, results: [ResultModel], dpi: int = 128):
        self.__results = results
        self.__dpi = dpi

    def __draw_contour(self, ax2, low_bound=None, upper_bound=None, param_name="sharp_ratio"):
        def judge(v):

            rtv = True

            if low_bound is not None:
                rtv = rtv and low_bound <= v

            if upper_bound is not None:
                rtv = rtv and v <= upper_bound

            return rtv

        new_line = [np.array([line.p1, line.p2, getattr(line, param_name)]) for line in self.__results if
                    judge(line.sharp_ratio)]

        if len(new_line) <= 4:
            self.logger.debug('NO RESULTS SELECTED')
            return

        new_line = np.array(new_line)

        points = new_line[:, 0:2]

        x = points[:, 0]
        y = points[:, 1]
        z = new_line[:, 2]

        ax2.tricontour(x, y, z, levels=14, linewidths=0.5, colors='k')
        cntr2 = ax2.tricontourf(x, y, z, levels=14, cmap="coolwarm")
        ax2.plot(x, y, 'ko', ms=0.1)
        ax2.set_title(f'(p1,p2) and {param_name}')
        ax2.locator_params(nbins=40)
        ax2.grid()

        return cntr2
        # p.subplots_adjust(hspace=0.5)

    def draw_contour(self, save_path, low_bound=None, upper_bound=None, param_name=None):
        fig = plt.figure(dpi=self.__dpi)
        ax = fig.subplots(nrows=1)
        cntr2 = self.__draw_contour(ax, low_bound, upper_bound, param_name)
        if cntr2 is None:
            return
        fig.colorbar(cntr2, ax=ax)
        fig.savefig(save_path)

    def __draw_line(self, ax, low_bound=None, upper_bound=None, param_name="sharp_ratio"):
        def judge(v):
            rtv = True
            if low_bound is not None:
                rtv = rtv and low_bound <= v

            if upper_bound is not None:
                rtv = rtv and v <= upper_bound

            return rtv

        new_line = [np.array([line.p1, getattr(line, param_name)]) for line in self.__results if
                    judge(line.sharp_ratio)]
        new_line = np.array(new_line)
        if len(new_line) is 0:
            self.logger.error('NO RESULTS SELECTED')
            return

        pair = new_line
        pair = pair[np.argsort(pair[:, 0])]
        ax.plot(pair[:, 0], pair[:, 1])
        ax.set(xlabel='p1', ylabel=param_name,
               title=f'p1-{param_name} curve')
        ax.grid()

    def draw_line(self, save_path, low_bound=None, upper_bound=None, param_name="sharp_ratio"):
        fig = plt.figure(dpi=self.__dpi)
        ax = fig.subplots(nrows=1)
        self.__draw_line(ax, low_bound, upper_bound, param_name)
        fig.savefig(save_path)

    def draw_lines(self, save_path,
                   params=["sharp_ratio", "ret", "win_rate", "trade_count", "draw_down", "plr", "draw_down_duration"]):
        fig = plt.figure(dpi=self.__dpi)

        n = len(params)

        fig.set_figheight(n * 3)
        fig.set_figwidth(12)

        axex = fig.subplots(ncols=1, nrows=len(params))
        i = 0
        for param in params:
            ax = axex[i] if n > 1 else axex
            self.__draw_line(ax, param_name=param)
            i += 1

        fig.subplots_adjust(wspace=0.5, hspace=0.5)

        fig.savefig(save_path)

    def draw_contours(self, save_path,
                      params=["sharp_ratio", "ret", "win_rate", "trade_count", "draw_down", "plr",
                              "draw_down_duration"]):

        n = len(params)

        fig = plt.figure(dpi=self.__dpi, figsize=(25, n * 25))
        axex = fig.subplots(ncols=1, nrows=len(params))
        i = 0
        for param in params:
            ax = axex[i] if n > 1 else axex
            cntr2 = self.__draw_contour(ax, param_name=param)
            i += 1
            if cntr2 is not None:
                fig.colorbar(cntr2, ax=ax)

        fig.subplots_adjust(wspace=0.5, hspace=0.5)

        fig.savefig(save_path)