class TestGeneralSocketMethods(unittest.TestCase):
    def setUp(self):
        self.socket = Socket(PAIR)

    def tearDown(self):
        self.socket.close()

    def test_bind(self):
        endpoint = self.socket.bind(SOCKET_ADDRESS)

        self.assertNotEqual(None, endpoint)

    def test_connect(self):
        endpoint = self.socket.connect(SOCKET_ADDRESS)

        self.assertNotEqual(None, endpoint)

    def test_is_open_is_true_when_open(self):
        self.assertTrue(self.socket.is_open())

    def test_is_open_is_false_when_closed(self):
        self.socket.close()

        self.assertFalse(self.socket.is_open())

    def test_set_and_get_int_option(self):
        expected = 500

        self.socket.set_int_option(SOL_SOCKET, SNDBUF, expected)

        actual = self.socket.get_int_option(SOL_SOCKET, SNDBUF)
        self.assertEqual(expected, actual)
class TestGeneralSocketMethods(unittest.TestCase):
    def setUp(self):
        self.socket = Socket(PAIR)

    def tearDown(self):
        self.socket.close()

    def test_bind(self):
        endpoint = self.socket.bind(SOCKET_ADDRESS)

        self.assertNotEqual(None, endpoint)

    def test_connect(self):
        endpoint = self.socket.connect(SOCKET_ADDRESS)

        self.assertNotEqual(None, endpoint)

    def test_is_open_is_true_when_open(self):
        self.assertTrue(self.socket.is_open())

    def test_is_open_is_false_when_closed(self):
        self.socket.close()

        self.assertFalse(self.socket.is_open())

    def test_set_and_get_int_option(self):
        expected = 500

        self.socket.set_int_option(SOL_SOCKET, SNDBUF, expected)

        actual = self.socket.get_int_option(SOL_SOCKET, SNDBUF)
        self.assertEqual(expected, actual)
Exemple #3
0
def sender(queue, addresses, stype):
    """
    Bind a queue to a connecting nanomsg socket's multiple endpoints
    in a separate thread.
    
    Parameters
    ----------
    queue : Queue
        A Queue object to be emptied by sender socket
        
    addresses : list
        A list of strings of format '<protocol>://<ip>:<port>' to bind to
        
    stype : int
        One of the nanomsg scalability socket types: PUSH, PULL, PUB, SUB, PAIR
        
    Returns
    -------
        nanomsg socket object
    """
    with err.applicationbound():
      out_sock = Socket(stype)
      
      out_sock.set_int_option(SOL_SOCKET, SNDTIMEO, 1000)
      
      for address in addresses:
          endpoint = out_sock.connect(address)
          out_endpoints.append(endpoint)
        
      def send_messages():
          """ """
          while True:
              try:
                  out_sock.send(queue.get(block=True))
                  log.info("Message has been sent")
              except NanoMsgAPIError as e:
                  log.debug(e)
                  log.debug(dir(e))
                  

      receiver = threading.Thread(target=send_messages)
      receiver.start()

      return out_sock
Exemple #4
0
def sender(queue, addresses, stype):
    """
    Bind a queue to a connecting nanomsg socket's multiple endpoints
    in a separate thread.
    
    Parameters
    ----------
    queue : Queue
        A Queue object to be emptied by sender socket
        
    addresses : list
        A list of strings of format '<protocol>://<ip>:<port>' to bind to
        
    stype : int
        One of the nanomsg scalability socket types: PUSH, PULL, PUB, SUB, PAIR
        
    Returns
    -------
        nanomsg socket object
    """
    with err.applicationbound():
        out_sock = Socket(stype)

        out_sock.set_int_option(SOL_SOCKET, SNDTIMEO, 1000)

        for address in addresses:
            endpoint = out_sock.connect(address)
            out_endpoints.append(endpoint)

        def send_messages():
            """ """
            while True:
                try:
                    out_sock.send(queue.get(block=True))
                    log.info("Message has been sent")
                except NanoMsgAPIError as e:
                    log.debug(e)
                    log.debug(dir(e))

        receiver = threading.Thread(target=send_messages)
        receiver.start()

        return out_sock
class ServiceDiscovery(object):
 
    def __init__(self, port, deadline=5000):
        self.socket = Socket(SURVEYOR)
        self.port = port
        self.deadline = deadline
        self.services = defaultdict(set)
 
    def bind(self):
        self.socket.bind('tcp://172.30.42.174:%s' % self.port)
        self.socket.set_int_option(SURVEYOR, SURVEYOR_DEADLINE, self.deadline)
 
    def discover(self):
        if not self.socket.is_open():
            return self.services
 
        self.services = defaultdict(set)
        self.socket.send('service query')
 
        while True:
            try:
                response = self.socket.recv()
            except NanoMsgAPIError:
                break
 
            service, address = response.split('|')
            self.services[service].add(address)
 
        return self.services
 
    def resolve(self, service):
        providers = self.services[service]
 
        if not providers:
            return None
 
        return random.choice(tuple(providers))
 
    def close(self):
        self.socket.close()
Exemple #6
0
class ServiceDiscovery(object):

    def __init__(self, port, deadline=5000):
        self.socket = Socket(SURVEYOR)
        self.port = port
        self.deadline = deadline
        self.services = defaultdict(set)

    def bind(self):
        self.socket.bind('tcp://*:%s' % self.port)
        self.socket.set_int_option(SURVEYOR, SURVEYOR_DEADLINE, self.deadline)

    def discover(self):
        if not self.socket.is_open():
            return self.services

        self.services = defaultdict(set)
        self.socket.send('service query')

        while True:
            try:
                response = self.socket.recv()
            except NanoMsgAPIError:
                break

            service, address = response.split('|')
            self.services[service].add(address)

        return self.services

    def resolve(self, service):
        providers = self.services[service]

        if not providers:
            return None

        return random.choice(tuple(providers))

    def close(self):
        self.socket.close()
Exemple #7
0
def sender(queue, network, stype=PUSH):
    out_sock = Socket(stype)

    out_sock.set_int_option(SOL_SOCKET, SNDTIMEO, 1000)

    for node in network['nodes']:
        endpoint = out_sock.connect('tcp://{ip}:{port}'.format(
            ip=node['ip'], port=node['port']))
        out_endpoints.append(endpoint)

    def send_messages():
        while True:
            try:
                out_sock.send(queue.get(block=True))
                print("Message has been sent")
            except NanoMsgAPIError as e:
                print(e)
                print(dir(e))

    receiver = threading.Thread(target=send_messages)
    receiver.start()

    return out_sock
Exemple #8
0
def sender(queue, network, stype=PUSH):
    out_sock = Socket(stype)
    
    out_sock.set_int_option(SOL_SOCKET, SNDTIMEO, 1000)
    
    for node in network['nodes']:
        endpoint = out_sock.connect('tcp://{ip}:{port}'.format(ip=node['ip'], 
                                                               port=node['port']))
        out_endpoints.append(endpoint)
      
    def send_messages():
        while True:
            try:
                out_sock.send(queue.get(block=True))
                print("Message has been sent")
            except NanoMsgAPIError as e:
                print(e)
                print(dir(e))
                

    receiver = threading.Thread(target=send_messages)
    receiver.start()

    return out_sock
class RecorderEngine(BaseEngine):
    """
    market data recorder 
    """
    config_filename = "config_server.yaml"
    setting_filename = "data_recorder_setting.json"

    # init
    def __init__(self, configfile: str = '', gateway: str = "CTP.MD"):
        super(RecorderEngine, self).__init__(event_engine=EventEngine(10))
        """
        two sockets to send and recv msg
        """
        self.__active = False
        self._thread = Thread(target=self._run)
        self.id = os.getpid()
        self.engine_type = EngineType.LIVE
        self._recv_sock = Socket(SUB)
        self._send_sock = Socket(PUSH)

        if configfile:
            self.config_filename = configfile
        if gateway:
            self.gateway = gateway
        filepath = Path.cwd().joinpath("etc/" + self.config_filename)
        with open(filepath, encoding='utf8') as fd:
            self._config = yaml.load(fd)

        self.tick_recordings = {}
        self.bar_recordings = {}
        self.bar_generators = {}
        self.contracts = {}
        self.subscribed = False
        self.dayswitched = False
        self.init_engine()

# init functions

    def init_engine(self):
        self.init_nng()
        self.load_contract()
        self.load_setting()
        self.register_event()
        self.put_event()

    def init_nng(self):
        self._recv_sock.set_string_option(SUB, SUB_SUBSCRIBE,
                                          '')  # receive msg start with all
        self._recv_sock.set_int_option(SOL_SOCKET, RCVTIMEO, 100)
        self._recv_sock.connect(self._config['serverpub_url'])
        self._send_sock.connect(self._config['serverpull_url'])

    def load_contract(self):
        contractfile = Path.cwd().joinpath("etc/ctpcontract.yaml")
        with open(contractfile, encoding='utf8') as fc:
            contracts = yaml.load(fc)
        print('loading contracts, total number:', len(contracts))
        for sym, data in contracts.items():
            contract = ContractData(
                symbol=data["symbol"],
                exchange=Exchange(data["exchange"]),
                name=data["name"],
                product=PRODUCT_CTP2VT[str(data["product"])],
                size=data["size"],
                pricetick=data["pricetick"],
                net_position=True
                if str(data["positiontype"]) == THOST_FTDC_PT_Net else False,
                long_margin_ratio=data["long_margin_ratio"],
                short_margin_ratio=data["short_margin_ratio"],
                full_symbol=data["full_symbol"])
            # For option only
            if contract.product == Product.OPTION:
                contract.option_underlying = data["option_underlying"],
                contract.option_type = OPTIONTYPE_CTP2VT.get(
                    str(data["option_type"]), None),
                contract.option_strike = data["option_strike"],
                contract.option_expiry = datetime.strptime(
                    str(data["option_expiry"]), "%Y%m%d"),
            self.contracts[contract.full_symbol] = contract

    def load_setting(self):
        """"""
        setting = load_json(self.setting_filename)
        self.tick_recordings = setting.get("tick", {})
        self.bar_recordings = setting.get("bar", {})

    def save_setting(self):
        """"""
        setting = {"tick": self.tick_recordings, "bar": self.bar_recordings}
        save_json(self.setting_filename, setting)

    def register_event(self):
        """"""
        self.event_engine.register(EventType.TICK, self.process_tick_event)
        self.event_engine.register(EventType.CONTRACT,
                                   self.process_contract_event)
        self.event_engine.register(EventType.RECORDER_CONTROL,
                                   self.process_recordercontrol_event)
        self.event_engine.register(EventType.HEADER,
                                   self.process_general_event)
        self.event_engine.register(EventType.TIMER, self.process_timer_event)

    def init_subcribe(self, src: str = 'CTP.MD'):
        symset = set(self.tick_recordings.keys())
        symset.update(self.bar_recordings.keys())
        for sym in symset:
            self.subscribe(sym, src)
        self.subscribed = True

# event handler

    def process_timer_event(self, event):
        # auto subscribe at 8:55, 20:55
        nowtime = datetime.now().time()
        if (nowtime > time(hour=8, minute=50)) and (nowtime < time(
                hour=8, minute=51)) and (not self.subscribed):
            self.init_subcribe()
            self.dayswitched = False
        if (nowtime > time(hour=20, minute=50)) and (nowtime < time(
                hour=20, minute=51)) and (not self.subscribed):
            self.init_subcribe()
            self.dayswitched = False
        # reset at 16:00 and 3:00
        if (nowtime > time(hour=16, minute=0)) and (nowtime < time(
                hour=16, minute=1)) and (not self.dayswitched):
            self.subscribed = False
            self.dayswitched = True
        if (nowtime > time(hour=3, minute=0)) and (nowtime < time(
                hour=3, minute=1)) and (not self.dayswitched):
            self.subscribed = False
            self.dayswitched = True

    def process_general_event(self, event):
        pass

    def process_tick_event(self, event: Event):
        """"""
        tick = event.data
        dayclosetime = tick.datetime.time() < time(
            hour=9, minute=0) and tick.datetime.time() > time(hour=8, minute=0)
        nightclosetime = tick.datetime.time() < time(
            hour=21, minute=0) and tick.datetime.time() > time(hour=16,
                                                               minute=0)
        if dayclosetime or nightclosetime:
            return
        # exclude onrtnsubscribe return first tick which time not in trade time
        if (tick.open_price) and tick.last_price and tick.ask_price_1:
            if tick.full_symbol in self.tick_recordings:
                self.record_tick(tick)

            if tick.full_symbol in self.bar_recordings:
                bg = self.get_bar_generator(tick.full_symbol)
                bg.update_tick(tick)

    def process_contract_event(self, event: Event):
        """"""
        contract = event.data
        self.contracts[contract.full_symbol] = contract

    def process_recordercontrol_event(self, event: Event):
        msgtype = event.msg_type
        deslist = ['@*', str(self.id), '@' + str(self.id)]
        if (event.destination not in deslist):
            return
        elif (msgtype == MSG_TYPE.MSG_TYPE_RECORDER_STATUS):
            m = Event(type=EventType.RECORDER_CONTROL,
                      des='@0',
                      src=str(self.id),
                      data=str(self.__active),
                      msgtype=MSG_TYPE.MSG_TYPE_RECORDER_STATUS)
            self._send_sock.send(m.serialize())
            self.put_event()
        elif (msgtype == MSG_TYPE.MSG_TYPE_RECORDER_ADD_TICK):
            full_symbol = event.data
            self.add_tick_recording(full_symbol, event.source)
        elif (msgtype == MSG_TYPE.MSG_TYPE_RECORDER_ADD_BAR):
            full_symbol = event.data
            self.add_bar_recording(full_symbol, event.source)
        elif (msgtype == MSG_TYPE.MSG_TYPE_RECORDER_REMOVE_TICK):
            full_symbol = event.data
            self.remove_tick_recording(full_symbol)
        elif (msgtype == MSG_TYPE.MSG_TYPE_RECORDER_REMOVE_BAR):
            full_symbol = event.data
            self.remove_bar_recording(full_symbol)
        elif (msgtype == MSG_TYPE.MSG_TYPE_RECORDER_START):
            self.init_subcribe()
        elif (msgtype == MSG_TYPE.MSG_TYPE_RECORDER_STOP):
            self.clear()
        elif (msgtype == MSG_TYPE.MSG_TYPE_RECORDER_RELOAD):
            pass
        elif (msgtype == MSG_TYPE.MSG_TYPE_RECORDER_RESET):
            pass
        elif (msgtype == MSG_TYPE.MSG_TYPE_RECORDER_GET_DATA):
            self.put_event()

    def put_event(self):
        """"""
        tick_symbols = list(self.tick_recordings.keys())
        tick_symbols.sort()

        bar_symbols = list(self.bar_recordings.keys())
        bar_symbols.sort()
        data = {"tick": tick_symbols, "bar": bar_symbols}
        msg = json.dumps(data)
        m = Event(type=EventType.RECORDER_CONTROL,
                  data=msg,
                  des='@0',
                  src=str(self.id),
                  msgtype=MSG_TYPE.MSG_TYPE_RECORDER_RTN_DATA)
        self._send_sock.send(m.serialize())

    def add_bar_recording(self, full_symbol: str, src: str = 'CTP.MD'):
        """"""
        if full_symbol in self.bar_recordings:
            self.write_log(f"已在K线记录列表中:{full_symbol}")
            return

        contract = self.contracts.get(full_symbol, None)
        if not contract:
            self.write_log(f"找不到合约:{full_symbol}")
            return

        self.bar_recordings[full_symbol] = {
            "symbol": contract.symbol,
            "exchange": contract.exchange.value,
            "gateway_name": self.gateway
        }

        self.subscribe(full_symbol, src)
        self.save_setting()
        self.put_event()

        self.write_log(f"添加K线记录成功:{full_symbol}")

    def add_tick_recording(self, full_symbol: str, src: str = 'CTP.MD'):
        """"""
        if full_symbol in self.tick_recordings:
            self.write_log(f"已在Tick记录列表中:{full_symbol}")
            return

        contract = self.contracts.get(full_symbol, None)
        if not contract:
            self.write_log(f"找不到合约:{full_symbol}")
            return

        self.tick_recordings[full_symbol] = {
            "symbol": contract.symbol,
            "exchange": contract.exchange.value,
            "gateway_name": self.gateway
        }

        self.subscribe(full_symbol, src)
        self.save_setting()
        self.put_event()

        self.write_log(f"添加Tick记录成功:{full_symbol}")

    def remove_bar_recording(self, full_symbol: str):
        """"""
        if full_symbol not in self.bar_recordings:
            self.write_log(f"不在K线记录列表中:{full_symbol}")
            return

        self.bar_recordings.pop(full_symbol)
        self.save_setting()
        self.put_event()

        self.write_log(f"移除K线记录成功:{full_symbol}")

    def remove_tick_recording(self, full_symbol: str):
        """"""
        if full_symbol not in self.tick_recordings:
            self.write_log(f"不在Tick记录列表中:{full_symbol}")
            return

        self.tick_recordings.pop(full_symbol)
        self.save_setting()
        self.put_event()

        self.write_log(f"移除Tick记录成功:{full_symbol}")

    def record_tick(self, tick: TickData):
        """"""
        database_manager.save_tick_data([tick])

    def record_bar(self, bar: BarData):
        """"""
        database_manager.save_bar_data([bar])

    def get_bar_generator(self, full_symbol: str):
        """"""
        bg = self.bar_generators.get(full_symbol, None)

        if not bg:
            bg = BarGenerator(self.record_bar)
            self.bar_generators[full_symbol] = bg

        return bg

    def subscribe(self, full_symbol: str, src: str = 'CTP.MD'):
        contract = self.contracts.get(full_symbol, None)
        if contract:
            m = Event(type=EventType.SUBSCRIBE,
                      msgtype=MSG_TYPE.MSG_TYPE_SUBSCRIBE_MARKET_DATA)
            m.destination = src
            m.source = str(self.id)
            req = SubscribeRequest()
            if src == 'CTP.MD':
                req.sym_type = SYMBOL_TYPE.CTP
                req.content = contract.symbol
            else:
                req.sym_type = SYMBOL_TYPE.FULL
                req.content = full_symbol
            m.data = req
            self._send_sock.send(m.serialize())
        else:
            self.write_log(f"行情订阅失败,找不到合约{full_symbol}")

    def clear(self):
        self.bar_recordings.clear()
        self.tick_recordings.clear()
        self.save_setting()
        self.put_event()

    def _run(self):
        while self.__active:
            try:
                msgin = self._recv_sock.recv(flags=0)
                msgin = msgin.decode("utf-8")
                if msgin is not None and msgin.index('|') > 0:
                    if msgin[0] == '@':
                        print('recorder(pid = %d) rec @ msg:' % (self.id),
                              msgin, 'at ', datetime.now())
                    if msgin[-1] == '\0':
                        msgin = msgin[:-1]
                    if msgin[-1] == '\x00':
                        msgin = msgin[:-1]
                    m = Event()
                    m.deserialize(msgin)
                    self.event_engine.put(m)
            except Exception as e:
                pass
                #print("TradeEngineError {0}".format(str(e.args[0])).encode("utf-8"))

# start and stop

    def start(self):
        """
        start the dispatcher thread and begin to recv msg through nng
        """
        print('tradeclient started ,pid = %d ' % os.getpid())
        self.event_engine.start()
        self.__active = True
        self._thread.start()

    def stop(self):
        """
        stop 
        """
        self.__active = False
        self.event_engine.stop()
        self._thread.join()

    def write_log(self, msg: str):
        """
        Create engine log event.
        """

        # log = LogData(msg=msg, gateway_name="CtaStrategy")
        # event = Event(type=EVENT_CTA_LOG, data=log)
        # self.event_engine.put(event)
        print(msg)
Exemple #10
0
class ClientMq(object):
    def __init__(self, config, ui_event_engine, outgoing_queue):
        self._ui_event_engine = ui_event_engine
        self._outgoing_queue = outgoing_queue
        self._config = config

        self._active = False
        self._thread = Thread(target=self._run)

    def _run(self):
        # os.system("taskset -cp 5 %d " % os.getpid())
        while self._active:
            try:
                # response msg from server
                msgin = self._recv_sock.recv(flags=0)
                msgin = msgin.decode("utf-8")
                if msgin is not None and msgin.index('|') > 0:
                    # print('client rec msg:',msgin,'at ', datetime.now())
                    if msgin[-1] == '\0':
                        msgin = msgin[:-1]
                    if msgin[-1] == '\x00':
                        msgin = msgin[:-1]
                    m = Event()
                    m.deserialize(msgin)
                    self._ui_event_engine.put(m)
            except Exception as e:
                pass
            try:
                # request, qry msg to server
                msgout = self._outgoing_queue.get(False)
                print('outgoing get msg,begin send', msgout, datetime.now())
                # self._send_sock.send(bytes(msgout,"ascii"), flags=0)
                self._send_sock.send(msgout, flags=1)
                print('outgoing end send', msgout, datetime.now())
            except Exception as e:
                pass

    def start(self, timer=True):
        """
        start the mq thread
        """
        self._recv_sock = Socket(SUB)
        self._send_sock = Socket(PUSH)
        self._monitor_sock = Socket(SUB)
        # print(os.getpid())
        self._recv_sock.connect(self._config['serverpub_url'])
        self._recv_sock.set_string_option(SUB, SUB_SUBSCRIBE, '')
        self._recv_sock.set_int_option(SOL_SOCKET, RCVTIMEO, 100)
        self._send_sock.connect(self._config['serverpull_url'])
        self._monitor_sock.connect(self._config['serversub_url'])
        self._active = True
        if not self._thread.isAlive():
            self._thread.start()

    def stop(self):
        """
        stop the mq thread
        """
        self._active = False

        if self._thread.isAlive():
            self._thread.join()
class StrategyEngine(BaseEngine):
    """
    Send to and receive from msg  server ,used for strategy 
    """
    config_filename = "config_server.yaml"
    setting_filename = "cta_strategy_setting.json"
    data_filename = "cta_strategy_data.json"
# init

    def __init__(self, configfile: str = '', id: int = 1):
        super(StrategyEngine, self).__init__(event_engine=EventEngine(10))
        """
        two sockets to send and recv msg
        """
        self.__active = False
        self.id = os.getpid()
        self.engine_type = EngineType.LIVE
        self._recv_sock = Socket(SUB)
        self._send_sock = Socket(PUSH)
        self._handlers = defaultdict(list)
        if configfile:
            self.config_filename = configfile
        filepath = Path.cwd().joinpath("etc/" + self.config_filename)
        with open(filepath, encoding='utf8') as fd:
            self._config = yaml.load(fd)
        self.ordercount = 0

        #  stragegy manage
        self.strategy_setting = {}  # strategy_name: dict
        self.strategy_data = {}     # strategy_name: dict

        self.classes = {}           # class_name: stategy_class
        self.strategies = {}        # strategy_name: strategy

        # self.classes_id = {}     # class_id : strategy
        # self.strategies_id = {}     # strategy_ID: strategy

        self.symbol_strategy_map = defaultdict(
            list)                   # full_symbol: strategy list
        self.orderid_strategy_map = {}  # vt_orderid: strategy
        self.strategy_orderid_map = defaultdict(
            set)                    # strategy_name: client_order_id list

        self.stop_order_count = 0   # for generating stop_orderid
        self.stop_orders = {}       # stop_orderid: stop_order
        self.init_thread = None
        self.init_queue = Queue()

        # order,tick,position ,etc manage
        self.ticks = {}
        self.orders = {}               # clientorder id list
        self.trades = {}
        self.positions = {}
        self.accounts = {}
        self.contracts = {}
        self.active_orders = {}        # SQ id list

        self.rq_client = None
        self.rq_symbols = set()

        self.offset_converter = OffsetConverter(self)

        self.autoinited = False
        self.autostarted = False
        self.dayswitched = False

        self.init_engine()

# init functions
    def init_engine(self):
        self.init_nng()
        self.init_rqdata()
        self.load_contract()
        self.load_strategy_class()
        self.load_strategy_setting()
        self.load_strategy_data()
        self.register_event()

    def init_nng(self):
        self._recv_sock.set_string_option(
            SUB, SUB_SUBSCRIBE, '')  # receive msg start with all
        self._recv_sock.set_int_option(SOL_SOCKET, RCVTIMEO, 100)
        self._recv_sock.connect(self._config['serverpub_url'])
        self._send_sock.connect(self._config['serverpull_url'])

    def init_rqdata(self):

        result = rqdata_client.init()
        if result:
            self.write_log("RQData数据接口初始化成功")

    def load_contract(self):
        contractfile = Path.cwd().joinpath("etc/ctpcontract.yaml")
        with open(contractfile, encoding='utf8') as fc:
            contracts = yaml.load(fc)
        print('loading contracts, total number:', len(contracts))
        for sym, data in contracts.items():
            contract = ContractData(
                symbol=data["symbol"],
                exchange=Exchange(data["exchange"]),
                name=data["name"],
                product=PRODUCT_CTP2VT[str(data["product"])],
                size=data["size"],
                pricetick=data["pricetick"],
                net_position=True if str(
                    data["positiontype"]) == THOST_FTDC_PT_Net else False,
                long_margin_ratio=data["long_margin_ratio"],
                short_margin_ratio=data["short_margin_ratio"],
                full_symbol=data["full_symbol"]
            )
            # For option only
            if contract.product == Product.OPTION:
                contract.option_underlying = data["option_underlying"],
                contract.option_type = OPTIONTYPE_CTP2VT.get(
                    str(data["option_type"]), None),
                contract.option_strike = data["option_strike"],
                contract.option_expiry = datetime.strptime(
                    str(data["option_expiry"]), "%Y%m%d"),
            self.contracts[contract.full_symbol] = contract

    def register_event(self):
        """"""
        self.event_engine.register(EventType.TICK, self.process_tick_event)
        self.event_engine.register(
            EventType.ORDERSTATUS, self.process_orderstatus_event)
        self.event_engine.register(EventType.FILL, self.process_trade_event)
        self.event_engine.register(
            EventType.POSITION, self.process_position_event)
        self.event_engine.register(
            EventType.ACCOUNT, self.process_account_event)
        self.event_engine.register(
            EventType.CONTRACT, self.process_contract_event)
        self.event_engine.register(
            EventType.STRATEGY_CONTROL, self.process_strategycontrol_event)
        self.event_engine.register(
            EventType.HEADER, self.process_general_event)
        self.event_engine.register(EventType.TIMER, self.process_timer_event)
# event handler

    def process_timer_event(self, event):
        # auto init and start strategy at 8:57, 20:57
        nowtime = datetime.now().time()
        dayinitflag = (nowtime > time(hour=8, minute=55)) and (
            nowtime < time(hour=8, minute=56))
        daystartflag = (nowtime > time(hour=8, minute=57)) and (
            nowtime < time(hour=8, minute=58))
        nightinitflag = (nowtime > time(hour=20, minute=55)) and (
            nowtime < time(hour=20, minute=56))
        nightstartflag = (nowtime > time(hour=20, minute=57)) and (
            nowtime < time(hour=20, minute=58))
        if (dayinitflag or nightinitflag) and (not self.autoinited):
            for name, strategy in self.strategies.items():
                if strategy.autostart:
                    self.init_strategy(name)
            self.dayswitched = False
            self.autoinited = True

        if (daystartflag or nightstartflag) and (not self.autostarted):
            for name, strategy in self.strategies.items():
                if strategy.autostart:
                    self.start_strategy(name)
            self.autostarted = True
            self.dayswitched = False

        # auto stop strategy at 16:00 and 3:00
        if (nowtime > time(hour=16, minute=0)) and (nowtime < time(hour=16, minute=1)) and (not self.dayswitched):
            for name, strategy in self.strategies.items():
                if strategy.autostart:
                    self.reset_strategy(name)
            self.dayswitched = True
            self.autostarted = False
            self.autoinited = False
        if (nowtime > time(hour=3, minute=0)) and (nowtime < time(hour=3, minute=1)) and (not self.dayswitched):
            for name, strategy in self.strategies.items():
                if strategy.autostart:
                    self.reset_strategy(name)
            self.dayswitched = True
            self.autostarted = False
            self.autoinited = False

    def process_general_event(self, event):
        for name, strategy in self.strategies.items():
            self.call_strategy_func(strategy, strategy.on_headermsg, event)
        pass

    def process_tick_event(self, event: Event):
        """"""
        tick = event.data

        strategies = self.symbol_strategy_map[tick.full_symbol]
        if not strategies:
            return
        # self.check_stop_order(tick)
        for strategy in strategies:
            if strategy.inited:
                self.call_strategy_func(strategy, strategy.on_tick, tick)
        self.ticks[tick.full_symbol] = tick

    def process_orderstatus_event(self, event: Event):
        """"""
        order = event.data

        self.offset_converter.update_order(order)  # 重新计算冻结

        if order.clientID != self.id:
            return

        self.orders[order.client_order_id] = order
        # If order is active, then update data in dict.
        if order.is_active():
            print('order is active')
            self.active_orders[order.client_order_id] = order
        # Otherwise, pop inactive order from in dict
        elif order.client_order_id in self.active_orders:
            self.active_orders.pop(order.client_order_id)

        strategy = self.orderid_strategy_map.get(order.client_order_id, None)
        if not strategy:
            print(order.client_order_id, 'dont find strategy')
            return

        # Remove client_order_id if order is no longer active.
        client_order_ids = self.strategy_orderid_map[strategy.strategy_name]
        if (order.client_order_id in client_order_ids) and (not order.is_active()):
            print('rm inactive order in strategy order map')
            client_order_ids.remove(order.client_order_id)

        # For server stop order, call strategy on_stop_order function
        # if order.type == OrderType.STOP:
        #     so = StopOrder(
        #         full_symbol=order.full_symbol,
        #         direction=order.direction,
        #         offset=order.offset,
        #         price=order.price,
        #         volume=order.volume,
        #         stop_orderid=order.vt_orderid,
        #         strategy_name=strategy.strategy_name,
        #         status=STOP_STATUS_MAP[order.status],
        #         vt_orderid=order.vt_orderid,
        #     )
        #     self.call_strategy_func(strategy, strategy.on_stop_order, so)

        # Call strategy on_order function
        self.call_strategy_func(strategy, strategy.on_order, order)

    def process_trade_event(self, event: Event):
        """"""
        trade = event.data

        self.offset_converter.update_trade(trade)

        if trade.clientID != self.id:
            return
        strategy = self.orderid_strategy_map.get(trade.client_order_id, None)
        if not strategy:
            return

        # if trade.direction == Direction.LONG:
        #     strategy.pos += trade.volume
        # else:
        #     strategy.pos -= trade.volume

        self.call_strategy_func(strategy, strategy.on_trade, trade)
        self.put_strategy_event(strategy)

        self.trades[trade.vt_tradeid] = trade

        # send qry pos to update position
        m = Event(type=EventType.QRY,
                  des=event.source,
                  src=str(self.id),
                  msgtype=MSG_TYPE.MSG_TYPE_QRY_POS)
        self._send_sock.send(m.serialize())
        # self.put(m)

    def process_position_event(self, event: Event):
        """"""
        position = event.data

        self.offset_converter.update_position(position)

        self.positions[position.key] = position

    def process_account_event(self, event: Event):
        """"""
        account = event.data
        self.accounts[account.accountid] = account

    def process_contract_event(self, event: Event):
        """"""
        contract = event.data
        self.contracts[contract.full_symbol] = contract

    def process_strategycontrol_event(self, event: Event):
        msgtype = event.msg_type
        deslist = ['@*', str(self.id), '@' + str(self.id)]
        if (event.destination not in deslist):
            return
        elif (msgtype == MSG_TYPE.MSG_TYPE_STRATEGY_STATUS):
            m = Event(type=EventType.STRATEGY_CONTROL,
                      des='@0',
                      src=str(self.id),
                      msgtype=MSG_TYPE.MSG_TYPE_STRATEGY_STATUS
                      )
            self._send_sock.send(m.serialize())
        # elif (event.destination not in deslist ) :
        #     return
        elif (msgtype == MSG_TYPE.MSG_TYPE_STRATEGY_ADD):
            v = event.data.split('|')
            classname = v[0]
            strname = v[1]
            fulsym = v[2]
            setting = json.loads(v[3])
            self.add_strategy(classname, strname, fulsym, setting)
        elif (msgtype == MSG_TYPE.MSG_TYPE_STRATEGY_INIT):
            self.init_strategy(event.data)
        elif (msgtype == MSG_TYPE.MSG_TYPE_STRATEGY_INIT_ALL):
            self.init_all_strategies()
        elif (msgtype == MSG_TYPE.MSG_TYPE_STRATEGY_START):
            self.start_strategy(event.data)
        elif (msgtype == MSG_TYPE.MSG_TYPE_STRATEGY_START_ALL):
            self.start_all_strategies()
        elif (msgtype == MSG_TYPE.MSG_TYPE_STRATEGY_STOP):
            self.stop_strategy(event.data)
        elif (msgtype == MSG_TYPE.MSG_TYPE_STRATEGY_STOP_ALL):
            self.stop_all_strategies()
        elif (msgtype == MSG_TYPE.MSG_TYPE_STRATEGY_RELOAD):
            self.classes.clear()
            self.load_strategy_class(True)
        elif (msgtype == MSG_TYPE.MSG_TYPE_STRATEGY_RESET):
            self.reset_strategy(event.data)
        elif (msgtype == MSG_TYPE.MSG_TYPE_STRATEGY_RESET_ALL):
            self.reset_all_strategies()
        elif (msgtype == MSG_TYPE.MSG_TYPE_STRATEGY_EDIT):
            v = event.data.split('|')
            setting = json.loads(v[1])
            self.edit_strategy(v[0], setting)
        elif (msgtype == MSG_TYPE.MSG_TYPE_STRATEGY_REMOVE):
            if self.remove_strategy(event.data):
                m = Event(type=EventType.STRATEGY_CONTROL,
                          data=event.data,
                          des='@0',
                          src=str(self.id),
                          msgtype=MSG_TYPE.MSG_TYPE_STRATEGY_RTN_REMOVE
                          )
                self._send_sock.send(m.serialize())
        elif (msgtype == MSG_TYPE.MSG_TYPE_STRATEGY_REMOVE_DUPLICATE):
            self.remove_strategy(event.data, True)
        elif (msgtype == MSG_TYPE.MSG_TYPE_STRATEGY_GET_DATA):
            # print('begin get data')
            if event.data:
                strategy = self.strategies.get(event.data, None)
                if strategy:
                    self.put_strategy_event(strategy)
            else:  # get all strategy data
                for strategy in self.strategies.values():
                    self.put_strategy_event(strategy)

    def call_strategy_func(
        self, strategy: StrategyBase, func: Callable, params: Any = None
    ):
        """
        Call function of a strategy and catch any exception raised.
        """
        try:
            if params:
                func(params)
            else:
                func()
        except Exception:
            strategy.trading = False
            strategy.inited = False

            msg = f"触发异常已停止\n{traceback.format_exc()}"
            self.write_log(msg, strategy)
# strategy manage

    def add_strategy(
        self, class_name: str, strategy_name: str, full_symbol: str, setting: dict
    ):
        """
        Add a new strategy.
        """
        print("begin add strategy")
        if strategy_name in self.strategies:
            self.write_log(f"创建策略失败,存在重名{strategy_name}")
            return
        if class_name not in self.classes:
            self.write_log(
                f'strategy class[{class_name}] not exist, please check')
            return
        strategy_class = self.classes[class_name]

        strategy = strategy_class(self, strategy_name, full_symbol, setting)
        self.strategies[strategy_name] = strategy

        # Add full_symbol to strategy map.
        strategies = self.symbol_strategy_map[full_symbol]
        strategies.append(strategy)
        # print("335 add strategy")
        # Update to setting file.
        self.update_strategy_setting(strategy_name, setting)

        self.put_strategy_event(strategy)
        print("end add strategy")

    def init_strategy(self, strategy_name: str):
        """
        Init a strategy.
        """
        self.init_queue.put(strategy_name)

        if not self.init_thread:
            self.init_thread = Thread(target=self._init_strategy)
            self.init_thread.start()

    def _init_strategy(self):
        """
        Init strategies in queue.
        """
        while not self.init_queue.empty():
            strategy_name = self.init_queue.get()
            strategy = self.strategies[strategy_name]

            if strategy.inited:
                self.write_log(f"{strategy_name}已经完成初始化,禁止重复操作")
                continue

            self.write_log(f"{strategy_name}开始执行初始化")

            # Call on_init function of strategy
            self.call_strategy_func(strategy, strategy.on_init)

            # Restore strategy data(variables)
            data = self.strategy_data.get(strategy_name, None)
            if data:
                for name in strategy.variables:
                    value = data.get(name, None)
                    if value:
                        setattr(strategy, name, value)

            # Subscribe market data
            contract = self.get_contract(strategy.full_symbol)
            if contract:
                m = Event(type=EventType.SUBSCRIBE,
                          msgtype=MSG_TYPE.MSG_TYPE_SUBSCRIBE_MARKET_DATA)
                m.destination = "CTP.MD"
                m.source = str(self.id)
                req = SubscribeRequest()
                req.sym_type = SYMBOL_TYPE.CTP
                req.content = contract.symbol
                m.data = req
                self._send_sock.send(m.serialize())
            else:
                self.write_log(f"行情订阅失败,找不到合约{strategy.full_symbol}", strategy)

            # qry pos and acc
            m = Event(type=EventType.QRY, msgtype=MSG_TYPE.MSG_TYPE_QRY_POS)
            m.destination = strategy.api + '.' + strategy.account
            m.source = str(self.id)
            self._send_sock.send(m.serialize())

            m = Event(type=EventType.QRY,
                      msgtype=MSG_TYPE.MSG_TYPE_QRY_ACCOUNT)
            m.destination = strategy.api + '.' + strategy.account
            m.source = str(self.id)
            self._send_sock.send(m.serialize())

            # Put event to update init completed status.
            strategy.inited = True
            self.put_strategy_event(strategy)
            self.write_log(f"{strategy_name}初始化完成")

        self.init_thread = None

    def start_strategy(self, strategy_name: str):
        """
        Start a strategy.
        """
        strategy = self.strategies[strategy_name]
        if not strategy.inited:
            self.write_log(f"策略{strategy.strategy_name}启动失败,请先初始化")
            return

        if strategy.trading:
            self.write_log(f"{strategy_name}已经启动,请勿重复操作")
            return

        # qry pos and acc
        m = Event(type=EventType.QRY, msgtype=MSG_TYPE.MSG_TYPE_QRY_POS)
        m.destination = strategy.api + '.' + strategy.account
        m.source = str(self.id)
        self._send_sock.send(m.serialize())

        m = Event(type=EventType.QRY,
                  msgtype=MSG_TYPE.MSG_TYPE_QRY_ACCOUNT)
        m.destination = strategy.api + '.' + strategy.account
        m.source = str(self.id)
        self._send_sock.send(m.serialize())

        self.call_strategy_func(strategy, strategy.on_start)
        strategy.trading = True

        self.put_strategy_event(strategy)

    def stop_strategy(self, strategy_name: str):
        """
        Stop a strategy.
        """
        strategy = self.strategies[strategy_name]
        if not strategy.trading:
            return

        # Call on_stop function of the strategy
        self.call_strategy_func(strategy, strategy.on_stop)

        # Change trading status of strategy to False
        strategy.trading = False

        # Cancel all orders of the strategy
        self.cancel_all(strategy)

        # Update GUI
        self.put_strategy_event(strategy)

    def reset_strategy(self, strategy_name: str):
        "Reset a strategy"
        strategy = self.strategies[strategy_name]
        if not strategy.inited:
            return
        # stop first
        self.call_strategy_func(strategy, strategy.on_stop)
        strategy.trading = False
        self.cancel_all(strategy)
        # reset
        self.call_strategy_func(strategy, strategy.on_reset)
        strategy.inited = False

        self.put_strategy_event(strategy)

    def edit_strategy(self, strategy_name: str, setting: dict):
        """
        Edit parameters of a strategy.
        """
        strategy = self.strategies[strategy_name]
        strategy.update_setting(setting)

        self.update_strategy_setting(strategy_name, setting)
        self.put_strategy_event(strategy)

    def remove_strategy(self, strategy_name: str, duplicate: bool = False):
        """
        Remove a strategy.
        """
        print("begin remove")
        strategy = self.strategies[strategy_name]
        if strategy.trading:
            self.write_log(f"策略{strategy.strategy_name}移除失败,请先停止")
            return

        # Remove setting
        if not duplicate:
            self.remove_strategy_setting(strategy_name)

        # Remove from symbol strategy map
        strategies = self.symbol_strategy_map[strategy.full_symbol]
        strategies.remove(strategy)

        # Remove from active orderid map
        if strategy_name in self.strategy_orderid_map:
            orderids = self.strategy_orderid_map.pop(strategy_name)

            # Remove vt_orderid strategy map
            for _orderid in orderids:
                if _orderid in self.orderid_strategy_map:
                    self.orderid_strategy_map.pop(_orderid)

        # Remove from strategies
        self.strategies.pop(strategy_name)
        print("end remove")
        return True

    def load_strategy_class(self, reload: bool = False):
        """
        Load strategy class from source code.
        """
        # app_path = Path(__file__).parent.parent
        # path1 = app_path.joinpath("cta_strategy", "strategies")
        # self.load_strategy_class_from_folder(
        #     path1, "vnpy.app.cta_strategy.strategies")

        path2 = Path.cwd().joinpath("mystrategy")
        self.load_strategy_class_from_folder(path2, "", reload)

    def load_strategy_class_from_folder(self, path: Path, module_name: str = "", reload: bool = False):
        """
        Load strategy class from certain folder.
        """
        for dirpath, dirnames, filenames in os.walk(path):
            for filename in filenames:
                if filename.endswith(".py"):
                    strategy_module_name = "mystrategy.".join(
                        [module_name, filename.replace(".py", "")])
                    self.load_strategy_class_from_module(
                        strategy_module_name, reload)

    def load_strategy_class_from_module(self, module_name: str, reload: bool = False):
        """
        Load strategy class from module file.
        """
        try:
            module = importlib.import_module(module_name)
        # if reload delete old attribute
            if reload:
                for attr in dir(module):
                    if attr not in ('__name__', '__file__'):
                        delattr(module, attr)
                importlib.reload(module)
            for name in dir(module):
                value = getattr(module, name)
                if (isinstance(value, type) and issubclass(value, CtaTemplate) and value is not CtaTemplate):
                    self.classes[value.__name__] = value
        except:  # noqa
            msg = f"策略文件{module_name}加载失败,触发异常:\n{traceback.format_exc()}"
            self.write_log(msg)

    def load_strategy_data(self):
        """
        Load strategy data from json file.
        """
        self.strategy_data = load_json(self.data_filename)

    def sync_strategy_data(self, strategy: StrategyBase):
        """
        Sync strategy data into json file.
        """
        data = strategy.get_variables()
        # Strategy status (inited, trading) should not be synced.
        data.pop("inited")
        data.pop("trading")

        self.strategy_data = load_json(self.data_filename)

        self.strategy_data[strategy.strategy_name] = data
        save_json(self.data_filename, self.strategy_data)

    def get_all_strategy_class_names(self):
        """
        Return names of strategy classes loaded.
        """
        return list(self.classes.keys())

    def get_strategy_class_parameters(self, class_name: str):
        """
        Get default parameters of a strategy class.
        """
        strategy_class = self.classes[class_name]

        parameters = {}
        for name in strategy_class.parameters:
            parameters[name] = getattr(strategy_class, name)

        return parameters

    def get_strategy_parameters(self, strategy_name):
        """
        Get parameters of a strategy.
        """
        strategy = self.strategies[strategy_name]
        return strategy.get_parameters()

    def init_all_strategies(self):
        """
        """
        for strategy_name in self.strategies.keys():
            self.init_strategy(strategy_name)

    def start_all_strategies(self):
        """
        """
        for strategy_name in self.strategies.keys():
            self.start_strategy(strategy_name)

    def stop_all_strategies(self):
        """
        """
        for strategy_name in self.strategies.keys():
            self.stop_strategy(strategy_name)

    def reset_all_strategies(self):
        for strategy_name in self.strategies.keys():
            self.reset_strategy(strategy_name)

    def load_strategy_setting(self):
        """
        Load setting file.
        """
        self.strategy_setting = load_json(self.setting_filename)

        for strategy_name, strategy_config in self.strategy_setting.items():
            self.add_strategy(
                strategy_config["class_name"],
                strategy_name,
                strategy_config["full_symbol"],
                strategy_config["setting"]
            )

    def update_strategy_setting(self, strategy_name: str, setting: dict):
        """
        Update setting file.
        """
        strategy = self.strategies[strategy_name]
        # in order to save other engine's setting, should load again
        self.strategy_setting = load_json(self.setting_filename)
        self.strategy_setting[strategy_name] = {
            "class_name": strategy.__class__.__name__,
            "full_symbol": strategy.full_symbol,
            "setting": setting,
        }

        save_json(self.setting_filename, self.strategy_setting)

    def remove_strategy_setting(self, strategy_name: str):
        """
        Update setting file.
        """
        if strategy_name not in self.strategy_setting:
            return
        # in order to save other engine's setting, should load again
        self.strategy_setting = load_json(self.setting_filename)
        self.strategy_setting.pop(strategy_name)
        save_json(self.setting_filename, self.strategy_setting)

    # def put_stop_order_event(self, stop_order: StopOrder):
    #     """
    #     Put an event to update stop order status.
    #     """
    #     event = Event(EVENT_CTA_STOPORDER, stop_order)
    #     self.event_engine.put(event)

    def put_strategy_event(self, strategy: StrategyBase):
        """
        Put an event to update strategy status.
        """
        data = strategy.get_data()
        sdata = {}
        sdata[strategy.strategy_name] = data
        # event = Event(EVENT_CTA_STRATEGY, data)
        # self.event_engine.put(event)
        msg = json.dumps(sdata)
        m = Event(type=EventType.STRATEGY_CONTROL, data=msg, des='@0', src=str(
            self.id), msgtype=MSG_TYPE.MSG_TYPE_STRATEGY_RTN_DATA)

        self._send_sock.send(m.serialize())

        #save_json(self.data_filename, sdata)

# strategy functions
  #get ,qry
    def query_bar_from_rq(
        self, symbol: str, exchange: Exchange, interval: Interval, start: datetime, end: datetime
    ):
        """
        Query bar data from RQData.
        """
        data = rqdata_client.query_bar(
            symbol, exchange, interval, start, end
        )
        return data

    def load_bar(
        self,
        full_symbol: str,
        days: int,
        interval: Interval,
        callback: Callable[[BarData], None],
        datasource: str = 'DataBase'
    ):
        """"""

        tradedays = abs(days)
        weekday = datetime.now().weekday()
        adddays = 2 if (days - weekday > 0) else 0
        if weekday == 6:
            tradedays = days + 1
        else:
            tradedays = days + adddays

        symbol, exchange = extract_full_symbol(full_symbol)
        end = datetime.now()
        start = end - timedelta(days=tradedays)
        # Query bars from RQData by default, if not found, load from database.
        bars = self.query_bar_from_rq(symbol, exchange, interval, start, end)
        if not bars:
            bars = database_manager.load_bar_data(
                symbol=symbol,
                exchange=exchange,
                interval=interval,
                start=start,
                end=end,
            )

        for bar in bars:
            callback(bar)

    def load_tick(self, full_symbol: str, days: int, callback: Callable, datasource: str = 'DataBase'):
        tradedays = abs(days)
        weekday = datetime.now().weekday()
        adddays = 2 if (days - weekday > 0) else 0
        if weekday == 6:
            tradedays = days + 1
        else:
            tradedays = days + adddays

        symbol, exchange = extract_full_symbol(full_symbol)
        end = datetime.now()
        start = end - timedelta(tradedays)

        ticks = database_manager.load_tick_data(symbol, exchange, start, end)

        for tick in ticks:
            callback(tick)

    def get_tick(self, full_symbol):
        """
        Get latest market tick data by full_symbol.
        """
        return self.ticks.get(full_symbol, None)

    def get_order(self, orderid: int):
        """
        Get latest order data by orderid.
        """
        return self.orders.get(orderid, None)

    def get_trade(self, vt_tradeid):
        """
        Get trade data by vt_tradeid.
        """
        return self.trades.get(vt_tradeid, None)

    def get_position(self, key):
        """
        Get latest position data by vt_positionid.
        """
        return self.positions.get(key, None)

    def get_account(self, accountid):
        """
        Get latest account data by accountid.
        """
        return self.accounts.get(accountid, None)

    def get_contract(self, full_symbol):
        """
        Get contract data by full_symbol.
        """
        return self.contracts.get(full_symbol, None)

    def get_all_ticks(self):
        """
        Get all tick data.
        """
        return list(self.ticks.values())

    def get_all_orders(self):
        """
        Get all order data.
        """
        return list(self.orders.values())

    def get_all_trades(self):
        """
        Get all trade data.
        """
        return list(self.trades.values())

    def get_all_positions(self):
        """
        Get all position data.
        """
        return list(self.positions.values())

    def get_all_accounts(self):
        """
        Get all account data.
        """
        return list(self.accounts.values())

    def get_all_contracts(self):
        """
        Get all contract data.
        """
        return list(self.contracts.values())

    def get_all_active_orders(self, full_symbol: str = ""):
        """
        Get all active orders by full_symbol.

        If full_symbol is empty, return all active orders.
        """
        if not full_symbol:
            return list(self.active_orders.values())
        else:
            active_orders = [
                order
                for order in self.active_orders.values()
                if order.full_symbol == full_symbol
            ]
            return active_orders

    def get_position_holding(self, acc: str, full_symbol: str):
        return self.offset_converter.get_position_holding(acc, full_symbol)

    def get_strategy_active_orderids(self, strategy_name: str):
        oidset = self.strategy_orderid_map[strategy_name]
        return oidset

  #order, cancel

    def send_order(
        self,
        strategy: StrategyBase,
        original_req: OrderRequest,
        lock: bool = False
    ):
        """
        Send a new order to server.
        """
        # Convert with offset converter
        req_list = self.offset_converter.convert_order_request(
            original_req, lock)

        # Send Orders
        orderids = []

        for req in req_list:
            req.clientID = self.id
            req.client_order_id = self.ordercount
            self.ordercount += 1
            m = Event(type=EventType.ORDER,
                      data=req,
                      des=req.api + '.' + req.account,
                      src=str(self.id)
                      )
            if req.api == "CTP.TD":
                m.msg_type = MSG_TYPE.MSG_TYPE_ORDER_CTP
            elif req.api == "PAPER.TD":
                m.msg_type = MSG_TYPE.MSG_TYPE_ORDER_PAPER
            else:
                print("error:api not support!")
                return []
            msg = m.serialize()
            print(f'tradeclient {self.id} send msg: {msg}')
            self._send_sock.send(msg)
            orderids.append(req.client_order_id)
            self.offset_converter.update_order_request(req)
            # Save relationship between orderid and strategy.
            self.orderid_strategy_map[req.client_order_id] = strategy
            self.strategy_orderid_map[strategy.strategy_name].add(
                req.client_order_id)

        return orderids

    def cancel_order(self, strategy: StrategyBase, orderid: int):
        """
        Cancel existing order by orderid.
        """
        order = self.get_order(orderid)
        if not order:
            self.write_log(f"撤单失败,找不到委托{orderid}", strategy)
            return

        req = order.create_cancel_request()
        m = Event(type=EventType.CANCEL,
                  data=req,
                  des=order.api + '.' + order.account,
                  src=str(self.id),
                  msgtype=MSG_TYPE.MSG_TYPE_ORDER_ACTION
                  )
        msg = m.serialize()
        print(f'tradeclient {self.id} send msg: {msg}')
        self._send_sock.send(msg)

    def cancel_all(self, strategy: StrategyBase):
        """
        Cancel all active orders of a strategy.
        """
        orderids = self.strategy_orderid_map[strategy.strategy_name]
        if not orderids:
            print(strategy.strategy_name, 'has no active order')
            return

        for orderid in copy(orderids):
            print('cancel oid:', orderid)
            self.cancel_order(strategy, orderid)

    def send_testmsg(self):
        m = Event(des='CTP.MD', src=str(self.id),
                  msgtype=MSG_TYPE.MSG_TYPE_TEST)
        msg = m.serialize()
        self._send_sock.send(msg)
        print(f'tradeclient {self.id} send msg: {msg}')

# start and stop
    def start(self, timer=True):
        """
        start the dispatcher thread and begin to recv msg through nng
        """
        self.event_engine.start()
        print('tradeclient started ,pid = %d ' % os.getpid())
        self.__active = True
        while self.__active:
            try:
                msgin = self._recv_sock.recv(flags=0)
                msgin = msgin.decode("utf-8")
                if msgin is not None and msgin.index('|') > 0:
                    if msgin[0] == '@':
                        print('tradeclient(pid = %d) rec @ msg:' %
                              (self.id), msgin, 'at ', datetime.now())
                    if msgin[-1] == '\0':
                        msgin = msgin[:-1]
                    if msgin[-1] == '\x00':
                        msgin = msgin[:-1]
                    m = Event()
                    m.deserialize(msgin)
                    self.event_engine.put(m)
            except Exception as e:
                pass
                #print("TradeEngineError {0}".format(str(e.args[0])).encode("utf-8"))

    def stop(self):
        """
        stop 
        """
        self.__active = False
        self.event_engine.stop()

    def put(self, event):
        """
        send event msg,TODO:check the event
        """
        #
        self._send_sock.send(event.serialize(), flags=1)

    def register_handler(self, type_, handler):
        """
        register handler/subscriber
        """
        # self.event_engine.register(type_,handler)
        # handlerList = self._handlers[type_]

        # if handler not in handlerList:
        #     self._handlers[type_].append(handler)
        #     #handlerList.append(handler)
        pass

    def unregister_handler(self, type_, handler):
        """
        unregister handler/subscriber
        """
        # handlerList = self._handlers[type_]

        # if handler in handlerList:
        #     self._handlers.remove(handler)

        # if not handlerList:
        #     del self._handlers[type_]
        pass

    def write_log(self, msg: str, strategy: StrategyBase = None):
        """
        Create engine log event.
        """
        # if strategy:
        #     msg = f"{strategy.strategy_name}: {msg}"

        # log = LogData(msg=msg, gateway_name="CtaStrategy")
        # event = Event(type=EVENT_CTA_LOG, data=log)
        # self.event_engine.put(event)
        print(msg)
Exemple #12
0
class TradeEngine(BaseEngine):
    """
    Send to and receive from msg  server ,used for strategy 
    """
    setting_filename = "cta_strategy_setting.json"
    data_filename = "cta_strategy_data.json"

    def __init__(self,config:dict):
        super(TradeEngine, self).__init__()
        """
        two sockets to send and recv msg
        """
        self.__active = False
        self.id = 0
        self.engine_type = EngineType.LIVE     
        self._recv_sock = Socket(SUB)
        self._send_sock = Socket(PUSH)
        self._config = config
        self._handlers = defaultdict(list)

#  stragegy manage
        self.strategy_setting = {}  # strategy_name: dict
        self.strategy_data = {}     # strategy_name: dict

        self.classes = {}           # class_name: stategy_class
        self.strategies = {}        # strategy_name: strategy

        self.symbol_strategy_map = defaultdict(
            list)                   # vt_symbol: strategy list
        self.orderid_strategy_map = {}  # vt_orderid: strategy
        self.strategy_orderid_map = defaultdict(
            set)                    # strategy_name: orderid list

        self.stop_order_count = 0   # for generating stop_orderid
        self.stop_orders = {}       # stop_orderid: stop_order
        self.init_thread = None
        self.init_queue = Queue()

# order,tick,position ,etc manage
        self.ticks = {}
        self.orders = {}
        self.trades = {}
        self.positions = {}
        self.accounts = {}
        self.contracts = {}

        self.active_orders = {}



        self.rq_client = None
        self.rq_symbols = set()

        self.offset_converter = OffsetConverter(self)

        self.init_engine()


    def init_engine(self):
        self.init_nng()
        self.init_rqdata()
        self.load_strategy_class()
        self.load_strategy_setting()
        self.load_strategy_data()  
        self.register_event()


    def init_rqdata(self):

        result = rqdata_client.init()
        if result:
            self.write_log("RQData数据接口初始化成功")

    def register_event(self):
        """"""
        self.event_engine.register(EventType.TICK, self.process_tick_event)
        self.event_engine.register(EventType.ORDERSTATUS, self.process_order_event)
        self.event_engine.register(EventType.FILL, self.process_trade_event)
        self.event_engine.register(EventType.POSITION, self.process_position_event)
        self.event_engine.register(EventType.ACCOUNT, self.process_account_event)
        self.event_engine.register(EventType.CONTRACT, self.process_contract_event)        


    def process_tick_event(self, event: Event):
        """"""
        tick = event

        strategies = self.symbol_strategy_map[tick.full_symbol]
        if not strategies:
            return
        # self.check_stop_order(tick)
        for strategy in strategies:
            if strategy.inited:
                self.call_strategy_func(strategy, strategy.on_tick, tick)
        self.ticks[tick.full_symbol] = tick

    def process_order_event(self, event: Event):
        """"""
        order = event
        
        self.offset_converter.update_order(order)

        strategy = self.orderid_strategy_map.get(order.vt_orderid, None)
        if not strategy:
            return

        # Remove vt_orderid if order is no longer active.
        vt_orderids = self.strategy_orderid_map[strategy.strategy_name]
        if order.vt_orderid in vt_orderids and not order.is_active():
            vt_orderids.remove(order.vt_orderid)

        # For server stop order, call strategy on_stop_order function
        # if order.type == OrderType.STOP:
        #     so = StopOrder(
        #         vt_symbol=order.vt_symbol,
        #         direction=order.direction,
        #         offset=order.offset,
        #         price=order.price,
        #         volume=order.volume,
        #         stop_orderid=order.vt_orderid,
        #         strategy_name=strategy.strategy_name,
        #         status=STOP_STATUS_MAP[order.status],
        #         vt_orderid=order.vt_orderid,
        #     )
        #     self.call_strategy_func(strategy, strategy.on_stop_order, so)  

        # Call strategy on_order function
        self.call_strategy_func(strategy, strategy.on_order, order)

        
        self.orders[order.vt_orderid] = order

        # If order is active, then update data in dict.
        if order.is_active():
            self.active_orders[order.vt_orderid] = order
        # Otherwise, pop inactive order from in dict
        elif order.vt_orderid in self.active_orders:
            self.active_orders.pop(order.vt_orderid)     

    def process_trade_event(self, event: Event):
        """"""
        trade = event

        self.offset_converter.update_trade(trade)

        strategy = self.orderid_strategy_map.get(trade.vt_orderid, None)
        if not strategy:
            return

        # if trade.direction == Direction.LONG:
        #     strategy.pos += trade.volume
        # else:
        #     strategy.pos -= trade.volume

        self.call_strategy_func(strategy, strategy.on_trade, trade)
        self.put_strategy_event(strategy)

        self.trades[trade.vt_tradeid] = trade


    def process_position_event(self, event: Event):
        """"""
        position = event

        self.offset_converter.update_position(position)

        self.positions[position.vt_positionid] = position

    def process_account_event(self, event: Event):
        """"""
        account = event
        self.accounts[account.vt_accountid] = account

    def process_contract_event(self, event: Event):
        """"""
        contract = event
        self.contracts[contract.vt_symbol] = contract

    def call_strategy_func(
        self, strategy: StrategyBase, func: Callable, params: Any = None
    ):
        """
        Call function of a strategy and catch any exception raised.
        """
        try:
            if params:
                func(params)
            else:
                func()
        except Exception:
            strategy.trading = False
            strategy.inited = False

            msg = f"触发异常已停止\n{traceback.format_exc()}"
            self.write_log(msg, strategy)

    def add_strategy(
        self, class_name: str, strategy_name: str, vt_symbol: str, setting: dict
    ):
        """
        Add a new strategy.
        """
        if strategy_name in self.strategies:
            self.write_log(f"创建策略失败,存在重名{strategy_name}")
            return

        strategy_class = self.classes[class_name]

        strategy = strategy_class(self, strategy_name, vt_symbol, setting)
        self.strategies[strategy_name] = strategy

        # Add vt_symbol to strategy map.
        strategies = self.symbol_strategy_map[vt_symbol]
        strategies.append(strategy)

        # Update to setting file.
        self.update_strategy_setting(strategy_name, setting)

        self.put_strategy_event(strategy)

    def init_strategy(self, strategy_name: str):
        """
        Init a strategy.
        """ 
        self.init_queue.put(strategy_name)

        if not self.init_thread:
            self.init_thread = Thread(target=self._init_strategy)
            self.init_thread.start()

    def _init_strategy(self):
        """
        Init strategies in queue.
        """
        while not self.init_queue.empty():
            strategy_name = self.init_queue.get()
            strategy = self.strategies[strategy_name]

            if strategy.inited:
                self.write_log(f"{strategy_name}已经完成初始化,禁止重复操作")
                continue

            self.write_log(f"{strategy_name}开始执行初始化")

            # Call on_init function of strategy
            self.call_strategy_func(strategy, strategy.on_init)

            # Restore strategy data(variables)
            data = self.strategy_data.get(strategy_name, None)
            if data:
                for name in strategy.variables:
                    value = data.get(name, None)
                    if value:
                        setattr(strategy, name, value)

            # Subscribe market data
            contract = self.get_contract(strategy.vt_symbol)
            if contract:
                req = SubscribeEvent()
                req.destination = contract.gateway_name
                req.source = "0"                
                req.content = strategy.symbol
                self.put(req)
            else:
                self.write_log(f"行情订阅失败,找不到合约{strategy.vt_symbol}", strategy)

            # Put event to update init completed status.
            strategy.inited = True
            self.put_strategy_event(strategy)
            self.write_log(f"{strategy_name}初始化完成")
        
        self.init_thread = None

    def start_strategy(self, strategy_name: str):
        """
        Start a strategy.
        """
        strategy = self.strategies[strategy_name]
        if not strategy.inited:
            self.write_log(f"策略{strategy.strategy_name}启动失败,请先初始化")
            return

        if strategy.trading:
            self.write_log(f"{strategy_name}已经启动,请勿重复操作")
            return

        self.call_strategy_func(strategy, strategy.on_start)
        strategy.trading = True

        self.put_strategy_event(strategy)

    def stop_strategy(self, strategy_name: str):
        """
        Stop a strategy.
        """
        strategy = self.strategies[strategy_name]
        if not strategy.trading:
            return

        # Call on_stop function of the strategy
        self.call_strategy_func(strategy, strategy.on_stop)

        # Change trading status of strategy to False
        strategy.trading = False

        # Cancel all orders of the strategy
        # self.cancel_all(strategy)

        # Update GUI
        self.put_strategy_event(strategy)

    def edit_strategy(self, strategy_name: str, setting: dict):
        """
        Edit parameters of a strategy.
        """
        strategy = self.strategies[strategy_name]
        strategy.update_setting(setting)

        self.update_strategy_setting(strategy_name, setting)
        self.put_strategy_event(strategy)

    def remove_strategy(self, strategy_name: str):
        """
        Remove a strategy.
        """
        strategy = self.strategies[strategy_name]
        if strategy.trading:
            self.write_log(f"策略{strategy.strategy_name}移除失败,请先停止")
            return

        # Remove setting
        self.remove_strategy_setting(strategy_name)

        # Remove from symbol strategy map
        strategies = self.symbol_strategy_map[strategy.vt_symbol]
        strategies.remove(strategy)

        # Remove from active orderid map
        if strategy_name in self.strategy_orderid_map:
            vt_orderids = self.strategy_orderid_map.pop(strategy_name)

            # Remove vt_orderid strategy map
            for vt_orderid in vt_orderids:
                if vt_orderid in self.orderid_strategy_map:
                    self.orderid_strategy_map.pop(vt_orderid)

        # Remove from strategies
        self.strategies.pop(strategy_name)

        return True

    def load_strategy_class(self):
        """
        Load strategy class from source code.
        """
        path1 = Path(__file__).parent.joinpath("")
        self.load_strategy_class_from_folder(
            path1, "mystrategy")

        path2 = Path.cwd().joinpath("")
        self.load_strategy_class_from_folder(path2, "mystrategy")

    def load_strategy_class_from_folder(self, path: Path, module_name: str = ""):
        """
        Load strategy class from certain folder.
        """
        for dirpath, dirnames, filenames in os.walk(str(path)):
            for filename in filenames:
                if filename.endswith(".py"):
                    strategy_module_name = ".".join(
                        [module_name, filename.replace(".py", "")])
                    self.load_strategy_class_from_module(strategy_module_name)

    def load_strategy_class_from_module(self, module_name: str):
        """
        Load strategy class from module file.
        """
        try:
            module = importlib.import_module(module_name)

            for name in dir(module):
                value = getattr(module, name)
                if (isinstance(value, type) and issubclass(value, StrategyBase) and value is not StrategyBase):
                    self.classes[value.__name__] = value
        except:  # noqa
            msg = f"策略文件{module_name}加载失败,触发异常:\n{traceback.format_exc()}"
            self.write_log(msg)

    def load_strategy_data(self):
        """
        Load strategy data from json file.
        """
        self.strategy_data = load_json(self.data_filename)

    def sync_strategy_data(self, strategy: StrategyBase):
        """
        Sync strategy data into json file.
        """
        data = strategy.get_variables()
        data.pop("inited")      # Strategy status (inited, trading) should not be synced.
        data.pop("trading")

        self.strategy_data[strategy.strategy_name] = data
        save_json(self.data_filename, self.strategy_data)

    def get_all_strategy_class_names(self):
        """
        Return names of strategy classes loaded.
        """
        return list(self.classes.keys())

    def get_strategy_class_parameters(self, class_name: str):
        """
        Get default parameters of a strategy class.
        """
        strategy_class = self.classes[class_name]

        parameters = {}
        for name in strategy_class.parameters:
            parameters[name] = getattr(strategy_class, name)

        return parameters

    def get_strategy_parameters(self, strategy_name):
        """
        Get parameters of a strategy.
        """
        strategy = self.strategies[strategy_name]
        return strategy.get_parameters()

    def init_all_strategies(self):
        """
        """
        for strategy_name in self.strategies.keys():
            self.init_strategy(strategy_name)

    def start_all_strategies(self):
        """
        """
        for strategy_name in self.strategies.keys():
            self.start_strategy(strategy_name)

    def stop_all_strategies(self):
        """
        """
        for strategy_name in self.strategies.keys():
            self.stop_strategy(strategy_name)

    def load_strategy_setting(self):
        """
        Load setting file.
        """
        self.strategy_setting = load_json(self.setting_filename)

        for strategy_name, strategy_config in self.strategy_setting.items():
            self.add_strategy(
                strategy_config["class_name"], 
                strategy_name,
                strategy_config["vt_symbol"], 
                strategy_config["setting"]
            )

    def update_strategy_setting(self, strategy_name: str, setting: dict):
        """
        Update setting file.
        """
        strategy = self.strategies[strategy_name]

        self.strategy_setting[strategy_name] = {
            "class_name": strategy.__class__.__name__,
            "vt_symbol": strategy.vt_symbol,
            "setting": setting,
        }
        save_json(self.setting_filename, self.strategy_setting)

    def remove_strategy_setting(self, strategy_name: str):
        """
        Update setting file.
        """
        if strategy_name not in self.strategy_setting:
            return

        self.strategy_setting.pop(strategy_name)
        save_json(self.setting_filename, self.strategy_setting)

    # def put_stop_order_event(self, stop_order: StopOrder):
    #     """
    #     Put an event to update stop order status.
    #     """
    #     event = Event(EVENT_CTA_STOPORDER, stop_order)
    #     self.event_engine.put(event)

    def put_strategy_event(self, strategy: StrategyBase):
        """
        Put an event to update strategy status.
        """
        data = strategy.get_data()
        # event = Event(EVENT_CTA_STRATEGY, data)
        # self.event_engine.put(event)
        pass






    def init_nng(self):
        self._recv_sock.set_string_option(SUB, SUB_SUBSCRIBE, '')  # receive msg start with all
        self._recv_sock.set_int_option(SOL_SOCKET,RCVTIMEO,100)
        self._recv_sock.connect(self._config['serverpub_url'])
        self._send_sock.connect(self._config['serverpull_url'])
    #------------------------------------ public functions -----------------------------#
    
    def query_bar_from_rq(
        self, symbol: str, exchange: Exchange, interval: Interval, start: datetime, end: datetime
    ):
        """
        Query bar data from RQData.
        """
        data = rqdata_client.query_bar(
            symbol, exchange, interval, start, end
        )
        return data   
    
    
    def load_bar(
        self, 
        vt_symbol: str, 
        days: int, 
        interval: Interval,
        callback: Callable[[BarData], None]
    ):
        """"""
        symbol, exchange = extract_vt_symbol(vt_symbol)
        end = datetime.now()
        start = end - timedelta(days)

        # Query bars from RQData by default, if not found, load from database.
        bars = self.query_bar_from_rq(symbol, exchange, interval, start, end)
        if not bars:
            bars = database_manager.load_bar_data(
                symbol=symbol,
                exchange=exchange,
                interval=interval,
                start=start,
                end=end,
            )

        for bar in bars:
            callback(bar)
    
    
    
    def get_tick(self, vt_symbol):
        """
        Get latest market tick data by vt_symbol.
        """
        return self.ticks.get(vt_symbol, None)

    def get_order(self, vt_orderid):
        """
        Get latest order data by vt_orderid.
        """
        return self.orders.get(vt_orderid, None)

    def get_trade(self, vt_tradeid):
        """
        Get trade data by vt_tradeid.
        """
        return self.trades.get(vt_tradeid, None)

    def get_position(self, vt_positionid):
        """
        Get latest position data by vt_positionid.
        """
        return self.positions.get(vt_positionid, None)

    def get_account(self, vt_accountid):
        """
        Get latest account data by vt_accountid.
        """
        return self.accounts.get(vt_accountid, None)

    def get_contract(self, vt_symbol):
        """
        Get contract data by vt_symbol.
        """
        return self.contracts.get(vt_symbol, None)

    def get_all_ticks(self):
        """
        Get all tick data.
        """
        return list(self.ticks.values())

    def get_all_orders(self):
        """
        Get all order data.
        """
        return list(self.orders.values())

    def get_all_trades(self):
        """
        Get all trade data.
        """
        return list(self.trades.values())

    def get_all_positions(self):
        """
        Get all position data.
        """
        return list(self.positions.values())

    def get_all_accounts(self):
        """
        Get all account data.
        """
        return list(self.accounts.values())

    def get_all_contracts(self):
        """
        Get all contract data.
        """
        return list(self.contracts.values())

    def get_all_active_orders(self, vt_symbol: str = ""):
        """
        Get all active orders by vt_symbol.

        If vt_symbol is empty, return all active orders.
        """
        if not vt_symbol:
            return list(self.active_orders.values())
        else:
            active_orders = [
                order
                for order in self.active_orders.values()
                if order.vt_symbol == vt_symbol
            ]
            return active_orders    
    


    
    
    def start(self, timer=True):
        """
        start the dispatcher thread and begin to recv msg through nng
        """
        self.event_engine.start()
        print('tradeclient started ,pid = %d ' % os.getpid())
        self.__active = True
        # print(self._config['serverpub_url'])
        while self.__active:
            try:
                msgin = self._recv_sock.recv(flags=0)
                msgin = msgin.decode("utf-8")
                if msgin is not None and msgin.index('|') > 0:
                    print('tradeclient(id = %d) rec server msg:'%(self.id), msgin,'at ', datetime.now())
                    if msgin[-1] == '\0':
                        msgin = msgin[:-1]
                    if msgin[-1] == '\x00':
                        msgin = msgin[:-1]
                    v = msgin.split('|')
                    msg2type = MSG_TYPE(int(v[2]))
                    if msg2type == MSG_TYPE.MSG_TYPE_TICK_L1:
                        m = TickEvent()
                        m.deserialize(msgin)
                    elif msg2type == MSG_TYPE.MSG_TYPE_RTN_ORDER:
                       m = OrderStatusEvent()
                       m.deserialize(msgin)
                    elif msg2type == MSG_TYPE.MSG_TYPE_RTN_TRADE:
                        m = FillEvent()
                        m.deserialize(msgin)
                    elif msg2type == MSG_TYPE.MSG_TYPE_RSP_POS:
                        m = PositionEvent()
                        m.deserialize(msgin)
                    elif msg2type == MSG_TYPE.MSG_TYPE_Hist:
                        m = HistoricalEvent()
                        m.deserialize(msgin)
                    elif msg2type == MSG_TYPE.MSG_TYPE_RSP_ACCOUNT:
                        m = AccountEvent()
                        m.deserialize(msgin)
                    elif msg2type == MSG_TYPE.MSG_TYPE_RSP_CONTRACT:
                        m = ContractEvent()
                        m.deserialize(msgin)
                    elif msg2type == MSG_TYPE.MSG_TYPE_INFO:
                        m = InfoEvent()
                        m.deserialize(msgin)
                    else:
                        m = GeneralReqEvent() 
                        m.deserialize(msgin)
                        pass
                    self.event_engine.put(m)
                    # if m.event_type in self._handlers:
                    #     [handler(m) for handler in self._handlers[m.event_type]]
            except Exception as e:
                pass
                #print("TradeEngineError {0}".format(str(e.args[0])).encode("utf-8"))
 
    def stop(self):
        """
        stop 
        """
        self.__active = False
        self.event_engine.stop()

    def put(self, event):
        """
        send event msg,TODO:check the event
        """
        # 
        self._send_sock.send(event.serialize(),flags=1)

    def register_handler(self, type_, handler):
        """
        register handler/subscriber
        """
        # handlerList = self._handlers[type_]

        # if handler not in handlerList:
        #     self._handlers[type_].append(handler)
        #     #handlerList.append(handler)
        pass

    def unregister_handler(self, type_, handler):
        """
        unregister handler/subscriber
        """
        # handlerList = self._handlers[type_]

        # if handler in handlerList:
        #     self._handlers.remove(handler)

        # if not handlerList:
        #     del self._handlers[type_]
        pass

    def write_log(self, msg: str, strategy: StrategyBase = None):
        """
        Create engine log event.
        """
        # if strategy:
        #     msg = f"{strategy.strategy_name}: {msg}"

        # log = LogData(msg=msg, gateway_name="CtaStrategy")
        # event = Event(type=EVENT_CTA_LOG, data=log)
        # self.event_engine.put(event)  
        print(msg)      

    # -------------------------------- end of public functions -----------------------------#
Exemple #13
0
class ClientMq(object):
    def __init__(self, config, ui_event_engine, outgoing_quue):
        self._ui_event_engine = ui_event_engine
        self._outgoing_quue = outgoing_quue
        self._config = config

        self._active = False
        self._thread = Thread(target=self._run)

    def _run(self):
        # os.system("taskset -cp 5 %d " % os.getpid())
        while self._active:
            try:
                # response msg from server
                msgin = self._recv_sock.recv(flags=0)
                msgin = msgin.decode("utf-8")
                if msgin is not None and msgin.index('|') > 0:
                    print('client rec broker msg:', msgin, 'at ',
                          datetime.now())
                    if msgin[-1] == '\0':
                        msgin = msgin[:-1]
                    if msgin[-1] == '\x00':
                        msgin = msgin[:-1]
                    v = msgin.split('|')
                    msg2type = MSG_TYPE(int(v[2]))
                    if msg2type == MSG_TYPE.MSG_TYPE_TICK_L1:
                        m = TickEvent()
                        m.deserialize(msgin)
                        self._ui_event_engine.put(m)
                    elif msg2type == MSG_TYPE.MSG_TYPE_RTN_ORDER:
                        m = OrderStatusEvent()
                        m.deserialize(msgin)
                        self._ui_event_engine.put(m)
                    elif msg2type == MSG_TYPE.MSG_TYPE_RTN_TRADE:
                        m = FillEvent()
                        m.deserialize(msgin)
                        self._ui_event_engine.put(m)
                    elif msg2type == MSG_TYPE.MSG_TYPE_RSP_POS:
                        m = PositionEvent()
                        m.deserialize(msgin)
                        self._ui_event_engine.put(m)
                    elif msg2type == MSG_TYPE.MSG_TYPE_Hist:
                        m = HistoricalEvent()
                        m.deserialize(msgin)
                        self._ui_event_engine.put(m)
                    elif msg2type == MSG_TYPE.MSG_TYPE_RSP_ACCOUNT:
                        m = AccountEvent()
                        m.deserialize(msgin)
                        self._ui_event_engine.put(m)
                    elif msg2type == MSG_TYPE.MSG_TYPE_RSP_CONTRACT:
                        m = ContractEvent()
                        m.deserialize(msgin)
                        self._ui_event_engine.put(m)
                    elif v[2].startswith(
                            '3'):  #msg2type == MSG_TYPE.MSG_TYPE_INFO:
                        m = InfoEvent()
                        m.deserialize(msgin)
                        self._ui_event_engine.put(m)
                        pass
            except Exception as e:
                pass
            try:
                # request, qry msg to server
                msgout = self._outgoing_quue.get(False)
                print('outgoing get msg,begin send', msgout, datetime.now())
                # self._send_sock.send(bytes(msgout,"ascii"), flags=0)
                self._send_sock.send(msgout, flags=1)
                print('outgoing end send', msgout, datetime.now())
            except Exception as e:
                pass

    def start(self, timer=True):
        """
        start the mq thread
        """
        self._recv_sock = Socket(SUB)
        self._send_sock = Socket(PUSH)
        self._monitor_sock = Socket(SUB)
        # print(os.getpid())
        self._recv_sock.connect(self._config['serverpub_url'])
        self._recv_sock.set_string_option(SUB, SUB_SUBSCRIBE,
                                          '')  # receive msg start with all
        self._recv_sock.set_int_option(SOL_SOCKET, RCVTIMEO, 100)
        self._send_sock.connect(self._config['serverpull_url'])
        self._monitor_sock.connect(self._config['serversub_url'])
        self._active = True
        if not self._thread.isAlive():
            self._thread.start()

    def stop(self):
        """
        stop the mq thread
        """
        self._active = False

        if self._thread.isAlive():
            self._thread.join()