def __init__(self): """Constructor""" # 记录今日日期 self.todayDate = datetime.now().strftime('%Y%m%d') # 创建事件引擎 self.eventEngine = EventEngine2() self.eventEngine.start() # 创建数据引擎 self.dataEngine = DataEngine(self, self.eventEngine) # MongoDB数据库相关 self.dbClient = None # MongoDB客户端对象 # 接口实例 self.gatewayDict = OrderedDict() self.gatewayDetailList = [] # 应用模块实例 self.appDict = OrderedDict() self.appDetailList = [] # 扩展模块 self.ctaEngine = CtaEngine(self, self.eventEngine) # cta策略运行模块 self.drEngine = DrEngine(self, self.eventEngine) # 数据记录模块 self.rmEngine = RmEngine(self, self.eventEngine) # 风险管理模块 self.connected_gw_name = u''
def __init__(self, client, eventEngine): """Constructor""" self.client = client self.eventEngine = eventEngine # 扩展模块 self.ctaEngine = CtaEngine(self, self.eventEngine) self.drEngine = DrEngine(self, self.eventEngine) self.rmEngine = RmEngine(self, self.eventEngine)
class ClientEngine(object): """客户端引擎,提供和MainEngine完全相同的API接口""" #---------------------------------------------------------------------- def __init__(self, client, eventEngine): """Constructor""" self.client = client self.eventEngine = eventEngine # 扩展模块 self.ctaEngine = CtaEngine(self, self.eventEngine) self.drEngine = DrEngine(self, self.eventEngine) self.rmEngine = RmEngine(self, self.eventEngine) #---------------------------------------------------------------------- def connect(self, gatewayName): """连接特定名称的接口""" self.client.connect(gatewayName) # ---------------------------------------------------------------------- def disconnect(self, gatewayName): """连接特定名称的接口""" self.client.disconnect(gatewayName) #---------------------------------------------------------------------- def subscribe(self, subscribeReq, gatewayName): """订阅特定接口的行情""" self.client.subscribe(subscribeReq, gatewayName) #---------------------------------------------------------------------- def sendOrder(self, orderReq, gatewayName): """对特定接口发单""" self.client.sendOrder(orderReq, gatewayName) #---------------------------------------------------------------------- def cancelOrder(self, cancelOrderReq, gatewayName): """对特定接口撤单""" self.client.cancelOrder(cancelOrderReq, gatewayName) #---------------------------------------------------------------------- def qryAccont(self, gatewayName): """查询特定接口的账户""" self.client.qryAccount(gatewayName) #---------------------------------------------------------------------- def qryPosition(self, gatewayName): """查询特定接口的持仓""" self.client.qryPosition(gatewayName) #---------------------------------------------------------------------- def exit(self): """退出程序前调用,保证正常退出""" # 停止事件引擎 self.eventEngine.stop() # 关闭客户端的推送数据接收 self.client.stop() # 停止数据记录引擎 self.drEngine.stop() #---------------------------------------------------------------------- def writeLog(self, content): """快速发出日志事件""" self.client.writeLog(content) #---------------------------------------------------------------------- def dbConnect(self): """连接MongoDB数据库""" self.client.dbConnect() #---------------------------------------------------------------------- def dbInsert(self, dbName, collectionName, d): """向MongoDB中插入数据,d是具体数据""" self.client.dbInsert(dbName, collectionName, d) #---------------------------------------------------------------------- def dbQuery(self, dbName, collectionName, d): """从MongoDB中读取数据,d是查询要求,返回的是数据库查询的数据列表""" return self.client.dbQuery(dbName, collectionName, d) #---------------------------------------------------------------------- def dbUpdate(self, dbName, collectionName, d, flt, upsert=False): """向MongoDB中更新数据,d是具体数据,flt是过滤条件,upsert代表若无是否要插入""" self.client.dbUpdate(dbName, collectionName, d, flt, upsert) #---------------------------------------------------------------------- def getContract(self, vtSymbol): """查询合约""" return self.client.getContract(vtSymbol) #---------------------------------------------------------------------- def getAllContracts(self): """查询所有合约(返回列表)""" return self.client.getAllContracts() #---------------------------------------------------------------------- def getOrder(self, vtOrderID): """查询委托""" return self.client.getOrder(vtOrderID) #---------------------------------------------------------------------- def getAllWorkingOrders(self): """查询所有的活跃的委托(返回列表)""" return self.client.getAllWorkingOrders() #---------------------------------------------------------------------- def getAllGatewayNames(self): """查询所有的接口名称""" return self.client.getAllGatewayNames() def getAccountInfo(self): """读取风控的账号与仓位数据 # Added by IncenseLee 仅支持一个账号。不支持多账号 以后支持跨市场套利才更新吧。 """ return self.rmEngine.getAccountInfo() def clearData(self): """清空数据引擎的数据""" self.dataEngine.clearData() self.ctaEngine.clearData() def saveData(self): self.ctaEngine.saveStrategyData()
class MainEngine(object): """主引擎""" #---------------------------------------------------------------------- def __init__(self): """Constructor""" # 记录今日日期 self.todayDate = datetime.now().strftime('%Y%m%d') # 创建事件引擎 self.eventEngine = EventEngine2() self.eventEngine.start() # 创建数据引擎 self.dataEngine = DataEngine(self, self.eventEngine) # MongoDB数据库相关 self.dbClient = None # MongoDB客户端对象 # 接口实例 self.gatewayDict = OrderedDict() self.gatewayDetailList = [] # 应用模块实例 self.appDict = OrderedDict() self.appDetailList = [] # 扩展模块 self.ctaEngine = CtaEngine(self, self.eventEngine) # cta策略运行模块 self.drEngine = DrEngine(self, self.eventEngine) # 数据记录模块 self.rmEngine = RmEngine(self, self.eventEngine) # 风险管理模块 self.connected_gw_name = u'' # ---------------------------------------------------------------------- def addGateway(self, gatewayModule, gateway_name=EMPTY_STRING): """添加底层接口""" # 是否使用指定的gateway_name if gateway_name == EMPTY_STRING: gatewayName = gatewayModule.gatewayName else: gatewayName = gateway_name # 创建接口实例 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) if gateway_name != self.connected_gw_name: self.connected_gw_name = gateway_name # ---------------------------------------------------------------------- def connect(self, gatewayName): """连接特定名称的接口""" if gatewayName in self.gatewayDict: gateway = self.gatewayDict[gatewayName] gateway.connect() if gatewayName != self.connected_gw_name: self.connected_gw_name = gatewayName # 接口连接后自动执行数据库连接的任务 self.dbConnect() return True else: self.writeLog(text.GATEWAY_NOT_EXIST.format(gateway=gatewayName)) return False def checkGatewayStatus(self, gatewayName): """check gateway connect status""" if gatewayName in self.gatewayDict: gateway = self.gatewayDict[gatewayName] return gateway.checkStatus() else: self.writeLog(text.GATEWAY_NOT_EXIST.format(gateway=gatewayName)) return False def qryStatus(self): """查询Status""" status_dict = OrderedDict() # gateway Status gw_status_dict = OrderedDict() for k, g in self.gatewayDict.items(): gw_status_dict[k] = g.checkStatus() status_dict['gateways'] = gw_status_dict # ctaEngine Status if self.ctaEngine: tick_dict, strategy_dict = self.ctaEngine.qryStatus() status_dict['ticks'] = tick_dict status_dict['strategies'] = strategy_dict event = vn_event(type_=EVENT_STATUS) event.dict_['data'] = status_dict self.eventEngine.put(event) return True # ---------------------------------------------------------------------- def subscribe(self, subscribeReq, gatewayName): """订阅特定接口的行情""" if gatewayName in self.gatewayDict: gateway = self.gatewayDict[gatewayName] gateway.subscribe(subscribeReq) else: if len(self.gatewayDict) > 0: for gateway in self.gatewayDict.values(): gateway.subscribe(subscribeReq) else: self.writeLog( text.GATEWAY_NOT_EXIST.format(gateway=gatewayName)) # ---------------------------------------------------------------------- def sendOrder(self, orderReq, gatewayName): """对特定接口发单""" # 如果风控检查失败则不发单 if not self.rmEngine.checkRisk(orderReq): self.writeCritical(u'风控检查不通过') return '' if gatewayName in self.gatewayDict: gateway = self.gatewayDict[gatewayName] return gateway.sendOrder(orderReq) else: self.writeLog(text.GATEWAY_NOT_EXIST.format(gateway=gatewayName)) # ---------------------------------------------------------------------- def cancelOrder(self, cancelOrderReq, gatewayName): """对特定接口撤单""" if gatewayName in self.gatewayDict: gateway = self.gatewayDict[gatewayName] gateway.cancelOrder(cancelOrderReq) else: self.writeLog(text.GATEWAY_NOT_EXIST.format(gateway=gatewayName)) # ---------------------------------------------------------------------- def qryAccount(self, gatewayName): """查询特定接口的账户""" if gatewayName in self.gatewayDict: gateway = self.gatewayDict[gatewayName] gateway.qryAccount() else: self.writeLog(text.GATEWAY_NOT_EXIST.format(gateway=gatewayName)) def getAccountInfo(self): """读取风控的账号与仓位数据 # Added by IncenseLee 仅支持一个账号。不支持多账号 以后支持跨市场套利才更新吧。 """ return self.rmEngine.getAccountInfo() # ---------------------------------------------------------------------- def qryPosition(self, gatewayName): """查询特定接口的持仓""" if gatewayName in self.gatewayDict: gateway = self.gatewayDict[gatewayName] gateway.qryPosition() else: self.writeLog(text.GATEWAY_NOT_EXIST.format(gateway=gatewayName)) # ---------------------------------------------------------------------- def exit(self): """退出程序前调用,保证正常退出""" # 安全关闭所有接口 for gateway in self.gatewayDict.values(): gateway.close() # 停止事件引擎 self.eventEngine.stop() # 停止数据记录引擎 self.drEngine.stop() # 保存数据引擎里的合约数据到硬盘 self.dataEngine.saveContracts() def disconnect(self, gateway_name=EMPTY_STRING): """断开底层gateway的连接""" try: # 只断开指定的gateway if gateway_name != EMPTY_STRING: if gateway_name in self.gatewayDict: gateway = self.gatewayDict[gateway_name] gateway.close() return else: self.writeLog(u'gateway接口不存在:%s' % gateway_name) # 断开所有的gateway for gateway in self.gatewayDict.values(): gateway.close() return True except Exception as ex: print u'vtEngine.disconnect Exception:{0} '.format(str(ex)) return False # ---------------------------------------------------------------------- def writeLog(self, content): """快速发出日志事件""" log = VtLogData() log.logContent = content event = vn_event(type_=EVENT_LOG) event.dict_['data'] = log self.eventEngine.put(event) # 写入本地log日志 logging.info(content) # ---------------------------------------------------------------------- def writeError(self, content): """快速发出错误日志事件""" log = VtErrorData() log.errorMsg = content event = vn_event(type_=EVENT_ERROR) event.dict_['data'] = log self.eventEngine.put(event) # 写入本地log日志 logging.error(content) # ---------------------------------------------------------------------- def writeWarning(self, content): """快速发出告警日志事件""" log = VtLogData() log.logContent = content event = vn_event(type_=EVENT_WARNING) event.dict_['data'] = log self.eventEngine.put(event) # 写入本地log日志 logging.warning(content) # 发出邮件 try: sendmail(subject=u'{0} Warning'.format(self.connected_gw_name), msgcontent=content) except: pass # ---------------------------------------------------------------------- def writeNotification(self, content): """快速发出通知日志事件""" log = VtLogData() log.logContent = content event = vn_event(type_=EVENT_NOTIFICATION) event.dict_['data'] = log self.eventEngine.put(event) # 发出邮件 try: sendmail(subject=u'{0} Notification'.format( self.connected_gw_name), msgcontent=content) except: pass # ---------------------------------------------------------------------- def writeCritical(self, content): """快速发出严重错误日志事件""" log = VtLogData() log.logContent = content event = vn_event(type_=EVENT_CRITICAL) event.dict_['data'] = log self.eventEngine.put(event) # 写入本地log日志 logging.critical(content) # 发出邮件 try: sendmail(subject=u'{0} Critical'.format(self.connected_gw_name), msgcontent=content) except: pass # ---------------------------------------------------------------------- def dbConnect(self): """连接MongoDB数据库""" if not self.dbClient: # 读取MongoDB的设置 host, port, logging = loadMongoSetting() try: # 设置MongoDB操作的超时时间为0.5秒 self.dbClient = MongoClient(host, port, connectTimeoutMS=500) # 调用server_info查询服务器状态,防止服务器异常并未连接成功 self.dbClient.server_info() self.writeLog(text.DATABASE_CONNECTING_COMPLETED) # 如果启动日志记录,则注册日志事件监听函数 if logging: self.eventEngine.register(EVENT_LOG, self.dbLogging) except ConnectionFailure: self.writeError(text.DATABASE_CONNECTING_FAILED) # ---------------------------------------------------------------------- def dbInsert(self, dbName, collectionName, d): """向MongoDB中插入数据,d是具体数据""" if self.dbClient: db = self.dbClient[dbName] collection = db[collectionName] collection.insert_one(d) else: self.writeLog(text.DATA_INSERT_FAILED) # ---------------------------------------------------------------------- def dbQuery(self, dbName, collectionName, d): """从MongoDB中读取数据,d是查询要求,返回的是数据库查询的指针""" if self.dbClient: db = self.dbClient[dbName] collection = db[collectionName] cursor = collection.find(d) if cursor: return list(cursor) else: return [] else: self.writeLog(text.DATA_QUERY_FAILED) return [] #---------------------------------------------------------------------- def dbUpdate(self, dbName, collectionName, d, flt, upsert=False): """向MongoDB中更新数据,d是具体数据,flt是过滤条件,upsert代表若无是否要插入""" if self.dbClient: db = self.dbClient[dbName] collection = db[collectionName] collection.replace_one(flt, d, upsert) else: self.writeLog(text.DATA_UPDATE_FAILED) #---------------------------------------------------------------------- def dbLogging(self, event): """向MongoDB中插入日志""" log = event.dict_['data'] d = { 'content': log.logContent, 'time': log.logTime, 'gateway': log.gatewayName } self.dbInsert(LOG_DB_NAME, self.todayDate, d) #---------------------------------------------------------------------- def getContract(self, vtSymbol): """查询合约""" return self.dataEngine.getContract(vtSymbol) #---------------------------------------------------------------------- def getAllContracts(self): """查询所有合约(返回列表)""" return self.dataEngine.getAllContracts() #---------------------------------------------------------------------- def getOrder(self, vtOrderID): """查询委托""" return self.dataEngine.getOrder(vtOrderID) #---------------------------------------------------------------------- def getAllWorkingOrders(self): """查询所有的活跃的委托(返回列表)""" return self.dataEngine.getAllWorkingOrders() # ---------------------------------------------------------------------- def getAllGatewayNames(self): """查询引擎中所有可用接口的名称""" return self.gatewayDict.keys() def clearData(self): """清空数据引擎的数据""" self.dataEngine.clearData() self.ctaEngine.clearData() def saveData(self): self.ctaEngine.saveStrategyData() def initStrategy(self, name, force=False): if not self.ctaEngine: self.writeError(u'Cta Engine not started') return self.ctaEngine.initStrategy(name=name, force=force) self.qryStatus() def startStrategy(self, name): if not self.ctaEngine: self.writeError(u'Cta Engine not started') return self.ctaEngine.startStrategy(name=name) self.qryStatus() def stopStrategy(self, name): if not self.ctaEngine: self.writeError(u'Cta Engine not started') return self.ctaEngine.stopStrategy(name=name) self.qryStatus()