class RpcEngine(BaseEngine): """""" setting_filename = "rpc_service_setting.json" def __init__(self, main_engine: MainEngine, event_engine: EventEngine): """""" super().__init__(main_engine, event_engine, APP_NAME) self.rep_address = "tcp://*:2014" self.pub_address = "tcp://*:4102" self.server: Optional[RpcServer] = None self.init_server() self.load_setting() self.register_event() def init_server(self): """""" self.server = RpcServer() self.server.register(self.main_engine.subscribe) self.server.register(self.main_engine.send_order) self.server.register(self.main_engine.send_orders) self.server.register(self.main_engine.cancel_order) self.server.register(self.main_engine.cancel_orders) self.server.register(self.main_engine.query_history) self.server.register(self.main_engine.get_tick) self.server.register(self.main_engine.get_order) self.server.register(self.main_engine.get_trade) self.server.register(self.main_engine.get_position) self.server.register(self.main_engine.get_account) self.server.register(self.main_engine.get_contract) self.server.register(self.main_engine.get_all_ticks) self.server.register(self.main_engine.get_all_orders) self.server.register(self.main_engine.get_all_trades) self.server.register(self.main_engine.get_all_positions) self.server.register(self.main_engine.get_all_accounts) self.server.register(self.main_engine.get_all_contracts) self.server.register(self.main_engine.get_all_active_orders) def load_setting(self): """""" setting = load_json(self.setting_filename) self.rep_address = setting.get("rep_address", self.rep_address) self.pub_address = setting.get("pub_address", self.pub_address) def save_setting(self): """""" setting = { "rep_address": self.rep_address, "pub_address": self.pub_address } save_json(self.setting_filename, setting) def start(self, rep_address: str, pub_address: str): """""" if self.server.is_active(): self.write_log("RPC service operation ") return False self.rep_address = rep_address self.pub_address = pub_address try: self.server.start(rep_address, pub_address) except: # noqa msg = traceback.format_exc() self.write_log(f"RPC service failed to start :{msg}") return False self.save_setting() self.write_log("RPC service starts successfully ") return True def stop(self): """""" if not self.server.is_active(): self.write_log("RPC service does not start ") return False self.server.stop() self.server.join() self.write_log("RPC service is stopped ") return True def close(self): """""" self.stop() def register_event(self): """""" self.event_engine.register_general(self.process_event) def process_event(self, event: Event): """""" if self.server.is_active(): self.server.publish("", event) def write_log(self, msg: str) -> None: """""" log = LogData(msg=msg, gateway_name=APP_NAME) event = Event(EVENT_RPC_LOG, log) self.event_engine.put(event)
class TcEngine(object): """交易复制引擎""" MODE_PROVIDER = 1 MODE_SUBSCRIBER = 2 #---------------------------------------------------------------------- def __init__(self, mainEngine, eventEngine): """Constructor""" self.mainEngine = mainEngine self.eventEngine = eventEngine self.mode = None # Subscriber/Provider self.posDict = defaultdict(int) # vtPositionName:int self.targetDict = defaultdict(int) # vtPositionName:int self.copyRatio = 1 self.interval = 1 self.subscribeSet = set() self.count = 0 self.server = None # RPC Server self.client = None # RPC Client self.registerEvent() #---------------------------------------------------------------------- def startProvider(self, repAddress, pubAddress, interval): """""" self.mode = self.MODE_PROVIDER self.interval = interval if not self.server: self.server = RpcServer(repAddress, pubAddress) self.server.usePickle() self.server.register(self.getPos) self.server.start() self.writeLog(u'启动发布者模式(如需修改通讯地址请重启程序)') #---------------------------------------------------------------------- def startSubscriber(self, reqAddress, subAddress, copyRatio): """""" self.mode = self.MODE_SUBSCRIBER self.copyRatio = copyRatio if not self.client: self.client = TcClient(self, reqAddress, subAddress) self.client.usePickle() self.client.subscribeTopic('') self.client.start() self.writeLog(u'启动订阅者模式,运行时请不要执行其他交易操作') self.initTarget() #---------------------------------------------------------------------- def stop(self): """""" if self.client: self.client.stop() self.writeLog(u'订阅者模式已停止') if self.server: self.server.stop() self.writeLog(u'发布者模式已停止') self.mode = None #---------------------------------------------------------------------- def registerEvent(self): """""" self.eventEngine.register(EVENT_POSITION, self.processPositionEvent) self.eventEngine.register(EVENT_TRADE, self.processTradeEvent) self.eventEngine.register(EVENT_TIMER, self.processTimerEvent) self.eventEngine.register(EVENT_ORDER, self.processOrderEvent) #---------------------------------------------------------------------- def checkAndTrade(self, vtSymbol): """""" if self.checkNoWorkingOrder(vtSymbol): self.newOrder(vtSymbol) else: self.cancelOrder(vtSymbol) #---------------------------------------------------------------------- def processTimerEvent(self, event): """""" if self.mode != self.MODE_PROVIDER: return self.count += 1 if self.count < self.interval: return self.count = 0 for vtPositionName in self.posDict.keys(): self.publishPos(vtPositionName) #---------------------------------------------------------------------- def processTradeEvent(self, event): """""" trade = event.dict_['data'] vtPositionName = '.'.join([trade.vtSymbol, trade.direction]) if trade.offset == OFFSET_OPEN: self.posDict[vtPositionName] += trade.volume else: self.posDict[vtPositionName] -= trade.volume if self.mode == self.MODE_PROVIDER: self.publishPos(vtPositionName) #---------------------------------------------------------------------- def processPositionEvent(self, event): """""" position = event.dict_['data'] self.posDict[position.vtPositionName] = position.position #---------------------------------------------------------------------- def processOrderEvent(self, event): """""" order = event.dict_['data'] if order.status == STATUS_REJECTED: self.writeLog(u'监控到委托拒单,停止运行') self.stop() #---------------------------------------------------------------------- def publishPos(self, vtPositionName): """""" l = vtPositionName.split('.') direction = l[-1] vtSymbol = vtPositionName.replace('.' + direction, '') data = { 'vtSymbol': vtSymbol, 'vtPositionName': vtPositionName, 'pos': self.posDict[vtPositionName] } self.server.publish('', data) #---------------------------------------------------------------------- def updatePos(self, data): """""" vtSymbol = data['vtSymbol'] if vtSymbol not in self.subscribeSet: contract = self.mainEngine.getContract(vtSymbol) req = VtSubscribeReq() req.symbol = contract.symbol req.exchange = contract.exchange self.mainEngine.subscribe(req, contract.gatewayName) vtPositionName = data['vtPositionName'] target = int(data['pos'] * self.copyRatio) self.targetDict[vtPositionName] = target self.checkAndTrade(vtSymbol) #---------------------------------------------------------------------- def newOrder(self, vtSymbol): """""" for vtPositionName in self.targetDict.keys(): if vtSymbol not in vtPositionName: continue pos = self.posDict[vtPositionName] target = self.targetDict[vtPositionName] if pos == target: continue contract = self.mainEngine.getContract(vtSymbol) tick = self.mainEngine.getTick(vtSymbol) if not tick: return req = VtOrderReq() req.symbol = contract.symbol req.exchange = contract.exchange req.priceType = PRICETYPE_LIMITPRICE req.volume = abs(target - pos) # Open position if target > pos: req.offset = OFFSET_OPEN if DIRECTION_LONG in vtPositionName: req.direction = DIRECTION_LONG if tick.upperLimit: req.price = tick.upperLimit else: req.price = tick.askPrice1 elif DIRECTION_SHORT in vtPositionName: req.direction = DIRECTION_SHORT if tick.lowerLimit: req.price = tick.lowerLimit else: req.price = tick.bidPrice1 self.mainEngine.sendOrder(req, contract.gatewayName) # Close position elif target < pos: req.offset = OFFSET_CLOSE if DIRECTION_LONG in vtPositionName: req.direction = DIRECTION_SHORT if tick.upperLimit: req.price = tick.upperLimit else: req.price = tick.askPrice1 elif DIRECTION_SHORT in vtPositionName: req.direction = DIRECTION_LONG if tick.lowerLimit: req.price = tick.lowerLimit else: req.price = tick.bidPrice1 # Use auto-convert for solving today/yesterday position problem reqList = self.mainEngine.convertOrderReq(req) for convertedReq in reqList: self.mainEngine.sendOrder(convertedReq, contract.gatewayName) # Write log msg = u'发出%s委托 %s%s %s@%s' % (vtSymbol, req.direction, req.offset, req.price, req.volume) self.writeLog(msg) #---------------------------------------------------------------------- def cancelOrder(self, vtSymbol): """ Cancel all orders of a certain vtSymbol """ l = self.mainEngine.getAllWorkingOrders() for order in l: if order.vtSymbol == vtSymbol: req = VtCancelOrderReq() req.orderID = order.orderID req.frontID = order.frontID req.sessionID = order.sessionID req.symbol = order.symbol req.exchange = order.exchange self.mainEngine.cancelOrder(req, order.gatewayName) self.writeLog(u'撤销%s全部活动中委托' % vtSymbol) #---------------------------------------------------------------------- def checkNoWorkingOrder(self, vtSymbol): """ Check if there is still any working orders of a certain vtSymbol """ l = self.mainEngine.getAllWorkingOrders() for order in l: if order.vtSymbol == vtSymbol: return False return True #---------------------------------------------------------------------- def writeLog(self, msg): """""" log = VtLogData() log.logContent = msg event = Event(EVENT_TC_LOG) event.dict_['data'] = log self.eventEngine.put(event) #---------------------------------------------------------------------- def getPos(self): """ Get currenct position data of provider """ return dict(self.posDict) #---------------------------------------------------------------------- def initTarget(self): """ Init target data of subscriber based on position data from provider """ d = self.client.getPos() for vtPositionName, pos in d.items(): l = vtPositionName.split('.') direction = l[-1] vtSymbol = vtPositionName.replace('.' + direction, '') data = { 'vtPositionName': vtPositionName, 'vtSymbol': vtSymbol, 'pos': pos } self.updatePos(data) self.writeLog(u'目标仓位初始化完成')
class TcEngine(object): """交易复制引擎""" MODE_PROVIDER = 1 MODE_SUBSCRIBER = 2 #---------------------------------------------------------------------- def __init__(self, mainEngine, eventEngine): """Constructor""" self.mainEngine = mainEngine self.eventEngine = eventEngine self.mode = None # Subscriber/Provider self.posDict = defaultdict(int) # vtPositionName:int self.targetDict = defaultdict(int) # vtPositionName:int self.copyRatio = 1 self.interval = 1 self.subscribeSet = set() self.count = 0 self.server = None # RPC Server self.client = None # RPC Client self.registerEvent() #---------------------------------------------------------------------- def startProvider(self, repAddress, pubAddress, interval): """""" self.mode = self.MODE_PROVIDER self.interval = interval if not self.server: self.server = RpcServer(repAddress, pubAddress) self.server.usePickle() self.server.register(self.getPos) self.server.start() self.writeLog(u'启动发布者模式(如需修改通讯地址请重启程序)') #---------------------------------------------------------------------- def startSubscriber(self, reqAddress, subAddress, copyRatio): """""" self.mode = self.MODE_SUBSCRIBER self.copyRatio = copyRatio if not self.client: self.client = TcClient(self, reqAddress, subAddress) self.client.usePickle() self.client.subscribeTopic('') self.client.start() self.writeLog(u'启动订阅者模式,运行时请不要执行其他交易操作') self.initTarget() #---------------------------------------------------------------------- def stop(self): """""" if self.client: self.client.stop() self.writeLog(u'订阅者模式已停止') if self.server: self.server.stop() self.writeLog(u'发布者模式已停止') self.mode = None #---------------------------------------------------------------------- def registerEvent(self): """""" self.eventEngine.register(EVENT_POSITION, self.processPositionEvent) self.eventEngine.register(EVENT_TRADE, self.processTradeEvent) self.eventEngine.register(EVENT_TIMER, self.processTimerEvent) self.eventEngine.register(EVENT_ORDER, self.processOrderEvent) #---------------------------------------------------------------------- def checkAndTrade(self, vtSymbol): """""" if self.checkNoWorkingOrder(vtSymbol): self.newOrder(vtSymbol) else: self.cancelOrder(vtSymbol) #---------------------------------------------------------------------- def processTimerEvent(self, event): """""" if self.mode != self.MODE_PROVIDER: return self.count += 1 if self.count < self.interval: return self.count = 0 for vtPositionName in self.posDict.keys(): self.publishPos(vtPositionName) #---------------------------------------------------------------------- def processTradeEvent(self, event): """""" trade = event.dict_['data'] vtPositionName = '.'.join([trade.vtSymbol, trade.direction]) if trade.offset == OFFSET_OPEN: self.posDict[vtPositionName] += trade.volume else: self.posDict[vtPositionName] -= trade.volume if self.mode == self.MODE_PROVIDER: self.publishPos(vtPositionName) #---------------------------------------------------------------------- def processPositionEvent(self, event): """""" position = event.dict_['data'] self.posDict[position.vtPositionName] = position.position #---------------------------------------------------------------------- def processOrderEvent(self, event): """""" order = event.dict_['data'] if order.status == STATUS_REJECTED: self.writeLog(u'监控到委托拒单,停止运行') self.stop() #---------------------------------------------------------------------- def publishPos(self, vtPositionName): """""" l = vtPositionName.split('.') direction = l[-1] vtSymbol = vtPositionName.replace('.' + direction, '') data = { 'vtSymbol': vtSymbol, 'vtPositionName': vtPositionName, 'pos': self.posDict[vtPositionName] } self.server.publish('', data) #---------------------------------------------------------------------- def updatePos(self, data): """""" vtSymbol = data['vtSymbol'] if vtSymbol not in self.subscribeSet: contract = self.mainEngine.getContract(vtSymbol) req = VtSubscribeReq() req.symbol = contract.symbol req.exchange = contract.exchange self.mainEngine.subscribe(req, contract.gatewayName) vtPositionName = data['vtPositionName'] target = int(data['pos'] * self.copyRatio) self.targetDict[vtPositionName] = target self.checkAndTrade(vtSymbol) #---------------------------------------------------------------------- def newOrder(self, vtSymbol): """""" for vtPositionName in self.targetDict.keys(): if vtSymbol not in vtPositionName: continue pos = self.posDict[vtPositionName] target = self.targetDict[vtPositionName] if pos == target: continue contract = self.mainEngine.getContract(vtSymbol) tick = self.mainEngine.getTick(vtSymbol) if not tick: return req = VtOrderReq() req.symbol = contract.symbol req.exchange = contract.exchange req.priceType = PRICETYPE_LIMITPRICE req.volume = abs(target - pos) # Open position if target > pos: req.offset = OFFSET_OPEN if DIRECTION_LONG in vtPositionName: req.direction = DIRECTION_LONG if tick.upperLimit: req.price = tick.upperLimit else: req.price = tick.askPrice1 elif DIRECTION_SHORT in vtPositionName: req.direction = DIRECTION_SHORT if tick.lowerLimit: req.price = tick.lowerLimit else: req.price = tick.bidPrice1 self.mainEngine.sendOrder(req, contract.gatewayName) # Close position elif target < pos: req.offset = OFFSET_CLOSE if DIRECTION_LONG in vtPositionName: req.direction = DIRECTION_SHORT if tick.upperLimit: req.price = tick.upperLimit else: req.price = tick.askPrice1 elif DIRECTION_SHORT in vtPositionName: req.direction = DIRECTION_LONG if tick.lowerLimit: req.price = tick.lowerLimit else: req.price = tick.bidPrice1 # Use auto-convert for solving today/yesterday position problem reqList = self.mainEngine.convertOrderReq(req) for convertedReq in reqList: self.mainEngine.sendOrder(convertedReq, contract.gatewayName) # Write log msg = u'发出%s委托 %s%s %s@%s' %(vtSymbol, req.direction, req.offset, req.price, req.volume) self.writeLog(msg) #---------------------------------------------------------------------- def cancelOrder(self, vtSymbol): """ Cancel all orders of a certain vtSymbol """ l = self.mainEngine.getAllWorkingOrders() for order in l: if order.vtSymbol == vtSymbol: req = VtCancelOrderReq() req.orderID = order.orderID req.frontID = order.frontID req.sessionID = order.sessionID req.symbol = order.symbol req.exchange = order.exchange self.mainEngine.cancelOrder(req, order.gatewayName) self.writeLog(u'撤销%s全部活动中委托' %vtSymbol) #---------------------------------------------------------------------- def checkNoWorkingOrder(self, vtSymbol): """ Check if there is still any working orders of a certain vtSymbol """ l = self.mainEngine.getAllWorkingOrders() for order in l: if order.vtSymbol == vtSymbol: return False return True #---------------------------------------------------------------------- def writeLog(self, msg): """""" log = VtLogData() log.logContent = msg event = Event(EVENT_TC_LOG) event.dict_['data'] = log self.eventEngine.put(event) #---------------------------------------------------------------------- def getPos(self): """ Get currenct position data of provider """ return dict(self.posDict) #---------------------------------------------------------------------- def initTarget(self): """ Init target data of subscriber based on position data from provider """ d = self.client.getPos() for vtPositionName, pos in d.items(): l = vtPositionName.split('.') direction = l[-1] vtSymbol = vtPositionName.replace('.' + direction, '') data = { 'vtPositionName': vtPositionName, 'vtSymbol': vtSymbol, 'pos': pos } self.updatePos(data) self.writeLog(u'目标仓位初始化完成')
class RsEngine(object): """RPC服务引擎""" settingFileName = 'RS_setting.json' settingFilePath = getJsonPath(settingFileName, __file__) name = 'RPC服务' #---------------------------------------------------------------------- def __init__(self, mainEngine, eventEngine): """Constructor""" self.mainEngine = mainEngine self.eventEngine = eventEngine self.server = None # RPC服务对象 self.repAddress = EMPTY_STRING # REP地址 self.pubAddress = EMPTY_STRING # PUB地址 self.functionDict = {} # 调用过的函数对象缓存字典 self.loadSetting() self.registerEvent() #---------------------------------------------------------------------- def loadSetting(self): """读取配置""" with open(self.settingFilePath) as f: d = json.load(f) self.repAddress = d['repAddress'] self.pubAddress = d['pubAddress'] self.server = RpcServer(self.repAddress, self.pubAddress) self.server.usePickle() self.server.register(self.call) self.server.start() #---------------------------------------------------------------------- def registerEvent(self): """注册事件监听""" self.eventEngine.registerGeneralHandler(self.processEvent) #---------------------------------------------------------------------- def call(self, d): """调用函数""" nameList = d['nameList'] # 对象属性列表 nameTuple = tuple(nameList) # 转化为元组 args = d['args'] # 调用参数 kwargs = d['kwargs'] # 如果已经有缓存,则直接调用 if nameTuple in self.functionDict: function = self.functionDict[nameTuple] result = function(*args, **kwargs) return result # 逐层寻找函数对象 else: # 根对象为主引擎 obj = self.mainEngine # 逐层寻找对象属性 for name in nameTuple: obj = obj.__getattribute__(name) # 缓存结果 self.functionDict[nameTuple] = obj # 调用最终对象 result = obj(*args, **kwargs) return result #---------------------------------------------------------------------- def processEvent(self, event): """处理事件推送""" self.server.publish(b'', event) #---------------------------------------------------------------------- def stop(self): """停止""" self.server.stop()
class RsEngine(object): """RPC服务引擎""" settingFileName = 'RS_setting.json' settingFilePath = getJsonPath(settingFileName, __file__) name = u'RPC服务' #---------------------------------------------------------------------- def __init__(self, mainEngine, eventEngine): """Constructor""" self.mainEngine = mainEngine self.eventEngine = eventEngine self.server = None # RPC服务对象 self.repAddress = EMPTY_STRING # REP地址 self.pubAddress = EMPTY_STRING # PUB地址 self.functionDict = {} # 调用过的函数对象缓存字典 self.loadSetting() self.registerEvent() #---------------------------------------------------------------------- def loadSetting(self): """读取配置""" with open(self.settingFilePath) as f: d = json.load(f) self.repAddress = d['repAddress'] self.pubAddress = d['pubAddress'] self.server = RpcServer(self.repAddress, self.pubAddress) self.server.usePickle() self.server.register(self.call) self.server.start() #---------------------------------------------------------------------- def registerEvent(self): """注册事件监听""" self.eventEngine.registerGeneralHandler(self.processEvent) #---------------------------------------------------------------------- def call(self, d): """调用函数""" nameList = d['nameList'] # 对象属性列表 nameTuple = tuple(nameList) # 转化为元组 args = d['args'] # 调用参数 kwargs = d['kwargs'] # 如果已经有缓存,则直接调用 if nameTuple in self.functionDict: function = self.functionDict[nameTuple] result = function(*args, **kwargs) return result # 逐层寻找函数对象 else: # 根对象为主引擎 obj = self.mainEngine # 逐层寻找对象属性 for name in nameTuple: obj = obj.__getattribute__(name) # 缓存结果 self.functionDict[nameTuple] = obj # 调用最终对象 result = obj(*args, **kwargs) return result #---------------------------------------------------------------------- def processEvent(self, event): """处理事件推送""" self.server.publish('', event) #---------------------------------------------------------------------- def stop(self): """停止""" self.server.stop()