Example #1
0
class QA_Market(QA_Trade):
    """
    QUANTAXIS MARKET 部分

    交易前置/可连接到多个broker中
    暂时还是采用多线程engine模式

    session 保存的是 QAAccout 对象
    """
    def __init__(self, if_start_orderthreading=True, *args, **kwargs):
        """[summary]

        Keyword Arguments:
            if_start_orderthreading {bool} -- 是否在初始化的时候开启查询子线程(实盘需要) (default: {False})

        @2018-08-06 change : 子线程全部变成后台线程 market线程崩了 子线程全部结束
        """

        super().__init__()
        # 以下是待初始化的账户session
        self.session = {}
        # 以下都是官方支持的交易前置
        self._broker = {
            BROKER_TYPE.BACKETEST: QA_BacktestBroker,
            BROKER_TYPE.RANODM: QA_RandomBroker,
            BROKER_TYPE.REAL: QA_RealBroker,
            BROKER_TYPE.SIMULATION: QA_SimulatedBroker,
            BROKER_TYPE.SHIPANE: QA_SPEBroker
        }
        self.broker = {}
        self.running_time = None
        self.last_query_data = None
        self.if_start_orderthreading = if_start_orderthreading
        self.order_handler = QA_OrderHandler()

    def __repr__(self):
        '''
                输出market市场对象的字符串
        '''
        return '<QA_Market with {} QA_Broker >'.format(list(
            self.broker.keys()))

    def upcoming_data(self, broker, data):
        '''
        更新市场数据
        broker 为名字,
        data 是市场数据
        被 QABacktest 中run 方法调用 upcoming_data
        '''
        # main thread'
        # if self.running_time is not None and self.running_time!= data.datetime[0]:
        #     for item in self.broker.keys():
        #         self._settle(item)
        self.running_time = data.datetime[0]
        for item in self.session.values():
            # session里面是已经注册的account
            self.submit(
                QA_Task(
                    worker=item,  # item 是Account 类型, 是 QA_Work类型, 处理这个 事件
                    event=QA_Event(
                        event_type=ENGINE_EVENT.UPCOMING_DATA,
                        # args 附加的参数
                        market_data=data,
                        broker_name=broker,
                        send_order=self.
                        insert_order,  # 🛠todo insert_order = insert_order
                        query_data=self.query_data_no_wait,
                        query_order=self.query_order,
                        query_assets=self.query_assets,
                        query_trade=self.query_trade)),
                nowait=True)

    def submit(self, QATask, nowait=False):
        """submit 一个任务给QAMarket的event_queue

        Arguments:
            QATask {[type]} -- [description]

        QATask 需要有
            - worker (需要这个类继承了QA_Worker)
            - engine(默认qamarket所在的thread)
            - event - QA_Event
                        - event_type
                        - 自定义参数
                        - callback

        Keyword Arguments:
            nowait {bool} -- [description] (default: {False})
        """

        assert isinstance(QATask, QA_Task)
        if nowait:
            self.event_queue.put_nowait(QATask)
        else:
            self.submit(QATask)

    def start(self):
        self.trade_engine.start()
        if self.if_start_orderthreading:
            """查询子线程开关
            """
            self.start_order_threading()

        # self.trade_engine.create_kernel('MARKET')
        # self.trade_engine.start_kernel('MARKET')

    def connect(self, broker):
        if broker in self._broker.keys():

            self.broker[broker] = self._broker[broker]()  # 在这里实例化
            # 2018-08-06 change : 子线程全部变成后台线程 market线程崩了 子线程全部结束
            self.trade_engine.create_kernel('{}'.format(broker), daemon=True)
            self.trade_engine.start_kernel('{}'.format(broker))
            # 开启trade事件子线程
            return True
        else:
            return False

    def register(self, broker_name, broker):
        if broker_name not in self._broker.keys():
            self.broker[broker_name] = broker
            self.trade_engine.create_kernel('{}'.format(broker_name),
                                            daemon=True)
            self.trade_engine.start_kernel('{}'.format(broker_name))
            return True
        else:
            return False

    def start_order_threading(self):
        """开启查询子线程(实盘中用)
        """

        self.if_start_orderthreading = True

        self.order_handler.if_start_orderquery = True
        self.trade_engine.create_kernel('ORDER', daemon=True)
        self.trade_engine.start_kernel('ORDER')
        # self._update_orders()

    def get_account(self, account_cookie):
        try:
            return self.session[account_cookie]
        except KeyError:
            print(
                'QAMARKET: this account {} is logoff, please login and retry'.
                format(account_cookie))

    def login(self, broker_name, account_cookie, account=None):
        """login 登录到交易前置

        2018-07-02 在实盘中,登录到交易前置后,需要同步资产状态

        Arguments:
            broker_name {[type]} -- [description]
            account_cookie {[type]} -- [description]

        Keyword Arguments:
            account {[type]} -- [description] (default: {None})

        Returns:
            [type] -- [description]
        """
        res = False
        if account is None:
            if account_cookie not in self.session.keys():
                self.session[account_cookie] = QA_Account(
                    account_cookie=account_cookie, broker=broker_name)
                if self.sync_account(broker_name, account_cookie):
                    res = True

                if self.if_start_orderthreading and res:
                    #
                    self.order_handler.subscribe(self.session[account_cookie],
                                                 self.broker[broker_name])

        else:
            if account_cookie not in self.session.keys():
                account.broker = broker_name
                self.session[account_cookie] = account
                if self.sync_account(broker_name, account_cookie):
                    res = True
                if self.if_start_orderthreading and res:
                    #
                    self.order_handler.subscribe(account,
                                                 self.broker[broker_name])

        if res:
            return res
        else:
            try:
                self.session.pop(account_cookie)
            except:
                pass
            return False

    def sync_order_and_deal(self):
        self.if_start_orderquery = True
        # self._sync_orders()

    def stop_sync_order_and_deal(self):
        self.if_start_orderquery = False

    def sync_account(self, broker_name, account_cookie):
        """同步账户信息

        Arguments:
            broker_id {[type]} -- [description]
            account_cookie {[type]} -- [description]
        """
        try:
            if isinstance(self.broker[broker_name], QA_BacktestBroker):
                pass
            else:
                self.session[account_cookie].sync_account(
                    self.broker[broker_name].query_positions(account_cookie))
            return True
        except Exception as e:
            print(e)
            return False

    def logout(self, account_cookie, broker_name):
        if account_cookie not in self.session.keys():
            return False
        else:
            self.order_handler.unsubscribe(self.session[account_cookie],
                                           self.broker[broker_name])
            self.session.pop(account_cookie)

    def get_trading_day(self):
        return self.running_time

    def get_account_id(self):
        return list(self.session.keys())

    def insert_order(self,
                     account_cookie,
                     amount,
                     amount_model,
                     time,
                     code,
                     price,
                     order_model,
                     towards,
                     market_type,
                     frequence,
                     broker_name,
                     money=None):
        #strDbg = QA_util_random_with_topic("QA_Market.insert_order")
        #print(">-----------------------insert_order----------------------------->", strDbg)

        flag = False

        #行情切片 bar/tick/realtime

        price_slice = self.query_data_no_wait(broker_name=broker_name,
                                              frequence=frequence,
                                              market_type=market_type,
                                              code=code,
                                              start=time)
        price_slice = price_slice if price_slice is None else price_slice[0]

        if order_model in [ORDER_MODEL.CLOSE, ORDER_MODEL.NEXT_OPEN]:
            if isinstance(price_slice, np.ndarray):
                if (price_slice != np.array(None)).any():
                    price = float(price_slice[4])
                    flag = True
                else:
                    QA_util_log_info(
                        'MARKET WARING: SOMEING WRONG WITH ORDER \n ')
                    QA_util_log_info(
                        'code {} date {} price {} order_model {} amount_model {}'
                        .format(code, time, price, order_model, amount_model))
            elif isinstance(price_slice, dict):
                if price_slice is not None:
                    price = float(price_slice['close'])
                    flag = True
                else:
                    QA_util_log_info(
                        'MARKET WARING: SOMEING WRONG WITH ORDER \n ')
                    QA_util_log_info(
                        'code {} date {} price {} order_model {} amount_model {}'
                        .format(code, time, price, order_model, amount_model))
            elif isinstance(price_slice, list):
                if price_slice is not None:
                    price = float(price_slice[4])
                    flag = True
                else:
                    QA_util_log_info(
                        'MARKET WARING: SOMEING WRONG WITH ORDER \n ')
                    QA_util_log_info(
                        'code {} date {} price {} order_model {} amount_model {}'
                        .format(code, time, price, order_model, amount_model))

        elif order_model is ORDER_MODEL.MARKET:
            if isinstance(price_slice, np.ndarray):
                if (price_slice != np.array(None)).any():
                    price = float(price_slice[1])
                    flag = True
                else:
                    QA_util_log_info(
                        'MARKET WARING: SOMEING WRONG WITH ORDER \n ')
                    QA_util_log_info(
                        'code {} date {} price {} order_model {} amount_model {}'
                        .format(code, time, price, order_model, amount_model))
            elif isinstance(price_slice, dict):

                if price_slice is not None:
                    price = float(price_slice['open'])
                    flag = True
                else:
                    QA_util_log_info(
                        'MARKET WARING: SOMEING WRONG WITH ORDER \n ')
                    QA_util_log_info(
                        'code {} date {} price {} order_model {} amount_model {}'
                        .format(code, time, price, order_model, amount_model))
        elif order_model is ORDER_MODEL.LIMIT:
            flag = True
        if flag:
            order = self.get_account(account_cookie).send_order(
                amount=amount,
                amount_model=amount_model,
                time=time,
                code=code,
                price=price,
                order_model=order_model,
                towards=towards,
                money=money)
            if order:
                # print(order)
                self.submit(QA_Task(worker=self.order_handler,
                                    engine='ORDER',
                                    event=QA_Event(
                                        broker=self.broker[self.get_account(
                                            account_cookie).broker],
                                        event_type=BROKER_EVENT.RECEIVE_ORDER,
                                        order=order,
                                        market_data=price_slice,
                                        callback=self.on_insert_order)),
                            nowait=True)
        else:
            pass

        #print("<-----------------------insert_order-----------------------------<", strDbg)

    def on_insert_order(self, order):
        print('on_insert_order')
        print(order)
        print(order.status)
        if order.status == ORDER_STATUS.FAILED:
            """如果订单创建失败, 恢复状态

            如果是买入单  恢复金钱 money

            如果是卖出单  恢复股数 sell_available
            """

            self.session[order.account_cookie].cancel_order(order)

    def _renew_account(self):
        for account in self.session.values():
            self.submit(
                QA_Task(worker=account,
                        event=QA_Event(event_type=ACCOUNT_EVENT.SETTLE)))

    def _sync_position(self):
        self.submit(QA_Task(worker=self.order_handler,
                            engine='ORDER',
                            event=QA_Event(
                                event_type=MARKET_EVENT.QUERY_POSITION,
                                account_cookie=list(self.session.keys()),
                                broker=[
                                    self.broker[item.broker]
                                    for item in self.session.values()
                                ])),
                    nowait=True)

    def _sync_deals(self):
        self.submit(QA_Task(
            worker=self.order_handler,
            engine='ORDER',
            event=QA_Event(
                event_type=MARKET_EVENT.QUERY_DEAL,
                account_cookie=list(self.session.keys()),
                broker=[
                    self.broker[item.broker] for item in self.session.values()
                ],
                event_queue=self.trade_engine.kernels_dict['ORDER'].queue)),
                    nowait=True)

    def _sync_orders(self):
        self.submit(
            QA_Task(
                worker=self.order_handler,
                engine='ORDER',
                event=QA_Event(
                    event_type=MARKET_EVENT.QUERY_ORDER,
                    # account_cookie=list(self.session.keys()),
                    # broker=[self.broker[item.broker]
                    #         for item in self.session.values()],
                    # 注意: 一定要给子线程的队列@@@!!!
                    # 2018-08-08 yutiansut
                    # 这个callback实现了子线程方法的自我驱动和异步任务
                    event_queue=self.trade_engine.kernels_dict['ORDER'].queue)
            ),
            nowait=True)

    def sync_strategy(self, broker_name, account_cookie):
        """同步  账户/委托/成交

        Arguments:
            broker_name {[type]} -- [description]
            account_cookie {[type]} -- [description]
        """
        pass

    def cancel_order(self, broker_name, account_cookie, order_id):
        pass

    def cancel_all(self, broker_name, account_cookie):
        try:
            self.broker[broker_name].cancel_all(account_cookie)
        except Exception as e:
            print(e)

    def query_order(self, account_cookie, realorder_id):

        # res = self.submit(
        #     QA_Task(
        #         worker=self.broker[self.get_account(
        #             account_cookie).broker],
        #         engine=self.get_account(
        #             account_cookie).broker,
        #         event=QA_Event(
        #             broker=self.broker[self.get_account(
        #                 account_cookie).broker],
        #             order_id=order_id
        #         )
        #     ),nowait=True)

        return self.order_handler.order_status.loc[account_cookie,
                                                   realorder_id]

    def query_assets(self, account_cookie):
        return self.get_account(account_cookie).assets

    def query_position(self, account_cookie):
        return self.get_account(account_cookie).hold

    def query_cash(self, account_cookie):
        return self.get_account(account_cookie).cash_available

    def query_data_no_wait(self,
                           broker_name,
                           frequence,
                           market_type,
                           code,
                           start,
                           end=None):
        return self.broker[broker_name].run(
            event=QA_Event(event_type=MARKET_EVENT.QUERY_DATA,
                           frequence=frequence,
                           market_type=market_type,
                           code=code,
                           start=start,
                           end=end))

    def query_data(self,
                   broker_name,
                   frequence,
                   market_type,
                   code,
                   start,
                   end=None):
        self.submit(
            QA_Task(worker=self.broker[broker_name],
                    engine=broker_name,
                    event=QA_Event(event_type=MARKET_EVENT.QUERY_DATA,
                                   frequence=frequence,
                                   market_type=market_type,
                                   code=code,
                                   start=start,
                                   end=end,
                                   callback=self.on_query_data)))

    def query_currentbar(self, broker_name, market_type, code):
        return self.broker[broker_name].run(
            event=QA_Event(event_type=MARKET_EVENT.QUERY_DATA,
                           frequence=FREQUENCE.CURRENT,
                           market_type=market_type,
                           code=code,
                           start=self.running_time,
                           end=None))

    def on_query_data(self, data):
        print('ON QUERY')
        print(data)
        self.last_query_data = data

    def on_trade_event(self, event):
        print('ON TRADE')
        print(event.res)

    def _trade(self, event):
        "内部函数"

        self.submit(
            QA_Task(worker=self.broker[event.broker_name],
                    engine=event.broker_name,
                    event=QA_Event(event_type=BROKER_EVENT.TRADE,
                                   broker=self.broker[event.broker_name],
                                   broker_name=event.broker_name,
                                   callback=self.on_trade_event)))

    def _settle(self, broker_name, callback=False):
        #strDbg = QA_util_random_with_topic("QA_Market._settle")
        #print(">-----------------------_settle----------------------------->", strDbg)

        # 向事件线程发送BROKER的SETTLE事件
        # 向事件线程发送ACCOUNT的SETTLE事件

        for account in self.session.values():
            """t0账户先结算当日仓位
            """
            if account.running_environment == RUNNING_ENVIRONMENT.TZERO:
                for order in account.close_positions_order:
                    self.submit(
                        QA_Task(worker=self.broker[account.broker],
                                engine=account.broker,
                                event=QA_Event(
                                    event_type=BROKER_EVENT.RECEIVE_ORDER,
                                    order=order,
                                    callback=self.on_insert_order)))
            """broker中账户结算
            """
            if account.broker == broker_name:
                self.submit(QA_Task(
                    worker=account,
                    engine=broker_name,
                    event=QA_Event(event_type=ACCOUNT_EVENT.SETTLE)),
                            nowait=True)
        """broker线程结算
        """
        self.submit(QA_Task(worker=self.broker[broker_name],
                            engine=broker_name,
                            event=QA_Event(event_type=BROKER_EVENT.SETTLE,
                                           broker=self.broker[broker_name],
                                           callback=callback)),
                    nowait=True)

        self.settle_order()
        print('===== SETTLED {} ====='.format(self.running_time))

    def settle_order(self):
        """交易前置结算

        1. 回测: 交易队列清空,待交易队列标记SETTLE
        2. 账户每日结算
        3. broker结算更新
        """

        if self.if_start_orderthreading:
            # print('setttle_order')
            self.submit(QA_Task(worker=self.order_handler,
                                engine='ORDER',
                                event=QA_Event(event_type=BROKER_EVENT.SETTLE,
                                               event_queue=self.trade_engine.
                                               kernels_dict['ORDER'].queue)),
                        nowait=True)

    def every_day_start(self):
        """盘前准备

        1. 计算盘前信号
        2. 账户同步
        """
        pass

    def _close(self):
        pass

    def clear(self):
        return self.trade_engine.clear()
Example #2
0
class QA_Market(QA_Trade):
    """
    QUANTAXIS MARKET 部分

    交易前置/可连接到多个broker中
    暂时还是采用多线程engine模式

    session 保存的是 QAAccout 对象
    """

    def __init__(self, if_start_orderthreading=True, *args, **kwargs):
        """MARKET的初始化过程
        Market的初始属性:
        session: MARKET的账户字典
        _broker: 当前所有的broker集合 TODO: 转移到QAParameter
        broker: MARKET的broker字典
        running_time: MARKET当前的运行时间
        last_query_data: MARKET上次获取的数据
        if_start_orderthreading: MARKET是否开启订单队列线程的开关
        order_handler: 订单队列

        Keyword Arguments:
            if_start_orderthreading {bool} -- 是否在初始化的时候开启查询子线程(实盘需要) (default: {False})

        @2018-08-06 change : 子线程全部变成后台线程 market线程崩了 子线程全部结束
        """

        super().__init__()
        # 以下是待初始化的账户session
        self.session = {}
        # 以下都是官方支持的交易前置
        self._broker = {
            BROKER_TYPE.BACKETEST: QA_BacktestBroker,
            BROKER_TYPE.RANDOM: QA_RandomBroker,
            BROKER_TYPE.REAL: QA_RealBroker,
            BROKER_TYPE.SIMULATION: QA_SimulatedBroker,
            BROKER_TYPE.SHIPANE: QA_SPEBroker,
            BROKER_TYPE.TTS: QA_TTSBroker,
        }
        self.broker = {}
        self.running_time = None
        self.last_query_data = None
        self.if_start_orderthreading = if_start_orderthreading
        self.order_handler = QA_OrderHandler()

    def __repr__(self):
        '''
        输出market市场对象的字符串
        '''
        return '<QA_Market with {} QA_Broker >'.format(list(self.broker.keys()))

    def upcoming_data(self, broker, data):
        '''
        根据更新的市场数据来更新账户信息
        broker 为名字,
        data 是市场数据
        被 QABacktest 中run 方法调用 upcoming_data
        '''
        # main thread'
        # if self.running_time is not None and self.running_time!= data.datetime[0]:
        #     for item in self.broker.keys():
        #         self._settle(item)
        self.running_time = data.datetime[0]
        for account in self.session.values():
            account.run(QA_Event(
                event_type=ENGINE_EVENT.UPCOMING_DATA,
                # args 附加的参数
                market_data=data,
                broker_name=broker,
                send_order=self.insert_order,  # 🛠todo insert_order = insert_order
                query_data=self.query_data_no_wait,
                query_order=self.query_order,
                query_assets=self.query_assets,
                query_trade=self.query_trade
            ))

    def start(self):
        '''
        1,开启交易引擎
        2,开启订单流线程
        :return:
        '''

        self.trade_engine.start()
        if self.if_start_orderthreading:
            """查询子线程开关
            """
            self.start_order_threading()
        print(threading.enumerate())

    def connect(self, broker):
        if broker in self._broker.keys():

            self.broker[broker] = self._broker[broker]() # 在这里实例化
                                                         # 2018-08-06 change : 子线程全部变成后台线程 market线程崩了 子线程全部结束
                                                         # self.trade_engine.create_kernel('{}'.format(broker), daemon=True)
                                                         # self.trade_engine.start_kernel('{}'.format(broker))

            # 2019-02-08 change: 在此 我们删除了BROKER所占用的线程

            # 子线程变成功能性线程
            # 开启trade事件子线程
            return True
        else:
            return False

    def next_tradeday(self):
        self.order_handler.run(
            QA_Event(
                event_type=BROKER_EVENT.NEXT_TRADEDAY,
                event_queue=self.trade_engine.kernels_dict['ORDER'].queue
            )
        )

    def register(self, broker_name, broker):
        '''
        注册broker
        :param broker_name:
        :param broker:
        :return:
        '''
        if broker_name not in self._broker.keys():
            self.broker[broker_name] = broker
            # self.trade_engine.create_kernel(
            #     '{}'.format(broker_name),
            #     daemon=True
            # )
            # self.trade_engine.start_kernel('{}'.format(broker_name))
            return True
        else:
            return False

    def start_order_threading(self):
        """开启查询子线程(实盘中用)
        """

        self.if_start_orderthreading = True

        self.order_handler.if_start_orderquery = True
        self.trade_engine.create_kernel('ORDER', daemon=True)
        self.trade_engine.start_kernel('ORDER')
        self.sync_order_and_deal()
        # self._update_orders()

    def get_account(self, account_cookie):
        try:
            return self.session[account_cookie]
        except KeyError:
            print(
                'QAMARKET: this account {} is logoff, please login and retry'
                .format(account_cookie)
            )

    def login(self, broker_name, account_cookie, account=None):
        """login 登录到交易前置
        1,在account和broker间同步信息
        2,order_handler订阅account和对应的broker

        2018-07-02 在实盘中,登录到交易前置后,需要同步资产状态

        Arguments:
            broker_name {[type]} -- [description]
            account_cookie {[type]} -- [description]

        Keyword Arguments:
            account {[type]} -- [description] (default: {None})

        Returns:
            [type] -- [description]
        """
        res = False
        if account is None:
            if account_cookie not in self.session.keys():

                # self.session[account_cookie] = QA_Account(
                #     account_cookie=account_cookie,
                #     broker=broker_name
                # )
                if self.sync_account(broker_name, account_cookie):
                    res = True

                if self.if_start_orderthreading and res:
                    #
                    self.order_handler.subscribe(
                        self.session[account_cookie],
                        self.broker[broker_name]
                    )

        else:
            if account_cookie not in self.session.keys():
                account.broker = broker_name
                self.session[account_cookie] = account
                if self.sync_account(broker_name, account_cookie):
                    res = True
                if self.if_start_orderthreading and res:
                    #
                    self.order_handler.subscribe(
                        account,
                        self.broker[broker_name]
                    )

        if res:
            return res
        else:
            try:
                self.session.pop(account_cookie)
            except:
                pass
            return False

    def sync_order_and_deal(self):
        self.order_handler.if_start_orderquery = True
        self._sync_orders()

    def stop_sync_order_and_deal(self):
        self.order_handler.if_start_orderquery = False

    def sync_account(self, broker_name, account_cookie):
        """同步账户信息
        若broker是回测的,那么不用同步,账户直接就是初始化的
        若broker是其他的,那么需要和broker同步信息,从broker获取初始持仓信息
        这是因为,回测刚开始的账户都是需要初始化的,不需要从broker核对
        Arguments:
            broker_id {[type]} -- [description]
            account_cookie {[type]} -- [description]
        """
        try:
            if isinstance(self.broker[broker_name], QA_BacktestBroker):
                pass
            else:
                self.session[account_cookie].sync_account(
                    self.broker[broker_name].query_positions(account_cookie)
                )
            return True
        except Exception as e:
            print(e)
            return False

    def logout(self, account_cookie, broker_name):
        if account_cookie not in self.session.keys():
            return False
        else:
            self.order_handler.unsubscribe(
                self.session[account_cookie],
                self.broker[broker_name]
            )
            self.session.pop(account_cookie)

    def get_trading_day(self):
        return self.running_time

    def get_account_cookie(self):
        return list(self.session.keys())

    def insert_order(
            self,
            account_cookie,
            amount,
            amount_model,
            time,
            code,
            price,
            order_model,
            towards,
            market_type,
            frequence,
            broker_name,
            money=None
    ):
        #strDbg = QA_util_random_with_topic("QA_Market.insert_order")
        print(
            ">-----------------------insert_order----------------------------->",
            "QA_Market.insert_order"
        )

        flag = False

        # 行情切片 bar/tick/realtime

        price_slice = self.query_data_no_wait(
            broker_name=broker_name,
            frequence=frequence,
            market_type=market_type,
            code=code,
            start=time
        )
        price_slice = price_slice if price_slice is None else price_slice[0]

        if order_model in [ORDER_MODEL.CLOSE, ORDER_MODEL.NEXT_OPEN]:
            if isinstance(price_slice, np.ndarray):
                if (price_slice != np.array(None)).any():
                    price = float(price_slice[4])
                    flag = True
                else:
                    QA_util_log_info(
                        'MARKET WARING: SOMEING WRONG WITH ORDER \n '
                    )
                    QA_util_log_info(
                        'code {} date {} price {} order_model {} amount_model {}'
                        .format(code,
                                time,
                                price,
                                order_model,
                                amount_model)
                    )
            elif isinstance(price_slice, dict):
                if price_slice is not None:
                    price = float(price_slice['close'])
                    flag = True
                else:
                    QA_util_log_info(
                        'MARKET WARING: SOMEING WRONG WITH ORDER \n '
                    )
                    QA_util_log_info(
                        'code {} date {} price {} order_model {} amount_model {}'
                        .format(code,
                                time,
                                price,
                                order_model,
                                amount_model)
                    )
            elif isinstance(price_slice, list):
                if price_slice is not None:
                    price = float(price_slice[4])
                    flag = True
                else:
                    QA_util_log_info(
                        'MARKET WARING: SOMEING WRONG WITH ORDER \n '
                    )
                    QA_util_log_info(
                        'code {} date {} price {} order_model {} amount_model {}'
                        .format(code,
                                time,
                                price,
                                order_model,
                                amount_model)
                    )

        elif order_model is ORDER_MODEL.MARKET:
            if isinstance(price_slice, np.ndarray):
                if (price_slice != np.array(None)).any():
                    price = float(price_slice[1])
                    flag = True
                else:
                    QA_util_log_info(
                        'MARKET WARING: SOMEING WRONG WITH ORDER \n '
                    )
                    QA_util_log_info(
                        'code {} date {} price {} order_model {} amount_model {}'
                        .format(code,
                                time,
                                price,
                                order_model,
                                amount_model)
                    )
            elif isinstance(price_slice, dict):

                if price_slice is not None:
                    price = float(price_slice['open'])
                    flag = True
                else:
                    QA_util_log_info(
                        'MARKET WARING: SOMEING WRONG WITH ORDER \n '
                    )
                    QA_util_log_info(
                        'code {} date {} price {} order_model {} amount_model {}'
                        .format(code,
                                time,
                                price,
                                order_model,
                                amount_model)
                    )
        elif order_model is ORDER_MODEL.LIMIT:
            flag = True
        print(
            amount,
            amount_model,
            time,
            code,
            price,
            order_model,
            towards,
            money
        )
        if flag:
            order = self.get_account(account_cookie).send_order(
                amount=amount,
                amount_model=amount_model,
                time=time,
                code=code,
                price=price,
                order_model=order_model,
                towards=towards,
                money=money
            )
            if order:
                self.order_handler.run(
                    QA_Event(
                        broker=self.broker[self.get_account(account_cookie
                                                           ).broker],
                        event_type=BROKER_EVENT.RECEIVE_ORDER,
                        order=order,
                        market_data=price_slice,
                        callback=self.on_insert_order
                    )
                )
        else:
            pass

    def on_insert_order(self, order: QA_Order):
        print(order)
        print(order.status)
        if order.status == ORDER_STATUS.FAILED:
            """如果订单创建失败, 恢复状态

            如果是买入单  恢复金钱 money

            如果是卖出单  恢复股数 sell_available
            """

            self.session[order.account_cookie].cancel_order(order)
        else:
            if order.order_model in [ORDER_MODEL.MARKET,
                                     ORDER_MODEL.CLOSE,
                                     ORDER_MODEL.LIMIT]:
                self.order_handler._trade(
                    order,
                    self.session[order.account_cookie]
                )                                      # 直接交易
            elif order.order_model in [ORDER_MODEL.NEXT_OPEN]:
                pass

    def _renew_account(self):
        for account in self.session.values():
            account.run(QA_Event(event_type=ACCOUNT_EVENT.SETTLE))

    def _sync_position(self):
        self.order_handler.run(
            QA_Event(
                event_type=MARKET_EVENT.QUERY_POSITION,
                account_cookie=list(self.session.keys()),
                broker=[
                    self.broker[item.broker] for item in self.session.values()
                ]
            )
        )

    def _sync_deals(self):

        self.order_handler.run(
            QA_Event(
                event_type=MARKET_EVENT.QUERY_DEAL,
                account_cookie=list(self.session.keys()),
                broker=[
                    self.broker[item.broker] for item in self.session.values()
                ],
                event_queue=self.trade_engine.kernels_dict['ORDER'].queue
            )
        )

    def _sync_orders(self):
        # account_cookie=list(self.session.keys()),
        # broker=[self.broker[item.broker]
        #         for item in self.session.values()],
        # 注意: 一定要给子线程的队列@@@!!!
        # 2018-08-08 yutiansut
        # 这个callback实现了子线程方法的自我驱动和异步任务
        self.order_handler.run(
            QA_Event(
                event_type=MARKET_EVENT.QUERY_ORDER,
                event_queue=self.trade_engine.kernels_dict['ORDER'].queue
            )
        )

    def sync_strategy(self, broker_name, account_cookie):
        """同步  账户/委托/成交

        Arguments:
            broker_name {[type]} -- [description]
            account_cookie {[type]} -- [description]
        """
        pass

    def cancel_order(self, broker_name, account_cookie, order_id):
        pass

    def cancel_all(self, broker_name, account_cookie):
        try:
            self.broker[broker_name].cancel_all(account_cookie)
        except Exception as e:
            print(e)

    def query_orders(self, account_cookie):
        '''
        从订单队列.订单状态中获取指定账户的所有订单信息
        :param account_cookie:
        :return:
        '''
        return self.order_handler.order_status.xs(account_cookie)

    def query_order(self, account_cookie, realorder_id):
        '''
        从订单队列.订单状态中获取指定账户的指定订单的信息
        :param account_cookie:
        :param realorder_id:
        :return:
        '''
        return self.order_handler.order_status.loc[account_cookie, realorder_id]

    def query_assets(self, account_cookie):
        '''
        查看指定账户的初始资产
        :param account_cookie:
        :return:
        '''
        return self.get_account(account_cookie).init_assets

    def query_position(self, account_cookie):
        '''
        查看指定账户的持仓
        :param account_cookie:
        :return:
        '''
        return self.get_account(account_cookie).hold

    def query_cash(self, account_cookie):
        '''
        查看指定账户的现金
        :param account_cookie:
        :return:
        '''
        return self.get_account(account_cookie).cash_available

    def query_data_no_wait(
            self,
            broker_name,
            frequence,
            market_type,
            code,
            start,
            end=None
        ):
        '''
        从broker获取数据
        :param broker_name:
        :param frequence:
        :param market_type:
        :param code:
        :param start:
        :param end:
        :return:
        '''
        return self.broker[broker_name].run(
            event=QA_Event(
                event_type=MARKET_EVENT.QUERY_DATA,
                frequence=frequence,
                market_type=market_type,
                code=code,
                start=start,
                end=end
            )
        )

    query_data = query_data_no_wait

    def query_currentbar(self, broker_name, market_type, code):
        return self.broker[broker_name].run(
            event=QA_Event(
                event_type=MARKET_EVENT.QUERY_DATA,
                frequence=FREQUENCE.CURRENT,
                market_type=market_type,
                code=code,
                start=self.running_time,
                end=None
            )
        )

    def on_query_data(self, data):
        print('ON QUERY')
        print(data)
        self.last_query_data = data

    def on_trade_event(self, event):
        print('ON TRADE')
        print(event.res)

    def _trade(self, event):
        "内部函数"
        print('==================================market enging: trade')
        print(self.order_handler.order_queue.pending)
        print('==================================')
        self.order_handler._trade()
        print('done')

    def _settle(self, broker_name, callback=False):
        #strDbg = QA_util_random_with_topic("QA_Market._settle")
        print(
            ">-----------------------_settle----------------------------->",
            "QA_Market._settle"
        )

        # 向事件线程发送BROKER的SETTLE事件
        # 向事件线程发送ACCOUNT的SETTLE事件

        for account in self.session.values():
            """t0账户先结算当日仓位
            """
            if account.broker == broker_name:
                if account.running_environment == RUNNING_ENVIRONMENT.TZERO:
                    for order in account.close_positions_order:
                        price_slice = self.query_data_no_wait(
                            broker_name=order.broker,
                            frequence=order.frequence,
                            market_type=order.market_type,
                            code=order.code,
                            start=order.datetime
                        )
                        price_slice = price_slice if price_slice is None else price_slice[
                            0]
                        self.order_handler.run(
                            QA_Event(
                                broker=self.broker[account.broker],
                                event_type=BROKER_EVENT.RECEIVE_ORDER,
                                order=order,
                                market_data=price_slice,
                                callback=self.on_insert_order
                            )
                        )

        self._trade(event=QA_Event(broker_name=broker_name))

        self.broker[broker_name].run(
            QA_Event(
                event_type=BROKER_EVENT.SETTLE,
                broker=self.broker[broker_name],
                callback=callback
            )
        )

        for account in self.session.values():
            print(account.history)
            account.settle()

        print('===== SETTLED {} ====='.format(self.running_time))

    def settle_order(self):
        """交易前置结算

        1. 回测: 交易队列清空,待交易队列标记SETTLE
        2. 账户每日结算
        3. broker结算更新
        """

        if self.if_start_orderthreading:

            self.order_handler.run(
                QA_Event(
                    event_type=BROKER_EVENT.SETTLE,
                    event_queue=self.trade_engine.kernels_dict['ORDER'].queue
                )
            )

    def every_day_start(self):
        """盘前准备

        1. 计算盘前信号
        2. 账户同步
        """
        pass

    def _close(self):
        pass

    def clear(self):
        return self.trade_engine.clear()
Example #3
0
class QA_Market(QA_Trade):
    """
    QUANTAXIS MARKET 部分

    交易前置/可连接到多个broker中
    暂时还是采用多线程engine模式

    session 保存的是 QAAccout 对象
    """

    def __init__(self, if_start_orderthreading=True, *args, **kwargs):
        """MARKET的初始化过程

        Keyword Arguments:
            if_start_orderthreading {bool} -- 是否在初始化的时候开启查询子线程(实盘需要) (default: {False})

        @2018-08-06 change : 子线程全部变成后台线程 market线程崩了 子线程全部结束
        """

        super().__init__()
        # 以下是待初始化的账户session
        self.session = {}
        # 以下都是官方支持的交易前置
        self._broker = {
            BROKER_TYPE.BACKETEST: QA_BacktestBroker,
            BROKER_TYPE.RANDOM: QA_RandomBroker,
            BROKER_TYPE.REAL: QA_RealBroker,
            BROKER_TYPE.SIMULATION: QA_SimulatedBroker,
            BROKER_TYPE.SHIPANE: QA_SPEBroker,
            BROKER_TYPE.TTS: QA_TTSBroker,
        }
        self.broker = {}
        self.running_time = None
        self.last_query_data = None
        self.if_start_orderthreading = if_start_orderthreading
        self.order_handler = QA_OrderHandler()

    def __repr__(self):
        '''
        输出market市场对象的字符串
        '''
        return '<QA_Market with {} QA_Broker >'.format(list(self.broker.keys()))

    def upcoming_data(self, broker, data):
        '''
        更新市场数据
        broker 为名字,
        data 是市场数据
        被 QABacktest 中run 方法调用 upcoming_data
        '''
        # main thread'
        # if self.running_time is not None and self.running_time!= data.datetime[0]:
        #     for item in self.broker.keys():
        #         self._settle(item)
        self.running_time = data.datetime[0]
        for account in self.session.values():
            account.run(QA_Event(
                event_type=ENGINE_EVENT.UPCOMING_DATA,
                # args 附加的参数
                market_data=data,
                broker_name=broker,
                send_order=self.insert_order,  # 🛠todo insert_order = insert_order
                query_data=self.query_data_no_wait,
                query_order=self.query_order,
                query_assets=self.query_assets,
                query_trade=self.query_trade
            ))

    def start(self):
        self.trade_engine.start()
        if self.if_start_orderthreading:
            """查询子线程开关
            """
            self.start_order_threading()
        print(threading.enumerate())

    def connect(self, broker):
        if broker in self._broker.keys():

            self.broker[broker] = self._broker[broker]() # 在这里实例化
                                                         # 2018-08-06 change : 子线程全部变成后台线程 market线程崩了 子线程全部结束
                                                         # self.trade_engine.create_kernel('{}'.format(broker), daemon=True)
                                                         # self.trade_engine.start_kernel('{}'.format(broker))

            # 2019-02-08 change: 在此 我们删除了BROKER所占用的线程

            # 子线程变成功能性线程
            # 开启trade事件子线程
            return True
        else:
            return False

    def next_tradeday(self):
        self.order_handler.run(
            QA_Event(
                event_type=BROKER_EVENT.NEXT_TRADEDAY,
                event_queue=self.trade_engine.kernels_dict['ORDER'].queue
            )
        )

    def register(self, broker_name, broker):
        if broker_name not in self._broker.keys():
            self.broker[broker_name] = broker
            # self.trade_engine.create_kernel(
            #     '{}'.format(broker_name),
            #     daemon=True
            # )
            # self.trade_engine.start_kernel('{}'.format(broker_name))
            return True
        else:
            return False

    def start_order_threading(self):
        """开启查询子线程(实盘中用)
        """

        self.if_start_orderthreading = True

        self.order_handler.if_start_orderquery = True
        self.trade_engine.create_kernel('ORDER', daemon=True)
        self.trade_engine.start_kernel('ORDER')
        self.sync_order_and_deal()
        # self._update_orders()

    def get_account(self, account_cookie):
        try:
            return self.session[account_cookie]
        except KeyError:
            print(
                'QAMARKET: this account {} is logoff, please login and retry'
                .format(account_cookie)
            )

    def login(self, broker_name, account_cookie, account=None):
        """login 登录到交易前置

        2018-07-02 在实盘中,登录到交易前置后,需要同步资产状态

        Arguments:
            broker_name {[type]} -- [description]
            account_cookie {[type]} -- [description]

        Keyword Arguments:
            account {[type]} -- [description] (default: {None})

        Returns:
            [type] -- [description]
        """
        res = False
        if account is None:
            if account_cookie not in self.session.keys():
                self.session[account_cookie] = QA_Account(
                    account_cookie=account_cookie,
                    broker=broker_name
                )
                if self.sync_account(broker_name, account_cookie):
                    res = True

                if self.if_start_orderthreading and res:
                    #
                    self.order_handler.subscribe(
                        self.session[account_cookie],
                        self.broker[broker_name]
                    )

        else:
            if account_cookie not in self.session.keys():
                account.broker = broker_name
                self.session[account_cookie] = account
                if self.sync_account(broker_name, account_cookie):
                    res = True
                if self.if_start_orderthreading and res:
                    #
                    self.order_handler.subscribe(
                        account,
                        self.broker[broker_name]
                    )

        if res:
            return res
        else:
            try:
                self.session.pop(account_cookie)
            except:
                pass
            return False

    def sync_order_and_deal(self):
        self.order_handler.if_start_orderquery = True
        self._sync_orders()

    def stop_sync_order_and_deal(self):
        self.order_handler.if_start_orderquery = False

    def sync_account(self, broker_name, account_cookie):
        """同步账户信息

        Arguments:
            broker_id {[type]} -- [description]
            account_cookie {[type]} -- [description]
        """
        try:
            if isinstance(self.broker[broker_name], QA_BacktestBroker):
                pass
            else:
                self.session[account_cookie].sync_account(
                    self.broker[broker_name].query_positions(account_cookie)
                )
            return True
        except Exception as e:
            print(e)
            return False

    def logout(self, account_cookie, broker_name):
        if account_cookie not in self.session.keys():
            return False
        else:
            self.order_handler.unsubscribe(
                self.session[account_cookie],
                self.broker[broker_name]
            )
            self.session.pop(account_cookie)

    def get_trading_day(self):
        return self.running_time

    def get_account_cookie(self):
        return list(self.session.keys())

    def insert_order(
            self,
            account_cookie,
            amount,
            amount_model,
            time,
            code,
            price,
            order_model,
            towards,
            market_type,
            frequence,
            broker_name,
            money=None
    ):
        #strDbg = QA_util_random_with_topic("QA_Market.insert_order")
        print(
            ">-----------------------insert_order----------------------------->",
            "QA_Market.insert_order"
        )

        flag = False

        # 行情切片 bar/tick/realtime

        price_slice = self.query_data_no_wait(
            broker_name=broker_name,
            frequence=frequence,
            market_type=market_type,
            code=code,
            start=time
        )
        price_slice = price_slice if price_slice is None else price_slice[0]

        if order_model in [ORDER_MODEL.CLOSE, ORDER_MODEL.NEXT_OPEN]:
            if isinstance(price_slice, np.ndarray):
                if (price_slice != np.array(None)).any():
                    price = float(price_slice[4])
                    flag = True
                else:
                    QA_util_log_info(
                        'MARKET WARING: SOMEING WRONG WITH ORDER \n '
                    )
                    QA_util_log_info(
                        'code {} date {} price {} order_model {} amount_model {}'
                        .format(code,
                                time,
                                price,
                                order_model,
                                amount_model)
                    )
            elif isinstance(price_slice, dict):
                if price_slice is not None:
                    price = float(price_slice['close'])
                    flag = True
                else:
                    QA_util_log_info(
                        'MARKET WARING: SOMEING WRONG WITH ORDER \n '
                    )
                    QA_util_log_info(
                        'code {} date {} price {} order_model {} amount_model {}'
                        .format(code,
                                time,
                                price,
                                order_model,
                                amount_model)
                    )
            elif isinstance(price_slice, list):
                if price_slice is not None:
                    price = float(price_slice[4])
                    flag = True
                else:
                    QA_util_log_info(
                        'MARKET WARING: SOMEING WRONG WITH ORDER \n '
                    )
                    QA_util_log_info(
                        'code {} date {} price {} order_model {} amount_model {}'
                        .format(code,
                                time,
                                price,
                                order_model,
                                amount_model)
                    )

        elif order_model is ORDER_MODEL.MARKET:
            if isinstance(price_slice, np.ndarray):
                if (price_slice != np.array(None)).any():
                    price = float(price_slice[1])
                    flag = True
                else:
                    QA_util_log_info(
                        'MARKET WARING: SOMEING WRONG WITH ORDER \n '
                    )
                    QA_util_log_info(
                        'code {} date {} price {} order_model {} amount_model {}'
                        .format(code,
                                time,
                                price,
                                order_model,
                                amount_model)
                    )
            elif isinstance(price_slice, dict):

                if price_slice is not None:
                    price = float(price_slice['open'])
                    flag = True
                else:
                    QA_util_log_info(
                        'MARKET WARING: SOMEING WRONG WITH ORDER \n '
                    )
                    QA_util_log_info(
                        'code {} date {} price {} order_model {} amount_model {}'
                        .format(code,
                                time,
                                price,
                                order_model,
                                amount_model)
                    )
        elif order_model is ORDER_MODEL.LIMIT:
            flag = True
        print(
            amount,
            amount_model,
            time,
            code,
            price,
            order_model,
            towards,
            money
        )
        if flag:
            order = self.get_account(account_cookie).send_order(
                amount=amount,
                amount_model=amount_model,
                time=time,
                code=code,
                price=price,
                order_model=order_model,
                towards=towards,
                money=money
            )
            if order:
                self.order_handler.run(
                    QA_Event(
                        broker=self.broker[self.get_account(account_cookie
                                                           ).broker],
                        event_type=BROKER_EVENT.RECEIVE_ORDER,
                        order=order,
                        market_data=price_slice,
                        callback=self.on_insert_order
                    )
                )
        else:
            pass

    def on_insert_order(self, order: QA_Order):
        print(order)
        print(order.status)
        if order.status == ORDER_STATUS.FAILED:
            """如果订单创建失败, 恢复状态

            如果是买入单  恢复金钱 money

            如果是卖出单  恢复股数 sell_available
            """

            self.session[order.account_cookie].cancel_order(order)
        else:
            if order.order_model in [ORDER_MODEL.MARKET,
                                     ORDER_MODEL.CLOSE,
                                     ORDER_MODEL.LIMIT]:
                self.order_handler._trade(
                    order,
                    self.session[order.account_cookie]
                )                                      # 直接交易
            elif order.order_model in [ORDER_MODEL.NEXT_OPEN]:
                pass

    def _renew_account(self):
        for account in self.session.values():
            account.run(QA_Event(event_type=ACCOUNT_EVENT.SETTLE))

    def _sync_position(self):
        self.order_handler.run(
            QA_Event(
                event_type=MARKET_EVENT.QUERY_POSITION,
                account_cookie=list(self.session.keys()),
                broker=[
                    self.broker[item.broker] for item in self.session.values()
                ]
            )
        )

    def _sync_deals(self):

        self.order_handler.run(
            QA_Event(
                event_type=MARKET_EVENT.QUERY_DEAL,
                account_cookie=list(self.session.keys()),
                broker=[
                    self.broker[item.broker] for item in self.session.values()
                ],
                event_queue=self.trade_engine.kernels_dict['ORDER'].queue
            )
        )

    def _sync_orders(self):
        # account_cookie=list(self.session.keys()),
        # broker=[self.broker[item.broker]
        #         for item in self.session.values()],
        # 注意: 一定要给子线程的队列@@@!!!
        # 2018-08-08 yutiansut
        # 这个callback实现了子线程方法的自我驱动和异步任务
        self.order_handler.run(
            QA_Event(
                event_type=MARKET_EVENT.QUERY_ORDER,
                event_queue=self.trade_engine.kernels_dict['ORDER'].queue
            )
        )

    def sync_strategy(self, broker_name, account_cookie):
        """同步  账户/委托/成交

        Arguments:
            broker_name {[type]} -- [description]
            account_cookie {[type]} -- [description]
        """
        pass

    def cancel_order(self, broker_name, account_cookie, order_id):
        pass

    def cancel_all(self, broker_name, account_cookie):
        try:
            self.broker[broker_name].cancel_all(account_cookie)
        except Exception as e:
            print(e)

    def query_orders(self, account_cookie):
        return self.order_handler.order_status.xs(account_cookie)

    def query_order(self, account_cookie, realorder_id):
        return self.order_handler.order_status.loc[account_cookie, realorder_id]

    def query_assets(self, account_cookie):
        return self.get_account(account_cookie).init_assets

    def query_position(self, account_cookie):
        return self.get_account(account_cookie).hold

    def query_cash(self, account_cookie):
        return self.get_account(account_cookie).cash_available

    def query_data_no_wait(
            self,
            broker_name,
            frequence,
            market_type,
            code,
            start,
            end=None
    ):
        return self.broker[broker_name].run(
            event=QA_Event(
                event_type=MARKET_EVENT.QUERY_DATA,
                frequence=frequence,
                market_type=market_type,
                code=code,
                start=start,
                end=end
            )
        )

    query_data = query_data_no_wait

    def query_currentbar(self, broker_name, market_type, code):
        return self.broker[broker_name].run(
            event=QA_Event(
                event_type=MARKET_EVENT.QUERY_DATA,
                frequence=FREQUENCE.CURRENT,
                market_type=market_type,
                code=code,
                start=self.running_time,
                end=None
            )
        )

    def on_query_data(self, data):
        print('ON QUERY')
        print(data)
        self.last_query_data = data

    def on_trade_event(self, event):
        print('ON TRADE')
        print(event.res)

    def _trade(self, event):
        "内部函数"
        print('==================================market enging: trade')
        print(self.order_handler.order_queue.pending)
        print('==================================')
        self.order_handler._trade()
        print('done')

    def _settle(self, broker_name, callback=False):
        #strDbg = QA_util_random_with_topic("QA_Market._settle")
        print(
            ">-----------------------_settle----------------------------->",
            "QA_Market._settle"
        )

        # 向事件线程发送BROKER的SETTLE事件
        # 向事件线程发送ACCOUNT的SETTLE事件

        for account in self.session.values():
            """t0账户先结算当日仓位
            """
            if account.broker == broker_name:
                if account.running_environment == RUNNING_ENVIRONMENT.TZERO:
                    for order in account.close_positions_order:
                        price_slice = self.query_data_no_wait(
                            broker_name=order.broker,
                            frequence=order.frequence,
                            market_type=order.market_type,
                            code=order.code,
                            start=order.datetime
                        )
                        price_slice = price_slice if price_slice is None else price_slice[
                            0]
                        self.order_handler.run(
                            QA_Event(
                                broker=self.broker[account.broker],
                                event_type=BROKER_EVENT.RECEIVE_ORDER,
                                order=order,
                                market_data=price_slice,
                                callback=self.on_insert_order
                            )
                        )

        self._trade(event=QA_Event(broker_name=broker_name))

        self.broker[broker_name].run(
            QA_Event(
                event_type=BROKER_EVENT.SETTLE,
                broker=self.broker[broker_name],
                callback=callback
            )
        )

        for account in self.session.values():
            print(account.history)
            account.settle()

        print('===== SETTLED {} ====='.format(self.running_time))

    def settle_order(self):
        """交易前置结算

        1. 回测: 交易队列清空,待交易队列标记SETTLE
        2. 账户每日结算
        3. broker结算更新
        """

        if self.if_start_orderthreading:

            self.order_handler.run(
                QA_Event(
                    event_type=BROKER_EVENT.SETTLE,
                    event_queue=self.trade_engine.kernels_dict['ORDER'].queue
                )
            )

    def every_day_start(self):
        """盘前准备

        1. 计算盘前信号
        2. 账户同步
        """
        pass

    def _close(self):
        pass

    def clear(self):
        return self.trade_engine.clear()