Beispiel #1
0
    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()
Beispiel #2
0
    def __init__(self, auto_logon=True):
        super().__init__()
        self.name = BROKER_TYPE.TTS
        self.config = TTSConfig()
        self.order_handler = QA_OrderHandler()
        self._endpoint = 'http://%s:%s/api' % (
            self.config.values['trade_server_ip'],
            self.config.values['trade_server_port'])
        self._encoding = "utf-8"
        if self.config.values['transport_enc_key'] == '' or self.config.values[
                'transport_enc_iv'] == '':
            self._transport_enc = False
            self._transport_enc_key = None
            self._transport_enc_iv = None
            self._cipher = None
        else:
            self._transport_enc = True
            self._transport_enc_key = bytes(
                self.config.values['transport_enc_key'],
                encoding=self._encoding)
            self._transport_enc_iv = bytes(
                self.config.values['transport_enc_iv'],
                encoding=self._encoding)
            self._cipher = Cipher(algorithms.AES(self._transport_enc_key),
                                  modes.CBC(self._transport_enc_iv),
                                  backend=default_backend())

        self._session = requests.Session()
        self.client_id = 0
        self.gddm_sh = 0  # 上海股东代码
        self.gddm_sz = 0  # 深圳股东代码

        if auto_logon is True:
            self.logon()
    def __init__(self, if_nondatabase=False):
        """[summary]


        Keyword Arguments:
            commission_fee_coeff {[type]} -- [description] (default: {0})
            environment {[type]} -- [description] (default: {RUNNING_ENVIRONMENT})
            if_nondatabase {[type]} -- [description] (default: {False})
        """
        super().__init__()
        self.dealer = QA_Dealer()
        self.order_handler = QA_OrderHandler()
        self.engine = {
            MARKET_TYPE.STOCK_CN: self.dealer.backtest_stock_dealer}

        self.fetcher = {(MARKET_TYPE.STOCK_CN, FREQUENCE.DAY): QA_fetch_stock_day, (MARKET_TYPE.STOCK_CN, FREQUENCE.FIFTEEN_MIN): QA_fetch_stock_min,
                        (MARKET_TYPE.STOCK_CN, FREQUENCE.ONE_MIN): QA_fetch_stock_min, (MARKET_TYPE.STOCK_CN, FREQUENCE.FIVE_MIN): QA_fetch_stock_min,
                        (MARKET_TYPE.STOCK_CN, FREQUENCE.THIRTY_MIN): QA_fetch_stock_min, (MARKET_TYPE.STOCK_CN, FREQUENCE.SIXTY_MIN): QA_fetch_stock_min,
                        (MARKET_TYPE.INDEX_CN, FREQUENCE.DAY): QA_fetch_index_day, (MARKET_TYPE.INDEX_CN, FREQUENCE.FIFTEEN_MIN): QA_fetch_index_min,
                        (MARKET_TYPE.INDEX_CN, FREQUENCE.ONE_MIN): QA_fetch_index_min, (MARKET_TYPE.INDEX_CN, FREQUENCE.FIVE_MIN): QA_fetch_index_min,
                        (MARKET_TYPE.INDEX_CN, FREQUENCE.THIRTY_MIN): QA_fetch_index_min, (MARKET_TYPE.INDEX_CN, FREQUENCE.SIXTY_MIN): QA_fetch_index_min,
                        (MARKET_TYPE.FUND_CN, FREQUENCE.DAY): QA_fetch_index_day, (MARKET_TYPE.FUND_CN, FREQUENCE.FIFTEEN_MIN): QA_fetch_index_min,
                        (MARKET_TYPE.FUND_CN, FREQUENCE.ONE_MIN): QA_fetch_index_min, (MARKET_TYPE.FUND_CN, FREQUENCE.FIVE_MIN): QA_fetch_index_min,
                        (MARKET_TYPE.FUND_CN, FREQUENCE.THIRTY_MIN): QA_fetch_index_min, (MARKET_TYPE.FUND_CN, FREQUENCE.SIXTY_MIN): QA_fetch_index_min}

        self.market_data = None
        self.if_nondatabase = if_nondatabase
        self.name = BROKER_TYPE.BACKETEST
        self._quotation = {}  # 一个可以缓存数据的dict
        self.broker_data = None
        self.deal_message = {}
Beispiel #4
0
    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()
Beispiel #5
0
 def __init__(self):
     super().__init__()
     self.name = BROKER_TYPE.SHIPANE
     self.order_handler = QA_OrderHandler()
     self.setting = get_config_SPE()
     self._session = requests
     self._endpoint = self.setting.uri
     self.key = self.setting.key
Beispiel #6
0
    def __init__(self,
                 endpoint="http://127.0.0.1:10092/api",
                 encoding="utf-8",
                 enc_key=None,
                 enc_iv=None):
        super().__init__()
        self.name = BROKER_TYPE.TTS
        self.order_handler = QA_OrderHandler()
        self._endpoint = endpoint
        self._encoding = "utf-8"
        if enc_key == None or enc_iv == None:
            self._transport_enc = False
            self._transport_enc_key = None
            self._transport_enc_iv = None
            self._cipher = None
        else:
            self._transport_enc = True
            self._transport_enc_key = enc_key
            self._transport_enc_iv = enc_iv
            backend = default_backend()
            self._cipher = Cipher(algorithms.AES(enc_key),
                                  modes.CBC(enc_iv),
                                  backend=backend)

        self._session = requests.Session()
        self.client_id = 0
        self.gddm_sh = 0  #上海股东代码
        self.gddm_sz = 0  #深圳股东代码

        self.fetcher = {
            (MARKET_TYPE.STOCK_CN, FREQUENCE.DAY): QA_fetch_get_stock_day,
            (MARKET_TYPE.STOCK_CN, FREQUENCE.FIFTEEN_MIN):
            QA_fetch_get_stock_min,
            (MARKET_TYPE.STOCK_CN, FREQUENCE.ONE_MIN): QA_fetch_get_stock_min,
            (MARKET_TYPE.STOCK_CN, FREQUENCE.FIVE_MIN): QA_fetch_get_stock_min,
            (MARKET_TYPE.STOCK_CN, FREQUENCE.THIRTY_MIN):
            QA_fetch_get_stock_min,
            (MARKET_TYPE.STOCK_CN, FREQUENCE.SIXTY_MIN):
            QA_fetch_get_stock_min,
            (MARKET_TYPE.INDEX_CN, FREQUENCE.DAY): QA_fetch_get_index_day,
            (MARKET_TYPE.INDEX_CN, FREQUENCE.FIFTEEN_MIN):
            QA_fetch_get_index_min,
            (MARKET_TYPE.INDEX_CN, FREQUENCE.ONE_MIN): QA_fetch_get_index_min,
            (MARKET_TYPE.INDEX_CN, FREQUENCE.FIVE_MIN): QA_fetch_get_index_min,
            (MARKET_TYPE.INDEX_CN, FREQUENCE.THIRTY_MIN):
            QA_fetch_get_index_min,
            (MARKET_TYPE.INDEX_CN, FREQUENCE.SIXTY_MIN):
            QA_fetch_get_index_min,
            (MARKET_TYPE.FUND_CN, FREQUENCE.DAY): QA_fetch_get_index_day,
            (MARKET_TYPE.FUND_CN, FREQUENCE.FIFTEEN_MIN):
            QA_fetch_get_index_min,
            (MARKET_TYPE.FUND_CN, FREQUENCE.ONE_MIN): QA_fetch_get_index_min,
            (MARKET_TYPE.FUND_CN, FREQUENCE.FIVE_MIN): QA_fetch_get_index_min,
            (MARKET_TYPE.FUND_CN, FREQUENCE.THIRTY_MIN):
            QA_fetch_get_index_min,
            (MARKET_TYPE.FUND_CN, FREQUENCE.SIXTY_MIN): QA_fetch_get_index_min
        }
Beispiel #7
0
    def __init__(self):
        self.order_handler = QA_OrderHandler()
        self.setting = get_config_SPE()
        self._session = requests
        self._endpoint = self.setting.uri
        self.key = self.setting.key

        #self.account_headers = ['forzen_cash','balance_available','cash_available','pnl_money_today','total_assets','pnl_holding','market_value','money_available']
        self.fillorder_headers = ['name', 'datetime', 'towards', 'price',
                                  'amount', 'money', 'trade_id', 'order_id', 'code', 'shareholder', 'other']
        self.holding_headers = ['code', 'name', 'hoding_price', 'price', 'pnl', 'amount',
                                'sell_available', 'pnl_money', 'holdings', 'total_amount', 'lastest_amounts', 'shareholder']
        self.askorder_headers = ['code', 'towards', 'price', 'amount', 'transaction_price',
                                 'transaction_amount', 'status', 'order_time', 'order_id', 'id', 'code', 'shareholders']
    def __init__(self,if_nondatabase=False):
        """[summary]


        Keyword Arguments:
            commission_fee_coeff {[type]} -- [description] (default: {0})
            environment {[type]} -- [description] (default: {RUNNING_ENVIRONMENT})
            if_nondatabase {[type]} -- [description] (default: {False})
        """
        super().__init__()
        self.dealer = QA_Dealer()
        self.order_handler = QA_OrderHandler()
        self.engine = {
            MARKET_TYPE.STOCK_CN: self.dealer.backtest_stock_dealer}

        self.fetcher = {(MARKET_TYPE.STOCK_CN, FREQUENCE.DAY): QA_fetch_stock_day, (MARKET_TYPE.STOCK_CN, FREQUENCE.FIFTEEN_MIN): QA_fetch_stock_min,
                        (MARKET_TYPE.STOCK_CN, FREQUENCE.ONE_MIN): QA_fetch_stock_min, (MARKET_TYPE.STOCK_CN, FREQUENCE.FIVE_MIN): QA_fetch_stock_min,
                        (MARKET_TYPE.STOCK_CN, FREQUENCE.THIRTY_MIN): QA_fetch_stock_min, (MARKET_TYPE.STOCK_CN, FREQUENCE.SIXTY_MIN): QA_fetch_stock_min,
                        (MARKET_TYPE.INDEX_CN, FREQUENCE.DAY): QA_fetch_index_day, (MARKET_TYPE.INDEX_CN, FREQUENCE.FIFTEEN_MIN): QA_fetch_index_min,
                        (MARKET_TYPE.INDEX_CN, FREQUENCE.ONE_MIN): QA_fetch_index_min, (MARKET_TYPE.INDEX_CN, FREQUENCE.FIVE_MIN): QA_fetch_index_min,
                        (MARKET_TYPE.INDEX_CN, FREQUENCE.THIRTY_MIN): QA_fetch_index_min, (MARKET_TYPE.INDEX_CN, FREQUENCE.SIXTY_MIN): QA_fetch_index_min,
                        (MARKET_TYPE.FUND_CN, FREQUENCE.DAY): QA_fetch_index_day, (MARKET_TYPE.FUND_CN, FREQUENCE.FIFTEEN_MIN): QA_fetch_index_min,
                        (MARKET_TYPE.FUND_CN, FREQUENCE.ONE_MIN): QA_fetch_index_min, (MARKET_TYPE.FUND_CN, FREQUENCE.FIVE_MIN): QA_fetch_index_min,
                        (MARKET_TYPE.FUND_CN, FREQUENCE.THIRTY_MIN): QA_fetch_index_min, (MARKET_TYPE.FUND_CN, FREQUENCE.SIXTY_MIN): QA_fetch_index_min}


        self.market_data = None
        self.if_nondatabase = if_nondatabase
        self.name = BROKER_TYPE.BACKETEST
        self._quotation = {}  # 一个可以缓存数据的dict
        self.broker_data = None
Beispiel #9
0
    def __init__(self, auto_logon=True):
        super().__init__()
        self.name = BROKER_TYPE.TTS
        self.config = TTSConfig()
        self.order_handler = QA_OrderHandler()
        self._endpoint = 'http://%s:%s/api' % (
            self.config.values['trade_server_ip'], self.config.values['trade_server_port'])
        self._encoding = "utf-8"
        if self.config.values['transport_enc_key'] == '' or self.config.values['transport_enc_iv'] == '':
            self._transport_enc = False
            self._transport_enc_key = None
            self._transport_enc_iv = None
            self._cipher = None
        else:
            self._transport_enc = True
            self._transport_enc_key = bytes(
                self.config.values['transport_enc_key'], encoding=self._encoding)
            self._transport_enc_iv = bytes(
                self.config.values['transport_enc_iv'], encoding=self._encoding)
            self._cipher = Cipher(
                algorithms.AES(self._transport_enc_key),
                modes.CBC(self._transport_enc_iv),
                backend=default_backend())

        self._session = requests.Session()
        self.client_id = 0
        self.gddm_sh = 0  # 上海股东代码
        self.gddm_sz = 0  # 深圳股东代码

        if auto_logon is True:
            self.logon()
Beispiel #10
0
    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()
Beispiel #11
0
 def __init__(self):
     super().__init__()
     self.name = BROKER_TYPE.SHIPANE
     self.order_handler = QA_OrderHandler()
     self.setting = get_config_SPE()
     self._session = requests
     self._endpoint = self.setting.uri
     self.key = self.setting.key
Beispiel #12
0
    def start_order_threading(self):
        """开启查询子线程(实盘中用)
        """

        self.if_start_orderthreading = True
        self.order_handler = QA_OrderHandler()
        self.trade_engine.create_kernel('ORDER')
        self.trade_engine.start_kernel('ORDER')
Beispiel #13
0
    def __init__(self,
                 endpoint="http://127.0.0.1:10092/api",
                 encoding="utf-8",
                 enc_key=None,
                 enc_iv=None):
        super().__init__()
        self.name = BROKER_TYPE.TTS
        self.order_handler = QA_OrderHandler()
        self._endpoint = endpoint
        self._encoding = "utf-8"
        if enc_key == None or enc_iv == None:
            self._transport_enc = False
            self._transport_enc_key = None
            self._transport_enc_iv = None
            self._cipher = None
        else:
            self._transport_enc = True
            self._transport_enc_key = enc_key
            self._transport_enc_iv = enc_iv
            backend = default_backend()
            self._cipher = Cipher(algorithms.AES(enc_key),
                                  modes.CBC(enc_iv),
                                  backend=backend)

        self._session = requests.Session()
        self.client_id = 0
        self.gddm_sh = 0  #上海股东代码
        self.gddm_sz = 0  #深圳股东代码

        self.fetcher = {
            (MARKET_TYPE.STOCK_CN, FREQUENCE.DAY): QA_fetch_get_stock_day,
            (MARKET_TYPE.STOCK_CN, FREQUENCE.FIFTEEN_MIN):
            QA_fetch_get_stock_min,
            (MARKET_TYPE.STOCK_CN, FREQUENCE.ONE_MIN): QA_fetch_get_stock_min,
            (MARKET_TYPE.STOCK_CN, FREQUENCE.FIVE_MIN): QA_fetch_get_stock_min,
            (MARKET_TYPE.STOCK_CN, FREQUENCE.THIRTY_MIN):
            QA_fetch_get_stock_min,
            (MARKET_TYPE.STOCK_CN, FREQUENCE.SIXTY_MIN):
            QA_fetch_get_stock_min,
            (MARKET_TYPE.INDEX_CN, FREQUENCE.DAY): QA_fetch_get_index_day,
            (MARKET_TYPE.INDEX_CN, FREQUENCE.FIFTEEN_MIN):
            QA_fetch_get_index_min,
            (MARKET_TYPE.INDEX_CN, FREQUENCE.ONE_MIN): QA_fetch_get_index_min,
            (MARKET_TYPE.INDEX_CN, FREQUENCE.FIVE_MIN): QA_fetch_get_index_min,
            (MARKET_TYPE.INDEX_CN, FREQUENCE.THIRTY_MIN):
            QA_fetch_get_index_min,
            (MARKET_TYPE.INDEX_CN, FREQUENCE.SIXTY_MIN):
            QA_fetch_get_index_min,
            (MARKET_TYPE.FUND_CN, FREQUENCE.DAY): QA_fetch_get_index_day,
            (MARKET_TYPE.FUND_CN, FREQUENCE.FIFTEEN_MIN):
            QA_fetch_get_index_min,
            (MARKET_TYPE.FUND_CN, FREQUENCE.ONE_MIN): QA_fetch_get_index_min,
            (MARKET_TYPE.FUND_CN, FREQUENCE.FIVE_MIN): QA_fetch_get_index_min,
            (MARKET_TYPE.FUND_CN, FREQUENCE.THIRTY_MIN):
            QA_fetch_get_index_min,
            (MARKET_TYPE.FUND_CN, FREQUENCE.SIXTY_MIN): QA_fetch_get_index_min
        }

        #通过代码前缀区分market_type
        self.code_table = {
            '000': {
                'type': 'stock',
                'market': 'SZ'
            },
            '001': {
                'type': 'stock',
                'market': 'SZ'
            },
            '002': {
                'type': 'stock',
                'market': 'SZ'
            },
            '150': {
                'type': 'fj',
                'market': 'SZ'
            },
            '159': {
                'type': 'etf',
                'market': 'SZ'
            },
            '161': {
                'type': 'etf',
                'market': 'SZ'
            },
            '163': {
                'type': 'etf',
                'market': 'SZ'
            },
            '164': {
                'type': 'etf',
                'market': 'SZ'
            },
            '168': {
                'type': 'etf',
                'market': 'SZ'
            },
            '169': {
                'type': 'etf',
                'market': 'SZ'
            },
            '300': {
                'type': 'stock',
                'market': 'SZ'
            },
            '501': {
                'type': 'etf',
                'market': 'SH'
            },
            '502': {
                'type': 'fj',
                'market': 'SH'
            },
            '510': {
                'type': 'etf',
                'market': 'SH'
            },
            '511': {
                'type': 'etf',
                'market': 'SH'
            },
            '512': {
                'type': 'etf',
                'market': 'SH'
            },
            '513': {
                'type': 'etf',
                'market': 'SH'
            },
            '518': {
                'type': 'etf',
                'market': 'SH'
            },
            '600': {
                'type': 'stock',
                'market': 'SH'
            },
            '601': {
                'type': 'stock',
                'market': 'SH'
            },
            '603': {
                'type': 'stock',
                'market': 'SH'
            },
        }
Beispiel #14
0
class QA_TTSBroker(QA_Broker):
    fetcher = {(MARKET_TYPE.STOCK_CN, FREQUENCE.DAY): QA_fetch_get_stock_day,
               (MARKET_TYPE.STOCK_CN, FREQUENCE.FIFTEEN_MIN): QA_fetch_get_stock_min,
               (MARKET_TYPE.STOCK_CN, FREQUENCE.ONE_MIN): QA_fetch_get_stock_min,
               (MARKET_TYPE.STOCK_CN, FREQUENCE.FIVE_MIN): QA_fetch_get_stock_min,
               (MARKET_TYPE.STOCK_CN, FREQUENCE.THIRTY_MIN): QA_fetch_get_stock_min,
               (MARKET_TYPE.STOCK_CN, FREQUENCE.SIXTY_MIN): QA_fetch_get_stock_min,
               (MARKET_TYPE.INDEX_CN, FREQUENCE.DAY): QA_fetch_get_index_day,
               (MARKET_TYPE.INDEX_CN, FREQUENCE.FIFTEEN_MIN): QA_fetch_get_index_min,
               (MARKET_TYPE.INDEX_CN, FREQUENCE.ONE_MIN): QA_fetch_get_index_min,
               (MARKET_TYPE.INDEX_CN, FREQUENCE.FIVE_MIN): QA_fetch_get_index_min,
               (MARKET_TYPE.INDEX_CN, FREQUENCE.THIRTY_MIN): QA_fetch_get_index_min,
               (MARKET_TYPE.INDEX_CN, FREQUENCE.SIXTY_MIN): QA_fetch_get_index_min,
               (MARKET_TYPE.FUND_CN, FREQUENCE.DAY): QA_fetch_get_index_day,
               (MARKET_TYPE.FUND_CN, FREQUENCE.FIFTEEN_MIN): QA_fetch_get_index_min,
               (MARKET_TYPE.FUND_CN, FREQUENCE.ONE_MIN): QA_fetch_get_index_min,
               (MARKET_TYPE.FUND_CN, FREQUENCE.FIVE_MIN): QA_fetch_get_index_min,
               (MARKET_TYPE.FUND_CN, FREQUENCE.THIRTY_MIN): QA_fetch_get_index_min,
               (MARKET_TYPE.FUND_CN, FREQUENCE.SIXTY_MIN): QA_fetch_get_index_min}

    def __init__(self, auto_logon=True):
        super().__init__()
        self.name = BROKER_TYPE.TTS
        self.config = TTSConfig()
        self.order_handler = QA_OrderHandler()
        self._endpoint = 'http://%s:%s/api' % (
            self.config.values['trade_server_ip'], self.config.values['trade_server_port'])
        self._encoding = "utf-8"
        if self.config.values['transport_enc_key'] == '' or self.config.values['transport_enc_iv'] == '':
            self._transport_enc = False
            self._transport_enc_key = None
            self._transport_enc_iv = None
            self._cipher = None
        else:
            self._transport_enc = True
            self._transport_enc_key = bytes(
                self.config.values['transport_enc_key'], encoding=self._encoding)
            self._transport_enc_iv = bytes(
                self.config.values['transport_enc_iv'], encoding=self._encoding)
            self._cipher = Cipher(
                algorithms.AES(self._transport_enc_key),
                modes.CBC(self._transport_enc_iv),
                backend=default_backend())

        self._session = requests.Session()
        self.client_id = 0
        self.gddm_sh = 0  # 上海股东代码
        self.gddm_sz = 0  # 深圳股东代码

        if auto_logon is True:
            self.logon()

    def call(self, func, params=None):

        json_obj = {
            "func": func
        }

        if params is not None:
            json_obj["params"] = params

        if self._transport_enc:
            data_to_send = self.encrypt(json_obj)
            response = self._session.post(self._endpoint, data=data_to_send)
        else:
            response = self._session.post(self._endpoint, json=json_obj)
        response.encoding = self._encoding
        text = response.text

        if self._transport_enc:
            decoded_text = self.decrypt(text)
            # print(decoded_text)
            return json.loads(decoded_text)
        else:
            return json.loads(text)

    def encrypt(self, source_obj):
        encrypter = self._cipher.encryptor()
        source = json.dumps(source_obj)
        source = source.encode(self._encoding)
        need_to_padding = 16 - (len(source) % 16)
        if need_to_padding > 0:
            source = source + b'\x00' * need_to_padding
        enc_data = encrypter.update(source) + encrypter.finalize()
        b64_enc_data = base64.encodebytes(enc_data)
        return urllib.parse.quote(b64_enc_data)

    def decrypt(self, source):
        decrypter = self._cipher.decryptor()
        source = urllib.parse.unquote(source)
        source = base64.decodebytes(source.encode("utf-8"))
        data_bytes = decrypter.update(source) + decrypter.finalize()
        return data_bytes.rstrip(b"\x00").decode(self._encoding)

    def data_to_df(self, result):
        if 'data' in result:
            data = result['data']
            df = pd.DataFrame(data=data)
            df.rename(
                columns=lambda x: cn_en_compare[x] if x in cn_en_compare else x, inplace=True)
            if hasattr(df, 'towards'):
                df.towards = df.towards.apply(
                    lambda x: trade_towards_cn_en[x] if x in trade_towards_cn_en else x)
            if hasattr(df, 'status'):
                df.status = df.status.apply(
                    lambda x: order_status_cn_en[x] if x in order_status_cn_en else x)
            if hasattr(df, 'order_time'):
                df.order_time = df.order_time.apply(
                    lambda x: '{} {}'.format(
                        datetime.date.today().strftime('%Y-%m-%d'),
                        datetime.datetime.strptime(x, '%H%M%S').strftime('%H:%M:%S')))
            if hasattr(df, 'trade_time'):
                df.trade_time = df.trade_time.apply(
                    lambda x: '{} {}'.format(
                        datetime.date.today().strftime('%Y-%m-%d'),
                        datetime.datetime.strptime(x, '%H%M%S').strftime('%H:%M:%S')))
            if hasattr(df, 'realorder_id'):
                df.realorder_id = df.realorder_id.apply(str)
            if hasattr(df, 'amount'):
                df.amount = df.amount.apply(pd.to_numeric)
            if hasattr(df, 'price'):
                df.price = df.price.apply(pd.to_numeric)
            if hasattr(df, 'money'):
                df.money = df.money.apply(pd.to_numeric)
            if hasattr(df, 'trade_amount'):
                df.trade_amount = df.trade_amount.apply(pd.to_numeric)
            if hasattr(df, 'trade_price'):
                df.trade_price = df.trade_price.apply(pd.to_numeric)
            if hasattr(df, 'trade_money'):
                df.trade_money = df.trade_money.apply(pd.to_numeric)
            if hasattr(df, 'order_price'):
                df.order_price = df.order_price.apply(pd.to_numeric)
            if hasattr(df, 'order_amount'):
                df.order_amount = df.order_amount.apply(pd.to_numeric)
            if hasattr(df, 'order_money'):
                df.order_money = df.order_money.apply(pd.to_numeric)
            if hasattr(df, 'cancel_amount'):
                df.cancel_amount = df.cancel_amount.apply(pd.to_numeric)
            return df
        else:
            return pd.DataFrame()

    #------ functions

    def ping(self):

        return self.call("ping", {})

    def logon(self):
        data = self.call("logon", {
            "ip": self.config.values['tdx_server_ip'],
            "port": int(self.config.values['tdx_server_port']),
            "version": self.config.values['tdx_version'],
            "yyb_id": int(self.config.values['user_yyb']),
            "account_no": self.config.values['user_name'],
            "trade_account": self.config.values['user_name'],
            "jy_password": self.config.values['user_pass'],
            "tx_password": self.config.values['user_tx_pass']
        })
        if data['success']:
            self.client_id = data["data"]["client_id"]
            self.gddm_sh = self.query_data(5)['data'][0]['股东代码']
            self.gddm_sz = self.query_data(5)['data'][1]['股东代码']
            print('上海股东代码:%s,深圳股东代码:%s', self.gddm_sh, self.gddm_sz)
        return data

    def logoff(self):
        return self.call("logoff", {
            "client_id": self.client_id
        })

    def query_data(self,  category):
        return self.call("query_data", {
            "client_id": self.client_id,
            "category": category
        })

    def send_order(self,  code, price, amount, towards, order_model, market=None):
        """下单

        Arguments:
            code {[type]} -- [description]
            price {[type]} -- [description]
            amount {[type]} -- [description]
            towards {[type]} -- [description]
            order_model {[type]} -- [description]
            market:市场,SZ 深交所,SH 上交所

        Returns:
            [type] -- [description]
        """

        towards = 0 if towards == ORDER_DIRECTION.BUY else 1
        if order_model == ORDER_MODEL.MARKET:
            order_model = 4
        elif order_model == ORDER_MODEL.LIMIT:
            order_model = 0

        if market is None:
            market = QAFetch.base.get_stock_market(code)
        if not isinstance(market, str):
            raise Exception('%s不正确,请检查code和market参数' % market)
        market = market.lower()
        if market not in ['sh', 'sz']:
            raise Exception('%s不支持,请检查code和market参数' % market)

        return self.data_to_df(self.call("send_order", {
            'client_id': self.client_id,
            'category': towards,
            'price_type': order_model,
            'gddm': self.gddm_sh if market == 'sh' else self.gddm_sz,
            'zqdm': code,
            'price': price,
            'quantity': amount
        }))

    def cancel_order(self, exchange_id, order_id):
        """

        Arguments:
            exchange_id {[type]} -- 交易所  0 深圳 1上海 (偶尔2是深圳)
            order_id {[type]} -- [description]

        Returns:
            [type] -- [description]
        """

        return self.call("cancel_order", {
            'client_id': self.client_id,
            'exchange_id': exchange_id,
            'hth': order_id
        })

    def get_quote(self, code):
        return self.call("get_quote", {
            'client_id': self.client_id,
            'code': code,
        })

    def repay(self,  amount):
        return self.call("repay", {
            'client_id': self.client_id,
            'amount': amount
        })

    def receive_order(self, event):
        res = self.send_order(code=event.order.code, price=event.order.price, amount=event.order.amount,
                              towards=event.order.towards, order_model=event.order.order_model)
        try:
            event.order.queued(res.realorder_id[0])
            print('success receive order {}'.format(event.order.realorder_id))
        except Exception as e:
            print(res.realorder_id[0])
            print(event.order)
            print(e)

            event.order.failed()
            print(
                'FAILED FOR CREATE ORDER {} {}'.format(
                    event.order.account_cookie,
                    event.order.status
                )
            )
        return event.order

    def run(self, event):
        # if event.event_type is MARKET_EVENT.QUERY_DATA:
        #    self.order_handler.run(event)
        #    try:
        #        data = self.fetcher[(event.market_type, event.frequence)](
        #            code=event.code, start=event.start, end=event.end).values[0]
        #        if 'vol' in data.keys() and 'volume' not in data.keys():
        #            data['volume'] = data['vol']
        #        elif 'vol' not in data.keys() and 'volume' in data.keys():
        #            data['vol'] = data['volume']
        #        return data
        #    except Exception as e:
        #        QA_util_log_info('MARKET_ENGING ERROR: {}'.format(e))
        #        return None
        # elif event.event_type is BROKER_EVENT.RECEIVE_ORDER:
        #    self.order_handler.run(event)
        # elif event.event_type is BROKER_EVENT.TRADE:
        #    event = self.order_handler.run(event)
        #    event.message = 'trade'
        #    if event.callback:
        #        event.callback(event)
        # el
        if event.event_type is MARKET_EVENT.QUERY_ORDER:
            self.order_handler.run(event)
        elif event.event_type is BROKER_EVENT.SETTLE:
            self.order_handler.run(event)
            if event.callback:
                event.callback('settle')

    def get_market(self, order):
        try:
            data = self.fetcher[(order.market_type, order.frequence)](
                code=order.code, start=order.datetime, end=order.datetime).values[0]
            if 'vol' in data.keys() and 'volume' not in data.keys():
                data['volume'] = data['vol']
            elif 'vol' not in data.keys() and 'volume' in data.keys():
                data['vol'] = data['volume']
            return data
        except Exception as e:
            QA_util_log_info('MARKET_ENGING ERROR: {}'.format(e))
            return None

    def query_orders(self, account_cookie, status='filled'):
        df = self.data_to_df(self.query_data(3 if status is 'filled' else 2))
        df['account_cookie'] = account_cookie
        if status is 'filled':
            df = df[self.dealstatus_headers] if len(
                df) > 0 else pd.DataFrame(columns=self.dealstatus_headers)
        else:
            df['cancel_amount'] = 0
            df = df[self.orderstatus_headers] if len(
                df) > 0 else pd.DataFrame(columns=self.orderstatus_headers)
        return df.set_index(['account_cookie',  'realorder_id']).sort_index()

    def query_positions(self, account_cookie):
        data = {
            'cash_available': 0.00,
            'hold_available': {},
        }
        try:
            result = self.query_data(0)
            if 'data' in result and len(result['data']) > 0:
                # 使用减法避免因为账户日内现金理财导致可用金额错误
                data['cash_available'] = round(
                    float(result['data'][0]['总资产']) - float(result['data'][0]['最新市值']) - float(
                        result['data'][0]['冻结资金']), 2)

            result = self.data_to_df(self.query_data(1))
            if len(result) > 0:
                result.index = result.code
                if hasattr(result, 'amount'):
                    data['hold_available'] = result.amount
            return data
        except:
            print(e)
            return data
Beispiel #15
0
class QA_SPEBroker(QA_Broker):
    """
    1. 查询账户:

    如果有该账户, 返回可用资金和持仓

    如果当前market不存在或异常, 返回False

    2. 查询所有订单:

    如果成功 返回一个DataFrame
    如果失败 返回False

    3. 查询未成交订单

    如果成功 返回DataFrame
    如果失败 返回False

    4. 查询已成交订单

    如果成功 返回DataFramne
    如果失败 返回False


    5. 下单 receive_order/send_order


    receive_order(QAMARKET 用法):
    输入一个QA_ORDER类

    如果下单成功 返回带realorder_id, ORDER_STATUS.QUEUED状态值 的QA_Order
    如果下单失败 返回带 ORDER_STATUS.FAILED状态值的  QA_Order

    send_order(测试用法)



    6. 撤单 cancel_order

    如果撤单成功 返回 True

    如果撤单失败 返回 具体的原因 dict/json格式

    7. 全撤

    如果成功 返回True


    """

    def __init__(self):
        super().__init__()
        self.name = BROKER_TYPE.SHIPANE
        self.order_handler = QA_OrderHandler()
        self.setting = get_config_SPE()
        self._session = requests
        self._endpoint = self.setting.uri
        self.key = self.setting.key

        #self.account_headers = ['forzen_cash','balance_available','cash_available','pnl_money_today','total_assets','pnl_holding','market_value','money_available']

    def run(self, event):
        if event.event_type is BROKER_EVENT.RECEIVE_ORDER:
            self.order_handler.run(event)
            #self.run(QA_Event(event_type=BROKER_EVENT.TRADE, broker=self))
        # elif event.event_type is BROKER_EVENT.TRADE:
        #     """实盘交易部分!!!!! ATTENTION
        #     这里需要开一个子线程去查询是否成交

        #     ATTENTION
        #     """

        #     event = self.order_handler.run(event)
        #     event.message = 'trade'
        #     if event.callback:
        #         event.callback(event)

        elif event.event_type is BROKER_EVENT.SETTLE:
            self.order_handler.run(event)
            if event.callback:
                event.callback('settle')

    def call(self, func, params=''):
        try:
            if self.key == '':
                uri = '{}/api/v1.0/{}?client={}'.format(
                    self._endpoint, func, params.pop('client'))
            else:
                uri = '{}/api/v1.0/{}?key={}&client={}'.format(
                    self._endpoint, func, self.key, params.pop('client'))
            # print(uri)
            response = self._session.get(uri, params)
            text = response.text

            return json.loads(text)
        except Exception as e:
            #print(e)
            if isinstance(e,ConnectionRefusedError):
                print('与主机失去连接')
                print(e)
            else:
                print(e)
            # print(uri)
            return None

    def call_post(self, func, params={}):
        if self.key == '':
            uri = '{}/api/v1.0/{}?client={}'.format(
                self._endpoint, func, params.pop('client'))
        else:
            uri = '{}/api/v1.0/{}?key={}&client={}'.format(
                self._endpoint, func, self.key, params.pop('client'))

        response = self._session.post(uri, json=params)
        text = response.text
        return json.loads(text)

    def call_delete(self, func, params=''):

        if self.key == '':
            uri = '{}/api/v1.0/{}?client={}'.format(
                self._endpoint, func, params.pop('client'))
        else:
            uri = '{}/api/v1.0/{}?key={}&client={}'.format(
                self._endpoint, func, self.key, params.pop('client'))

        response = self._session.delete(uri)

        text = response.text
        # print(text)
        try:
            if text in ['', '获取提示对话框超时,因为:组件为空']:
                print('success')
                return True

            else:
                return json.loads(text)
        except:
            return text

    def data_to_df(self, result):
        return pd.DataFrame(data=result)

    #------ functions

    def ping(self):
        return self.call("ping", {})

    def query_accounts(self, accounts):
        return self.call("accounts", {
            'client': accounts
        })

    def query_positions(self, accounts):
        """查询现金和持仓

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

        Returns:
            dict-- {'cash':xxx,'position':xxx}
        """
        try:
            data = self.call("positions", {
                'client': accounts
            })
            #print(data)
            if data is not None:
                cash_part = data.get('subAccounts', {}).get('人民币', False)
                if cash_part:
                    cash_available = cash_part.get('可用金额')
                position_part = data.get('dataTable', False)
                if position_part:
                    res = data.get('dataTable', False)
                    if res:
                        hold_headers = res['columns']
                        hold_headers = [cn_en_compare[item]
                                        for item in hold_headers]
                        hold_available = pd.DataFrame(
                            res['rows'], columns=hold_headers)

                return {'cash_available': cash_available, 'hold_available': hold_available.assign(amount=hold_available.amount.apply(float)).loc[:, ['code', 'amount']].set_index('code').amount}
            else:
                print(data)
                return False, 'None ACCOUNT'
        except:
            return False

    def query_clients(self):
        return self.call("clients")

    def query_orders(self, accounts, status='filled'):
        """查询订单

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

        Keyword Arguments:
            status {str} -- 'open' 待成交 'filled' 成交 (default: {'filled'})

        Returns:
            [type] -- [description]
        """
        try:
            data = self.call("orders", {
                'client': accounts,
                'status': status
            })

            if data is not None:
                orders = data.get('dataTable', False)

                order_headers = orders['columns']
                order_headers = [cn_en_compare[item] for item in order_headers]
                order_all = pd.DataFrame(
                    orders['rows'], columns=order_headers).assign(account_cookie=accounts)

                order_all.towards = order_all.towards.apply(
                    lambda x: trade_towards_cn_en[x])
                
                if 'order_time' in order_headers:
                    # 这是order_status
                    order_all.status = order_all.status.apply(lambda x: order_status_cn_en[x])
                    if 'order_date' not in order_headers:
                        order_all.order_time = order_all.order_time.apply(
                            lambda x: QA_util_get_order_datetime(dt='{} {}'.format(datetime.date.today(), x)))
                    else:
                        order_all = order_all.assign(order_time=order_all.order_date.apply(QA_util_date_int2str)+' '+order_all.order_time)

                if 'trade_time' in order_headers:

                    order_all.trade_time = order_all.trade_time.apply(
                        lambda x: '{} {}'.format(datetime.date.today(), x))

                if status is 'filled':
                    return order_all.loc[:, self.dealstatus_headers].set_index(['account_cookie', 'realorder_id']).sort_index()
                else:
                    return order_all.loc[:, self.orderstatus_headers].set_index(['account_cookie', 'realorder_id']).sort_index()
            else:
                print('response is None')
                return False
        except Exception as e:
            print(e)
            return False

    def send_order(self, accounts, code='000001', price=9, amount=100, order_direction=ORDER_DIRECTION.BUY, order_model=ORDER_MODEL.LIMIT):
        """[summary]

        Arguments:
            accounts {[type]} -- [description]
            code {[type]} -- [description]
            price {[type]} -- [description]
            amount {[type]} -- [description]

        Keyword Arguments:
            order_direction {[type]} -- [description] (default: {ORDER_DIRECTION.BUY})
            order_model {[type]} -- [description] (default: {ORDER_MODEL.LIMIT})



        priceType 可选择: 上海交易所:

            0 - 限价委托
            4 - 五档即时成交剩余撤销
            6 - 五档即时成交剩余转限

        深圳交易所:

            0 - 限价委托
            1 - 对手方最优价格委托
            2 - 本方最优价格委托
            3 - 即时成交剩余撤销委托
            4 - 五档即时成交剩余撤销
            5 - 全额成交或撤销委托

        Returns:
            [type] -- [description]
        """
        try:
            #print(code, price, amount)
            return self.call_post('orders', {
                'client': accounts,
                "action": 'BUY' if order_direction == 1 else 'SELL',
                "symbol": code,
                "type": order_model,
                "priceType": 0 if order_model == ORDER_MODEL.LIMIT else 4,
                "price": price,
                "amount": amount
            })
        except json.decoder.JSONDecodeError:
            print(RuntimeError('TRADE ERROR'))
            return None

    def cancel_order(self, accounts, orderid):
        return self.call_delete('orders/{}'.format(orderid), {
            'client': accounts
        })

    def cancel_all(self, accounts):
        return self.call_delete('orders', {
            'client': accounts
        })

    def receive_order(self, event):
        order = event.order
        res = self.send_order(accounts=order.account_cookie, code=order.code, price=order.price,
                              amount=order.amount, order_direction=order.towards, order_model=order.order_model)
        try:
            # if res is not None and 'id' in res.keys():

            # order.status = ORDER_STATUS.QUEUED
            # order.text = 'SUCCESS'
            order.queued(realorder_id=res['id'])
            print('success receive order {}'.format(order.realorder_id))
            return order
            # else:

        except:

            text = 'WRONG' if res is None else res.get(
                'message', 'WRONG')

            order.failed(text)

            print('FAILED FOR CREATE ORDER {} {}'.format(
                order.account_cookie, order.status))
            print(res)
            return order
Beispiel #16
0
class QA_TTSBroker(QA_Broker):
    fetcher = {
        (MARKET_TYPE.STOCK_CN, FREQUENCE.DAY): QA_fetch_get_stock_day,
        (MARKET_TYPE.STOCK_CN, FREQUENCE.FIFTEEN_MIN): QA_fetch_get_stock_min,
        (MARKET_TYPE.STOCK_CN, FREQUENCE.ONE_MIN): QA_fetch_get_stock_min,
        (MARKET_TYPE.STOCK_CN, FREQUENCE.FIVE_MIN): QA_fetch_get_stock_min,
        (MARKET_TYPE.STOCK_CN, FREQUENCE.THIRTY_MIN): QA_fetch_get_stock_min,
        (MARKET_TYPE.STOCK_CN, FREQUENCE.SIXTY_MIN): QA_fetch_get_stock_min,
        (MARKET_TYPE.INDEX_CN, FREQUENCE.DAY): QA_fetch_get_index_day,
        (MARKET_TYPE.INDEX_CN, FREQUENCE.FIFTEEN_MIN): QA_fetch_get_index_min,
        (MARKET_TYPE.INDEX_CN, FREQUENCE.ONE_MIN): QA_fetch_get_index_min,
        (MARKET_TYPE.INDEX_CN, FREQUENCE.FIVE_MIN): QA_fetch_get_index_min,
        (MARKET_TYPE.INDEX_CN, FREQUENCE.THIRTY_MIN): QA_fetch_get_index_min,
        (MARKET_TYPE.INDEX_CN, FREQUENCE.SIXTY_MIN): QA_fetch_get_index_min,
        (MARKET_TYPE.FUND_CN, FREQUENCE.DAY): QA_fetch_get_index_day,
        (MARKET_TYPE.FUND_CN, FREQUENCE.FIFTEEN_MIN): QA_fetch_get_index_min,
        (MARKET_TYPE.FUND_CN, FREQUENCE.ONE_MIN): QA_fetch_get_index_min,
        (MARKET_TYPE.FUND_CN, FREQUENCE.FIVE_MIN): QA_fetch_get_index_min,
        (MARKET_TYPE.FUND_CN, FREQUENCE.THIRTY_MIN): QA_fetch_get_index_min,
        (MARKET_TYPE.FUND_CN, FREQUENCE.SIXTY_MIN): QA_fetch_get_index_min
    }

    def __init__(self, auto_logon=True):
        super().__init__()
        self.name = BROKER_TYPE.TTS
        self.config = TTSConfig()
        self.order_handler = QA_OrderHandler()
        self._endpoint = 'http://%s:%s/api' % (
            self.config.values['trade_server_ip'],
            self.config.values['trade_server_port'])
        self._encoding = "utf-8"
        if self.config.values['transport_enc_key'] == '' or self.config.values[
                'transport_enc_iv'] == '':
            self._transport_enc = False
            self._transport_enc_key = None
            self._transport_enc_iv = None
            self._cipher = None
        else:
            self._transport_enc = True
            self._transport_enc_key = bytes(
                self.config.values['transport_enc_key'],
                encoding=self._encoding)
            self._transport_enc_iv = bytes(
                self.config.values['transport_enc_iv'],
                encoding=self._encoding)
            self._cipher = Cipher(algorithms.AES(self._transport_enc_key),
                                  modes.CBC(self._transport_enc_iv),
                                  backend=default_backend())

        self._session = requests.Session()
        self.client_id = 0
        self.gddm_sh = 0  # 上海股东代码
        self.gddm_sz = 0  # 深圳股东代码

        if auto_logon is True:
            self.logon()

    def call(self, func, params=None):

        json_obj = {"func": func}

        if params is not None:
            json_obj["params"] = params

        if self._transport_enc:
            data_to_send = self.encrypt(json_obj)
            response = self._session.post(self._endpoint, data=data_to_send)
        else:
            response = self._session.post(self._endpoint, json=json_obj)
        response.encoding = self._encoding
        text = response.text

        if self._transport_enc:
            decoded_text = self.decrypt(text)
            # print(decoded_text)
            return json.loads(decoded_text)
        else:
            return json.loads(text)

    def encrypt(self, source_obj):
        encrypter = self._cipher.encryptor()
        source = json.dumps(source_obj)
        source = source.encode(self._encoding)
        need_to_padding = 16 - (len(source) % 16)
        if need_to_padding > 0:
            source = source + b'\x00' * need_to_padding
        enc_data = encrypter.update(source) + encrypter.finalize()
        b64_enc_data = base64.encodebytes(enc_data)
        return urllib.parse.quote(b64_enc_data)

    def decrypt(self, source):
        decrypter = self._cipher.decryptor()
        source = urllib.parse.unquote(source)
        source = base64.decodebytes(source.encode("utf-8"))
        data_bytes = decrypter.update(source) + decrypter.finalize()
        return data_bytes.rstrip(b"\x00").decode(self._encoding)

    def data_to_df(self, result):
        if 'data' in result:
            data = result['data']
            df = pd.DataFrame(data=data)
            df.rename(columns=lambda x: cn_en_compare[x]
                      if x in cn_en_compare else x,
                      inplace=True)
            if hasattr(df, 'towards'):
                df.towards = df.towards.apply(lambda x: trade_towards_cn_en[
                    x] if x in trade_towards_cn_en else x)
            if hasattr(df, 'status'):
                df.status = df.status.apply(lambda x: order_status_cn_en[x]
                                            if x in order_status_cn_en else x)
            if hasattr(df, 'order_time'):
                df.order_time = df.order_time.apply(lambda x: '{} {}'.format(
                    datetime.date.today().strftime('%Y-%m-%d'),
                    datetime.datetime.strptime(x, '%H%M%S').strftime('%H:%M:%S'
                                                                     )))
            if hasattr(df, 'trade_time'):
                df.trade_time = df.trade_time.apply(lambda x: '{} {}'.format(
                    datetime.date.today().strftime('%Y-%m-%d'),
                    datetime.datetime.strptime(x, '%H%M%S').strftime('%H:%M:%S'
                                                                     )))
            if hasattr(df, 'amount'):
                df.amount = df.amount.apply(pd.to_numeric)
            if hasattr(df, 'price'):
                df.price = df.price.apply(pd.to_numeric)
            if hasattr(df, 'money'):
                df.money = df.money.apply(pd.to_numeric)
            if hasattr(df, 'trade_amount'):
                df.trade_amount = df.trade_amount.apply(pd.to_numeric)
            if hasattr(df, 'trade_price'):
                df.trade_price = df.trade_price.apply(pd.to_numeric)
            if hasattr(df, 'trade_money'):
                df.trade_money = df.trade_money.apply(pd.to_numeric)
            if hasattr(df, 'order_price'):
                df.order_price = df.order_price.apply(pd.to_numeric)
            if hasattr(df, 'order_amount'):
                df.order_amount = df.order_amount.apply(pd.to_numeric)
            if hasattr(df, 'order_money'):
                df.order_money = df.order_money.apply(pd.to_numeric)
            if hasattr(df, 'cancel_amount'):
                df.cancel_amount = df.cancel_amount.apply(pd.to_numeric)
            return df
        else:
            return pd.DataFrame()

    #------ functions

    def ping(self):

        return self.call("ping", {})

    def logon(self):
        data = self.call(
            "logon", {
                "ip": self.config.values['tdx_server_ip'],
                "port": int(self.config.values['tdx_server_port']),
                "version": self.config.values['tdx_version'],
                "yyb_id": int(self.config.values['user_yyb']),
                "account_no": self.config.values['user_name'],
                "trade_account": self.config.values['user_name'],
                "jy_password": self.config.values['user_pass'],
                "tx_password": self.config.values['user_tx_pass']
            })
        if data['success']:
            self.client_id = data["data"]["client_id"]
            self.gddm_sh = self.query_data(5)['data'][0]['股东代码']
            self.gddm_sz = self.query_data(5)['data'][1]['股东代码']
            print('上海股东代码:%s,深圳股东代码:%s', self.gddm_sh, self.gddm_sz)
        return data

    def logoff(self):
        return self.call("logoff", {"client_id": self.client_id})

    def query_data(self, category):
        return self.call("query_data", {
            "client_id": self.client_id,
            "category": category
        })

    def send_order(self,
                   code,
                   price,
                   amount,
                   towards,
                   order_model,
                   market=None):
        """下单

        Arguments:
            code {[type]} -- [description]
            price {[type]} -- [description]
            amount {[type]} -- [description]
            towards {[type]} -- [description]
            order_model {[type]} -- [description]
            market:市场,SZ 深交所,SH 上交所

        Returns:
            [type] -- [description]
        """

        towards = 0 if towards == ORDER_DIRECTION.BUY else 1
        if order_model == ORDER_MODEL.MARKET:
            order_model = 4
        elif order_model == ORDER_MODEL.LIMIT:
            order_model = 0

        if market is None:
            market = QAFetch.base.get_stock_market(code)
        if not isinstance(market, str):
            raise Exception('%s不正确,请检查code和market参数' % market)
        market = market.lower()
        if market not in ['sh', 'sz']:
            raise Exception('%s不支持,请检查code和market参数' % market)

        return self.data_to_df(
            self.call(
                "send_order", {
                    'client_id': self.client_id,
                    'category': towards,
                    'price_type': order_model,
                    'gddm': self.gddm_sh if market == 'sh' else self.gddm_sz,
                    'zqdm': code,
                    'price': price,
                    'quantity': amount
                }))

    def cancel_order(self, exchange_id, order_id):
        """

        Arguments:
            exchange_id {[type]} -- 交易所  0 深圳 1上海 (偶尔2是深圳)
            order_id {[type]} -- [description]

        Returns:
            [type] -- [description]
        """

        return self.call(
            "cancel_order", {
                'client_id': self.client_id,
                'exchange_id': exchange_id,
                'hth': order_id
            })

    def get_quote(self, code):
        return self.call("get_quote", {
            'client_id': self.client_id,
            'code': code,
        })

    def repay(self, amount):
        return self.call("repay", {
            'client_id': self.client_id,
            'amount': amount
        })

    def receive_order(self, event):
        res = self.send_order(code=event.order.code,
                              price=event.order.price,
                              amount=event.order.amount,
                              towards=event.order.towards,
                              order_model=event.order.order_model)
        try:
            event.order.queued(realorder_id=res.realorder_id[0])
            print('success receive order {}'.format(event.order.realorder_id))
        except:
            event.order.failed()

            print('FAILED FOR CREATE ORDER {} {}'.format(
                event.order.account_cookie, event.order.status))
        return event.order

    def run(self, event):
        # if event.event_type is MARKET_EVENT.QUERY_DATA:
        #    self.order_handler.run(event)
        #    try:
        #        data = self.fetcher[(event.market_type, event.frequence)](
        #            code=event.code, start=event.start, end=event.end).values[0]
        #        if 'vol' in data.keys() and 'volume' not in data.keys():
        #            data['volume'] = data['vol']
        #        elif 'vol' not in data.keys() and 'volume' in data.keys():
        #            data['vol'] = data['volume']
        #        return data
        #    except Exception as e:
        #        QA_util_log_info('MARKET_ENGING ERROR: {}'.format(e))
        #        return None
        # elif event.event_type is BROKER_EVENT.RECEIVE_ORDER:
        #    self.order_handler.run(event)
        # elif event.event_type is BROKER_EVENT.TRADE:
        #    event = self.order_handler.run(event)
        #    event.message = 'trade'
        #    if event.callback:
        #        event.callback(event)
        # el
        if event.event_type is MARKET_EVENT.QUERY_ORDER:
            self.order_handler.run(event)
        elif event.event_type is BROKER_EVENT.SETTLE:
            self.order_handler.run(event)
            if event.callback:
                event.callback('settle')

    def get_market(self, order):
        try:
            data = self.fetcher[(order.market_type, order.frequence)](
                code=order.code, start=order.datetime,
                end=order.datetime).values[0]
            if 'vol' in data.keys() and 'volume' not in data.keys():
                data['volume'] = data['vol']
            elif 'vol' not in data.keys() and 'volume' in data.keys():
                data['vol'] = data['volume']
            return data
        except Exception as e:
            QA_util_log_info('MARKET_ENGING ERROR: {}'.format(e))
            return None

    def query_orders(self, account_cookie, status='filled'):
        df = self.data_to_df(self.query_data(3 if status is 'filled' else 2))
        df['account_cookie'] = account_cookie
        if status is 'filled':
            df = df[self.dealstatus_headers] if len(df) > 0 else pd.DataFrame(
                columns=self.dealstatus_headers)
        else:
            df['cancel_amount'] = 0
            df = df[self.orderstatus_headers] if len(df) > 0 else pd.DataFrame(
                columns=self.orderstatus_headers)
        return df.set_index(['account_cookie', 'realorder_id']).sort_index()

    def query_positions(self, account_cookie):
        data = {
            'cash_available': 0.00,
            'hold_available': {},
        }
        try:
            result = self.query_data(0)
            if 'data' in result and len(result['data']) > 0:
                # 使用减法避免因为账户日内现金理财导致可用金额错误
                data['cash_available'] = round(
                    float(result['data'][0]['总资产']) -
                    float(result['data'][0]['最新市值']) -
                    float(result['data'][0]['冻结资金']), 2)

            result = self.data_to_df(self.query_data(1))
            if len(result) > 0:
                result.index = result.code
                if hasattr(result, 'amount'):
                    data['hold_available'] = result.amount
            return data
        except:
            print(e)
            return data
Beispiel #17
0
class QA_SPEBroker(QA_Broker):
    """
    1. 查询账户:

    如果有该账户, 返回可用资金和持仓

    如果当前market不存在或异常, 返回False

    2. 查询所有订单:

    如果成功 返回一个DataFrame
    如果失败 返回False

    3. 查询未成交订单

    如果成功 返回DataFrame
    如果失败 返回False

    4. 查询已成交订单

    如果成功 返回DataFramne
    如果失败 返回False


    5. 下单 receive_order/send_order


    receive_order(QAMARKET 用法):
    输入一个QA_ORDER类

    如果下单成功 返回带realorder_id, ORDER_STATUS.QUEUED状态值 的QA_Order
    如果下单失败 返回带 ORDER_STATUS.FAILED状态值的  QA_Order

    send_order(测试用法)



    6. 撤单 cancel_order

    如果撤单成功 返回 True

    如果撤单失败 返回 具体的原因 dict/json格式

    7. 全撤

    如果成功 返回True


    """

    def __init__(self):
        super().__init__()
        self.name = BROKER_TYPE.SHIPANE
        self.order_handler = QA_OrderHandler()
        self.setting = get_config_SPE()
        self._session = requests
        self._endpoint = self.setting.uri
        self.key = self.setting.key

        #self.account_headers = ['forzen_cash','balance_available','cash_available','pnl_money_today','total_assets','pnl_holding','market_value','money_available']

    def run(self, event):
        if event.event_type is BROKER_EVENT.RECEIVE_ORDER:
            self.order_handler.run(event)

        elif event.event_type is BROKER_EVENT.SETTLE:
            self.order_handler.run(event)
            if event.callback:
                event.callback('settle')

    def call(self, func, params=''):
        try:
            if self.key == '':
                uri = '{}/api/v1.0/{}?client={}'.format(
                    self._endpoint,
                    func,
                    params.pop('client')
                )
            else:
                uri = '{}/api/v1.0/{}?key={}&client={}'.format(
                    self._endpoint,
                    func,
                    self.key,
                    params.pop('client')
                )
            # print(uri)
            response = self._session.get(uri, params)
            text = response.text

            return json.loads(text)
        except Exception as e:
            # print(e)
            if isinstance(e, ConnectionRefusedError):
                print('与主机失去连接')
                print(e)
            else:
                print(e)
            # print(uri)
            return None

    def call_post(self, func, params={}):
        if self.key == '':
            uri = '{}/api/v1.0/{}?client={}'.format(
                self._endpoint,
                func,
                params.pop('client')
            )
        else:
            uri = '{}/api/v1.0/{}?key={}&client={}'.format(
                self._endpoint,
                func,
                self.key,
                params.pop('client')
            )

        response = self._session.post(uri, json=params)
        text = response.text
        return json.loads(text)

    def call_delete(self, func, params=''):

        if self.key == '':
            uri = '{}/api/v1.0/{}?client={}'.format(
                self._endpoint,
                func,
                params.pop('client')
            )
        else:
            uri = '{}/api/v1.0/{}?key={}&client={}'.format(
                self._endpoint,
                func,
                self.key,
                params.pop('client')
            )

        response = self._session.delete(uri)

        text = response.text
        # print(text)
        try:
            if text in ['', '获取提示对话框超时,因为:组件为空']:
                print('success')
                return True

            else:
                return json.loads(text)
        except:
            return text

    def data_to_df(self, result):
        return pd.DataFrame(data=result)

    #------ functions

    def ping(self):
        return self.call("ping", {})

    def query_accounts(self, accounts):
        return self.call("accounts", {'client': accounts})

    def query_positions(self, accounts):
        """查询现金和持仓

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

        Returns:
            dict-- {'cash_available':xxx,'hold_available':xxx}
        """
        try:
            data = self.call("positions", {'client': accounts})
            if data is not None:
                cash_part = data.get('subAccounts', {}).get('人民币', False)
                if cash_part:
                    cash_available = cash_part.get('可用金额', cash_part.get('可用'))

                position_part = data.get('dataTable', False)
                if position_part:
                    res = data.get('dataTable', False)
                    if res:
                        hold_headers = res['columns']
                        hold_headers = [
                            cn_en_compare[item] for item in hold_headers
                        ]
                        hold_available = pd.DataFrame(
                            res['rows'],
                            columns=hold_headers
                        )
                if len(hold_available) == 1 and hold_available.amount[0] in [
                        None,
                        '',
                        0
                ]:
                    hold_available = pd.DataFrame(
                        data=None,
                        columns=hold_headers
                    )
                return {
                    'cash_available':
                    cash_available,
                    'hold_available':
                    hold_available.assign(
                        amount=hold_available.amount.apply(float)
                    ).loc[:,
                          ['code',
                           'amount']].set_index('code').amount
                }
            else:
                print(data)
                return False, 'None ACCOUNT'
        except:
            return False

    def query_clients(self):
        """查询clients

        Returns:
            [type] -- [description]
        """

        try:
            data = self.call("clients", {'client': 'None'})
            if len(data) > 0:
                return pd.DataFrame(data).drop(
                    ['commandLine',
                     'processId'],
                    axis=1
                )
            else:
                return pd.DataFrame(
                    None,
                    columns=[
                        'id',
                        'name',
                        'windowsTitle',
                        'accountInfo',
                        'status'
                    ]
                )
        except Exception as e:
            return False, e

    def query_orders(self, accounts, status='filled'):
        """查询订单

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

        Keyword Arguments:
            status {str} -- 'open' 待成交 'filled' 成交 (default: {'filled'})

        Returns:
            [type] -- [description]
        """
        try:
            data = self.call("orders", {'client': accounts, 'status': status})

            if data is not None:
                orders = data.get('dataTable', False)

                order_headers = orders['columns']
                if ('成交状态' in order_headers
                        or '状态说明' in order_headers) and ('备注' in order_headers):
                    order_headers[order_headers.index('备注')] = '废弃'

                order_headers = [cn_en_compare[item] for item in order_headers]
                order_all = pd.DataFrame(
                    orders['rows'],
                    columns=order_headers
                ).assign(account_cookie=accounts)

                order_all.towards = order_all.towards.apply(
                    lambda x: trade_towards_cn_en[x]
                )
                if 'order_time' in order_headers:
                    # 这是order_status
                    order_all['status'] = order_all.status.apply(
                        lambda x: order_status_cn_en[x]
                    )
                    if 'order_date' not in order_headers:
                        order_all.order_time = order_all.order_time.apply(
                            lambda x: QA_util_get_order_datetime(
                                dt='{} {}'.format(datetime.date.today(),
                                                  x)
                            )
                        )
                    else:
                        order_all = order_all.assign(
                            order_time=order_all.order_date
                            .apply(QA_util_date_int2str) + ' ' +
                            order_all.order_time
                        )

                if 'trade_time' in order_headers:

                    order_all.trade_time = order_all.trade_time.apply(
                        lambda x: '{} {}'.format(datetime.date.today(),
                                                 x)
                    )

                if status is 'filled':
                    return order_all.loc[:,
                                         self.dealstatus_headers].set_index(
                                             ['account_cookie',
                                              'realorder_id']
                    ).sort_index()
                else:
                    return order_all.loc[:,
                                         self.orderstatus_headers].set_index(
                                             ['account_cookie',
                                              'realorder_id']
                    ).sort_index()
            else:
                print('response is None')
                return False
        except Exception as e:
            print(e)
            return False

    def send_order(
            self,
            accounts,
            code='000001',
            price=9,
            amount=100,
            order_direction=ORDER_DIRECTION.BUY,
            order_model=ORDER_MODEL.LIMIT
    ):
        """[summary]

        Arguments:
            accounts {[type]} -- [description]
            code {[type]} -- [description]
            price {[type]} -- [description]
            amount {[type]} -- [description]

        Keyword Arguments:
            order_direction {[type]} -- [description] (default: {ORDER_DIRECTION.BUY})
            order_model {[type]} -- [description] (default: {ORDER_MODEL.LIMIT})



        priceType 可选择: 上海交易所:

            0 - 限价委托
            4 - 五档即时成交剩余撤销
            6 - 五档即时成交剩余转限

        深圳交易所:

            0 - 限价委托
            1 - 对手方最优价格委托
            2 - 本方最优价格委托
            3 - 即时成交剩余撤销委托
            4 - 五档即时成交剩余撤销
            5 - 全额成交或撤销委托

        Returns:
            [type] -- [description]
        """
        try:
            #print(code, price, amount)
            return self.call_post(
                'orders',
                {
                    'client': accounts,
                    "action": 'BUY' if order_direction == 1 else 'SELL',
                    "symbol": code,
                    "type": order_model,
                    "priceType": 0 if order_model == ORDER_MODEL.LIMIT else 4,
                    "price": price,
                    "amount": amount
                }
            )
        except json.decoder.JSONDecodeError:
            print(RuntimeError('TRADE ERROR'))
            return None

    def cancel_order(self, accounts, orderid):
        return self.call_delete(
            'orders/{}'.format(orderid),
            {'client': accounts}
        )

    def cancel_all(self, accounts):
        return self.call_delete('orders', {'client': accounts})

    def receive_order(self, event):
        order = event.order
        res = self.send_order(
            accounts=order.account_cookie,
            code=order.code,
            price=order.price,
            amount=order.amount,
            order_direction=order.towards,
            order_model=order.order_model
        )
        try:
            # if res is not None and 'id' in res.keys():

            # order.status = ORDER_STATUS.QUEUED
            # order.text = 'SUCCESS'
            order.queued(realorder_id=res['id'])
            print('success receive order {}'.format(order.realorder_id))
            return order
            # else:

        except:

            text = 'WRONG' if res is None else res.get('message', 'WRONG')

            order.failed(text)

            print(
                'FAILED FOR CREATE ORDER {} {}'.format(
                    order.account_cookie,
                    order.status
                )
            )
            print(res)
            return order
Beispiel #18
0
class QA_BacktestBroker(QA_Broker):
    """
    QUANTAXIS Broker 部分

    回测
    股票/指数/期货/债券/ETF/基金
    @yutiansut


    对于不同的市场规则:
    股票市场 t+1
    期货/期权/加密货币市场 t+0

    股票/加密货币市场不允许卖空
    期货/期权市场允许卖空

    t+1的市场是
    当日的买入 更新持仓- 不更新可卖数量- 资金冻结
    当日的卖出 及时更新可用资金

    t+0市场是:
    当日买入 即时更新持仓和可卖
    当日卖出 即时更新

    卖空的规则是
    允许无仓位的时候卖出证券(按市值和保证金比例限制算)
    """

    def __init__(self, if_nondatabase=False):
        """[summary]


        Keyword Arguments:
            commission_fee_coeff {[type]} -- [description] (default: {0})
            environment {[type]} -- [description] (default: {RUNNING_ENVIRONMENT})
            if_nondatabase {[type]} -- [description] (default: {False})
        """
        super().__init__()
        self.dealer = QA_Dealer()
        self.order_handler = QA_OrderHandler()

        self.fetcher = {
            (MARKET_TYPE.STOCK_CN,
             FREQUENCE.DAY): QA_fetch_stock_day,
            (MARKET_TYPE.STOCK_CN,
             FREQUENCE.FIFTEEN_MIN): QA_fetch_stock_min,
            (MARKET_TYPE.STOCK_CN,
             FREQUENCE.ONE_MIN): QA_fetch_stock_min,
            (MARKET_TYPE.STOCK_CN,
             FREQUENCE.FIVE_MIN): QA_fetch_stock_min,
            (MARKET_TYPE.STOCK_CN,
             FREQUENCE.THIRTY_MIN): QA_fetch_stock_min,
            (MARKET_TYPE.STOCK_CN,
             FREQUENCE.SIXTY_MIN): QA_fetch_stock_min,
            (MARKET_TYPE.FUTURE_CN,
             FREQUENCE.DAY): QA_fetch_future_day,
            (MARKET_TYPE.FUTURE_CN,
             FREQUENCE.FIFTEEN_MIN): QA_fetch_future_min,
            (MARKET_TYPE.FUTURE_CN,
             FREQUENCE.ONE_MIN): QA_fetch_future_min,
            (MARKET_TYPE.FUTURE_CN,
             FREQUENCE.FIVE_MIN): QA_fetch_future_min,
            (MARKET_TYPE.FUTURE_CN,
             FREQUENCE.THIRTY_MIN): QA_fetch_future_min,
            (MARKET_TYPE.FUTURE_CN,
             FREQUENCE.SIXTY_MIN): QA_fetch_future_min,
            (MARKET_TYPE.INDEX_CN,
             FREQUENCE.DAY): QA_fetch_index_day,
            (MARKET_TYPE.INDEX_CN,
             FREQUENCE.FIFTEEN_MIN): QA_fetch_index_min,
            (MARKET_TYPE.INDEX_CN,
             FREQUENCE.ONE_MIN): QA_fetch_index_min,
            (MARKET_TYPE.INDEX_CN,
             FREQUENCE.FIVE_MIN): QA_fetch_index_min,
            (MARKET_TYPE.INDEX_CN,
             FREQUENCE.THIRTY_MIN): QA_fetch_index_min,
            (MARKET_TYPE.INDEX_CN,
             FREQUENCE.SIXTY_MIN): QA_fetch_index_min,
            (MARKET_TYPE.FUND_CN,
             FREQUENCE.DAY): QA_fetch_index_day,
            (MARKET_TYPE.FUND_CN,
             FREQUENCE.FIFTEEN_MIN): QA_fetch_index_min,
            (MARKET_TYPE.FUND_CN,
             FREQUENCE.ONE_MIN): QA_fetch_index_min,
            (MARKET_TYPE.FUND_CN,
             FREQUENCE.FIVE_MIN): QA_fetch_index_min,
            (MARKET_TYPE.FUND_CN,
             FREQUENCE.THIRTY_MIN): QA_fetch_index_min,
            (MARKET_TYPE.FUND_CN,
             FREQUENCE.SIXTY_MIN): QA_fetch_index_min
        }

        self.market_data = None
        self.if_nondatabase = if_nondatabase
        self.name = BROKER_TYPE.BACKETEST
        self._quotation = {} # 一个可以缓存数据的dict
        self.broker_data = None
        self.deal_message = {}

    def run(self, event):
        #strDbg = QA_util_random_with_topic("QABacktestBroker.run")
        #print("         >-----------------------QABacktestBroker.run----------------------------->", strDbg,'evt->', event)

        if event.event_type is MARKET_EVENT.QUERY_DATA:
            # 查询数据部分
            code = event.code
            frequence = event.frequence
            start = event.start
            end = start if event.end is None else event.end
            market_type = event.market_type
            res = self.query_data(code, start, end, frequence, market_type)
            if event.callback:
                event.callback(res)
            else:
                return res
        elif event.event_type is MARKET_EVENT.QUERY_ORDER:
            self.order_handler.run(event)
        elif event.event_type is ENGINE_EVENT.UPCOMING_DATA:
            # QABacktest 回测发出的事件

            new_marketdata_dict = event.market_data.dicts
            for item in new_marketdata_dict.keys():
                if item not in self._quotation.keys():
                    self._quotation[item] = new_marketdata_dict[item]
            # if self.broker_data is None:
            #     self.broker_data = event.market_data
            # else:
            #     self.broker_data.append(event.market_data)
            # self.broker_data=event.market_data

        elif event.event_type is BROKER_EVENT.RECEIVE_ORDER:
            self.order_handler.run(event)
            #self.run(QA_Event(event_type=BROKER_EVENT.TRADE, broker=self))
        elif event.event_type is BROKER_EVENT.TRADE:
            event = self.order_handler.run(event)
            event.message = 'trade'
            if event.callback:
                event.callback(event)
        elif event.event_type is BROKER_EVENT.SETTLE:
            #self.deal_message = {}
            # self.order_handler.run(event)
            if event.callback:
                event.callback('settle')
        #print("         <-----------------------QABacktestBroker.run-----------------------------<",strDbg,'evt->',event)

    def query_data(self, code, start, end, frequence, market_type=None):
        """
        标准格式是numpy
        """
        try:
            return self.broker_data.select_time(start,
                                                end).select_code(code
                                                                ).to_json()[0]

        except:
            return self.fetcher[(market_type,
                                 frequence)](
                                     code,
                                     start,
                                     end,
                                     frequence=frequence,
                                     format='json'
                                 )

    def receive_order(self, event):
        """
        get the order and choice which market to trade

        """
        order = event.order
        # print(event.market_data)
        # print(order)
        if 'market_data' in event.__dict__.keys():

            self.market_data = self.get_market(
                order
            ) if event.market_data is None else event.market_data

            if isinstance(self.market_data, dict):
                pass
            elif isinstance(self.market_data, pd.DataFrame):
                self.market_data = QA_util_to_json_from_pandas(
                    self.market_data
                )[0]
            elif isinstance(self.market_data, pd.core.series.Series):
                self.market_data = self.market_data.to_dict()
            elif isinstance(self.market_data, np.ndarray):
                data = self.market_data[0]

            else:
                # print(type(self.market_data))
                self.market_data = self.market_data.to_json()[0]
        else:
            self.market_data = self.get_market(order)
        if self.market_data is not None:

            order = self.warp(order)
            self.dealer.deal(order, self.market_data)
            order.queued(order.order_id) # 模拟的order_id 和 realorder_id 一致

        else:

            order.failed('MARKET DATA IS NONE')
            #raise ValueError('MARKET DATA IS NONE CANNOT TRADE')
        return order

    def query_orders(self, account, status=''):

        if status == '':
            return self.dealer.deal_df.query(
                'account_cookie=="{}"'.format(account)
            ).loc[:,
                  self.orderstatus_headers].set_index(
                      ['account_cookie',
                       'realorder_id']
                  )
        elif status == 'filled':
            return self.dealer.deal_df.query(
                'account_cookie=="{}"'.format(account)
            ).loc[:,
                  self.dealstatus_headers].set_index(
                      ['account_cookie',
                       'realorder_id']
                  )
        elif status == 'open':
            pass

    def query_deal(self, account):
        pass

    def warp(self, order):
        """对order/market的封装

        [description]

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

        Returns:
            [type] -- [description]
        """

        # 因为成交模式对时间的封装
        if order.order_model == ORDER_MODEL.MARKET:
            """
            市价单模式
            """
            if order.frequence is FREQUENCE.DAY:
                # exact_time = str(datetime.datetime.strptime(
                #     str(order.datetime), '%Y-%m-%d %H-%M-%S') + datetime.timedelta(day=1))

                order.date = order.datetime[0:10]
                order.datetime = '{} 09:30:00'.format(order.date)
            elif order.frequence in [FREQUENCE.ONE_MIN,
                                     FREQUENCE.FIVE_MIN,
                                     FREQUENCE.FIFTEEN_MIN,
                                     FREQUENCE.THIRTY_MIN,
                                     FREQUENCE.SIXTY_MIN]:

                order.date = str(order.datetime)[0:10]
            #_original_marketvalue = order.price*order.amount

            order.price = (
                float(self.market_data.get('high')) +
                float(self.market_data.get('low'))
            ) * 0.5

        elif order.order_model == ORDER_MODEL.NEXT_OPEN:
            # try:
            #     order.date = QA_util_get_next_day(str(order.datetime)[0:10])
            #     order.datetime = '{} 09:30:00'.format(order.date)
            # except:
            #     order.datetime = '{} 15:00:00'.format(order.date)
            # self.market_data = self.get_market(order)
            # if self.market_data is None:
            #     return order
            # order.price = float(self.market_data["close"])
            raise NotImplementedError
        elif order.order_model == ORDER_MODEL.CLOSE:
            """
            收盘价模式
            """
            try:
                order.date = order.datetime[0:10]
                order.datetime = '{} 15:00:00'.format(order.date)
            except:
                if len(str(order.datetime)) == 19:
                    pass
                else:
                    order.datetime = '{} 15:00:00'.format(order.date)

            order.price = float(self.market_data.get('close'))

        elif order.order_model == ORDER_MODEL.LIMIT:
            """
            限价单模式
            """
            if order.frequence is FREQUENCE.DAY:
                # exact_time = str(datetime.datetime.strptime(
                #     str(order.datetime), '%Y-%m-%d %H-%M-%S') + datetime.timedelta(day=1))

                order.date = order.datetime[0:10]
                order.datetime = '{} 09:30:00'.format(order.date)
            elif order.frequence in [FREQUENCE.ONE_MIN,
                                     FREQUENCE.FIVE_MIN,
                                     FREQUENCE.FIFTEEN_MIN,
                                     FREQUENCE.THIRTY_MIN,
                                     FREQUENCE.SIXTY_MIN]:

                order.date = str(order.datetime)[0:10]
        elif order.order_model == ORDER_MODEL.STRICT:
            """
            严格模式
            """
            if order.frequence is FREQUENCE.DAY:
                # exact_time = str(datetime.datetime.strptime(
                #     str(order.datetime), '%Y-%m-%d %H-%M-%S') + datetime.timedelta(day=1))

                order.date = order.datetime[0:10]
                order.datetime = '{} 09:30:00'.format(order.date)
            elif order.frequence in [FREQUENCE.ONE_MIN,
                                     FREQUENCE.FIVE_MIN,
                                     FREQUENCE.FIFTEEN_MIN,
                                     FREQUENCE.THIRTY_MIN,
                                     FREQUENCE.SIXTY_MIN]:

                order.date = str(order.datetime)[0:10]

            if order.towards == 1:
                order.price = float(self.market_data.get('high'))
            else:
                order.price = float(self.market_data.get('low'))

        if order.market_type == MARKET_TYPE.STOCK_CN:
            if order.towards == ORDER_DIRECTION.BUY:
                if order.order_model == AMOUNT_MODEL.BY_MONEY:
                    amount = order.money / \
                        (order.price*(1+order.commission_coeff))
                    money = order.money
                else:

                    amount = order.amount
                    money = order.amount * order.price * \
                        (1+order.commission_coeff)

                order.amount = int(amount / 100) * 100
                order.money = money
            elif order.towards == ORDER_DIRECTION.SELL:
                if order.order_model == AMOUNT_MODEL.BY_MONEY:
                    amount = order.money / \
                        (order.price*(1+order.commission_coeff+order.tax_coeff))
                    money = order.money
                else:

                    amount = order.amount
                    money = order.amount * order.price * \
                        (1+order.commission_coeff+order.tax_coeff)

                order.amount = amount
                order.money = money
        return order

    def get_market(self, order):
        """get_market func

        [description]

        Arguments:
            order {orders} -- [description]

        Returns:
            [type] -- [description]
        """

        # 首先判断是否在_quotation里面
        if (pd.Timestamp(order.datetime), order.code) in self._quotation.keys():
            return self._quotation[(pd.Timestamp(order.datetime), order.code)]

        else:
            try:
                data = self.fetcher[(order.market_type,
                                     order.frequence)](
                                         code=order.code,
                                         start=order.datetime,
                                         end=order.datetime,
                                         format='json',
                                         frequence=order.frequence
                                     )[0]
                if 'vol' in data.keys() and 'volume' not in data.keys():
                    data['volume'] = data['vol']
                elif 'vol' not in data.keys() and 'volume' in data.keys():
                    data['vol'] = data['volume']
                return data
            except Exception as e:
                QA_util_log_info('MARKET_ENGING ERROR: {}'.format(e))
                return None
class QA_BacktestBroker(QA_Broker):
    """
    QUANTAXIS Broker 部分

    回测
    股票/指数/期货/债券/ETF/基金
    @yutiansut


    对于不同的市场规则:
    股票市场 t+1
    期货/期权/加密货币市场 t+0

    股票/加密货币市场不允许卖空
    期货/期权市场允许卖空

    t+1的市场是
    当日的买入 更新持仓- 不更新可卖数量- 资金冻结
    当日的卖出 及时更新可用资金

    t+0市场是:
    当日买入 即时更新持仓和可卖
    当日卖出 即时更新

    卖空的规则是
    允许无仓位的时候卖出证券(按市值和保证金比例限制算)
    """

    def __init__(self,if_nondatabase=False):
        """[summary]


        Keyword Arguments:
            commission_fee_coeff {[type]} -- [description] (default: {0})
            environment {[type]} -- [description] (default: {RUNNING_ENVIRONMENT})
            if_nondatabase {[type]} -- [description] (default: {False})
        """
        super().__init__()
        self.dealer = QA_Dealer()
        self.order_handler = QA_OrderHandler()
        self.engine = {
            MARKET_TYPE.STOCK_CN: self.dealer.backtest_stock_dealer}

        self.fetcher = {(MARKET_TYPE.STOCK_CN, FREQUENCE.DAY): QA_fetch_stock_day, (MARKET_TYPE.STOCK_CN, FREQUENCE.FIFTEEN_MIN): QA_fetch_stock_min,
                        (MARKET_TYPE.STOCK_CN, FREQUENCE.ONE_MIN): QA_fetch_stock_min, (MARKET_TYPE.STOCK_CN, FREQUENCE.FIVE_MIN): QA_fetch_stock_min,
                        (MARKET_TYPE.STOCK_CN, FREQUENCE.THIRTY_MIN): QA_fetch_stock_min, (MARKET_TYPE.STOCK_CN, FREQUENCE.SIXTY_MIN): QA_fetch_stock_min,
                        (MARKET_TYPE.INDEX_CN, FREQUENCE.DAY): QA_fetch_index_day, (MARKET_TYPE.INDEX_CN, FREQUENCE.FIFTEEN_MIN): QA_fetch_index_min,
                        (MARKET_TYPE.INDEX_CN, FREQUENCE.ONE_MIN): QA_fetch_index_min, (MARKET_TYPE.INDEX_CN, FREQUENCE.FIVE_MIN): QA_fetch_index_min,
                        (MARKET_TYPE.INDEX_CN, FREQUENCE.THIRTY_MIN): QA_fetch_index_min, (MARKET_TYPE.INDEX_CN, FREQUENCE.SIXTY_MIN): QA_fetch_index_min,
                        (MARKET_TYPE.FUND_CN, FREQUENCE.DAY): QA_fetch_index_day, (MARKET_TYPE.FUND_CN, FREQUENCE.FIFTEEN_MIN): QA_fetch_index_min,
                        (MARKET_TYPE.FUND_CN, FREQUENCE.ONE_MIN): QA_fetch_index_min, (MARKET_TYPE.FUND_CN, FREQUENCE.FIVE_MIN): QA_fetch_index_min,
                        (MARKET_TYPE.FUND_CN, FREQUENCE.THIRTY_MIN): QA_fetch_index_min, (MARKET_TYPE.FUND_CN, FREQUENCE.SIXTY_MIN): QA_fetch_index_min}


        self.market_data = None
        self.if_nondatabase = if_nondatabase
        self.name = BROKER_TYPE.BACKETEST
        self._quotation = {}  # 一个可以缓存数据的dict
        self.broker_data = None

    def run(self, event):
        #strDbg = QA_util_random_with_topic("QABacktestBroker.run")
        #print("         >-----------------------QABacktestBroker.run----------------------------->", strDbg,'evt->', event)

        if event.event_type is MARKET_EVENT.QUERY_DATA:
            # 查询数据部分
            code = event.code
            frequence = event.frequence
            start = event.start
            end = start if event.end is None else event.end
            market_type = event.market_type
            res = self.query_data(code, start, end, frequence, market_type)
            if event.callback:
                event.callback(res)
            else:
                return res
        elif event.event_type is MARKET_EVENT.QUERY_ORDER:
            self.order_handler.run(event)
        elif event.event_type is ENGINE_EVENT.UPCOMING_DATA:
            # QABacktest 回测发出的事件
            new_marketdata_dict = event.market_data.dicts
            for item in new_marketdata_dict.keys():
                if item not in self._quotation.keys():
                    self._quotation[item] = new_marketdata_dict[item]
            # if self.broker_data is None:
            #     self.broker_data = event.market_data
            # else:
            #     self.broker_data.append(event.market_data)
            # self.broker_data=event.market_data

        elif event.event_type is BROKER_EVENT.RECEIVE_ORDER:
            self.order_handler.run(event)
            self.run(QA_Event(event_type=BROKER_EVENT.TRADE, broker=self))
        elif event.event_type is BROKER_EVENT.TRADE:
            event = self.order_handler.run(event)
            event.message = 'trade'
            if event.callback:
                event.callback(event)
        elif event.event_type is BROKER_EVENT.SETTLE:
            self.order_handler.run(event)
            if event.callback:
                event.callback('settle')
        #print("         <-----------------------QABacktestBroker.run-----------------------------<",strDbg,'evt->',event)


    def query_data(self, code, start, end, frequence, market_type=None):
        """
        标准格式是numpy
        """
        try:
            return self.broker_data.select_time(
                start, end).select_code(code).to_numpy()
        except:
            return self.fetcher[(market_type, frequence)](
                code, start, end, frequence=frequence)

    def receive_order(self, event):
        """
        get the order and choice which market to trade

        """
        order = event.order
        if 'market_data' in event.__dict__.keys():
            self.market_data = self.get_market(
                order) if event.market_data is None else event.market_data
            if isinstance(self.market_data,dict):
                pass
            elif isinstance(self.market_data,pd.DataFrame):
                self.market_data=QA_util_to_json_from_pandas(self.market_data)[0]
            else:
                self.market_data=self.market_data.to_json()[0]
        else:
            self.market_data = self.get_market(order)
        if self.market_data is not None:
            
            order = self.warp(order)
            return self.dealer.deal(order, self.market_data)
        else:
            raise ValueError('MARKET DATA IS NONE CANNOT TRADE')

    def warp(self, order):
        """对order/market的封装

        [description]

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

        Returns:
            [type] -- [description]
        """

        # 因为成交模式对时间的封装
        if order.order_model == ORDER_MODEL.MARKET:
            """
            市价单模式
            """
            if order.frequence is FREQUENCE.DAY:
                # exact_time = str(datetime.datetime.strptime(
                #     str(order.datetime), '%Y-%m-%d %H-%M-%S') + datetime.timedelta(day=1))

                order.date = order.datetime[0:10]
                order.datetime = '{} 09:30:00'.format(order.date)
            elif order.frequence in [FREQUENCE.ONE_MIN, FREQUENCE.FIVE_MIN, FREQUENCE.FIFTEEN_MIN, FREQUENCE.THIRTY_MIN, FREQUENCE.SIXTY_MIN]:

                order.date = str(order.datetime)[0:10]
            #_original_marketvalue = order.price*order.amount

            order.price = (float(self.market_data.get('high')) +
                        float(self.market_data.get('low'))) * 0.5

        elif order.order_model == ORDER_MODEL.NEXT_OPEN:
            # try:
            #     order.date = QA_util_get_next_day(str(order.datetime)[0:10])
            #     order.datetime = '{} 09:30:00'.format(order.date)
            # except:
            #     order.datetime = '{} 15:00:00'.format(order.date)
            # self.market_data = self.get_market(order)
            # if self.market_data is None:
            #     return order
            # order.price = float(self.market_data["close"])
            raise NotImplementedError
        elif order.order_model == ORDER_MODEL.CLOSE:
            """
            收盘价模式
            """
            try:
                order.date = order.datetime[0:10]
                order.datetime = '{} 15:00:00'.format(order.date)
            except:
                if len(str(order.datetime)) == 19:
                    pass
                else:
                    order.datetime = '{} 15:00:00'.format(order.date)

            order.price = float(self.market_data.get('close'))

        elif order.order_model == ORDER_MODEL.LIMIT:
            """
            限价单模式
            """
            if order.frequence is FREQUENCE.DAY:
                # exact_time = str(datetime.datetime.strptime(
                #     str(order.datetime), '%Y-%m-%d %H-%M-%S') + datetime.timedelta(day=1))

                order.date = order.datetime[0:10]
                order.datetime = '{} 09:30:00'.format(order.date)
            elif order.frequence in [FREQUENCE.ONE_MIN, FREQUENCE.FIVE_MIN, FREQUENCE.FIFTEEN_MIN, FREQUENCE.THIRTY_MIN, FREQUENCE.SIXTY_MIN]:

                order.date = str(order.datetime)[0:10]
        elif order.order_model == ORDER_MODEL.STRICT:
            """
            严格模式
            """
            if order.frequence is FREQUENCE.DAY:
                # exact_time = str(datetime.datetime.strptime(
                #     str(order.datetime), '%Y-%m-%d %H-%M-%S') + datetime.timedelta(day=1))

                order.date = order.datetime[0:10]
                order.datetime = '{} 09:30:00'.format(order.date)
            elif order.frequence in [FREQUENCE.ONE_MIN, FREQUENCE.FIVE_MIN, FREQUENCE.FIFTEEN_MIN, FREQUENCE.THIRTY_MIN, FREQUENCE.SIXTY_MIN]:

                order.date = str(order.datetime)[0:10]

            if order.towards == 1:
                order.price = float(self.market_data.get('high'))
            else:
                order.price = float(self.market_data.get('low'))


        if order.market_type == MARKET_TYPE.STOCK_CN:
            if order.towards == ORDER_DIRECTION.BUY:
                if order.order_model == AMOUNT_MODEL.BY_MONEY:
                    amount = order.money/(order.price*(1+order.commission_coeff))
                    money = order.money
                else:

                    amount = order.amount
                    money = order.amount * order.price*(1+order.commission_coeff)

                order.amount = int(amount / 100) * 100
                order.money =  money
            elif order.towards == ORDER_DIRECTION.SELL:
                if order.order_model == AMOUNT_MODEL.BY_MONEY:
                    amount = order.money/(order.price*(1+order.commission_coeff+order.tax_coeff))
                    money = order.money
                else:

                    amount = order.amount
                    money = order.amount * order.price*(1+order.commission_coeff+order.tax_coeff)

                order.amount = amount
                order.money =  money
        return order

    def get_market(self, order):
        """get_market func

        [description]

        Arguments:
            order {orders} -- [description]

        Returns:
            [type] -- [description]
        """

        # 首先判断是否在_quotation里面
        if (pd.Timestamp(order.datetime), order.code) in self._quotation.keys():
            return self._quotation[(pd.Timestamp(order.datetime), order.code)]

        else:
            try:
                data = self.fetcher[(order.market_type, order.frequence)](
                    code=order.code, start=order.datetime, end=order.datetime, format='json')[0]
                if 'vol' in data.keys() and 'volume' not in data.keys():
                    data['volume'] = data['vol']
                elif 'vol' not in data.keys() and 'volume' in data.keys():
                    data['vol'] = data['volume']
                return data
            except Exception as e:
                QA_util_log_info('MARKET_ENGING ERROR: {}'.format(e))
                return None
Beispiel #20
0
class QA_BacktestBroker(QA_Broker):
    """
    QUANTAXIS Broker 部分

    回测
    股票/指数/期货/债券/ETF/基金
    @yutiansut


    对于不同的市场规则:
    股票市场 t+1
    期货/期权/加密货币市场 t+0

    股票/加密货币市场不允许卖空
    期货/期权市场允许卖空

    t+1的市场是
    当日的买入 更新持仓- 不更新可卖数量- 资金冻结
    当日的卖出 及时更新可用资金

    t+0市场是:
    当日买入 即时更新持仓和可卖
    当日卖出 即时更新

    卖空的规则是
    允许无仓位的时候卖出证券(按市值和保证金比例限制算)
    """

    def __init__(self, commission_fee_coeff=0.0015, if_nondatabase=False):
        """[summary]


        Keyword Arguments:
            commission_fee_coeff {[type]} -- [description] (default: {0})
            environment {[type]} -- [description] (default: {RUNNING_ENVIRONMENT})
            if_nondatabase {[type]} -- [description] (default: {False})
        """
        super().__init__()
        self.dealer = QA_Dealer(commission_fee_coeff)
        self.order_handler = QA_OrderHandler()
        self.engine = {
            MARKET_TYPE.STOCK_CN: self.dealer.backtest_stock_dealer}

        self.fetcher = {(MARKET_TYPE.STOCK_CN, FREQUENCE.DAY): QA_fetch_stock_day, (MARKET_TYPE.STOCK_CN, FREQUENCE.FIFTEEN_MIN): QA_fetch_stock_min,
                        (MARKET_TYPE.STOCK_CN, FREQUENCE.ONE_MIN): QA_fetch_stock_min, (MARKET_TYPE.STOCK_CN, FREQUENCE.FIVE_MIN): QA_fetch_stock_min,
                        (MARKET_TYPE.STOCK_CN, FREQUENCE.THIRTY_MIN): QA_fetch_stock_min, (MARKET_TYPE.STOCK_CN, FREQUENCE.SIXTY_MIN): QA_fetch_stock_min,
                        (MARKET_TYPE.INDEX_CN, FREQUENCE.DAY): QA_fetch_index_day, (MARKET_TYPE.INDEX_CN, FREQUENCE.FIFTEEN_MIN): QA_fetch_index_min,
                        (MARKET_TYPE.INDEX_CN, FREQUENCE.ONE_MIN): QA_fetch_index_min, (MARKET_TYPE.INDEX_CN, FREQUENCE.FIVE_MIN): QA_fetch_index_min,
                        (MARKET_TYPE.INDEX_CN, FREQUENCE.THIRTY_MIN): QA_fetch_index_min, (MARKET_TYPE.INDEX_CN, FREQUENCE.SIXTY_MIN): QA_fetch_index_min,
                        (MARKET_TYPE.FUND_CN, FREQUENCE.DAY): QA_fetch_index_day, (MARKET_TYPE.FUND_CN, FREQUENCE.FIFTEEN_MIN): QA_fetch_index_min,
                        (MARKET_TYPE.FUND_CN, FREQUENCE.ONE_MIN): QA_fetch_index_min, (MARKET_TYPE.FUND_CN, FREQUENCE.FIVE_MIN): QA_fetch_index_min,
                        (MARKET_TYPE.FUND_CN, FREQUENCE.THIRTY_MIN): QA_fetch_index_min, (MARKET_TYPE.FUND_CN, FREQUENCE.SIXTY_MIN): QA_fetch_index_min}

        self.commission_fee_coeff = commission_fee_coeff
        self.market_data = None
        self.if_nondatabase = if_nondatabase
        self.name = BROKER_TYPE.BACKETEST
        self._quotation = {}  # 一个可以缓存数据的dict
        self.broker_data = None

    def run(self, event):
        if event.event_type is MARKET_EVENT.QUERY_DATA:
            # 查询数据部分
            code = event.code
            frequence = event.frequence
            start = event.start
            end = start if event.end is None else event.end
            market_type = event.market_type
            res = self.query_data(code, start, end, frequence, market_type)
            if event.callback:
                event.callback(res)
            else:
                return res
        elif event.event_type is MARKET_EVENT.QUERY_ORDER:
            self.order_handler.run(event)
        elif event.event_type is ENGINE_EVENT.UPCOMING_DATA:
            new_marketdata_dict = event.market_data.dicts
            for item in new_marketdata_dict.keys():
                if item not in self._quotation.keys():
                    self._quotation[item] = new_marketdata_dict[item]
            # if self.broker_data is None:
            #     self.broker_data = event.market_data
            # else:
            #     self.broker_data.append(event.market_data)
            # self.broker_data=event.market_data

        elif event.event_type is BROKER_EVENT.RECEIVE_ORDER:
            self.order_handler.run(event)
            self.run(QA_Event(event_type=BROKER_EVENT.TRADE, broker=self))
        elif event.event_type is BROKER_EVENT.TRADE:
            event = self.order_handler.run(event)

            event.message = 'trade'
            if event.callback:
                event.callback(event)
        elif event.event_type is BROKER_EVENT.SETTLE:
            self.order_handler.run(event)
            if event.callback:
                event.callback('settle')

    def query_data(self, code, start, end, frequence, market_type=None):
        """
        标准格式是numpy
        """
        try:
            return self.broker_data.select_time(
                start, end).select_code(code).to_numpy()
        except:
            return self.fetcher[(market_type, frequence)](
                code, start, end, frequence=frequence)

    def receive_order(self, event):
        """
        get the order and choice which market to trade

        """
        order = event.order

        if 'market_data' in event.__dict__.keys():
            self.market_data = self.get_market(
                order) if event.market_data is None else event.market_data
        else:
            self.market_data = self.get_market(order)

        order = self.warp(order)

        return self.dealer.deal(order, self.market_data)

    def warp(self, order):
        """对order/market的封装

        [description]

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

        Returns:
            [type] -- [description]
        """

        # 因为成交模式对时间的封装

        if order.order_model == ORDER_MODEL.MARKET:

            if order.frequence is FREQUENCE.DAY:
                # exact_time = str(datetime.datetime.strptime(
                #     str(order.datetime), '%Y-%m-%d %H-%M-%S') + datetime.timedelta(day=1))

                order.date = order.datetime[0:10]
                order.datetime = '{} 09:30:00'.format(order.date)
            elif order.frequence in [FREQUENCE.ONE_MIN, FREQUENCE.FIVE_MIN, FREQUENCE.FIFTEEN_MIN, FREQUENCE.THIRTY_MIN, FREQUENCE.SIXTY_MIN]:
                print(order.datetime)
                exact_time = str(datetime.datetime.strptime(
                    str(order.datetime), '%Y-%m-%d %H:%M:%S') + datetime.timedelta(minutes=1))
                order.date = exact_time[0:10]
                order.datetime = exact_time
            self.market_data = self.get_market(order)
            if self.market_data is None:
                return order
            order.price = (float(self.market_data["high"]) +
                           float(self.market_data["low"])) * 0.5
        elif order.order_model == ORDER_MODEL.NEXT_OPEN:
            try:
                exact_time = str(datetime.datetime.strptime(
                    str(order.datetime), '%Y-%m-%d %H-%M-%S') + datetime.timedelta(day=1))
                order.date = exact_time[0:10]
                order.datetime = '{} 09:30:00'.format(order.date)
            except:
                order.datetime = '{} 15:00:00'.format(order.date)
            self.market_data = self.get_market(order)
            if self.market_data is None:
                return order
            order.price = float(self.market_data["close"])
        elif order.order_model == ORDER_MODEL.CLOSE:

            try:
                order.datetime = self.market_data.datetime
            except:
                if len(str(order.datetime)) == 19:
                    pass
                else:
                    order.datetime = '{} 15:00:00'.format(order.date)
            self.market_data = self.get_market(order)
            if self.market_data is None:
                return order
            order.price = float(self.market_data["close"])

        elif order.order_model == ORDER_MODEL.STRICT:
            '加入严格模式'
            if order.frequence is FREQUENCE.DAY:
                exact_time = str(datetime.datetime.strptime(
                    order.datetime, '%Y-%m-%d %H-%M-%S') + datetime.timedelta(day=1))

                order.date = exact_time[0:10]
                order.datetime = '{} 09:30:00'.format(order.date)
            elif order.frequence in [FREQUENCE.ONE_MIN, FREQUENCE.FIVE_MIN, FREQUENCE.FIFTEEN_MIN, FREQUENCE.THIRTY_MIN, FREQUENCE.SIXTY_MIN]:
                exact_time = str(datetime.datetime.strptime(
                    order.datetime, '%Y-%m-%d %H-%M-%S') + datetime.timedelta(minute=1))
                order.date = exact_time[0:10]
                order.datetime = exact_time
            self.market_data = self.get_market(order)
            if self.market_data is None:
                return order
            if order.towards == 1:
                order.price = float(self.market_data["high"])
            else:
                order.price = float(self.market_data["low"])

        return order

    def get_market(self, order):
        """get_market func

        [description]

        Arguments:
            order {orders} -- [description]

        Returns:
            [type] -- [description]
        """

        # 首先判断是否在_quotation里面

        if (order.datetime, order.code) in self._quotation.keys():
            return self._quotation[(QA_util_to_datetime(order.datetime), order.code)]

        else:
            try:
                data = self.fetcher[(order.market_type, order.frequence)](
                    code=order.code, start=order.datetime, end=order.datetime, format='json')[0]
                if 'vol' in data.keys() and 'volume' not in data.keys():
                    data['volume'] = data['vol']
                elif 'vol' not in data.keys() and 'volume' in data.keys():
                    data['vol'] = data['volume']
                return data
            except Exception as e:
                QA_util_log_info('MARKET_ENGING ERROR: {}'.format(e))
                return None
Beispiel #21
0
class QA_SPEBroker(QA_Broker):
    def __init__(self):
        self.order_handler = QA_OrderHandler()
        self.setting = get_config_SPE()
        self._session = requests
        self._endpoint = self.setting.uri
        self.key = self.setting.key

        #self.account_headers = ['forzen_cash','balance_available','cash_available','pnl_money_today','total_assets','pnl_holding','market_value','money_available']
        self.fillorder_headers = ['name', 'datetime', 'towards', 'price',
                                  'amount', 'money', 'trade_id', 'order_id', 'code', 'shareholder', 'other']
        self.holding_headers = ['code', 'name', 'hoding_price', 'price', 'pnl', 'amount',
                                'sell_available', 'pnl_money', 'holdings', 'total_amount', 'lastest_amounts', 'shareholder']
        self.askorder_headers = ['code', 'towards', 'price', 'amount', 'transaction_price',
                                 'transaction_amount', 'status', 'order_time', 'order_id', 'id', 'code', 'shareholders']

    def __repr__(self):
        return ' <QA_BROKER SHIPANE> '

    def run(self, event):
        if event.event_type is BROKER_EVENT.RECEIVE_ORDER:
            self.order_handler.run(event)
            self.run(QA_Event(event_type=BROKER_EVENT.TRADE, broker=self))
        elif event.event_type is BROKER_EVENT.TRADE:
            """实盘交易部分!!!!! ATTENTION
            这里需要开一个子线程去查询是否成交

            ATTENTION
            """
            
            event = self.order_handler.run(event)
            event.message = 'trade'
            if event.callback:
                event.callback(event)

    def call(self, func, params=''):
        try:
            if self.key == '':
                uri = '{}/api/v1.0/{}?client={}'.format(
                    self._endpoint, func, params.pop('client'))
            else:
                uri = '{}/api/v1.0/{}?key={}&client={}'.format(
                    self._endpoint, func, self.key, params.pop('client'))
            print(uri)
            response = self._session.get(uri, params)
            text = response.text

            return json.loads(text)
        except Exception as e:
            print(e)
            return None

    def call_post(self, func, params={}):
        if self.key == '':
            uri = '{}/api/v1.0/{}?client={}'.format(
                self._endpoint, func, params.pop('client'))
        else:
            uri = '{}/api/v1.0/{}?key={}&client={}'.format(
                self._endpoint, func, self.key, params.pop('client'))
        response = self._session.post(uri, json=params)
        text = response.text
        return json.loads(text)

    def call_delete(self, func, params=''):

        if self.key == '':
            uri = '{}/api/v1.0/{}?client={}'.format(
                self._endpoint, func, params.pop('client'))
        else:
            uri = '{}/api/v1.0/{}?key={}&client={}'.format(
                self._endpoint, func, self.key, params.pop('client'))

        response = self._session.delete(uri)

        text = response.text
        try:
            if text == '':
                print('success')
                return True
            elif text == '获取提示对话框超时,因为:组件为空':
                print('do not query too fast')
                return False
            else:
                return json.loads(text)
        except:
            return text

    def data_to_df(self, result):
        return pd.DataFrame(data=result)

    #------ functions

    def ping(self):
        return self.call("ping", {})

    def query_accounts(self, accounts):
        return self.call("accounts", {
            'client': accounts
        })

    def query_positions(self, accounts):
        """查询现金和持仓

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

        Returns:
            dict-- {'cash':xxx,'position':xxx}
        """

        data = self.call("positions", {
            'client': accounts
        })

        cash_part = data.get('subAccounts', {}).get('人民币', False)
        if cash_part:
            cash_available = cash_part.get('可用金额')
        position_part = data.get('dataTable', False)
        if position_part:
            res = data.get('dataTable', False)
            if res:
                hold_headers = res['columns']
                hold_headers = [cn_en_compare[item] for item in hold_headers]
                hold_available = pd.DataFrame(
                    res['rows'], columns=hold_headers)

        return {'cash_available': cash_available, 'hold_available': hold_available.loc[:, ['code', 'amount']].set_index('code').amount}

    def query_clients(self):
        return self.call("clients")

    def query_orders(self, accounts, status='filled'):
        """查询订单

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

        Keyword Arguments:
            status {str} -- 'open' 待成交 'filled' 成交 (default: {'filled'})

        Returns:
            [type] -- [description]
        """

        return self.call("orders", {
            'client': accounts,
            'status': status
        })




    def send_order(self, accounts, code='000001', price=9, amount=100, order_direction=ORDER_DIRECTION.BUY, order_model=ORDER_MODEL.LIMIT):
        """[summary]

        Arguments:
            accounts {[type]} -- [description]
            code {[type]} -- [description]
            price {[type]} -- [description]
            amount {[type]} -- [description]

        Keyword Arguments:
            order_direction {[type]} -- [description] (default: {ORDER_DIRECTION.BUY})
            order_model {[type]} -- [description] (default: {ORDER_MODEL.LIMIT})



        priceType 可选择: 上海交易所:

            0 - 限价委托
            4 - 五档即时成交剩余撤销
            6 - 五档即时成交剩余转限

        深圳交易所:

            0 - 限价委托
            1 - 对手方最优价格委托
            2 - 本方最优价格委托
            3 - 即时成交剩余撤销委托
            4 - 五档即时成交剩余撤销
            5 - 全额成交或撤销委托

        Returns:
            [type] -- [description]
        """
        try:
            return self.call_post('orders', {
                'client': accounts,
                "action": 'BUY' if order_direction == 1 else 'SELL',
                "symbol": code,
                "type": order_model,
                "priceType": 0 if order_model == ORDER_MODEL.LIMIT else 4,
                "price": price,
                "amount": amount
            })
        except json.decoder.JSONDecodeError:
            print(RuntimeError('TRADE ERROR'))
            return None

    def cancel_order(self, accounts, orderid):
        return self.call_delete('orders/{}'.format(orderid), {
            'client': accounts
        })

    def cancel_all(self, accounts):
        return self.call_delete('orders', {
            'client': accounts
        })

    def receive_order(self, event):
        order = event.order
        callback = self.send_order(accounts=order.account_cookie, code=order.code,
                                   amount=order.amount, order_direction=order.towards, order_model=order.order_model)
        order.realorder_id = callback['id']
        order.status = ORDER_STATUS.QUEUED
        print('success receive order {}'.format(order.realorder_id))
Beispiel #22
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()
Beispiel #23
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()
Beispiel #24
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()