class Sender(object): def __init__(self, eventEngine): self._engine = eventEngine self._logger = Logger() # Account Balance 事件 def sendListenAccountBalanceEvent(self, exchange): try: # 构造事件对象 TEMP_EVENT = json.loads( LISTEN_ACCOUNT_BALANCE_EVENT.substitute( id=self._engine.getEventID(), timeStamp=utcnow_timestamp(), exchange=exchange)) event = Event(TEMP_EVENT) self._logger.debug( "src.core.engine.sender.Sender.sendListenAccountBalanceEvent: " + json.dumps(TEMP_EVENT)) # 发送事件 self._engine.sendEvent(event) # 返回参数 return event.id except Exception as err: errStr = "src.core.engine.sender.Sender.sendListenAccountBalanceEvent: %s" % EngineException( err) raise EngineException(errStr) # Account Withdraw 事件 def sendListenAccountWithdrawEvent(self, exchange, asset): try: # 构造事件对象 TEMP_EVENT = json.loads( LISTEN_ACCOUNT_WITHDRAW_EVENT.substitute( id=self._engine.getEventID(), timeStamp=utcnow_timestamp(), exchange=exchange, asset=asset)) event = Event(TEMP_EVENT) self._logger.debug( "src.core.engine.sender.Sender.sendListenAccountWithdrawEvent: " + json.dumps(TEMP_EVENT)) # 发送事件 self._engine.sendEvent(event) # 返回参数 return event.id except Exception as err: errStr = "src.core.engine.sender.Sender.sendListenAccountWithdrawEvent: %s" % EngineException( err) raise EngineException(errStr) # Market Depth 事件 def sendListenMarketDepthEvent(self, exchange, fSymbol, tSymbol, limit=100): try: # 构造事件对象 TEMP_EVENT = json.loads( LISTEN_MARKET_DEPTH_EVENT.substitute( id=self._engine.getEventID(), timeStamp=utcnow_timestamp(), exchange=exchange, fSymbol=fSymbol, tSymbol=tSymbol, limit=limit)) event = Event(TEMP_EVENT) self._logger.debug( "src.core.engine.sender.Sender.sendListenMarketDepthEvent: " + json.dumps(TEMP_EVENT)) # 发送事件 self._engine.sendEvent(event) # 返回参数 return event.id except Exception as err: errStr = "src.core.engine.sender.Sender.sendListenMarketDepthEvent: %s" % EngineException( err) raise EngineException(errStr) # Market Kline 事件 def sendListenMarketKlineEvent(self, exchange, fSymbol, tSymbol, interval, start, end): try: # 构造事件对象 TEMP_EVENT = json.loads( LISTEN_MARKET_KLINE_EVENT.substitute( id=self._engine.getEventID(), timeStamp=utcnow_timestamp(), exchange=exchange, fSymbol=fSymbol, tSymbol=tSymbol, interval=interval, start=start, end=end)) event = Event(TEMP_EVENT) self._logger.debug( "src.core.engine.sender.Sender.sendListenMarketKlineEvent: " + json.dumps(TEMP_EVENT)) # 发送事件 self._engine.sendEvent(event) # 返回参数 return event.id except Exception as err: errStr = "src.core.engine.sender.Sender.sendListenMarketKlineEvent: %s" % EngineException( err) raise EngineException(errStr) # Market ticker 事件 def sendListenMarketTickerEvent(self, exchange, fSymbol, tSymbol, aggDepth): try: # 构造事件对象 TEMP_EVENT = json.loads( LISTEN_MARKET_TICKER_EVENT.substitute( id=self._engine.getEventID(), timeStamp=utcnow_timestamp(), exchange=exchange, fSymbol=fSymbol, tSymbol=tSymbol, aggDepth=aggDepth)) event = Event(TEMP_EVENT) self._logger.debug( "src.core.engine.sender.Sender.sendListenMarketTickerEvent: " + json.dumps(TEMP_EVENT)) # 发送事件 self._engine.sendEvent(event) # 返回参数 return event.id except Exception as err: errStr = "src.core.engine.sender.Sender.sendListenMarketTickerEvent: %s" % EngineException( err) raise EngineException(errStr) # Judge 事件 def sendJudgeMarketDepthEvent(self, args): try: # 构造事件对象 TEMP_EVENT = json.loads( JUDGE_MARKET_DEPTH_EVENT.substitute( id=self._engine.getEventID(), timeStamp=utcnow_timestamp(), args="")) event = Event(TEMP_EVENT) self._logger.debug( "src.core.engine.sender.Sender.sendJudgeMarketDepthEvent: " + json.dumps(TEMP_EVENT)) # 发送事件 pass except Exception as err: errStr = "src.core.engine.sender.Sender.sendJudgeMarketDepthEvent: %s" % EngineException( err) raise EngineException(errStr) def sendJudgeMarketKlineEvent(self, args): try: # 构造事件对象 TEMP_EVENT = json.loads( JUDGE_MARKET_KLINE_EVENT.substitute( id=self._engine.getEventID(), timeStamp=utcnow_timestamp(), args="")) event = Event(TEMP_EVENT) self._logger.debug( "src.core.engine.sender.Sender.sendJudgeMarketKlineEvent: " + json.dumps(TEMP_EVENT)) # 发送事件 pass except Exception as err: errStr = "src.core.engine.sender.Sender.sendJudgeMarketKlineEvent: %s" % EngineException( err) raise EngineException(errStr) def sendJudgeMarketTickerEvent(self, exchange, types): try: # 构造事件对象 TEMP_EVENT = json.loads( JUDGE_MARKET_TICKER_EVENT.substitute( id=self._engine.getEventID(), timeStamp=utcnow_timestamp(), exchange=exchange, types=types)) event = Event(TEMP_EVENT) self._logger.debug( "src.core.engine.sender.Sender.sendJudgeMarketTickerEvent: " + json.dumps(TEMP_EVENT)) # 发送事件 self._engine.sendEvent(event) # 返回参数 return event.id except Exception as err: errStr = "src.core.engine.sender.Sender.sendJudgeMarketTickerEvent: %s" % EngineException( err) raise EngineException(errStr) # Backtest 事件 def sendBacktestHistoryCreatEvent(self, exchange, signals, timeout): try: # 构造事件对象 TEMP_EVENT = json.loads( BACKTEST_HISTORY_CREAT_EVENT.substitute( id=self._engine.getEventID(), timeStamp=utcnow_timestamp(), exchange=exchange, signals=signals, timeout=timeout)) event = Event(TEMP_EVENT) self._logger.debug( "src.core.engine.sender.Sender.sendBacktestHistoryCreatEvent: " + json.dumps(TEMP_EVENT)) # 发送事件 self._engine.sendEvent(event) # 返回参数 return event.id except Exception as err: errStr = "src.core.engine.sender.Sender.sendBacktestHistoryCreatEvent: %s" % EngineException( err) raise EngineException(errStr) # Order 事件 def sendOrderHistorySyncEvent(self, exchange, fSymbol, tSymbol, limit, ratio): try: # 构造事件对象 TEMP_EVENT = json.loads( ORDER_HISTORY_SYNC_EVENT.substitute( id=self._engine.getEventID(), timeStamp=utcnow_timestamp(), exchange=exchange, fSymbol=fSymbol, tSymbol=tSymbol, limit=limit, ratio=ratio)) event = Event(TEMP_EVENT) self._logger.debug( "src.core.engine.sender.Sender.sendOrderHistorySyncEvent: " + json.dumps(TEMP_EVENT)) # 发送事件 self._engine.sendEvent(event) # 返回参数 return event.id except Exception as err: errStr = "src.core.engine.sender.Sender.sendOrderHistorySyncEvent: %s" % EngineException( err) raise EngineException(errStr) def sendOrderHistoryCreatEvent(self, exchange, signals, timeout): try: # 构造事件对象 TEMP_EVENT = json.loads( BACKTEST_HISTORY_CREAT_EVENT.substitute( id=self._engine.getEventID(), timeStamp=utcnow_timestamp(), exchange=exchange, signals=signals, timeout=timeout)) event = Event(TEMP_EVENT) self._logger.debug( "src.core.engine.sender.Sender.sendOrderHistoryCreatEvent: " + json.dumps(TEMP_EVENT)) # 发送事件 self._engine.sendEvent(event) # 返回参数 return event.id except Exception as err: errStr = "src.core.engine.sender.Sender.sendOrderHistoryCreatEvent: %s" % EngineException( err) raise EngineException(errStr) # Statistic 事件 def sendStatiscJudgeEvent(self, exchange, types): try: # 构造事件对象 TEMP_EVENT = json.loads( STATISTIC_JUDGE_EVENT.substitute(id=self._engine.getEventID(), timeStamp=utcnow_timestamp(), exchange=exchange, types=types)) event = Event(TEMP_EVENT) self._logger.debug( "src.core.engine.sender.Sender.sendStatiscJudgeEvent: " + json.dumps(TEMP_EVENT)) # 发送事件 self._engine.sendEvent(event) # 返回参数 return event.id except Exception as err: errStr = "src.core.engine.sender.Sender.sendStatiscJudgeEvent: %s" % EngineException( err) raise EngineException(errStr) def sendStatiscBacktestEvent(self, signals): try: for signal in signals: signal['status_assets'] = json_escape(signal['status_assets']) # 构造事件对象 TEMP_EVENT = json.loads( STATISTIC_BACKTEST_EVENT.substitute( id=self._engine.getEventID(), timeStamp=utcnow_timestamp(), signals=signals)) event = Event(TEMP_EVENT) self._logger.debug( "src.core.engine.sender.Sender.sendStatiscBacktestEvent: " + json.dumps(TEMP_EVENT)) # 发送事件 self._engine.sendEvent(event) # 返回参数 return event.id except Exception as err: errStr = "src.core.engine.sender.Sender.sendStatiscBacktestEvent: %s" % EngineException( err) raise EngineException(errStr) def sendStatiscOrderEvent(self, signals): try: for signal in signals: signal['status_assets'] = json_escape(signal['status_assets']) # 构造事件对象 TEMP_EVENT = json.loads( STATISTIC_ORDER_EVENT.substitute(id=self._engine.getEventID(), timeStamp=utcnow_timestamp(), signals=signals)) event = Event(TEMP_EVENT) self._logger.debug( "src.core.engine.sender.Sender.sendStatiscOrderEvent: " + json.dumps(TEMP_EVENT)) # 发送事件 self._engine.sendEvent(event) # 返回参数 return event.id except Exception as err: errStr = "src.core.engine.sender.Sender.sendStatiscOrderEvent: %s" % EngineException( err) raise EngineException(errStr)
class EventEngine(object): # 初始化事件事件驱动引擎 def __init__(self): # Config init self.__epoch = Config()._Engine_epoch self.__maxProcess = Config()._Engine_maxProcess # 保存事件列表 按优先级不同分别保存 self.__lowEnventQueue = Queue() self.__mediumEventQueue = Queue() self.__highEventQueue = Queue() # 引擎开关 self.__active = Value('b', False) # 事件处理字典{'event1': [handler1,handler2] , 'event2':[handler3, ...,handler4]} self.__handlers = {} # 保存事件处理进程池 控制最大进程数量 以及关闭引擎时处理已启动进程 self.__processPool = Manager().list() # 保存已执行事件处理状态 self.__status = Status() # 事件引擎主进程 self.__mainProcess = Process(target=self.__run) # logger self.__logger = Logger() # 执行事件循环 def __run(self): self.__logger.debug( "src.core.engine.engine.EventEngine.__mainProcess.__run") try: while self.__active.value: # 执行 Epoch time.sleep(self.__epoch) # 控制最大进程数量 if self.getActiveEventNum() > int(self.__maxProcess): self.__logger.warn( "src.core.engine.engine.EventEngine.__mainProcess.__run.__eventQueue: Too Many" ) else: # 按优先级 获取队列中的事件 超时1秒 event = None if not self.__highEventQueue.empty(): self.__logger.debug( "src.core.engine.engine.EventEngine.__mainProcess.__run.__highEventQueue" ) event = self.__highEventQueue.get(block=False) while utcnow_timestamp( ) - event.timeStamp > HIGH_PRIORITY_EVENT_TIMEOUT: self.__status.delEventStatus(event) if not self.__highEventQueue.empty(): self.__logger.error( "src.core.engine.engine.EventEngine.__mainProcess.__run.__highEventQueue TIMEOUT: {id=%s, type=%s, priority=%s, timeStamp=%s, args=%s}" % (event.id, event.type, event.priority, event.timeStamp, event.args)) event = self.__highEventQueue.get(block=False) else: event = None break if not self.__mediumEventQueue.empty() and event == None: self.__logger.debug( "src.core.engine.engine.EventEngine.__mainProcess.__run.__mediumEventQueue" ) event = self.__mediumEventQueue.get(block=False) while utcnow_timestamp( ) - event.timeStamp > MEDIUM_PRIORITY_EVENT_TIMEOUT: self.__status.delEventStatus(event) if not self.__mediumEventQueue.empty(): self.__logger.error( "src.core.engine.engine.EventEngine.__mainProcess.__run.__mediumEventQueue TIMEOUT: {id=%s, type=%s, priority=%s, timeStamp=%s, args=%s}" % (event.id, event.type, event.priority, event.timeStamp, event.args)) event = self.__mediumEventQueue.get( block=False) else: event = None break if not self.__lowEnventQueue.empty() and event == None: self.__logger.debug( "src.core.engine.engine.EventEngine.__mainProcess.__run.__lowEnventQueue" ) event = self.__lowEnventQueue.get(block=False) while utcnow_timestamp( ) - event.timeStamp > LOW_PRIORITY_EVENT_TIMEOUT: self.__status.delEventStatus(event) if not self.__lowEnventQueue.empty(): self.__logger.error( "src.core.engine.engine.EventEngine.__mainProcess.__run.__lowEnventQueue TIMEOUT: {id=%s, type=%s, priority=%s, timeStamp=%s, args=%s}" % (event.id, event.type, event.priority, event.timeStamp, event.args)) event = self.__lowEnventQueue.get(block=False) else: event = None break # 事件队列非空 if not event == None: # 执行事件 self.__logger.debug( "src.core.engine.engine.EventEngine.__mainProcess.__run.__eventQueue: {id=%s, type=%s, priority=%s, timeStamp=%s, args=%s}" % (event.id, event.type, event.priority, event.timeStamp, event.args)) self.__process(event) else: self.__logger.debug( "src.core.engine.engine.EventEngine.__mainProcess.__run.__eventQueue: empty" ) # 定期清理进程池 if len(self.__processPool) > self.__maxProcess: for (_id, _pid) in self.__processPool: if not psutil.pid_exists(_pid): self.__processPool.remove((_id, _pid)) # break out while # 终止所有事件处理进程 for (_id, _pid) in self.__processPool: if psutil.pid_exists(_pid): _p = psutil.Process(_pid) _p.terminate() self.__processPool.remove((_id, _pid)) except Exception as err: errStr = "src.core.engine.engine.EventEngine.__mainProcess.__run: exception err=%s" % EngineException( err) raise EngineException(errStr) # 执行事件 def __process(self, event): self.__logger.debug( "src.core.engine.engine.EventEngine.__mainProcess.__run.__process: {id=%s, type=%s, priority=%s, timeStamp=%s, args=%s}" % (event.id, event.type, event.priority, event.timeStamp, event.args)) try: if event.type in self.__handlers: for handler in self.__handlers[event.type]: # 开一个进程去异步处理 p = Process( target=handler, args=(event, self.__status.delEventStatus)) # 运行进程 p.start() # 同步抄送至事件运行状态表格里 self.__status.addEventStatus(event.id) # 保存到进程池 self.__processPool.append((event.id, p.pid)) except Exception as err: errStr = "src.core.engine.engine.EventEngine.__mainProcess.__run.__process: {id=%s, type=%s, priority=%s, timeStamp=%s, args=%s}, exception err=%s" % ( event.id, event.type, event.priority, event.timeStamp, event.args, EngineException(err)) raise EngineException(errStr) # 开启事件引擎 def start(self): self.__logger.debug("src.core.engine.engine.EventEngine.start") try: if not self.__active.value: self.__active.value = True # 开启事件引擎主进程 self.__mainProcess.start() except Exception as err: errStr = "src.core.engine.engine.EventEngine.start: exception err=%s" % EngineException( err) raise EngineException(errStr) # 暂停事件引擎 def stop(self): self.__logger.debug("src.core.engine.engine.EventEngine.stop") try: if self.__active.value: # 将事件管理器设为停止 self.__active.value = False # 等待事件引擎主进程退出 self.__mainProcess.join() except Exception as err: errStr = "src.core.engine.engine.EventEngine.stop: exception err=%s" % EngineException( err) raise EngineException(errStr) # 终止事件引擎 def terminate(self): self.__logger.debug("src.core.engine.engine.EventEngine.terminate") try: # 将事件管理器设为停止 self.__active.value = False # 引擎主进程直接退出 self.__mainProcess.terminate() except Exception as err: errStr = "src.core.engine.engine.EventEngine.terminate: exception err=%s" % EngineException( err) raise EngineException(errStr) # 注册事件 def register(self, type, handler): self.__logger.debug( "src.core.engine.engine.EventEngine.register: {type:%s, handler:%s}" % (type, handler)) # 尝试获取该事件类型对应的处理函数列表,若无则创建 try: try: handlerList = self.__handlers[type] except KeyError: handlerList = [] # 若要注册的处理器不在该事件的处理器列表中,则注册该事件 if handler not in handlerList: handlerList.append(handler) self.__handlers[type] = handlerList except (KeyError, Exception) as err: errStr = "src.core.engine.engine.EventEngine.register: {type:%s, handler:%s}, exception err=%s" % (type, handler, EngineException( err)) raise EngineException(errStr) # 注销事件 def unregister(self, type, handler): self.__logger.debug( "src.core.engine.engine.EventEngine.unregister: {type:%s, handler:%s}" % (type, handler)) # 尝试获取该事件类型对应的处理函数列表,若无则忽略该次注销请求 try: handlerList = self.__handlers[type] # 如果该函数存在于列表中,则移除 if handler in handlerList: handlerList.remove(handler) # 如果函数列表为空,则从引擎中移除该事件类型 if not handlerList: del self.__handlers[type] except (KeyError, Exception) as err: errStr = "src.core.engine.engine.EventEngine.unregister: {type:%s, handler:%s}, exception err=%s" % ( type, handler, EngineException(err)) raise EngineException(errStr) # 发送事件 def sendEvent(self, event): self.__logger.debug( "src.core.engine.engine.EventEngine.sendEvent: {id=%s, type=%s, priority=%s, timeStamp=%s, args=%s}" % ( event.id, event.type, event.priority, event.timeStamp, event.args)) try: # 发送事件 像队列里存入事件 if event.priority == LOW_PRIORITY_EVENT: self.__lowEnventQueue.put(event) if event.priority == MEDIUM_PRIORITY_EVENT: self.__mediumEventQueue.put(event) if event.priority == HIGH_PRIORITY_EVENT: self.__highEventQueue.put(event) except Exception as err: errStr = "src.core.engine.engine.EventEngine.sendEvent: {id=%s, type=%s, priority=%s, timeStamp=%s, args=%s}, exception err=%s" % ( event.id, event.type, event.priority, event.timeStamp, event.args, EngineException(err)) raise EngineException(errStr) # kill 事件 def killEvent(self, id): self.__logger.debug( "src.core.engine.engine.EventEngine.killEvent: {id=%s}" % id) try: # 查询事件状态 status = self.getEventStatus(id) # 删除事件进程 if not status == DONE_STATUS_EVENT: for (_id, _pid) in self.__processPool: if _id == id: if psutil.pid_exists(_pid): _p = psutil.Process(_pid) _p.terminate() # 更新事件状态 self.__processPool.remove((_id, _pid)) self.__status.delEventStatus(id) # 确认事件状态 status = self.getEventStatus(id) if not status == DONE_STATUS_EVENT: return False return True except Exception as err: errStr = "src.core.engine.engine.EventEngine.killEvent: {id=%s}, exception err=%s" % ( id, EngineException(err)) raise EngineException(errStr) # 获取事件ID def getEventID(self): try: id = self.__status.calcEventID() self.__logger.debug( "src.core.engine.engine.EventEngine.getEventID: {id=%s}" % id) return id except Exception as err: errStr = "src.core.engine.engine.EventEngine.getEventID: exception err=%s" % EngineException( err) raise EngineException(errStr) def getEventStatus(self, id): try: status = QUEUE_STATUS_EVENT res = self.__status.getActiveStatusTable() if not res == []: if id in res: status = ACTIVE_STATUS_EVENT res = self.__status.getDoneStatusTable() if not res == []: if id in res: status = DONE_STATUS_EVENT # 进程池二次确认 if status == ACTIVE_STATUS_EVENT: for (_id, _pid) in self.__processPool: if _id == id: if not psutil.pid_exists(_pid): status = DONE_STATUS_EVENT self.__status.delEventStatus(_id) self.__processPool.remove((_id, _pid)) self.__logger.debug( "src.core.engine.engine.EventEngine.getEventStatus: {id=%s, status=%s}" % (id, status)) return status except Exception as err: errStr = "src.core.engine.engine.EventEngine.getEventStatus: exception err=%s" % EngineException( err) raise EngineException(errStr) def getActiveEventNum(self): try: res = self.__status.calcActiveEventNum() self.__logger.debug( "src.core.engine.engine.EventEngine.getActiveEventNum: {res=%s}" % res) return res except Exception as err: errStr = "src.core.engine.engine.EventEngine.getActiveEventNum: exception err=%s" % EngineException( err) raise EngineException(errStr) def getActiveEventTable(self): try: res = self.__status.getActiveStatusTable() self.__logger.debug( "src.core.engine.engine.EventEngine.getActiveEventTable: {res=%s}" % res) return res except Exception as err: errStr = "src.core.engine.engine.EventEngine.getActiveEventTable: exception err=%s" % EngineException( err) raise EngineException(errStr) def getDoneEventTable(self): try: res = self.__status.getDoneStatusTable() self.__logger.debug( "src.core.engine.engine.EventEngine.getDoneEventTable: {res=%s}" % res) return res except Exception as err: errStr = "src.core.engine.engine.EventEngine.getDoneEventTable: exception err=%s" % EngineException( err) raise EngineException(errStr)
class Status(object): def __init__(self): # Status ID self._id = Value('i', 0) self._activeStatus = Manager().list() self._doneStatus = Manager().list() self._cachesize = Config()._Engine_cacheSize # logger self._logger = Logger() def getActiveStatusTable(self): self._logger.debug( "src.core.engine.status.Status.getActiveStatusTable") try: return self._activeStatus except Exception as err: raise (EngineException(err)) def getDoneStatusTable(self): self._logger.debug("src.core.engine.status.Status.getDoneStatusTable") try: return self._doneStatus except Exception as err: raise (EngineException(err)) def calcEventID(self): self._logger.debug("src.core.engine.status.Status.calcEventID") try: self._id.value = self._id.value + 1 return self._id.value except Exception as err: raise (EngineException(err)) def calcActiveEventNum(self): self._logger.debug("src.core.engine.status.Status.calcActiveEventNum") try: num = len(self._activeStatus) return num except Exception as err: raise (EngineException(err)) def addEventStatus(self, id): self._logger.debug( "src.core.engine.status.Status.addEventStatus: {id=%s}" % id) try: if id not in self._activeStatus: self._activeStatus.append(id) except Exception as err: raise (EngineException(err)) def delEventStatus(self, id): self._logger.debug( "src.core.engine.status.Status.delEventStatus: {id=%s}" % id) try: if id in self._activeStatus: self._activeStatus.remove(id) if id not in self._doneStatus: if len(self._doneStatus) < self._cachesize: self._doneStatus.append(id) else: self._doneStatus.pop(0) self._doneStatus.append(id) except Exception as err: raise (EngineException(err))
# -*- coding: utf-8 -*- import os import sys sys.path.append(os.getcwd()) from src.core.util.log import Logger logger = Logger() # Begin Test if __name__ == '__main__': # 1. unit test for test_coin logger.debug("1. unit testing... python3 tests/test_coin.py") os.system("python3 tests/test_coin.py") # 2. unit test for test_db logger.debug("2. unit testing... python3 tests/test_db.py") os.system("python3 tests/test_db.py") # 3. integration test for test_engine logger.debug("3. intergration testing... python3 tests/test_engine.py") os.system("python3 tests/test_engine.py") # # 4. system test for test_router logger.debug("4. system testing... python3 tests/test_router.py") os.system("python3 tests/test_router.py") # # 5. system test for test_main logger.debug("5. system testing... python3 tests/test_main.py") os.system("python3 tests/test_main.py")
class Register(object): def __init__(self, eventEngine, handler): self._eventEngine = eventEngine self._handler = handler self._logger = Logger() # 事件 # listen event self.LISTEN_ACCOUNT_BALANCE_EVENT_TYPE = json.loads( LISTEN_ACCOUNT_BALANCE_EVENT.substitute())["type"] self.LISTEN_ACCOUNT_WITHDRAW_EVENT_TYPE = json.loads( LISTEN_ACCOUNT_WITHDRAW_EVENT.substitute())["type"] self.LISTEN_MARKET_KLINE_EVENT_TYPE = json.loads( LISTEN_MARKET_KLINE_EVENT.substitute())["type"] self.LISTEN_MARKET_TICKER_EVENT_TYPE = json.loads( LISTEN_MARKET_TICKER_EVENT.substitute())["type"] self.LISTEN_MARKET_DEPTH_EVENT_TYPE = json.loads( LISTEN_MARKET_DEPTH_EVENT.substitute())["type"] # judge event self.JUDGE_MARKET_DEPTH_EVENT_TYPE = json.loads( JUDGE_MARKET_DEPTH_EVENT.substitute())["type"] self.JUDGE_MARKET_KLINE_EVENT_TYPE = json.loads( JUDGE_MARKET_KLINE_EVENT.substitute())["type"] self.JUDGE_MARKET_TICKER_EVENT_TYPE = json.loads( JUDGE_MARKET_TICKER_EVENT.substitute())["type"] # backtest event self.BACKTEST_HISTORY_CREAT_EVENT_TYPE = json.loads( BACKTEST_HISTORY_CREAT_EVENT.substitute())["type"] # order event self.ORDER_HISTORY_SYNC_EVENT_TYPE = json.loads( ORDER_HISTORY_SYNC_EVENT.substitute())["type"] self.ORDER_HISTORY_CREAT_EVENT_TYPE = json.loads( ORDER_HISTORY_CREAT_EVENT.substitute())["type"] # statistic event self.STATISTIC_JUDGE_EVENT_TYPE = json.loads( STATISTIC_JUDGE_EVENT.substitute())["type"] self.STATISTIC_BACKTEST_EVENT_TYPE = json.loads( STATISTIC_BACKTEST_EVENT.substitute())["type"] self.STATISTIC_ORDER_EVENT_TYPE = json.loads( STATISTIC_ORDER_EVENT.substitute())["type"] # handler # listen handler self.LISTEN_ACCOUNT_BALANCE_EVENT_HANDLER = self._handler.handleListenAccountBalanceEvent self.LISTEN_ACCOUNT_WITHDRAW_EVENT_HANDLER = self._handler.handleListenAccountWithdrawEvent self.LISTEN_MARKET_KLINE_EVENT_HANDLER = self._handler.handleListenMarketKlineEvent self.LISTEN_MARKET_TICKER_EVENT_HANDLER = self._handler.handleListenMarketTickerEvent self.LISTEN_MARKET_DEPTH_EVENT_HANDLER = self._handler.handleListenMarketDepthEvent # judge handler self.JUDGE_MARKET_DEPTH_EVENT_HANDLER = self._handler.handleJudgeMarketDepthEvent self.JUDGE_MARKET_KLINE_EVENT_HANDLER = self._handler.handleJudgeMarketKlineEvent self.JUDGE_MARKET_TICKER_EVENT_HANDLER = self._handler.handleJudgeMarketTickerEvent # backtest handler self.BACKTEST_HISTORY_CREAT_EVENT_HANDLER = self._handler.handleBacktestHistoryCreatEvent # order handler self.ORDER_HISTORY_SYNC_EVENT_HANDLER = self._handler.handleOrderHistorySyncEvent self.ORDER_HISTORY_CREAT_EVENT_HANDLER = self._handler.handleOrderHistoryCreatEvent # statistic handler self.STATISTIC_JUDGE_EVENT_HANDLER = self._handler.handleStatisticJudgeEvent self.STATISTIC_BACKTEST_EVENT_HANDLER = self._handler.handleStatisticBacktestEvent self.STATISTIC_ORDER_EVENT_HANDLER = self._handler.handleStatisticOrderEvent def register(self): self._logger.debug("src.core.engine.register.Register.register") try: # 注册事件 self._eventEngine.register( self.LISTEN_ACCOUNT_BALANCE_EVENT_TYPE, self.LISTEN_ACCOUNT_BALANCE_EVENT_HANDLER) self._eventEngine.register( self.LISTEN_ACCOUNT_WITHDRAW_EVENT_TYPE, self.LISTEN_ACCOUNT_WITHDRAW_EVENT_HANDLER) self._eventEngine.register(self.LISTEN_MARKET_KLINE_EVENT_TYPE, self.LISTEN_MARKET_KLINE_EVENT_HANDLER) self._eventEngine.register(self.LISTEN_MARKET_TICKER_EVENT_TYPE, self.LISTEN_MARKET_TICKER_EVENT_HANDLER) self._eventEngine.register(self.LISTEN_MARKET_DEPTH_EVENT_TYPE, self.LISTEN_MARKET_DEPTH_EVENT_HANDLER) self._eventEngine.register(self.JUDGE_MARKET_DEPTH_EVENT_TYPE, self.JUDGE_MARKET_DEPTH_EVENT_HANDLER) self._eventEngine.register(self.JUDGE_MARKET_KLINE_EVENT_TYPE, self.JUDGE_MARKET_KLINE_EVENT_HANDLER) self._eventEngine.register(self.JUDGE_MARKET_TICKER_EVENT_TYPE, self.JUDGE_MARKET_TICKER_EVENT_HANDLER) self._eventEngine.register( self.BACKTEST_HISTORY_CREAT_EVENT_TYPE, self.BACKTEST_HISTORY_CREAT_EVENT_HANDLER) self._eventEngine.register(self.ORDER_HISTORY_SYNC_EVENT_TYPE, self.ORDER_HISTORY_SYNC_EVENT_HANDLER) self._eventEngine.register(self.ORDER_HISTORY_CREAT_EVENT_TYPE, self.ORDER_HISTORY_CREAT_EVENT_HANDLER) self._eventEngine.register(self.STATISTIC_JUDGE_EVENT_TYPE, self.STATISTIC_JUDGE_EVENT_HANDLER) self._eventEngine.register(self.STATISTIC_BACKTEST_EVENT_TYPE, self.STATISTIC_BACKTEST_EVENT_HANDLER) self._eventEngine.register(self.STATISTIC_ORDER_EVENT_TYPE, self.STATISTIC_ORDER_EVENT_HANDLER) except Exception as err: errStr = "src.core.engine.register.Register.register: %s" % EngineException( err) self._logger.error(errStr) raise EngineException(err) def unregister(self): self._logger.debug("src.core.engine.register.Register.unregister") try: # 注销事件 self._eventEngine.unregister( self.LISTEN_ACCOUNT_BALANCE_EVENT_TYPE, self.LISTEN_ACCOUNT_BALANCE_EVENT_HANDLER) self._eventEngine.unregister( self.LISTEN_ACCOUNT_WITHDRAW_EVENT_TYPE, self.LISTEN_ACCOUNT_WITHDRAW_EVENT_HANDLER) self._eventEngine.unregister( self.LISTEN_MARKET_KLINE_EVENT_TYPE, self.LISTEN_MARKET_KLINE_EVENT_HANDLER) self._eventEngine.unregister( self.LISTEN_MARKET_TICKER_EVENT_TYPE, self.LISTEN_MARKET_TICKER_EVENT_HANDLER) self._eventEngine.unregister( self.LISTEN_MARKET_DEPTH_EVENT_TYPE, self.LISTEN_MARKET_DEPTH_EVENT_HANDLER) self._eventEngine.unregister(self.JUDGE_MARKET_KLINE_EVENT_TYPE, self.JUDGE_MARKET_KLINE_EVENT_HANDLER) self._eventEngine.unregister( self.BACKTEST_HISTORY_CREAT_EVENT_TYPE, self.BACKTEST_HISTORY_CREAT_EVENT_HANDLER) self._eventEngine.unregister(self.ORDER_HISTORY_SYNC_EVENT_TYPE, self.ORDER_HISTORY_SYNC_EVENT_HANDLER) self._eventEngine.unregister( self.ORDER_HISTORY_CREAT_EVENT_TYPE, self.ORDER_HISTORY_CREAT_EVENT_HANDLER) self._eventEngine.unregister(self.STATISTIC_JUDGE_EVENT_TYPE, self.STATISTIC_JUDGE_EVENT_HANDLER) self._eventEngine.unregister(self.STATISTIC_BACKTEST_EVENT_TYPE, self.STATISTIC_BACKTEST_EVENT_HANDLER) self._eventEngine.unregister(self.STATISTIC_ORDER_EVENT_TYPE, self.STATISTIC_ORDER_EVENT_HANDLER) except Exception as err: errStr = "src.core.engine.register.Register.unregister: %s" % EngineException( err) self._logger.error(errStr) raise EngineException(err)
class Handler(object): def __init__(self, eventEngine): self._engine = eventEngine self._logger = Logger() # Account Balance 事件 def handleListenAccountBalanceEvent(self, event, callback): # 接收事件 self._logger.debug( "src.core.engine.handler.Handler.handleListenAccountBalanceEvent: {id=%s, type=%s, priority=%s, timeStamp=%s, args=%s}" % (event.id, event.type, event.priority, event.timeStamp, event.args)) [exchange] = event.args exchange = str_to_list(exchange) try: db = DB() db.insertAccountBalanceHistory(exchange) except (DBException, CalcException, EngineException, Exception) as err: errStr = "src.core.engine.handler.Handler.handleListenAccountBalanceEvent: { type=%s, priority=%s, args=%s }, err=%s" % ( event.type, event.priority, event.args, err) self._logger.error(errStr) callback(event.id) # Account Withdraw 事件 def handleListenAccountWithdrawEvent(self, event, callback): # 接收事件 self._logger.debug( "src.core.engine.handler.Handler.handleListenAccountWithdrawEvent: {id=%s, type=%s, priority=%s, timeStamp=%s, args=%s}" % (event.id, event.type, event.priority, event.timeStamp, event.args)) [exchange, asset] = event.args exchange = str_to_list(exchange) try: db = DB() db.insertAccountWithdrawHistoryAsset(exchange, asset) except (DBException, CalcException, EngineException, Exception) as err: errStr = "src.core.engine.handler.Handler.handleListenAccountWithdrawEvent: { type=%s, priority=%s, args=%s }, err=%s" % ( event.type, event.priority, event.args, err) self._logger.error(errStr) callback(event.id) # Market Depth 事件 def handleListenMarketDepthEvent(self, event, callback): # 接收事件 self._logger.debug( "src.core.engine.handler.Handler.handleListenMarketDepthEvent: {id=%s, type=%s, priority=%s, timeStamp=%s, args=%s}" % (event.id, event.type, event.priority, event.timeStamp, event.args)) [exchange, fSymbol, tSymbol, limit] = event.args exchange = str_to_list(exchange) try: db = DB() db.insertMarketDepth(exchange, fSymbol, tSymbol, limit) except (DBException, CalcException, EngineException, Exception) as err: errStr = "src.core.engine.handler.Handler.handleListenDepthEvent { type=%s, priority=%s, args=%s }, err=%s" % ( event.type, event.priority, event.args, err) self._logger.error(errStr) callback(event.id) # Market Kline 事件 def handleListenMarketKlineEvent(self, event, callback): # 接收事件 self._logger.debug( "src.core.engine.handler.Handler.handleListenMarketKlineEvent: {id=%s, type=%s, priority=%s, timeStamp=%s, args=%s}" % (event.id, event.type, event.priority, event.timeStamp, event.args)) [exchange, fSymbol, tSymbol, interval, start, end] = event.args exchange = str_to_list(exchange) try: db = DB() db.insertMarketKline(exchange, fSymbol, tSymbol, interval, start, end) except (DBException, CalcException, EngineException, Exception) as err: errStr = "src.core.engine.handler.Handler.handleListenKlineEvent: { type=%s, priority=%s, args=%s }, err=%s" % ( event.type, event.priority, event.args, err) self._logger.error(errStr) callback(event.id) # Market ticker 事件 def handleListenMarketTickerEvent(self, event, callback): self._logger.debug( "src.core.engine.handler.Handler.handleListenMarketTickerEvent: {id=%s, type=%s, priority=%s, timeStamp=%s, args=%s}" % (event.id, event.type, event.priority, event.timeStamp, event.args)) # 接收事件 [exchange, fSymbol, tSymbol, aggDepth] = event.args exchange = str_to_list(exchange) try: db = DB() db.insertMarketTicker(exchange, fSymbol, tSymbol, aggDepth) except (DBException, CalcException, EngineException, Exception) as err: errStr = "src.core.engine.handler.Handler.handleListenTickerEvent: { type=%s, priority=%s, args=%s }, err=%s" % ( event.type, event.priority, event.args, err) self._logger.error(errStr) callback(event.id) # Judge 事件 def handleJudgeMarketDepthEvent(self, event, callback): self._logger.debug( "src.core.engine.handler.Handler.handleJudgeMarketDepthEvent: {id=%s, type=%s, priority=%s, timeStamp=%s, args=%s}" % (event.id, event.type, event.priority, event.timeStamp, event.args)) # 接收事件 [args] = event.args try: pass except (DBException, CalcException, EngineException, Exception) as err: errStr = "src.core.engine.handler.Handler.handleJudgeMarketDepthEvent: { type=%s, priority=%s, args=%s }, err=%s" % ( event.type, event.priority, event.args, err) self._logger.error(errStr) callback(event.id) def handleJudgeMarketKlineEvent(self, event, callback): self._logger.debug( "src.core.engine.handler.Handler.handleJudgeMarketKlineEvent: {id=%s, type=%s, priority=%s, timeStamp=%s, args=%s}" % (event.id, event.type, event.priority, event.timeStamp, event.args)) # 接收事件 [args] = event.args try: pass except (DBException, CalcException, EngineException, Exception) as err: errStr = "src.core.engine.handler.Handler.handleJudgeMarketKlineEvent: { type=%s, priority=%s, args=%s }, err=%s" % ( event.type, event.priority, event.args, err) self._logger.error(errStr) callback(event.id) def handleJudgeMarketTickerEvent(self, event, callback): self._logger.debug( "src.core.engine.handler.Handler.handleJudgeMarketTickerEvent: " + event.type) # 接收事件 [exchange, types] = event.args exchange = str_to_list(exchange) types = str_to_list(types) try: db = DB() calc = Calc() resInfoSymbol = pd.DataFrame(db.getViewMarketSymbolPairs(exchange)) prs = [] # calc dis type if TYPE_DIS in types: signalDis = calc.calcJudgeMarketTickerDis( exchange, TYPE_DIS_THRESHOLD, resInfoSymbol) if not signalDis == []: db.insertJudgeMarketTickerDis(signalDis) # calc tra type if TYPE_TRA in types: signalTra = calc.calcJudgeMarketTickerTra( exchange, TYPE_TRA_THRESHOLD, resInfoSymbol) if not signalTra == []: db.insertJudgeMarketTickerTra(signalTra) # calc pair type if TYPE_PAIR in types: signalPair = calc.calcJudgeMarketTickerPair( exchange, TYPE_PAIR_THRESHOLD, resInfoSymbol) if not signalPair == []: db.insertJudgeMarketTickerPair(signalPair) except (DBException, CalcException, EngineException, Exception) as err: errStr = "src.core.engine.handler.Handler.handleJudgeMarketTickerEvent: { type=%s, priority=%s, args=%s }, err=%s" % ( event.type, event.priority, event.args, err) self._logger.error(errStr) callback(event.id) # Backtest 事件 def rollbackHandleBacktestHistoryCreatEvent(self, sgn, pdOrders, exchange, resInfoSymbol): self._logger.debug( "src.core.engine.handler.Handler.rollbackHandleBacktestHistoryCreatEvent" ) try: db = DB() # update orders sgn status infoOrders = [] if not pdOrders.empty: for server in exchange: res = [] orderIDs = pdOrders[( pdOrders['server'] == server)]['order_id'].tolist() res = db.getTradeBacktestHistoryServerOrder([server], orderIDs) if not res == []: infoOrders.extend(res) if not infoOrders == []: infoOrders = pd.DataFrame(infoOrders) isError = SIGNAL_MAX_NUM while isError > 0: try: isError = isError - 1 sgn.backtestUpdateSignalStatusByOrders( infoOrders, resInfoSymbol) isError = 0 except Exception as err: self._logger.warn('rollback failed, will try again...') if isError > 0: raise Exception( 'rollback error, start_base assets may loss control.') # insert db signals db.insertSignalTradeDis(sgn.signals(exchange, [TYPE_DIS]), SIGNAL_BACKTEST) db.insertSignalTradeTra(sgn.signals(exchange, [TYPE_TRA]), SIGNAL_BACKTEST) db.insertSignalTradePair(sgn.signals(exchange, [TYPE_PAIR]), SIGNAL_BACKTEST) # rollback assets isError = SIGNAL_MAX_NUM while isError > 0: isError = isError - 1 # calc after orders afterOrders = [] isSubError = SIGNAL_MAX_NUM while isSubError > 0: try: isSubError = isSubError - 1 afterOrders = sgn.backtestSignalsAfterTrade( resInfoSymbol) isSubError = 0 except Exception as err: self._logger.warn('rollback failed, will try again...') if isSubError > 0: raise Exception( 'rollback error, start_base assets may loss control.') # calc afterExecOrders afterExecOrders = [] if not afterOrders == []: for order in afterOrders: identify = identify + 1 isSubError = SIGNAL_MAX_NUM res = [] while isSubError > 0: try: isSubError = isSubError - 1 res = db.insertCreatTradeBacktestHistory( order['server'], order['fSymbol'], order['tSymbol'], order['ask_or_bid'], order['price'], order['quantity'], order['ratio'], order['type'], order['signal_id'], order['group_id'], identify) isSubError = 0 except Exception as err: self._logger.warn( 'rollback failed, will try again...') if not res == []: afterExecOrders.extend(res) if isSubError > 0: raise Exception( 'rollback error, start_base assets may loss control.' ) # calc afterInfoOrders afterInfoOrders = [] if not afterExecOrders == []: afterExecOrders = pd.DataFrame(afterExecOrders) for server in exchange: res = [] orderIDs = preExecOrders[( preExecOrders['server'] == server )]['order_id'].tolist() res = db.getTradeBacktestHistoryServerOrder([server], orderIDs) if not res == []: afterInfoOrders.extend(res) # update signals status if not afterInfoOrders == []: afterInfoOrders = pd.DataFrame(afterInfoOrders) isSubError = SIGNAL_MAX_NUM while isSubError > 0: try: isSubError = isSubError - 1 sgn.backtestUpdateSignalStatusByOrders( afterInfoOrders, resInfoSymbol) isSubError = 0 except Exception as err: self._logger.warn( 'rollback failed, will try again...') if isSubError > 0: raise Exception( 'rollback error, start_base assets may loss control.' ) # insert db signals db.insertSignalTradeDis(sgn.signals(exchange, [TYPE_DIS]), SIGNAL_BACKTEST) db.insertSignalTradeTra(sgn.signals(exchange, [TYPE_TRA]), SIGNAL_BACKTEST) db.insertSignalTradePair( sgn.signals(exchange, [TYPE_PAIR]), SIGNAL_BACKTEST) # update isError isMore = sgn.backtestSignalsIsRunMore(resInfoSymbol) if not isMore: isError = 0 except Exception as err: errStr = "src.core.engine.handler.Handler.rollbackHandleBacktestHistoryCreatEvent, err=%s" % err self._logger.critical(errStr) def handleBacktestHistoryCreatEvent(self, event, callback): self._logger.debug( "src.core.engine.handler.Handler.handleBacktestHistoryCreatEvent: {id=%s, type=%s, priority=%s, timeStamp=%s, args=%s}" % (event.id, event.type, event.priority, event.timeStamp, event.args)) # 接收事件 [exchange, signals, timeout] = event.args exchange = str_to_list(exchange) signals = str_to_list(signals) timeout = float(timeout) # 处理事件 try: db = DB() sgn = Signal(signals) resInfoSymbol = pd.DataFrame(db.getViewMarketSymbolPairs(exchange)) # 0. start identify = 0 startTime = time.time() str = "src.core.engine.handler.Handler.handleBacktestHistoryCreatEvent: { type=%s, priority=%s, args=%s }" % ( event.type, event.priority, event.args) warnStr = Template( ", err=$err, backtest trade filed at $here, will try again...") errStr = Template( "BACKTEST TRADE ERROR. pre trade failed at $here.") ######################################## # 1. pre trade # 1.1 calc pre orders preOrders = [] isError = SIGNAL_MAX_NUM while isError > 0: try: isError = isError - 1 preOrders = sgn.backtestSignalsPreTrade(resInfoSymbol) isError = 0 except Exception as err: self._logger.warn(str + warnStr.substitute( err=err, here='1.1 calc pre orders')) if isError > 0: raise Exception(errStr.substitute(here='1.1 calc pre orders')) # print('1. pre signals preOrders:\n%s' % preOrders) # 1.2 calc preExecOrders preExecOrders = [] if not preOrders == []: for order in preOrders: identify = identify + 1 isError = SIGNAL_MAX_NUM res = [] while isError > 0: try: isError = isError - 1 res = db.insertCreatTradeBacktestHistory( order['server'], order['fSymbol'], order['tSymbol'], order['ask_or_bid'], order['price'], order['quantity'], order['ratio'], order['type'], order['signal_id'], order['group_id'], identify) isError = 0 except Exception as err: self._logger.warn(str + warnStr.substitute( err=err, here='1.2 excute preOrders')) if not res == []: preExecOrders.extend(res) if isError > 0: # rollback: pdOrders = pd.DataFrame(preExecOrders) self.rollbackHandleBacktestHistoryCreatEvent( sgn, pdOrders, exchange, resInfoSymbol) raise Exception( errStr.substitute(here='1.2 excute preOrders')) # print('1. pre signals preExecOrders:\n%s' % preExecOrders) # 1.3 calc preInfoOrders preInfoOrders = [] if not preExecOrders == []: preExecOrders = pd.DataFrame(preExecOrders) for server in exchange: res = [] orderIDs = preExecOrders[(preExecOrders['server'] == server )]['order_id'].tolist() res = db.getTradeBacktestHistoryServerOrder([server], orderIDs) if not res == []: preInfoOrders.extend(res) # print('1. pre signals preInfoOrders:\n%s' % preInfoOrders) # 1.4 update signals status if not preInfoOrders == []: preInfoOrders = pd.DataFrame(preInfoOrders) isError = SIGNAL_MAX_NUM while isError > 0: try: isError = isError - 1 sgn.backtestUpdateSignalStatusByOrders( preInfoOrders, resInfoSymbol) isError = 0 except Exception as err: self._logger.warn(str + warnStr.substitute( err=err, here='1.4 update signals status')) if isError > 0: # rollback: pdOrders = preExecOrders self.rollbackHandleBacktestHistoryCreatEvent( sgn, pdOrders, exchange, resInfoSymbol) raise Exception( errStr.substitute(here='1.4 update signals status')) # insert db signals db.insertSignalTradeDis(sgn.signals(exchange, [TYPE_DIS]), SIGNAL_BACKTEST) db.insertSignalTradeTra(sgn.signals(exchange, [TYPE_TRA]), SIGNAL_BACKTEST) db.insertSignalTradePair(sgn.signals(exchange, [TYPE_PAIR]), SIGNAL_BACKTEST) # print('1. pre signals after update:\n%s' % sgn.signals()) ######################################## # 2. run trade isError = True while isError and (time.time() - startTime < timeout or timeout == 0): # 2.1 calc run orders runOrders = [] isSubError = SIGNAL_MAX_NUM while isSubError > 0 and (time.time() - startTime < timeout or timeout == 0): try: isSubError = isSubError - 1 runOrders = sgn.backtestSignalsRunTrade(resInfoSymbol) isSubError = 0 except Exception as err: self._logger.warn(str + warnStr.substitute( err=err, here='2.1 calc run orders')) if isSubError > 0: # rollback: pdOrders = [] self.rollbackHandleBacktestHistoryCreatEvent( sgn, pdOrders, exchange, resInfoSymbol) raise Exception( errStr.substitute(here='2.1 calc run orders')) # print('2. run signals runOrders:\n%s' % runOrders) # 2.2 calc runExecOrders runExecOrders = [] if not runOrders == []: for order in runOrders: identify = identify + 1 isSubError = SIGNAL_MAX_NUM res = [] while isSubError > 0 and (time.time() - startTime < timeout or timeout == 0): try: isSubError = isSubError - 1 res = db.insertCreatTradeBacktestHistory( order['server'], order['fSymbol'], order['tSymbol'], order['ask_or_bid'], order['price'], order['quantity'], order['ratio'], order['type'], order['signal_id'], order['group_id'], identify) isSubError = 0 except Exception as err: self._logger.warn(str + warnStr.substitute( err=err, here='2.2 execute runOrders')) if not res == []: runExecOrders.extend(res) if isSubError > 0: # rollback: pdOrders = pd.DataFrame(runExecOrders) self.rollbackHandleBacktestHistoryCreatEvent( sgn, pdOrders, exchange, resInfoSymbol) raise Exception( errStr.substitute(here='2.2 execute runOrders')) # print('2. run signals runExecOrders:\n%s' % runExecOrders) # 2.3 calc runInfoOrders runInfoOrders = [] if not runExecOrders == []: runExecOrders = pd.DataFrame(runExecOrders) for server in exchange: res = [] orderIDs = runExecOrders[( runExecOrders['server'] == server )]['order_id'].tolist() res = db.getTradeBacktestHistoryServerOrder([server], orderIDs) if not res == []: runInfoOrders.extend(res) # print('2. run signals runInfoOrders:\n%s' % runInfoOrders) # 2.4 update signals status if not runInfoOrders == []: runInfoOrders = pd.DataFrame(runInfoOrders) isSubError = SIGNAL_MAX_NUM while isSubError > 0 and (time.time() - startTime < timeout or timeout == 0): try: isSubError = isSubError - 1 sgn.backtestUpdateSignalStatusByOrders( runInfoOrders, resInfoSymbol) isSubError = 0 except Exception as err: self._logger.warn(str + warnStr.substitute( err=err, here='2.4 update signals status')) if isSubError > 0: # rollback: pdOrders = runExecOrders self.rollbackHandleBacktestHistoryCreatEvent( sgn, pdOrders, exchange, resInfoSymbol) raise Exception( errStr.substitute( here='2.4 update signals status')) # insert db signals db.insertSignalTradeDis(sgn.signals(exchange, [TYPE_DIS]), SIGNAL_BACKTEST) db.insertSignalTradeTra(sgn.signals(exchange, [TYPE_TRA]), SIGNAL_BACKTEST) db.insertSignalTradePair( sgn.signals(exchange, [TYPE_PAIR]), SIGNAL_BACKTEST) # print('2. run signals after update:\n%s' % sgn.signals()) # 2.5 update isError isMore = sgn.backtestSignalsIsRunMore(resInfoSymbol) if not isMore: isError = False ######################################## # 3. after trade isError = SIGNAL_MAX_NUM while isError > 0: isError = isError - 1 # 3.1 calc after orders afterOrders = [] isSubError = SIGNAL_MAX_NUM while isSubError > 0: try: isSubError = isSubError - 1 afterOrders = sgn.backtestSignalsAfterTrade( resInfoSymbol) isSubError = 0 except Exception as err: self._logger.warn(str + warnStr.substitute( err=err, here='3.1 calc after orders')) if isSubError > 0: # rollback pdOrders = [] self.rollbackHandleBacktestHistoryCreatEvent( sgn, pdOrders, exchange, resInfoSymbol) raise Exception( errStr.substitute(here='3.1 calc after orders')) # print('3. after signals afterOrders:\n%s' % afterOrders) # 3.2 calc afterExecOrders afterExecOrders = [] if not afterOrders == []: for order in afterOrders: identify = identify + 1 isSubError = SIGNAL_MAX_NUM res = [] while isSubError > 0: try: isSubError = isSubError - 1 res = db.insertCreatTradeBacktestHistory( order['server'], order['fSymbol'], order['tSymbol'], order['ask_or_bid'], order['price'], order['quantity'], order['ratio'], order['type'], order['signal_id'], order['group_id'], identify) isSubError = 0 except Exception as err: self._logger.warn(str + warnStr.substitute( err=err, here='3.2 excute preOrders')) if not res == []: afterExecOrders.extend(res) if isSubError > 0: # rollback: pdOrders = pd.DataFrame(afterExecOrders) self.rollbackHandleBacktestHistoryCreatEvent( sgn, pdOrders, exchange, resInfoSymbol) raise Exception( errStr.substitute(here='3.2 excute preOrders')) # print('3. after signals afterExecOrders:\n%s' % afterExecOrders) # 3.3 calc afterInfoOrders afterInfoOrders = [] if not afterExecOrders == []: afterExecOrders = pd.DataFrame(afterExecOrders) for server in exchange: res = [] orderIDs = preExecOrders[( preExecOrders['server'] == server )]['order_id'].tolist() res = db.getTradeBacktestHistoryServerOrder([server], orderIDs) if not res == []: afterInfoOrders.extend(res) # print('3. after signals afterInfoOrders:\n%s' % afterInfoOrders) # 3.4 update signals status if not afterInfoOrders == []: afterInfoOrders = pd.DataFrame(afterInfoOrders) isSubError = SIGNAL_MAX_NUM while isSubError > 0: try: isSubError = isSubError - 1 sgn.backtestUpdateSignalStatusByOrders( afterInfoOrders, resInfoSymbol) isSubError = 0 except Exception as err: self._logger.warn(str + warnStr.substitute( err=err, here='3.4 update signals status')) if isSubError > 0: # rollback: pdOrders = afterExecOrders self.rollbackHandleBacktestHistoryCreatEvent( sgn, pdOrders, exchange, resInfoSymbol) raise Exception( errStr.substitute( here='3.4 update signals status')) # insert db signals db.insertSignalTradeDis(sgn.signals(exchange, [TYPE_DIS]), SIGNAL_BACKTEST) db.insertSignalTradeTra(sgn.signals(exchange, [TYPE_TRA]), SIGNAL_BACKTEST) db.insertSignalTradePair( sgn.signals(exchange, [TYPE_PAIR]), SIGNAL_BACKTEST) # print('3. after signals after update:\n%s' % sgn.signals()) # 3.5 update isError isMore = sgn.backtestSignalsIsRunMore(resInfoSymbol) if not isMore: isError = 0 except (DBException, CalcException, EngineException, Exception) as err: errStr = "src.core.engine.handler.Handler.handleBacktestHistoryCreatEvent: { type=%s, priority=%s, args=%s }, err=%s" % ( event.type, event.priority, event.args, err) self._logger.error(errStr) callback(event.id) # Order 事件 def handleOrderHistorySyncEvent(self, event, callback): self._logger.debug( "src.core.engine.handler.Handler.handleOrderHistorySyncEvent: {id=%s, type=%s, priority=%s, timeStamp=%s, args=%s}" % (event.id, event.type, event.priority, event.timeStamp, event.args)) # 接收事件 [exchange, fSymbol, tSymbol, limit, ratio] = event.args exchange = str_to_list(exchange) try: db = DB() db.insertSyncTradeOrderHistory(exchange, fSymbol, tSymbol, limit, ratio) except (DBException, CalcException, EngineException, Exception) as err: errStr = "src.core.engine.handler.Handler.handleOrderHistorySyncEvent: { type=%s, priority=%s, args=%s }, err=%s" % ( event.type, event.priority, event.args, err) self._logger.error(errStr) callback(event.id) def handleOrderHistoryCreatEvent(self, event, callback): self._logger.debug( "src.core.engine.handler.Handler.handleOrderHistoryCreatEvent: {id=%s, type=%s, priority=%s, timeStamp=%s, args=%s}" % (event.id, event.type, event.priority, event.timeStamp, event.args)) # 接收事件 pass # Statistic 事件 def handleStatisticJudgeEvent(self, event, callback): self._logger.debug( "src.core.engine.handler.Handler.handleStatisticJudgeEvent: {id=%s, type=%s, priority=%s, timeStamp=%s, args=%s}" % (event.id, event.type, event.priority, event.timeStamp, event.args)) # 接收事件 [exchange, types] = event.args exchange = str_to_list(exchange) types = str_to_list(types) try: db = DB() calc = Calc() # calc dis type if TYPE_DIS in types: statisticDis = calc.calcStatisticJudgeMarketTickerDis( exchange, TYPE_DIS_TIMEWINDOW) if not statisticDis == []: db.insertStatisticJudgeMarketTickerDis(statisticDis) # calc tra type if TYPE_TRA in types: statisticTra = calc.calcStatisticJudgeMarketTickerTra( exchange, TYPE_TRA_TIMEWINDOW) if not statisticTra == []: db.insertStatisticJudgeMarketTickerTra(statisticTra) # calc pair type if TYPE_PAIR in types: statisticPair = calc.calcStatisticJudgeMarketTickerPair( exchange, TYPE_PAIR_TIMEWINDOW) if not statisticPair == []: db.insertStatisticJudgeMarketTickerPair(statisticPair) except (DBException, CalcException, EngineException, Exception) as err: errStr = "src.core.engine.handler.Handler.handleStatisticJudgeEvent: { type=%s, priority=%s, args=%s }, err=%s" % ( event.type, event.priority, event.args, err) self._logger.error(errStr) callback(event.id) def handleStatisticBacktestEvent(self, event, callback): self._logger.debug( "src.core.engine.handler.Handler.handleStatisticBacktestEvent: {id=%s, type=%s, priority=%s, timeStamp=%s, args=%s}" % (event.id, event.type, event.priority, event.timeStamp, event.args)) # 接收事件 [signals] = event.args signals = str_to_list(signals) for signal in signals: signal['status_assets'] = json.loads( json_reverse(signal['status_assets'])) try: db = DB() calc = Calc() statistic = calc.calcStatisticTradeBacktestHistory(signals) db.insertStatisticTradeBacktestHistory(statistic) except (DBException, CalcException, EngineException, Exception) as err: errStr = "src.core.engine.handler.Handler.handleStatisticBacktestEvent: { type=%s, priority=%s, args=%s }, err=%s" % ( event.type, event.priority, event.args, err) self._logger.error(errStr) callback(event.id) def handleStatisticOrderEvent(self, event, callback): self._logger.debug( "src.core.engine.handler.Handler.handleStatisticOrderEvent: {id=%s, type=%s, priority=%s, timeStamp=%s, args=%s}" % (event.id, event.type, event.priority, event.timeStamp, event.args)) # 接收事件 [signals] = event.args signals = str_to_list(signals) for signal in signals: signal['status_assets'] = json.loads( json_reverse(signal['status_assets'])) try: db = DB() calc = Calc() statistic = calc.calcStatisticTradeOrderHistory(signals) db.insertStatisticTradeOrderHistory(statistic) except (DBException, CalcException, EngineException, Exception) as err: errStr = "src.core.engine.handler.Handler.handleStatisticOrderEvent: { type=%s, priority=%s, args=%s }, err=%s" % ( event.type, event.priority, event.args, err) self._logger.error(errStr) callback(event.id)
class Signal(object): def __init__(self, signals=[]): # signal init self._signals = signals self._signals_str = SIGNAL_SIGNALS # logger self._logger = Logger() def signals(self, exchange='all', types='all', auto=SIGNAL_AUTO): self._logger.debug( "src.core.calc.signal.Signal.signals: {exchange=%s, types=%s, auto=%s}" % (exchange, types, auto)) try: if not self._signals == []: signals = [] for s in self._signals: if s['type'] == TYPE_DIS: if (types == 'all' or TYPE_DIS in types) and ( exchange == 'all' or (s['bid_server'] in exchange and s['ask_server'] in exchange)): signals.append(s) if s['type'] == TYPE_TRA: if (types == 'all' or TYPE_TRA in types) and ( exchange == 'all' or s['server'] in exchange): signals.append(s) if s['type'] == TYPE_PAIR: if (types == 'all' or TYPE_PAIR in types) and ( exchange == 'all' or (s['J1_server'] in exchange and s['J2_server'] in exchange)): signals.append(s) return signals if auto: return self._autoSignals(exchange, types) if not auto: return self._configSignals(exchange, types) except Exception as err: errStr = "src.core.calc.signal.Signal.signals: {exchange=%s, types=%s, auto=%s}, exception err=%s" % ( exchange, types, auto, err) raise CalcException(errStr) def _autoSignals(self, exchange, types): self._logger.debug("src.core.calc.signal.Signal._autoSignals") try: signals = [] # return signals return signals except Exception as err: errStr = "src.core.calc.signal.Signal.signals, exception err=%s" % err raise CalcException(errStr) def _configSignals(self, exchange, types): self._logger.debug("src.core.calc.signal.Signal._configSignals") try: signals = [] strList = ast.literal_eval(self._signals_str) if not strList == []: pid = os.getpid() timeStamp = utcnow_timestamp() id = 0 for s in strList: id = id + 1 signal = {} if s['type'] == TYPE_DIS: if (types == 'all' or TYPE_DIS in types) and ( exchange == 'all' or (s['bid_server'] in exchange and s['ask_server'] in exchange)): id_str = str(pid) + str(timeStamp) + str(id) signal['timeStamp'] = timeStamp signal['signal_id'] = '0x1c-' + str( uuid.uuid3(uuid.NAMESPACE_DNS, id_str)) signal['type'] = s['type'] signal['bid_server'] = s['bid_server'] signal['ask_server'] = s['ask_server'] signal['fSymbol'] = s['fSymbol'] signal['tSymbol'] = s['tSymbol'] signal['forward_ratio'] = float(s['forward_ratio']) signal['backward_ratio'] = float( s['backward_ratio']) signal['base_start'] = float(s['base_start']) signal['base_gain'] = float(s['base_gain']) signal['base_timeout'] = float(s['base_timeout']) signal['group_id'] = str(s['group_id']) signal['status_done'] = False signal['status_assets'] = [{ "server": s['bid_server'], "asset": SIGNAL_BASECOIN, "balance": float(s['base_start']) / 2, "free": float(s['base_start']) / 2, "locked": 0.0 }, { "server": s['ask_server'], "asset": SIGNAL_BASECOIN, "balance": float(s['base_start']) / 2, "free": float(s['base_start']) / 2, "locked": 0.0 }] signal['status_gain'] = 0.0 if s['type'] == TYPE_TRA: if (types == 'all' or TYPE_TRA in types) and ( exchange == 'all' or s['server'] in exchange): tuple = tuple_str_to_list(s['symbol_pair']) id_str = str(pid) + str(timeStamp) + str(id) signal['timeStamp'] = timeStamp signal['signal_id'] = '0x2c-' + str( uuid.uuid3(uuid.NAMESPACE_DNS, id_str)) signal['type'] = s['type'] signal['server'] = s['server'] signal['V1_fSymbol'] = tuple[0][0] signal['V1_tSymbol'] = tuple[0][1] signal['V2_fSymbol'] = tuple[1][0] signal['V2_tSymbol'] = tuple[1][1] signal['V3_fSymbol'] = tuple[2][0] signal['V3_tSymbol'] = tuple[2][1] signal['forward_ratio'] = float(s['forward_ratio']) signal['base_start'] = float(s['base_start']) signal['base_gain'] = float(s['base_gain']) signal['base_timeout'] = float(s['base_timeout']) signal['group_id'] = str(s['group_id']) signal['status_done'] = False signal['status_assets'] = [{ "server": s['server'], "asset": SIGNAL_BASECOIN, "balance": float(s['base_start']), "free": float(s['base_start']), "locked": 0.0 }] signal['status_gain'] = 0.0 if s['type'] == TYPE_PAIR: if (types == 'all' or TYPE_PAIR in types) and ( exchange == 'all' or (s['J1_server'] in exchange and s['J2_server'] in exchange)): tuple = tuple_str_to_list(s['symbol_pair']) id_str = str(pid) + str(timeStamp) + str(id) signal['timeStamp'] = timeStamp signal['signal_id'] = '0x3c-' + str( uuid.uuid3(uuid.NAMESPACE_DNS, id_str)) signal['type'] = s['type'] signal['J1_server'] = s['J1_server'] signal['J2_server'] = s['J2_server'] signal['V1_fSymbol'] = tuple[0][0] signal['V1_tSymbol'] = tuple[0][1] signal['V2_fSymbol'] = tuple[1][0] signal['V2_tSymbol'] = tuple[1][1] signal['V3_fSymbol'] = tuple[2][0] signal['V3_tSymbol'] = tuple[2][1] signal['forward_ratio'] = float(s['forward_ratio']) signal['base_start'] = float(s['base_start']) signal['base_gain'] = float(s['base_gain']) signal['base_timeout'] = float(s['base_timeout']) signal['group_id'] = str(s['group_id']) signal['status_done'] = False signal['status_assets'] = [{ "server": s['J1_server'], "asset": SIGNAL_BASECOIN, "balance": float(s['base_start']) / 2, "free": float(s['base_start']) / 2, "locked": 0.0 }, { "server": s['J2_server'], "asset": SIGNAL_BASECOIN, "balance": float(s['base_start']) / 2, "free": float(s['base_start']) / 2, "locked": 0.0 }] signal['status_gain'] = 0.0 if not signal == {}: signals.append(signal) # return signals return signals except Exception as err: errStr = "src.core.calc.signal.Signal.signals, exception err=%s" % err raise CalcException(errStr) def backtestUpdateSignalStatusByOrders(self, infoOrders, resInfoSymbol): self._logger.debug( "src.core.calc.signal.Signal.backtestUpdateSignalStatusByOrders: {infoOrders=%s, resInfoSymbol=%s}" % ('infoOrders', 'resInfoSymbol')) try: if not self._signals: raise Exception("NO SIGNAL ERROR, signals empty.") calc = Calc() resStatus = [] timeStamp = utcnow_timestamp() for signal in self._signals: orders = infoOrders[( infoOrders['group_id'] == signal['group_id'])] status = calc.calcSignalStatusByOrders(signal, orders, resInfoSymbol, SIGNAL_BASECOIN) if not status == []: resStatus.append({ "signal_id": signal['signal_id'], "status": status }) if not resStatus == []: for signal in self._signals: for res in resStatus: if signal['signal_id'] == res['signal_id']: signal['timeStamp'] = timeStamp signal['status_done'] = res['status'][ 'status_done'] signal['status_assets'] = res['status'][ 'status_assets'] signal['status_gain'] = res['status'][ 'status_gain'] except Exception as err: errStr = "src.core.calc.signal.Signal.backtestUpdateSignalStatusByOrders: {infoOrders=%s, resInfoSymbol=%s}, exception err=%s" % ( 'infoOrders', 'resInfoSymbol', err) raise CalcException(errStr) def backtestSignalsPreTrade(self, resInfoSymbol): self._logger.debug( "src.core.calc.signal.Signal.backtestSignalsPreTrade: {resInfoSymbol=%s}" % 'resInfoSymbol') try: if not self._signals: raise Exception("NO SIGNAL ERROR, signals empty.") calc = Calc() res = [] for signal in self._signals: orders = calc.calcSignalPreTradeOrders(signal, resInfoSymbol, SIGNAL_BASECOIN) if not orders == []: res.extend(orders) return res except Exception as err: errStr = "src.core.calc.signal.Signal.backtestSignalsPreTrade: {resInfoSymbol=%s}, exception err=%s" % ( 'resInfoSymbol', err) raise CalcException(errStr) def backtestSignalsRunTrade(self, resInfoSymbol): self._logger.debug( "src.core.calc.signal.Signal.backtestSignalsRunTrade: {resInfoSymbol=%s}" % 'resInfoSymbol') try: if not self._signals: raise Exception("NO SIGNAL ERROR, signals empty.") calc = Calc() res = [] for signal in self._signals: if signal['status_gain'] < signal['base_gain']: orders = calc.calcSignalRunTradeOrders( signal, resInfoSymbol) if not orders == []: res.extend(orders) if signal['status_gain'] >= signal['base_gain']: orders = calc.calcSignalAfterTradeOrders( signal, resInfoSymbol, SIGNAL_BASECOIN) if not orders == []: res.extend(orders) return res except Exception as err: errStr = "src.core.calc.signal.Signal.backtestSignalsRunTrade: {resInfoSymbol=%s}, exception err=%s" % ( 'resInfoSymbol', err) raise CalcException(errStr) def backtestSignalsIsRunMore(self, resInfoSymbol): self._logger.debug( "src.core.calc.signal.Signal.backtestSignalsIsRunMore: {resInfoSymbol=%s}" % 'resInfoSymbol') try: if not self._signals: raise Exception("NO SIGNAL ERROR, signals empty.") isMore = False for signal in self._signals: if signal['status_gain'] < signal['base_gain']: isMore = True break return isMore except Exception as err: errStr = "src.core.calc.signal.Signal.backtestSignalsIsRunMore: {resInfoSymbol=%s}, exception err=%s" % ( 'resInfoSymbol', err) raise CalcException(errStr) def backtestSignalsAfterTrade(self, resInfoSymbol): self._logger.debug( "src.core.calc.signal.Signal.backtestSignalsAfterTrade: {resInfoSymbol=%s}" % 'resInfoSymbol') try: if not self._signals: raise Exception("NO SIGNAL ERROR, signals empty.") calc = Calc() res = [] for signal in self._signals: orders = calc.calcSignalAfterTradeOrders( signal, resInfoSymbol, SIGNAL_BASECOIN) if not orders == []: res.extend(orders) return res except Exception as err: errStr = "src.core.calc.signal.Signal.backtestSignalsAfterTrade: {resInfoSymbol=%s}, exception err=%s" % ( 'resInfoSymbol', err) raise CalcException(errStr) def backtestSignalsIsAfterMore(self, resInfoSymbol): self._logger.debug( "src.core.calc.signal.Signal.backtestSignalsIsAfterMore: {resInfoSymbol=%s}" % 'resInfoSymbol') try: if not self._signals: raise Exception("NO SIGNAL ERROR, signals empty.") calc = Calc() isMore = False for signal in self._signals: isMore = calc.calcSignalIsAfterMore(signal, resInfoSymbol, SIGNAL_BASECOIN) if isMore: break return isMore except Exception as err: errStr = "src.core.calc.signal.Signal.backtestSignalsIsAfterMore: {resInfoSymbol=%s}, exception err=%s" % ( 'resInfoSymbol', err) raise CalcException(errStr)