class MainEngine: """主引擎,负责对API的调度""" #---------------------------------------------------------------------- def __init__(self): """Constructor""" self.ee = EventEngine() # 创建事件驱动引擎 self.ee.start() # 启动事件驱动引擎 # 循环查询持仓和账户相关 self.countGet = 0 # 查询延时计数 self.lastGet = 'Account' # 上次查询的性质 # 合约储存相关 self.dictInstrument = {} # 字典(保存合约查询数据) #---------------------------------------------------------------------- #---------------------------------------------------------------------- def exit(self): """退出""" # 销毁API对象 self.td = None self.md = None # 停止事件驱动引擎 self.ee.stop()
class MainEngine(): def __init__(self, event_engine:EventEngine=None): if event_engine: self.event_engine = event_engine else: self.event_engine = EventEngine() self.event_engine.start() self.gateways: dict[str, BaseGateway] = {} self.engines: dict[str, BaseEngine] = {} def add_engine(self, engine_class): engine = engine_class(self, self.event_engine) self.engines[engine.engine_name] = engine return engine # deal with gatewayclass same as engine def add_gateway(self, gateway_class): gateway = gateway_class(self, self.event_engine) self.gateways[gateway.engine_name] = gateway return gateway def connect(self, gateway_name): g = self.gateways[gateway_name] if g: g.start()
class MainEngine: #---------------------------------------------------------------------- def __init__(self, account, _plus_path, bg): self.ee = EventEngine(account) # 创建事件驱动引擎 self.bridge = bg self.__lock = Lock() self.userid = str(account['userid']) self.password = str(account['password']) self.brokerid = str(account['brokerid']) self.mdaddress = str(account['mdfront']) self.tdaddress = str(account['tdfront']) self.instrument = account['instrument'] # sub list str self.pluspath = _plus_path self.dictInstrument = {} # 字典(保存合约查询数据) self.dictProduct = {} # 字典(保存合约查询数据) self.dictExchange= {} self.tmpInstrument = {} # 字典(保存合约查询数据) self.tmpProduct = {} # 字典(保存合约查询数据) self.tmpExchange= {} self.dictUpdate = None self.subInstrument = set() self.subedInstrument = set() self.master = {} # 记录主力合约对应关系 self.masterSubed = False self.subedMaster = {} self.tickpass = set() self.now = datetime.now() self.socket = None self.coreServer = str(account['zmqserver']) self.corefunc = passit if int(account['usezmq'])>0: if self.coreServer[:4] == 'tcp:': context = zmq.Context() socket = context.socket(zmq.REQ) socket.connect(self.coreServer) self.socket = socket self.corefunc = tcpfunc elif self.coreServer[:5] == 'http:': self.socket = True self.corefunc = httpfunc self.ee.start() # 启动事件驱动引擎 self.som = {} self.lastError = 0 self.lastTodo = 0 self.eq = 0 # 循环查询持仓和账户相关 self.countGet = 0 # 查询延时计数 self.lastGet = 'Account' # 上次查询的性质 self.ee.register(EVENT_TDLOGIN, self.initGet,True) # 登录成功后开始初始化查询 self.__timer = time()+3 self.__readySubscribe = {} # 合约储存相关 self.get_instrument() self.get_subscribe(self.instrument) self.ee.register(EVENT_MDLOGIN, self.ready_subscribe,True) self.ee.register(EVENT_TDLOGIN, self.ready_subscribe,True) self.ee.register(EVENT_ERROR, self.get_error,False) self.ee.register(EVENT_INSTRUMENT, self.insertInstrument,True) self.ee.register(EVENT_TIMER, self.getAccountPosition,False) self.ee.register(EVENT_TRADE, self.get_trade,False) self.ee.register(EVENT_ORDER, self.get_order,False) self.ee.register(EVENT_TICK, self.get_tick,True) self.ee.register(EVENT_POSITION, self.get_position,False) self.ee.register(EVENT_ACCOUNT, self.get_account,False) self.ee.register(EVENT_TICK, self.check_timer,False) self.ee.register(EVENT_ORDER, self.check_timer,False) import eventType for k,v in eventType.__dict__.items(): if 'EVENT_' in k and v[0]!='_': self.ee.register(v,self.websocket_send,False) self.md = ctpMdApi(self, self.mdaddress, self.userid, self.password, self.brokerid, plus_path=_plus_path) # 创建API接口 self.td = ctpTdApi(self, self.tdaddress, self.userid, self.password, self.brokerid, plus_path=_plus_path) def get_subscribe(self,_inst): if '#' in _inst: _instlist = [ (v.get('_vol_',0),k) for k,v in self.dictInstrument.items()] _instlist.sort(reverse=True) _only = set() for v,_instrumentid in _instlist[:10]: _product = self.dictInstrument[_instrumentid]['ProductID'] if _product not in _only: _exchangeid = self.dictInstrument.get(_instrumentid,{}).get("ExchangeID",'') self.subInstrument.add((_instrumentid,_exchangeid)) self.subedMaster[_instrumentid] = 1 self.tickpass.add(_instrumentid) _only.add(_product) for _productid in ['IF','IH','IC']: if _productid in self.dictProduct and _productid not in _only: _product = self.dictProduct[_productid] _productlist = [ (v,k) for k,v in _product.items()] _productlist.sort(reverse=True) _instrumentid = _productlist[0][-1] _exchangeid = self.dictInstrument.get(_instrumentid,{}).get("ExchangeID",'') self.subInstrument.add((_instrumentid,_exchangeid)) self.master[_productid] = _product self.subedMaster[_instrumentid] = 1 self.tickpass.add(_instrumentid) for _productid,_product in self.dictProduct.items(): self.master[_productid] = _product else: _all = _inst.split('+') for one in _all: if '=' in one: _productid = one[:-1] if _productid in self.dictProduct: _product = self.dictProduct[_productid] _productlist = [ (v,k) for k,v in _product.items()] _productlist.sort(reverse=True) _instrumentid = _productlist[0][-1] _exchangeid = self.dictInstrument.get(_instrumentid,{}).get("ExchangeID",'') self.subInstrument.add((_instrumentid,_exchangeid)) self.master[_productid] = _product self.subedMaster[_instrumentid] = 1 self.tickpass.add(_instrumentid) else: _instrumentid = one _exchangeid = self.dictInstrument.get(_instrumentid,{}).get("ExchangeID",'') self.subInstrument.add((_instrumentid,_exchangeid)) self.tickpass.add(_instrumentid) print(self.subInstrument) def ready_subscribe(self,event): self.__readySubscribe[event.type_] = 1 if len(self.__readySubscribe) == 2: for one in self.subInstrument: if one[0] in self.subedMaster: event = Event(type_=EVENT_LOG) log = u'订阅主力合约:%s[%s]'%(one[0],self.dictInstrument[one[0]]['InstrumentName']) event.dict_['log'] = log self.ee.put(event) else: event = Event(type_=EVENT_LOG) log = u'订阅合约:%s[%s]'%(one[0],self.dictInstrument[one[0]]['InstrumentName']) event.dict_['log'] = log self.ee.put(event) self.subscribe(one[0],one[1]) def get_instrument(self): _dict = self.bridge.get_instrument() self.dictInstrument = _dict.get('instrument',{}) self.dictExchange = _dict.get('exchange',{}) self.dictProduct = _dict.get('product',{}) self.dictUpdate = _dict.get('day',None) def set_instrument(self): _dict = {} _dict['instrument'] = self.dictInstrument _dict['exchange'] = self.dictExchange _dict['product'] = self.dictProduct _dict['day'] = date.today() self.bridge.set_instrument(_dict) def get_som(self,event): try: symbol = event.dict_['data']['InstrumentID'] if symbol: if symbol not in self.tickpass:return if symbol in self.som: return self.som[symbol] else: _data = None if symbol in self.dictInstrument: _data = self.dictInstrument[symbol] event = Event(type_=EVENT_LOG) log = u'初始化合约[%s]并填充其基本信息'%symbol event.dict_['log'] = log self.ee.put(event) else: _productid = filter(lambda x:x in _chars+_CHARS,symbol) if _productid in self.dictProduct: for _instrument in self.dictProduct[_productid].keys(): if _instrument in self.dictInstrument: _data = self.dictInstrument[_instrument] event = Event(type_=EVENT_LOG) log = u'注意:初始化合约[%s]但填充了<%s>的基本信息'%(symbol,_instrument) event.dict_['log'] = log self.ee.put(event) break if _data: one = SymbolOrdersManager(symbol,_data,self) self.som[symbol] = one return one else: event = Event(type_=EVENT_LOG) log = u'警告:初始化合约[%s]失败,未发现其基本信息'%symbol event.dict_['log'] = log self.ee.put(event) print("ctpEngine.py MainEngine get_som not found Instrument Info") return None else: return None except Exception,e: print("ctpEngine.py MainEngine get_som ERROR",e) print(event.type_,event.dict_['data'])
class MainEngine: """主引擎,负责对API的调度""" #---------------------------------------------------------------------- def __init__(self): """Constructor""" self.ee = EventEngine() # 创建事件驱动引擎 self.md = DemoMdApi(self.ee) # 创建API接口 self.td = DemoTdApi(self.ee) self.ee.start() # 启动事件驱动引擎 # 循环查询持仓和账户相关 self.countGet = 0 # 查询延时计数 self.lastGet = 'Account' # 上次查询的性质 self.ee.register(EVENT_TDLOGIN, self.initGet) # 登录成功后开始初始化查询 # 合约储存相关 self.dictInstrument = {} # 字典(保存合约查询数据) self.ee.register(EVENT_INSTRUMENT, self.insertInstrument) #---------------------------------------------------------------------- def login(self, userid, password, brokerid, mdAddress, tdAddress): """登陆""" self.md.login(mdAddress, userid, password, brokerid) self.td.login(tdAddress, userid, password, brokerid) #---------------------------------------------------------------------- def subscribe(self, instrumentid, exchangeid): """订阅合约""" self.md.subscribe(instrumentid, exchangeid) #---------------------------------------------------------------------- def getAccount(self): """查询账户""" self.td.getAccount() #---------------------------------------------------------------------- def getInvestor(self): """查询投资者""" self.td.getInvestor() #---------------------------------------------------------------------- def getPosition(self): """查询持仓""" self.td.getPosition() #---------------------------------------------------------------------- def getInstrument(self): """获取合约""" event = Event(type_=EVENT_LOG) log = u'查询合约信息' event.dict_['log'] = log self.ee.put(event) self.td.getInstrument() #---------------------------------------------------------------------- def sendOrder(self, instrumentid, exchangeid, price, pricetype, volume, direction, offset): """发单""" ref = self.td.sendOrder(instrumentid, exchangeid, price, pricetype, volume, direction, offset) return str(ref) #---------------------------------------------------------------------- def cancelOrder(self, instrumentid, exchangeid, orderref, frontid, sessionid): """撤单""" self.td.cancelOrder(instrumentid, exchangeid, orderref, frontid, sessionid) #---------------------------------------------------------------------- def getAccountPosition(self, event): """循环查询账户和持仓""" self.countGet = self.countGet + 1 # 每5秒发一次查询 if self.countGet > 5: self.countGet = 0 # 清空计数 if self.lastGet == 'Account': self.getPosition() self.lastGet = 'Position' else: self.getAccount() self.lastGet = 'Account' #---------------------------------------------------------------------- def initGet(self, event): """在交易服务器登录成功后,开始初始化查询""" # 打开设定文件setting.vn f = shelve.open('setting.vn') # 尝试读取设定字典,若该字典不存在,则发出查询请求 try: d = f['instrument'] # 如果本地保存的合约数据是今日的,则载入,否则发出查询请求 today = date.today() if d['date'] == today: self.dictInstrument = d['dictInstrument'] event = Event(type_=EVENT_LOG) log = u'合约信息读取完成' event.dict_['log'] = log self.ee.put(event) self.getInvestor() # 开始循环查询 self.ee.register(EVENT_TIMER, self.getAccountPosition) else: self.getInstrument() except KeyError: self.getInstrument() f.close() #---------------------------------------------------------------------- def insertInstrument(self, event): """插入合约对象""" data = event.dict_['data'] last = event.dict_['last'] self.dictInstrument[data['InstrumentID']] = data # 合约对象查询完成后,查询投资者信息并开始循环查询 if last: # 将查询完成的合约信息保存到本地文件,今日登录可直接使用不再查询 self.saveInstrument() event = Event(type_=EVENT_LOG) log = u'合约信息查询完成' event.dict_['log'] = log self.ee.put(event) self.getInvestor() # 开始循环查询 self.ee.register(EVENT_TIMER, self.getAccountPosition) #---------------------------------------------------------------------- def selectInstrument(self, instrumentid): """获取合约信息对象""" try: instrument = self.dictInstrument[instrumentid] except KeyError: instrument = None return instrument #---------------------------------------------------------------------- def exit(self): """退出""" # 销毁API对象 self.td = None self.md = None # 停止事件驱动引擎 self.ee.stop() #---------------------------------------------------------------------- def saveInstrument(self): """保存合约属性数据""" f = shelve.open('setting.vn') d = {} d['dictInstrument'] = self.dictInstrument d['date'] = date.today() f['instrument'] = d f.close()
class MainEngine: """主引擎,负责对API的调度""" #---------------------------------------------------------------------- def __init__(self, ws, account, _plus_path, justCopySignal=False, useZmq = False, zmqServer = "tcp://localhost:9999"): """Constructor :type self: object """ self.ee = EventEngine(account) # 创建事件驱动引擎 self.justCopySignal = justCopySignal self.userid = str(account['userid']) self.password = str(account['password']) self.brokerid = str(account['brokerid']) self.mdaddress = str(account['mdfront']) self.tdaddress = str(account['tdfront']) self.pluspath = _plus_path self.symbol = None self.socket = None self.websocket = ws # websocket list to send msg if useZmq: context = zmq.Context() socket = context.socket(zmq.REQ) socket.connect(zmqServer) self.socket = socket self.ee.start() # 启动事件驱动引擎 self.havedposi = False self.position = {} self.todayposition = {} self.lastError = 0 self.lastTodo = 0 self.__timer = time()+60 self.__orders = {} self.__retry = 0 self.__maxRetry = 5 # 循环查询持仓和账户相关 self.countGet = 0 # 查询延时计数 self.lastGet = 'Account' # 上次查询的性质 self.ee.register(EVENT_TDLOGIN, self.initGet) # 登录成功后开始初始化查询 # 合约储存相关 self.dictInstrument = {} # 字典(保存合约查询数据) self.dictProduct = {} # 字典(保存合约查询数据) self.dictExchange= {} self.volInstrument = {} self.subInstrument = set() self.subedInst = set() self.price = {} # 存储报价,分品种 self.todo = 0 self.ee.register(EVENT_ERROR, self.get_error) self.ee.register(EVENT_INSTRUMENT, self.insertInstrument) self.ee.register(EVENT_TIMER, self.getAccountPosition) self.ee.register(EVENT_TRADE, self.get_trade) self.ee.register(EVENT_ORDER, self.get_order) self.ee.register(EVENT_TICK, self.get_tick) self.ee.register(EVENT_POSITION, self.get_position) import eventType for k,v in eventType.__dict__.items(): if 'EVENT_' in k and v[0]!='_': self.ee.register(v,self.websocket_send) self.md = DemoMdApi(self.ee, self.mdaddress, self.userid, self.password, self.brokerid,plus_path=_plus_path) # 创建API接口 self.td = DemoTdApi(self.ee, self.tdaddress, self.userid, self.password, self.brokerid,plus_path=_plus_path) def set_ws(self,ws): self.websocket = ws def websocket_send(self,event): try: _data = json.dumps(event.dict_,ensure_ascii=False) for _ws in self.websocket: try: _ws.send(_data) except Exception,e: print(_data,e) except Exception,e: print(event.dict_,e)
class MainEngine: """主引擎,负责对API的调度""" #---------------------------------------------------------------------- def __init__(self): """Constructor :type self: object """ self.ee = EventEngine() # 创建事件驱动引擎 self.md = DemoMdApi(self.ee) # 创建API接口 self.td = DemoTdApi(self.ee) self.ee.start() # 启动事件驱动引擎 self.havedposi = False self.position = {} self.todayposition = {} self.__orders = {} self.__retry = 0 # 循环查询持仓和账户相关 self.countGet = 0 # 查询延时计数 self.lastGet = 'Account' # 上次查询的性质 self.ee.register(EVENT_TDLOGIN, self.initGet) # 登录成功后开始初始化查询 # 合约储存相关 self.dictInstrument = {} # 字典(保存合约查询数据) self.ee.register(EVENT_INSTRUMENT, self.insertInstrument) self.ee.register(EVENT_TRADE_DATA, self.get_trade) self.ee.register(EVENT_ORDER_DATA, self.get_order) self.ee.register(EVENT_ERROR, self.get_error) self.ee.register(EVENT_MARKETDATA_DATA, self.get_data) self.ee.register(EVENT_POSITION_DATA, self.get_position) def set_app(self,_app):self.app = _app def get_order(self,event): _data = event.dict_['data'] if _data['OrderStatus'] == '5': self.__retry += 1 _saved = self.__orders.pop(int(_data['OrderRef'])) if self.__retry>5: self.__retry = 0 return 0 print("Plus...Order") if _saved[6] == defineDict['THOST_FTDC_OF_Open']: _tr = 1 elif _saved[6] == defineDict['THOST_FTDC_OF_Close']: _tr = -1 else: _tr = 0 if _saved[5] == defineDict["THOST_FTDC_D_Buy"]: _kr = 1 elif _saved[5] == defineDict["THOST_FTDC_D_Sell"]: _kr = -1 else: _kr = 0 if _tr*_kr>0: price = float(_saved[2])+0.2 else: price = float(_saved[2])-0.2 _ref = self.td.sendOrder(_saved[0],_saved[1],price,_saved[3],_saved[4],_saved[5],_saved[6]) self.__orders[_ref] = (_saved[0],_saved[1],price,_saved[3],_saved[4],_saved[5],_saved[6]) def get_trade(self,event): _data = event.dict_['data'] print('get_trade',_data['OrderRef']) _done = _data['Volume'] if int(_data['OrderRef']) in self.__orders: _saved = self.__orders.pop(int(_data['OrderRef'])) _goon = _saved[4] - _done else: _goon = 0 if _goon != 0: self.__retry += 1 if self.__retry>5: self.__retry = 0 return 0 print("Plus...Trade") if _saved[6] == defineDict['THOST_FTDC_OF_Open']: _tr = 1 elif _saved[6] == defineDict['THOST_FTDC_OF_Close']: _tr = -1 else: _tr = 0 if _saved[5] == defineDict["THOST_FTDC_D_Buy"]: _kr = 1 elif _saved[5] == defineDict["THOST_FTDC_D_Sell"]: _kr = -1 else: _kr = 0 if _tr*_kr>0: price = float(_saved[2])+0.2 else: price = float(_saved[2])-0.2 _ref = self.td.sendOrder(_saved[0],_saved[1],price,_saved[3],_goon,_saved[5],_saved[6]) self.__orders[_ref] = (_saved[0],_saved[1],price,_saved[3],_goon,_saved[5],_saved[6]) def set_symbol(self,_s): self.symbol = _s def set_socket(self,_s): self.socket = _s def get_position(self,event): _data = event.dict_['data'] if _data['TodayPosition']: self.todayposition[_data['PosiDirection']] = _data['TodayPosition'] if _data['Position']:pass # self.position[_data['PosiDirection']] = _data['Position'] self.havedposi = True self.__orders = {} def openPosition(self,tr,volume): self.__retry = 0 offset = defineDict['THOST_FTDC_OF_Open'] pricetype = defineDict['THOST_FTDC_OPT_LimitPrice'] if tr>0: price = self.ask+0.2*2.0 direction = defineDict["THOST_FTDC_D_Buy"] else: price = self.bid-0.2*2.0 direction = defineDict["THOST_FTDC_D_Sell"] _ref = self.td.sendOrder(self.symbol,self.exchangeid,price,pricetype,volume,direction,offset) self.__orders[_ref] = (self.symbol,self.exchangeid,price,pricetype,volume,direction,offset) def closePosition(self,tr,volume): self.__retry = 0 offset = defineDict['THOST_FTDC_OF_Close'] pricetype = defineDict['THOST_FTDC_OPT_LimitPrice'] if tr<0: price = self.ask+0.2*2.0 direction = defineDict["THOST_FTDC_D_Buy"] else: price = self.bid-0.2*2.0 direction = defineDict["THOST_FTDC_D_Sell"] _ref = self.td.sendOrder(self.symbol,self.exchangeid,price,pricetype,volume,direction,offset) self.__orders[_ref] = (self.symbol,self.exchangeid,price,pricetype,volume,direction,offset) def closeTodayPosition(self,tr,volume): self.__retry = 0 offset = defineDict['THOST_FTDC_OF_CloseToday'] pricetype = defineDict['THOST_FTDC_OPT_LimitPrice'] if tr<0: price = self.ask+0.2*2.0 direction = defineDict["THOST_FTDC_D_Buy"] else: price = self.bid-0.2*2.0 direction = defineDict["THOST_FTDC_D_Sell"] _ref = self.td.sendOrder(self.symbol,self.exchangeid,price,pricetype,volume,direction,offset) self.__orders[_ref] = (self.symbol,self.exchangeid,price,pricetype,volume,direction,offset) def get_error(self,event): _err = event.dict_['ErrorID'] self.socket.send(bytes("error_%s"%_err)) _bk = self.socket.recv() print("ERROR",event.dict_) self.__orders = {} def get_data(self,event): _data = event.dict_['data'] self.ask = _data['AskPrice1'] self.bid = _data['BidPrice1'] price = (self.ask+self.bid)/2.0 self.socket.send(bytes(str(price))) _bk = int(self.socket.recv()) self.todo = _bk # print '%.0f %s = %d'%(time(),_data['LastPrice'],_bk) if self.__orders: print(self.__orders) elif self.havedposi: _long = defineDict["THOST_FTDC_PD_Long"] _short = defineDict["THOST_FTDC_PD_Short"] if self.todo==0: if self.position.get(_long,0)>0: self.closePosition(1,self.position[_long]) self.havedposi = False if self.todayposition.get(_long,0)>0: self.closeTodayPosition(1,self.todayposition[_long]) self.havedposi = False if self.position.get(_short,0)>0: self.closePosition(-1,self.position[_short]) self.havedposi = False if self.todayposition.get(_short,0)>0: self.closeTodayPosition(-1,self.todayposition[_short]) self.havedposi = False def do_it(_todo,_pass,_reverse,d_pass,d_reverse): if self.position.get(_reverse,0)>0: self.closePosition(d_reverse,self.position[_reverse]) self.havedposi = False if self.todayposition.get(_reverse,0)>0: self.closeTodayPosition(d_reverse,self.todayposition[_reverse]) self.havedposi = False _haved = self.position.get(_pass,0)+self.todayposition.get(_pass,0) if _todo>_haved: self.openPosition(d_pass,_todo-_haved) self.havedposi = False if _todo<_haved: if self.position.get(_pass,0)>0: self.closePosition(d_pass,min(self.position[_pass],_haved-_todo)) self.havedposi = False if self.position[_pass]<_haved-_todo: self.closeTodayPosition(d_pass,_haved-_todo-self.position[_pass]) self.havedposi = False elif self.todayposition.get(_pass,0)>0: self.closeTodayPosition(d_pass,_haved-_todo) self.havedposi = False if self.todo>0: _todo = self.todo _pass = _long _reverse = _short d_pass = 1 d_reverse = -1 do_it(_todo,_pass,_reverse,d_pass,d_reverse) if self.todo<0: _todo = abs(self.todo) _pass = _short _reverse = _long d_pass = -1 d_reverse = 1 do_it(_todo,_pass,_reverse,d_pass,d_reverse) if not self.havedposi: self.todayposition = {} self.position = {} #---------------------------------------------------------------------- def login(self, userid, password, brokerid, mdAddress, tdAddress): """登陆""" self.td.login(tdAddress, userid, password, brokerid) self.md.login(mdAddress, userid, password, brokerid) #---------------------------------------------------------------------- def subscribe(self, instrumentid, exchangeid): """订阅合约""" self.md.subscribe(instrumentid, exchangeid) #---------------------------------------------------------------------- def getAccount(self): """查询账户""" self.td.getAccount() #---------------------------------------------------------------------- def getInvestor(self): """查询投资者""" self.td.getInvestor() #---------------------------------------------------------------------- def getPosition(self): """查询持仓""" self.td.getPosition() #---------------------------------------------------------------------- def getInstrument(self): """获取合约""" event = Event(type_=EVENT_LOG) log = u'查询合约信息' event.dict_['log'] = log self.ee.put(event) self.td.getInstrument() #---------------------------------------------------------------------- def sendOrder(self, instrumentid, exchangeid, price, pricetype, volume, direction, offset): """发单""" self.td.sendOrder(instrumentid, exchangeid, price, pricetype, volume, direction, offset) #---------------------------------------------------------------------- def cancelOrder(self, instrumentid, exchangeid, orderref, frontid, sessionid): """撤单""" self.td.cancelOrder(instrumentid, exchangeid, orderref, frontid, sessionid) #---------------------------------------------------------------------- def getAccountPosition(self, event): """循环查询账户和持仓""" self.countGet = self.countGet + 1 # 每1秒发一次查询 if self.countGet >= 20: self.countGet = 0 if self.lastGet == 'Account': self.getPosition() self.lastGet = 'Position' else: self.lastGet = 'Account' self.getAccount() #---------------------------------------------------------------------- def initGet(self, event): """在交易服务器登录成功后,开始初始化查询""" # 打开设定文件setting.vn f = shelve.open('setting.vn') # 尝试读取设定字典,若该字典不存在,则发出查询请求 try: d = f['instrument'] # 如果本地保存的合约数据是今日的,则载入,否则发出查询请求 today = date.today() if d['date'] == today: self.dictInstrument = d['dictInstrument'] event = Event(type_=EVENT_LOG) log = u'合约信息读取完成' event.dict_['log'] = log self.ee.put(event) self.getInvestor() # 开始循环查询 self.ee.register(EVENT_TIMER, self.getAccountPosition) else: self.getInstrument() except KeyError: self.getInstrument() f.close() # _exchangeid = self.dictInstrument[self.symbol]['ExchangeID'] self.exchangeid = ""#_exchangeid self.subscribe(self.symbol,self.exchangeid) #---------------------------------------------------------------------- def insertInstrument(self, event): """插入合约对象""" data = event.dict_['data'] last = event.dict_['last'] self.dictInstrument[data['InstrumentID']] = data # 合约对象查询完成后,查询投资者信息并开始循环查询 if last: # 将查询完成的合约信息保存到本地文件,今日登录可直接使用不再查询 self.saveInstrument() event = Event(type_=EVENT_LOG) log = u'合约信息查询完成' event.dict_['log'] = log self.ee.put(event) self.getInvestor() # 开始循环查询 self.ee.register(EVENT_TIMER, self.getAccountPosition) #---------------------------------------------------------------------- def selectInstrument(self, instrumentid): """获取合约信息对象""" try: instrument = self.dictInstrument[instrumentid] except KeyError: instrument = None return instrument #---------------------------------------------------------------------- def exit(self): """退出""" # 销毁API对象 self.td = None self.md = None # 停止事件驱动引擎 self.ee.stop() #---------------------------------------------------------------------- def saveInstrument(self): """保存合约属性数据""" f = shelve.open('setting.vn') d = {} d['dictInstrument'] = self.dictInstrument d['date'] = date.today() f['instrument'] = d f.close()
class MainEngine: """主引擎,负责对API的调度""" #---------------------------------------------------------------------- def __init__(self): """Constructor :type self: object """ self.ee = EventEngine() # 创建事件驱动引擎 self.md = DemoMdApi(self.ee) # 创建API接口 self.td = DemoTdApi(self.ee) self.ee.start() # 启动事件驱动引擎 self.havedposi = False self.position = {} self.todayposition = {} self.__orders = {} self.__retry = 0 # 循环查询持仓和账户相关 self.countGet = 0 # 查询延时计数 self.lastGet = 'Account' # 上次查询的性质 self.ee.register(EVENT_TDLOGIN, self.initGet) # 登录成功后开始初始化查询 # 合约储存相关 self.dictInstrument = {} # 字典(保存合约查询数据) self.ee.register(EVENT_INSTRUMENT, self.insertInstrument) self.ee.register(EVENT_TRADE_DATA, self.get_trade) self.ee.register(EVENT_ORDER_DATA, self.get_order) self.ee.register(EVENT_ERROR, self.get_error) self.ee.register(EVENT_MARKETDATA_DATA, self.get_data) self.ee.register(EVENT_POSITION_DATA, self.get_position) def set_app(self, _app): self.app = _app def get_order(self, event): _data = event.dict_['data'] if _data['OrderStatus'] == '5': self.__retry += 1 if int(_data['OrderRef']) in self.__orders: _saved = self.__orders.pop(int(_data['OrderRef'])) else: self.__orders = {} return 0 if self.__retry > 5: self.__retry = 0 return 0 print("Plus...Order") if _saved[6] == defineDict['THOST_FTDC_OF_Open']: _tr = 1 elif _saved[6] == defineDict['THOST_FTDC_OF_Close']: _tr = -1 else: _tr = 0 if _saved[5] == defineDict["THOST_FTDC_D_Buy"]: _kr = 1 elif _saved[5] == defineDict["THOST_FTDC_D_Sell"]: _kr = -1 else: _kr = 0 if _tr * _kr > 0: price = float(_saved[2]) + 0.2 else: price = float(_saved[2]) - 0.2 _ref = self.td.sendOrder(_saved[0], _saved[1], price, _saved[3], _saved[4], _saved[5], _saved[6]) self.__orders[_ref] = (_saved[0], _saved[1], price, _saved[3], _saved[4], _saved[5], _saved[6]) def get_trade(self, event): _data = event.dict_['data'] print('get_trade', _data['OrderRef']) _done = _data['Volume'] if int(_data['OrderRef']) in self.__orders: _saved = self.__orders.pop(int(_data['OrderRef'])) _goon = _saved[4] - _done else: _goon = 0 if _goon != 0: self.__retry += 1 if self.__retry > 5: self.__retry = 0 return 0 print("Plus...Trade") if _saved[6] == defineDict['THOST_FTDC_OF_Open']: _tr = 1 elif _saved[6] == defineDict['THOST_FTDC_OF_Close']: _tr = -1 else: _tr = 0 if _saved[5] == defineDict["THOST_FTDC_D_Buy"]: _kr = 1 elif _saved[5] == defineDict["THOST_FTDC_D_Sell"]: _kr = -1 else: _kr = 0 if _tr * _kr > 0: price = float(_saved[2]) + 0.2 else: price = float(_saved[2]) - 0.2 _ref = self.td.sendOrder(_saved[0], _saved[1], price, _saved[3], _goon, _saved[5], _saved[6]) self.__orders[_ref] = (_saved[0], _saved[1], price, _saved[3], _goon, _saved[5], _saved[6]) def set_symbol(self, _s): self.symbol = _s def set_socket(self, _s): self.socket = _s def get_position(self, event): _data = event.dict_['data'] if _data['TodayPosition']: self.todayposition[_data['PosiDirection']] = _data['TodayPosition'] if _data['Position']: pass # self.position[_data['PosiDirection']] = _data['Position'] self.havedposi = True self.__orders = {} def openPosition(self, tr, volume): self.__retry = 0 offset = defineDict['THOST_FTDC_OF_Open'] pricetype = defineDict['THOST_FTDC_OPT_LimitPrice'] if tr > 0: price = self.ask + 0.2 * 2.0 direction = defineDict["THOST_FTDC_D_Buy"] else: price = self.bid - 0.2 * 2.0 direction = defineDict["THOST_FTDC_D_Sell"] _ref = self.td.sendOrder(self.symbol, self.exchangeid, price, pricetype, volume, direction, offset) self.__orders[_ref] = (self.symbol, self.exchangeid, price, pricetype, volume, direction, offset) def closePosition(self, tr, volume): self.__retry = 0 offset = defineDict['THOST_FTDC_OF_Close'] pricetype = defineDict['THOST_FTDC_OPT_LimitPrice'] if tr < 0: price = self.ask + 0.2 * 2.0 direction = defineDict["THOST_FTDC_D_Buy"] else: price = self.bid - 0.2 * 2.0 direction = defineDict["THOST_FTDC_D_Sell"] _ref = self.td.sendOrder(self.symbol, self.exchangeid, price, pricetype, volume, direction, offset) self.__orders[_ref] = (self.symbol, self.exchangeid, price, pricetype, volume, direction, offset) def closeTodayPosition(self, tr, volume): self.__retry = 0 offset = defineDict['THOST_FTDC_OF_CloseToday'] pricetype = defineDict['THOST_FTDC_OPT_LimitPrice'] if tr < 0: price = self.ask + 0.2 * 2.0 direction = defineDict["THOST_FTDC_D_Buy"] else: price = self.bid - 0.2 * 2.0 direction = defineDict["THOST_FTDC_D_Sell"] _ref = self.td.sendOrder(self.symbol, self.exchangeid, price, pricetype, volume, direction, offset) self.__orders[_ref] = (self.symbol, self.exchangeid, price, pricetype, volume, direction, offset) def get_error(self, event): _err = event.dict_['ErrorID'] self.socket.send(bytes("error_%s" % _err)) _bk = self.socket.recv() print("ERROR", event.dict_) self.__orders = {} def get_data(self, event): _data = event.dict_['data'] self.ask = _data['AskPrice1'] self.bid = _data['BidPrice1'] price = (self.ask + self.bid) / 2.0 self.socket.send(bytes(str(price))) _bk = int(self.socket.recv()) self.todo = _bk # print '%.0f %s = %d'%(time(),_data['LastPrice'],_bk) if self.__orders: print(self.__orders) elif self.havedposi: _long = defineDict["THOST_FTDC_PD_Long"] _short = defineDict["THOST_FTDC_PD_Short"] if self.todo == 0: if self.position.get(_long, 0) > 0: self.closePosition(1, self.position[_long]) self.havedposi = False if self.todayposition.get(_long, 0) > 0: self.closeTodayPosition(1, self.todayposition[_long]) self.havedposi = False if self.position.get(_short, 0) > 0: self.closePosition(-1, self.position[_short]) self.havedposi = False if self.todayposition.get(_short, 0) > 0: self.closeTodayPosition(-1, self.todayposition[_short]) self.havedposi = False def do_it(_todo, _pass, _reverse, d_pass, d_reverse): if self.position.get(_reverse, 0) > 0: self.closePosition(d_reverse, self.position[_reverse]) self.havedposi = False if self.todayposition.get(_reverse, 0) > 0: self.closeTodayPosition(d_reverse, self.todayposition[_reverse]) self.havedposi = False _haved = self.position.get(_pass, 0) + self.todayposition.get( _pass, 0) if _todo > _haved: self.openPosition(d_pass, _todo - _haved) self.havedposi = False if _todo < _haved: if self.position.get(_pass, 0) > 0: self.closePosition( d_pass, min(self.position[_pass], _haved - _todo)) self.havedposi = False if self.position[_pass] < _haved - _todo: self.closeTodayPosition( d_pass, _haved - _todo - self.position[_pass]) self.havedposi = False elif self.todayposition.get(_pass, 0) > 0: self.closeTodayPosition(d_pass, _haved - _todo) self.havedposi = False if self.todo > 0: _todo = self.todo _pass = _long _reverse = _short d_pass = 1 d_reverse = -1 do_it(_todo, _pass, _reverse, d_pass, d_reverse) if self.todo < 0: _todo = abs(self.todo) _pass = _short _reverse = _long d_pass = -1 d_reverse = 1 do_it(_todo, _pass, _reverse, d_pass, d_reverse) if not self.havedposi: self.todayposition = {} self.position = {} #---------------------------------------------------------------------- def login(self, userid, password, brokerid, mdAddress, tdAddress): """登陆""" self.td.login(tdAddress, userid, password, brokerid) self.md.login(mdAddress, userid, password, brokerid) #---------------------------------------------------------------------- def subscribe(self, instrumentid, exchangeid): """订阅合约""" self.md.subscribe(instrumentid, exchangeid) #---------------------------------------------------------------------- def getAccount(self): """查询账户""" self.td.getAccount() #---------------------------------------------------------------------- def getInvestor(self): """查询投资者""" self.td.getInvestor() #---------------------------------------------------------------------- def getPosition(self): """查询持仓""" self.td.getPosition() #---------------------------------------------------------------------- def getInstrument(self): """获取合约""" event = Event(type_=EVENT_LOG) log = u'查询合约信息' event.dict_['log'] = log self.ee.put(event) self.td.getInstrument() #---------------------------------------------------------------------- def sendOrder(self, instrumentid, exchangeid, price, pricetype, volume, direction, offset): """发单""" self.td.sendOrder(instrumentid, exchangeid, price, pricetype, volume, direction, offset) #---------------------------------------------------------------------- def cancelOrder(self, instrumentid, exchangeid, orderref, frontid, sessionid): """撤单""" self.td.cancelOrder(instrumentid, exchangeid, orderref, frontid, sessionid) #---------------------------------------------------------------------- def getAccountPosition(self, event): """循环查询账户和持仓""" self.countGet = self.countGet + 1 # 每1秒发一次查询 if self.countGet >= 20: self.countGet = 0 if self.lastGet == 'Account': self.getPosition() self.lastGet = 'Position' else: self.lastGet = 'Account' self.getAccount() #---------------------------------------------------------------------- def initGet(self, event): """在交易服务器登录成功后,开始初始化查询""" # 打开设定文件setting.vn f = shelve.open('setting.vn') # 尝试读取设定字典,若该字典不存在,则发出查询请求 try: d = f['instrument'] # 如果本地保存的合约数据是今日的,则载入,否则发出查询请求 today = date.today() if d['date'] == today: self.dictInstrument = d['dictInstrument'] event = Event(type_=EVENT_LOG) log = u'合约信息读取完成' event.dict_['log'] = log self.ee.put(event) self.getInvestor() # 开始循环查询 self.ee.register(EVENT_TIMER, self.getAccountPosition) else: self.getInstrument() except KeyError: self.getInstrument() f.close() # _exchangeid = self.dictInstrument[self.symbol]['ExchangeID'] self.exchangeid = "" #_exchangeid self.subscribe(self.symbol, self.exchangeid) #---------------------------------------------------------------------- def insertInstrument(self, event): """插入合约对象""" data = event.dict_['data'] last = event.dict_['last'] self.dictInstrument[data['InstrumentID']] = data # 合约对象查询完成后,查询投资者信息并开始循环查询 if last: # 将查询完成的合约信息保存到本地文件,今日登录可直接使用不再查询 self.saveInstrument() event = Event(type_=EVENT_LOG) log = u'合约信息查询完成' event.dict_['log'] = log self.ee.put(event) self.getInvestor() # 开始循环查询 self.ee.register(EVENT_TIMER, self.getAccountPosition) #---------------------------------------------------------------------- def selectInstrument(self, instrumentid): """获取合约信息对象""" try: instrument = self.dictInstrument[instrumentid] except KeyError: instrument = None return instrument #---------------------------------------------------------------------- def exit(self): """退出""" # 销毁API对象 self.td = None self.md = None # 停止事件驱动引擎 self.ee.stop() #---------------------------------------------------------------------- def saveInstrument(self): """保存合约属性数据""" f = shelve.open('setting.vn') d = {} d['dictInstrument'] = self.dictInstrument d['date'] = date.today() f['instrument'] = d f.close()
class MainEngine: """主引擎,负责对API的调度""" #---------------------------------------------------------------------- def __init__(self, ws, account, _plus_path, justCopySignal=False, useZmq=False, zmqServer="tcp://192.168.1.234:9999"): """Constructor :type self: object """ self.ee = EventEngine(account) # 创建事件驱动引擎 self.justCopySignal = justCopySignal self.userid = str(account['userid']) self.password = str(account['password']) self.brokerid = str(account['brokerid']) self.mdaddress = str(account['mdfront']) self.tdaddress = str(account['tdfront']) self.pluspath = _plus_path self.symbol = None self.socket = None self.websocket = ws # websocket list to send msg if useZmq: context = zmq.Context() socket = context.socket(zmq.REQ) socket.connect(zmqServer) self.socket = socket self.ee.start() # 启动事件驱动引擎 self.havedposi = False self.position = {} self.todayposition = {} self.lastError = 0 self.lastTodo = 0 self.__timer = time() + 60 self.__orders = {} self.__retry = 0 self.__maxRetry = 5 # 循环查询持仓和账户相关 self.countGet = 0 # 查询延时计数 self.lastGet = 'Account' # 上次查询的性质 self.ee.register(EVENT_TDLOGIN, self.initGet) # 登录成功后开始初始化查询 # 合约储存相关 self.dictInstrument = {} # 字典(保存合约查询数据) self.dictProduct = {} # 字典(保存合约查询数据) self.dictExchange = {} self.volInstrument = {} self.subInstrument = set() self.subedInst = set() self.todo = 0 self.ee.register(EVENT_ERROR, self.get_error) self.ee.register(EVENT_INSTRUMENT, self.insertInstrument) self.ee.register(EVENT_TIMER, self.getAccountPosition) self.ee.register(EVENT_TRADE, self.get_trade) self.ee.register(EVENT_ORDER, self.get_order) self.ee.register(EVENT_TICK, self.get_tick) self.ee.register(EVENT_POSITION, self.get_position) import eventType for k, v in eventType.__dict__.items(): if 'EVENT_' in k and v[0] != '_': self.ee.register(v, self.websocket_send) self.md = DemoMdApi(self.ee, self.mdaddress, self.userid, self.password, self.brokerid, plus_path=_plus_path) # 创建API接口 self.td = DemoTdApi(self.ee, self.tdaddress, self.userid, self.password, self.brokerid, plus_path=_plus_path) def set_ws(self, ws): self.websocket = ws def websocket_send(self, event): try: _data = json.dumps(event.dict_, ensure_ascii=False) for _ws in self.websocket: try: _ws.send(_data) except Exception, e: print(_data, e) except Exception, e: print(event.dict_, e)
class MainEngine: """主引擎,负责对API的调度""" # ---------------------------------------------------------------------- def __init__(self): """Constructor""" self.eventEngine = EventEngine() # 创建事件驱动引擎 self.md = DemoMdApi(self.eventEngine) # 创建API接口 # self.md = DemoL2Api(self.ee) # 如果使用L2行情就改为这行 self.td = DemoTdApi(self.eventEngine) self.eventEngine.start() # 启动事件驱动引擎 self.dataEngine = DataEngine(self, self.eventEngine) # 循环查询持仓和账户相关 self.countGet = 0 # 查询延时计数 self.lastGet = 'Account' # 上次查询的性质 self.eventEngine.register(EVENT_TDLOGIN, self.initGet) # 登录成功后开始初始化查询 # 合约储存相关 # self.dictInstrument = {} # 字典(保存合约查询数据) # self.eventEngine.register(EVENT_INSTRUMENT, self.insertInstrument) # 接口实例 self.gatewayDict = OrderedDict() self.gatewayDetailList = [] # 应用模块实例 self.appDict = OrderedDict() self.appDetailList = [] # 风控引擎实例(特殊独立对象) self.rmEngine = None # ---------------------------------------------------------------------- def addGateway(self, gatewayModule): """添加底层接口""" gatewayName = gatewayModule.gatewayName # 创建接口实例 self.gatewayDict[gatewayName] = gatewayModule.gatewayClass(self.eventEngine, gatewayName) # 设置接口轮询 if gatewayModule.gatewayQryEnabled: self.gatewayDict[gatewayName].setQryEnabled( gatewayModule.gatewayQryEnabled) # 保存接口详细信息 d = { 'gatewayName': gatewayModule.gatewayName, 'gatewayDisplayName': gatewayModule.gatewayDisplayName, 'gatewayType': gatewayModule.gatewayType } self.gatewayDetailList.append(d) # ---------------------------------------------------------------------- def addApp(self, appModule): """添加上层应用""" appName = appModule.appName # 创建应用实例 self.appDict[appName] = appModule.appEngine(self, self.eventEngine) # 保存应用信息 d = { 'appName': appModule.appName, 'appDisplayName': appModule.appDisplayName, 'appWidget': appModule.appWidget, 'appIco': appModule.appIco } self.appDetailList.append(d) # ---------------------------------------------------------------------- def getGateway(self, gatewayName): """获取接口""" if gatewayName in self.gatewayDict: return self.gatewayDict[gatewayName] else: self.writeLog('{gateway}接口不存在'.format(gateway=gatewayName)) return None # ---------------------------------------------------------------------- def writeLog(self, content): """快速发出日志事件""" log = VtLogData() log.logContent = content event = Event(type_=EVENT_LOG) event.dict_['data'] = log self.eventEngine.put(event) # ---------------------------------------------------------------------- def connect(self, gatewayName): """连接特定名称的接口""" gateway = self.getGateway(gatewayName) if gateway: gateway.connect() # ---------------------------------------------------------------------- def login(self, userid, mdPassword, tdPassword, mdAddress, tdAddress): """登陆""" db_path = {} db_path['SH'] = userid db_path['SZ'] = mdPassword db_path['Order'] = tdPassword db_path['HB'] = mdAddress db_path['Acct'] = tdAddress print(db_path) self.md.login(db_path) self.td.login(db_path) # ---------------------------------------------------------------------- def subscribe(self, instrumentid, exchangeid): """订阅合约""" self.md.subscribe(instrumentid, exchangeid) # ---------------------------------------------------------------------- def getAccount(self): """查询账户""" self.dataEngine.getAccount() # ---------------------------------------------------------------------- def getPosition(self): """查询持仓""" self.dataEngine.getPosition() # ---------------------------------------------------------------------- def getInstrument(self): """获取合约""" event = Event(type_=EVENT_LOG) log = VtLogData() log.gatewayName = 'MainEngine' log.logContent = u'查询合约信息' event.dict_['log'] = log self.eventEngine.put(event) self.md.getInstrument() # ---------------------------------------------------------------------- def sendOrder(self, instrumentid, exchangeid, price, pricetype, volume, direction): """发单""" self.td.sendOrder(instrumentid, exchangeid, price, pricetype, volume, direction) # ---------------------------------------------------------------------- def cancelOrder(self, orderref): """撤单""" self.td.cancelOrder(orderref) # ---------------------------------------------------------------------- def getAccountPosition(self, event): """循环查询账户和持仓""" self.countGet = self.countGet + 1 # 每5秒发一次查询 if self.countGet > 5: self.countGet = 0 # 清空计数 if self.lastGet == 'Account': self.getPosition() self.lastGet = 'Position' else: self.getAccount() self.lastGet = 'Account' # ---------------------------------------------------------------------- def initGet(self, event): """在交易服务器登录成功后,开始初始化查询""" # 打开设定文件setting.vn if self.dataEngine.no_data: self.getInstrument() self.getAccount() self.getPosition() self.eventEngine.register(EVENT_TIMER, self.getAccountPosition) # ---------------------------------------------------------------------- def selectInstrument(self, instrumentid): """获取合约信息对象""" return self.dataEngine.getContract(instrumentid) # ---------------------------------------------------------------------- def exit(self): """退出""" # 销毁API对象 self.td.exit() self.md.exit() self.td = None self.md = None # 停止事件驱动引擎 self.eventEngine.stop() # ---------------------------------------------------------------------- def getAllContracts(self): """查询所有合约(返回列表)""" return self.dataEngine.getAllContracts() # ---------------------------------------------------------------------- def getOrder(self, vtOrderID): """查询委托""" return self.dataEngine.getOrder(vtOrderID) # ---------------------------------------------------------------------- def getAllWorkingOrders(self): """查询所有的活跃的委托(返回列表)""" return self.dataEngine.getAllWorkingOrders() # ---------------------------------------------------------------------- def getAllGatewayDetails(self): """查询引擎中所有底层接口的信息""" return self.gatewayDetailList # ---------------------------------------------------------------------- def getAllAppDetails(self): """查询引擎中所有上层应用的信息""" return self.appDetailList def getacc_list(self): """获取账户列表""" return self.dataEngine.getacc_list() def getProtfolio(self, account): """获取指定账户信息""" return self.dataEngine.getPosition(account)
class MainEngine: #---------------------------------------------------------------------- def __init__(self, account, _plus_path, bg): self.ee = EventEngine(account) # 创建事件驱动引擎 self.bridge = bg self.__lock = Lock() self.userid = str(account['userid']) self.password = str(account['password']) self.brokerid = str(account['brokerid']) self.mdaddress = str(account['mdfront']) self.tdaddress = str(account['tdfront']) self.instrument = account['instrument'] # sub list str self.pluspath = _plus_path self.dictInstrument = {} # 字典(保存合约查询数据) self.dictProduct = {} # 字典(保存合约查询数据) self.dictExchange = {} self.tmpInstrument = {} # 字典(保存合约查询数据) self.tmpProduct = {} # 字典(保存合约查询数据) self.tmpExchange = {} self.dictUpdate = None self.subInstrument = set() self.subedInstrument = set() self.master = {} # 记录主力合约对应关系 self.masterSubed = False self.subedMaster = {} self.tickpass = set() self.now = datetime.now() self.socket = None self.coreServer = str(account['zmqserver']) self.corefunc = passit if int(account['usezmq']) > 0: if self.coreServer[:4] == 'tcp:': context = zmq.Context() socket = context.socket(zmq.REQ) socket.connect(self.coreServer) self.socket = socket self.corefunc = tcpfunc elif self.coreServer[:5] == 'http:': self.socket = True self.corefunc = httpfunc self.ee.start() # 启动事件驱动引擎 self.som = {} self.lastError = 0 self.lastTodo = 0 self.eq = 0 # 循环查询持仓和账户相关 self.countGet = 0 # 查询延时计数 self.lastGet = 'Account' # 上次查询的性质 self.ee.register(EVENT_TDLOGIN, self.initGet, True) # 登录成功后开始初始化查询 self.__timer = time() + 3 self.__readySubscribe = {} # 合约储存相关 self.get_instrument() self.get_subscribe(self.instrument) self.ee.register(EVENT_MDLOGIN, self.ready_subscribe, True) self.ee.register(EVENT_TDLOGIN, self.ready_subscribe, True) self.ee.register(EVENT_ERROR, self.get_error, False) self.ee.register(EVENT_INSTRUMENT, self.insertInstrument, True) self.ee.register(EVENT_TIMER, self.getAccountPosition, False) self.ee.register(EVENT_TRADE, self.get_trade, False) self.ee.register(EVENT_ORDER, self.get_order, False) self.ee.register(EVENT_TICK, self.get_tick, True) self.ee.register(EVENT_POSITION, self.get_position, True) self.ee.register(EVENT_ACCOUNT, self.get_account, False) self.ee.register(EVENT_TICK, self.check_timer, False) import eventType for k, v in eventType.__dict__.items(): if 'EVENT_' in k and v[0] != '_': self.ee.register(v, self.websocket_send, False) self.md = ctpMdApi(self, self.mdaddress, self.userid, self.password, self.brokerid, plus_path=_plus_path) # 创建API接口 self.td = ctpTdApi(self, self.tdaddress, self.userid, self.password, self.brokerid, plus_path=_plus_path) def get_subscribe(self, _inst): if '#' in _inst: _instlist = [(v.get('_vol_', 0), k) for k, v in self.dictInstrument.items()] _instlist.sort(reverse=True) _only = set() for v, _instrumentid in _instlist[:10]: _product = self.dictInstrument[_instrumentid]['ProductID'] if _product not in _only: _exchangeid = self.dictInstrument.get(_instrumentid, {}).get( "ExchangeID", '') self.subInstrument.add((_instrumentid, _exchangeid)) self.subedMaster[_instrumentid] = 1 self.tickpass.add(_instrumentid) _only.add(_product) for _productid in ['IF', 'IH', 'IC']: if _productid in self.dictProduct and _productid not in _only: _product = self.dictProduct[_productid] _productlist = [(v, k) for k, v in _product.items()] _productlist.sort(reverse=True) _instrumentid = _productlist[0][-1] _exchangeid = self.dictInstrument.get(_instrumentid, {}).get( "ExchangeID", '') self.subInstrument.add((_instrumentid, _exchangeid)) self.master[_productid] = _product self.subedMaster[_instrumentid] = 1 self.tickpass.add(_instrumentid) for _productid, _product in self.dictProduct.items(): self.master[_productid] = _product else: _all = _inst.split('+') for one in _all: if '=' in one: _productid = one[:-1] if _productid in self.dictProduct: _product = self.dictProduct[_productid] _productlist = [(v, k) for k, v in _product.items()] _productlist.sort(reverse=True) _instrumentid = _productlist[0][-1] _exchangeid = self.dictInstrument.get( _instrumentid, {}).get("ExchangeID", '') self.subInstrument.add((_instrumentid, _exchangeid)) self.master[_productid] = _product self.subedMaster[_instrumentid] = 1 self.tickpass.add(_instrumentid) else: _instrumentid = one _exchangeid = self.dictInstrument.get(_instrumentid, {}).get( "ExchangeID", '') self.subInstrument.add((_instrumentid, _exchangeid)) self.tickpass.add(_instrumentid) print(self.subInstrument) def ready_subscribe(self, event): self.__readySubscribe[event.type_] = 1 if len(self.__readySubscribe) == 2: for one in self.subInstrument: if one[0] in self.subedMaster: event = Event(type_=EVENT_LOG) log = u'订阅主力合约:%s[%s]' % ( one[0], self.dictInstrument[one[0]]['InstrumentName']) event.dict_['log'] = log self.ee.put(event) else: event = Event(type_=EVENT_LOG) log = u'订阅合约:%s[%s]' % ( one[0], self.dictInstrument[one[0]]['InstrumentName']) event.dict_['log'] = log self.ee.put(event) self.subscribe(one[0], one[1]) def get_instrument(self): _dict = self.bridge.get_instrument() self.dictInstrument = _dict.get('instrument', {}) self.dictExchange = _dict.get('exchange', {}) self.dictProduct = _dict.get('product', {}) self.dictUpdate = _dict.get('day', None) def set_instrument(self): _dict = {} _dict['instrument'] = self.dictInstrument _dict['exchange'] = self.dictExchange _dict['product'] = self.dictProduct _dict['day'] = date.today() self.bridge.set_instrument(_dict) def get_som(self, event): try: symbol = event.dict_['data']['InstrumentID'] if symbol: if symbol not in self.tickpass: return if symbol in self.som: return self.som[symbol] else: _data = None if symbol in self.dictInstrument: _data = self.dictInstrument[symbol] event = Event(type_=EVENT_LOG) log = u'初始化合约[%s]并填充其基本信息' % symbol event.dict_['log'] = log self.ee.put(event) else: _productid = filter(lambda x: x in _chars + _CHARS, symbol) if _productid in self.dictProduct: for _instrument in self.dictProduct[ _productid].keys(): if _instrument in self.dictInstrument: _data = self.dictInstrument[_instrument] event = Event(type_=EVENT_LOG) log = u'注意:初始化合约[%s]但填充了<%s>的基本信息' % ( symbol, _instrument) event.dict_['log'] = log self.ee.put(event) break if _data: one = SymbolOrdersManager(symbol, _data, self) self.som[symbol] = one return one else: event = Event(type_=EVENT_LOG) log = u'警告:初始化合约[%s]失败,未发现其基本信息' % symbol event.dict_['log'] = log self.ee.put(event) print( "ctpEngine.py MainEngine get_som not found Instrument Info" ) return None else: return None except Exception, e: print("ctpEngine.py MainEngine get_som ERROR", e) print(event.type_, event.dict_['data'])
from eventType import * from eventEngine import EventEngine import os import tdxApi def timer_fun(event): print("test_func:{}".format(event.type_)) if __name__ == "__main__": engine = EventEngine() engine.register(EVENT_TIMER, timer_fun) engine.start()
class MainEngine: """主引擎,负责对API的调度""" #---------------------------------------------------------------------- def __init__(self): """Constructor""" self.ee = EventEngine() # 创建事件驱动引擎 self.dsa = DemoStockApi(('192.168.16.59', 9991), self.ee) # 现货报单 self.dma = DemoMarketApi(('10.10.1.186', 9101), self.ee) # 现货报单 # self.md = DemoL2Api(self.ee) # 如果使用L2行情就改为这行 # self.td = DemoTdApi(self.ee) self.ee.start() # 启动事件驱动引擎 # 循环查询持仓和账户相关 self.countGet = 0 # 查询延时计数 self.lastGet = 'Account' # 上次查询的性质 # self.ee.register(EVENT_TDLOGIN, self.initGet) # 登录成功后开始初始化查询 # 合约储存相关 self.dictInstrument = {} # 字典(保存合约查询数据) # self.ee.register(EVENT_INSTRUMENT, self.insertInstrument) #---------------------------------------------------------------------- def login(self, userid, mdPassword, tdPassword, brokerid, mdAddress, tdAddress): """登陆""" self.dsa.login_req() # self.md.login(mdAddress, userid, mdPassword, brokerid) # self.td.login(tdAddress, userid, tdPassword, brokerid) #---------------------------------------------------------------------- def subscribe(self, instrumentid, exchangeid): """订阅合约""" # self.md.subscribe(instrumentid, exchangeid) #---------------------------------------------------------------------- def getAccount(self): """查询账户""" # self.td.getAccount() #---------------------------------------------------------------------- def getInvestor(self): """查询投资者""" # self.td.getInvestor() #---------------------------------------------------------------------- def getPosition(self): """查询持仓""" # self.td.getPosition() #---------------------------------------------------------------------- def getInstrument(self): """获取合约""" # event = Event(type_=EVENT_LOG) # log = u'查询合约信息' # event.dict_['log'] = log # self.ee.put(event) # self.td.getInstrument() #---------------------------------------------------------------------- def sendOrder(self, instrumentid, exchangeid, price, pricetype, volume, direction, offset): """发单""" # self.td.sendOrder(instrumentid, exchangeid, price, pricetype, volume, direction, offset) #---------------------------------------------------------------------- def cancelOrder(self, instrumentid, exchangeid, orderref, frontid, sessionid): """撤单""" # self.td.cancelOrder(instrumentid, exchangeid, orderref, frontid, sessionid) #---------------------------------------------------------------------- def getAccountPosition(self, event): """循环查询账户和持仓""" # self.countGet = self.countGet + 1 # # # 每5秒发一次查询 # if self.countGet > 5: # self.countGet = 0 # 清空计数 # # if self.lastGet == 'Account': # self.getPosition() # self.lastGet = 'Position' # else: # self.getAccount() # self.lastGet = 'Account' #---------------------------------------------------------------------- def initGet(self, event): """在交易服务器登录成功后,开始初始化查询""" # 打开设定文件setting.vn # f = shelve.open('setting.vn') # # # 尝试读取设定字典,若该字典不存在,则发出查询请求 # try: # d = f['instrument'] # # # 如果本地保存的合约数据是今日的,则载入,否则发出查询请求 # today = date.today() # if d['date'] == today: # self.dictInstrument = d['dictInstrument'] # # # event = Event(type_=EVENT_LOG) # # log = u'合约信息读取完成' # # event.dict_['log'] = log # # self.ee.put(event) # # # # self.getInvestor() # # # # # 开始循环查询 # # self.ee.register(EVENT_TIMER, self.getAccountPosition) # else: # self.getInstrument() # except KeyError: # self.getInstrument() # # f.close() #---------------------------------------------------------------------- def insertInstrument(self, event): """插入合约对象""" # data = event.dict_['data'] # last = event.dict_['last'] # # self.dictInstrument[data['InstrumentID']] = data # # # 合约对象查询完成后,查询投资者信息并开始循环查询 # if last: # # 将查询完成的合约信息保存到本地文件,今日登录可直接使用不再查询 # self.saveInstrument() # event = Event(type_=EVENT_LOG) # log = u'合约信息查询完成' # event.dict_['log'] = log # self.ee.put(event) # # self.getInvestor() # # # 开始循环查询 # self.ee.register(EVENT_TIMER, self.getAccountPosition) #---------------------------------------------------------------------- def selectInstrument(self, instrumentid): """获取合约信息对象""" # try: # instrument = self.dictInstrument[instrumentid] # except KeyError: # instrument = None # return instrument #---------------------------------------------------------------------- def exit(self): """退出""" # 销毁API对象 # self.td = None # self.md = None self.dsa = None # 停止事件驱动引擎 self.ee.stop() #---------------------------------------------------------------------- def saveInstrument(self): """保存合约属性数据""" # f = shelve.open('setting.vn') # d = {} # d['dictInstrument'] = self.dictInstrument # d['date'] = date.today() # f['instrument'] = d # f.close()