示例#1
0
 def connect(self, userID, password, brokerID, address):
     """初始化连接"""
     self.userID = userID                # 账号
     self.password = password            # 密码
     self.brokerID = brokerID            # 经纪商代码
     self.address = address              # 服务器地址
     
     # 如果尚未建立服务器连接,则进行连接
     if not self.connectionStatus:
         # 创建C++环境中的API对象,这里传入的参数是需要用来保存.con文件的文件夹路径
         path = getTempPath(self.gatewayName + '_')
         self.createFtdcMdApi(path)
         
         # 订阅主题
         self.subscribeMarketDataTopic(100, 2)
         # 注册服务器地址
         self.registerFront(self.address)
         
         # 初始化连接,成功会调用onFrontConnected
         self.init()
         
     # 若已经连接但尚未登录,则进行登录
     else:
         if not self.loginStatus:
             self.login()
示例#2
0
    def connect(self, userID, password, brokerID, address, productInfo, authCode):
        """初始化连接"""
        self.userID = userID                # 账号
        self.password = password            # 密码
        self.brokerID = brokerID            # 经纪商代码
        self.address = address              # 服务器地址
        self.productInfo = productInfo
        self.authCode = authCode        
        
        # 如果尚未建立服务器连接,则进行连接
        if not self.connectionStatus:
            # 创建C++环境中的API对象,这里传入的参数是需要用来保存.con文件的文件夹路径
            path = getTempPath(self.gatewayName + '_')
            self.createFtdcQueryApi(path)
            
            # 注册服务器地址
            self.registerFront(self.address)
            
            # 初始化连接,成功会调用onFrontConnected
            self.init()

        # 若已经连接但尚未登录,则进行登录
        else:
            if not self.loginStatus:
                self.login()    
示例#3
0
    def connect(self, userID, password, brokerID, address, authCode, userProductInfo):
        """初始化连接"""
        # print "%s.%s.%s" % (__name__, self.__class__.__name__, get_current_function_name())
        self.userID = userID  # 账号
        self.password = password  # 密码
        self.brokerID = brokerID  # 经纪商代码
        self.address = address  # 服务器地址
        self.authCode = authCode  # 验证码
        self.userProductInfo = userProductInfo  # 产品信息

        # 如果尚未建立服务器连接,则进行连接
        if not self.connectionStatus:
            # 创建C++环境中的API对象,这里传入的参数是需要用来保存.con文件的文件夹路径
            path = getTempPath(self.gatewayName + '_')
            self.createFtdcTraderApi(path)

            # 设置数据同步模式为推送从今日开始所有数据
            self.subscribePrivateTopic(0)
            self.subscribePublicTopic(0)

            # 注册服务器地址
            self.registerFront(self.address)

            # 初始化连接,成功会调用onFrontConnected
            self.init()

        # 若已经连接但尚未登录,则进行登录
        else:
            if self.requireAuthentication and not self.authStatus:
                self.authenticate()
            elif not self.loginStatus:
                self.login()
示例#4
0
 def connect(self, userID, password, brokerID, address):
     """初始化连接"""
     self.userID = userID                # 账号
     self.password = password            # 密码
     self.brokerID = brokerID            # 经纪商代码
     self.address = address              # 服务器地址
     
     # 如果尚未建立服务器连接,则进行连接
     if not self.connectionStatus:
         # 创建C++环境中的API对象,这里传入的参数是需要用来保存.con文件的文件夹路径
         path = getTempPath(self.gatewayName + '_')
         self.createFtdcTraderApi(path)
         
         # 设置数据同步模式为推送从今日开始所有数据
         self.subscribePrivateTopic(0)
         self.subscribePublicTopic(0)            
         
         # 注册服务器地址
         self.registerFront(self.address)
         
         # 初始化连接,成功会调用onFrontConnected
         self.init()
         
     # 若已经连接但尚未登录,则进行登录
     else:
         if not self.loginStatus:
             self.login()    
示例#5
0
    def connect(self, userID, password, brokerID, address, productInfo,
                authCode):
        """初始化连接"""
        self.userID = userID  # 账号
        self.password = password  # 密码
        self.brokerID = brokerID  # 经纪商代码
        self.address = address  # 服务器地址
        self.productInfo = productInfo
        self.authCode = authCode

        # 如果尚未建立服务器连接,则进行连接
        if not self.connectionStatus:
            # 创建C++环境中的API对象,这里传入的参数是需要用来保存.con文件的文件夹路径
            path = getTempPath(self.gatewayName + '_')
            self.createFtdcTraderApi(path)

            # 设置数据同步模式为推送从今日开始所有数据
            self.subscribePrivateTopic(0)
            self.subscribePublicTopic(0)

            # 注册服务器地址
            self.registerFront(self.address)

            # 初始化连接,成功会调用onFrontConnected
            self.init()

        # 若已经连接但尚未登录,则进行登录
        else:
            if not self.loginStatus:
                self.login()
示例#6
0
 def addFileHandler(self):
     """添加文件输出"""
     if not self.fileHandler:
         filename = 'vt.log'
         filepath = getTempPath(filename)
         self.fileHandler = logging.FileHandler(filepath)
         self.fileHandler.setLevel(self.level)
         self.fileHandler.setFormatter(self.formatter)
         self.logger.addHandler(self.fileHandler)
示例#7
0
 def addFileHandler(self):
     """添加文件输出"""
     if not self.fileHandler:
         filename = 'vt_' + datetime.now().strftime('%Y%m%d') + '.log'
         filepath = getTempPath(filename)
         self.fileHandler = logging.FileHandler(filepath)
         self.fileHandler.setLevel(self.level)
         self.fileHandler.setFormatter(self.formatter)
         self.logger.addHandler(self.fileHandler)
示例#8
0
 def __init__(self):
     super(SqliteMetricSender, self).__init__()
     filename = "ctaMetric.sqlite"
     filepath = getTempPath(filename)
     engine = create_engine('sqlite:///%s' % filepath)
     self.engine = engine
     self.ensure_table()
     Session = sessionmaker()
     Session.configure(bind=engine)
     self.session = Session()
示例#9
0
 def addFileHandler(self, filename=''):
     """添加文件输出"""
     if not self.fileHandler:
         if not filename:
             filename = 'vt_' + datetime.now().strftime('%Y%m%d') + '.log'
         filepath = getTempPath(filename)
         self.fileHandler = logging.FileHandler(filepath, mode='w', encoding='utf-8')
         self.fileHandler.setLevel(self.level)
         self.fileHandler.setFormatter(self.formatter)
         self.logger.addHandler(self.fileHandler)
示例#10
0
 def __init__(self):
     super(LogfileMetricSender, self).__init__()
     logger = logging.getLogger(__name__)
     filename = "ctaMetric.log"
     filepath = getTempPath(filename)
     self.hander = TimedRotatingFileHandler(filepath, when="d", backupCount=7)
     formater = logging.Formatter(fmt="%(asctime)s|%(message)s")
     self.hander.setFormatter(formater)
     logger.addHandler(self.hander)
     logger.setLevel(logging.INFO)
     logger.propagate = False
     self.logger = logger
示例#11
0
 def addFileHandler(self):
     """添加文件输出"""
     if not self.fileHandler:
         filename = 'vt_' + datetime.now().strftime('%Y%m%d') + '.log'
         filepath = getTempPath(filename)
         # self.fileHandler = logging.FileHandler(filepath) # 引擎原有的handler
         # 限制日志文件大小为20M,一天最多 400 MB
         self.fileHandler = logging.handlers.RotatingFileHandler(
             filepath, maxBytes=20971520, backupCount=20)
         self.fileHandler.setLevel(self.level)
         self.fileHandler.setFormatter(self.formatter)
         self.logger.addHandler(self.fileHandler)
示例#12
0
    def connect(self, userID, password, brokerID, address):
        """初始化连接"""
        # print "%s.%s.%s" % (__name__, self.__class__.__name__, get_current_function_name())
        self.userID = userID  # 账号
        self.password = password  # 密码
        self.brokerID = brokerID  # 经纪商代码
        self.address = address  # 服务器地址

        # 如果尚未建立服务器连接,则进行连接
        if not self.connectionStatus:
            # 创建C++环境中的API对象,这里传入的参数是需要用来保存.con文件的文件夹路径
            path = getTempPath(self.gatewayName + '_')
            self.createFtdcMdApi(path)

            # 注册服务器地址
            self.registerFront(self.address)

            # 初始化连接,成功会调用onFrontConnected
            self.init()

        # 若已经连接但尚未登录,则进行登录
        else:
            if not self.loginStatus:
                self.login()
示例#13
0
class DataEngine(object):
    """数据引擎"""
    contractFileName = 'ContractData.vt'
    contractFilePath = getTempPath(contractFileName)

    FINISHED_STATUS = [STATUS_ALLTRADED, STATUS_REJECTED, STATUS_CANCELLED]

    def __init__(self, eventEngine):
        """Constructor"""
        self.eventEngine = eventEngine

        # 保存合约详细信息的字典
        self.contractDict = {}
        self.accountDict = {}

        # 保存委托数据的字典
        self.orderDict = {}

        # 保存活动委托数据的字典(即可撤销)
        self.workingOrderDict = {}

        # 持仓细节相关
        self.detailDict = {}  # vtSymbol:PositionDetail
        self.tdPenaltyList = globalSetting['tdPenalty']  # 平今手续费惩罚的产品代码列表

        # 读取保存在硬盘的合约数据
        self.loadContracts()

        # 注册事件监听
        self.registerEvent()

    def registerEvent(self):
        """注册事件监听"""
        # print('-----------vtEngine.py registerEvent line393------------')
        self.eventEngine.register(EVENT_CONTRACT, self.processContractEvent)
        self.eventEngine.register(EVENT_ORDER, self.processOrderEvent)
        self.eventEngine.register(EVENT_TRADE, self.processTradeEvent)
        self.eventEngine.register(EVENT_POSITION, self.processPositionEvent)
        self.eventEngine.register(EVENT_ACCOUNT, self.processAccountEvent)
        # # 下面是zls添加用于ib
        # self.eventEngine.register(EVENT_TICK, self.processContractEvent)

    def processAccountEvent(self, event):

        account = event.dict_['data']
        self.accountDict[account.gatewayName] = account

    def processContractEvent(self, event):
        """处理合约事件"""
        # print('----------vtEngine processContractEvent line408 -----------')
        contract = event.dict_['data']
        self.contractDict[contract.vtSymbol] = contract
        self.contractDict[contract.symbol] = contract  # 使用常规代码(不包括交易所)可能导致重复

    def processOrderEvent(self, event):
        """处理委托事件"""
        order = event.dict_['data']
        self.orderDict[order.vtOrderID] = order

        # 如果订单的状态是全部成交或者撤销,则需要从workingOrderDict中移除
        if order.status in self.FINISHED_STATUS:
            if order.vtOrderID in self.workingOrderDict:
                del self.workingOrderDict[order.vtOrderID]
        # 否则则更新字典中的数据
        else:
            self.workingOrderDict[order.vtOrderID] = order

        # 更新到持仓细节中
        detail = self.getPositionDetail(order.vtSymbol)
        detail.updateOrder(order)

    def processTradeEvent(self, event):
        """处理成交事件"""
        trade = event.dict_['data']

        # 更新到持仓细节中
        detail = self.getPositionDetail(trade.vtSymbol)
        detail.updateTrade(trade)

    def processPositionEvent(self, event):
        """处理持仓事件"""
        pos = event.dict_['data']

        # 更新到持仓细节中
        detail = self.getPositionDetail(pos.vtSymbol)
        detail.updatePosition(pos)

    def getContract(self, vtSymbol):
        """查询合约对象"""
        try:
            # print 'vtEngine.py line453 查询合约对象:', vtSymbol, len(self.contractDict), [contract.vtSymbol for contract in self.contractDict.values()] # 0
            return self.contractDict[vtSymbol]
        except KeyError:
            return None

    def getAllContracts(self):
        """查询所有合约对象(返回列表)"""
        return self.contractDict.values()

    def saveContracts(self):
        """保存所有合约对象到硬盘"""
        f = shelve.open(self.contractFilePath)
        f['data'] = self.contractDict
        f.close()

    def loadContracts(self):
        """从硬盘读取合约对象"""
        f = shelve.open(self.contractFilePath)
        if 'data' in f:
            d = f['data']
            for key, value in d.items():
                self.contractDict[key] = value
        f.close()

    def getOrder(self, vtOrderID):
        """查询委托"""
        try:
            return self.orderDict[vtOrderID]
        except KeyError:
            return None

    def getAllWorkingOrders(self):
        """查询所有活动委托(返回列表)"""
        return self.workingOrderDict.values()

    def getPositionDetail(self, vtSymbol):
        """查询持仓细节"""
        if vtSymbol in self.detailDict:
            detail = self.detailDict[vtSymbol]
        else:
            detail = PositionDetail(vtSymbol)
            self.detailDict[vtSymbol] = detail

            # 设置持仓细节的委托转换模式
            contract = self.getContract(vtSymbol)

            if contract:
                detail.exchange = contract.exchange

                # 上期所合约
                if contract.exchange == EXCHANGE_SHFE:
                    detail.mode = detail.MODE_SHFE

                # 检查是否有平今惩罚
                for productID in self.tdPenaltyList:
                    if str(productID) in contract.symbol:
                        detail.mode = detail.MODE_TDPENALTY

        return detail

    def updateOrderReq(self, req, vtOrderID):
        """委托请求更新"""
        vtSymbol = req.vtSymbol

        detail = self.getPositionDetail(vtSymbol)
        detail.updateOrderReq(req, vtOrderID)

    def convertOrderReq(self, req):
        """根据规则转换委托请求"""
        detail = self.detailDict.get(req.vtSymbol, None)
        if not detail:
            # print("ctaEngine 21")
            return [req]
        else:
            # print("ctaEngine 22")
            return detail.convertOrderReq(req)
示例#14
0
class DataEngine(object):
    """数据引擎"""
    contractFileName = 'ContractData.vt'
    contractFilePath = getTempPath(contractFileName)

    # ----------------------------------------------------------------------
    def __init__(self, mainEngine, eventEngine):
        """Constructor"""
        self.mainEngine = mainEngine
        self.eventEngine = eventEngine

        # 保存合约详细信息的字典
        self.contractDict = {}

        # 本地自定义的合约详细配置字典
        self.custom_contract_setting = {}

        # 合约与自定义套利合约映射表
        self.contract_spd_mapping = {}

        # 保存委托数据的字典
        self.orderDict = {}

        # 保存活动委托数据的字典(即可撤销)
        self.workingOrderDict = {}

        # 读取保存在硬盘的合约数据
        self.loadContracts()

        # 注册事件监听
        self.registerEvent()

        # 已订阅合约代码
        self.subscribedSymbols = set()

    # ----------------------------------------------------------------------
    def updateContract(self, event):
        """更新合约数据"""
        contract = event.dict_['data']
        if contract.vtSymbol.endswith('99'):
            old_contract = self.contractDict.get(contract.vtSymbol, None)
            if old_contract is not None:
                contract.size = max(contract.size, old_contract.size)
                contract.longMarginRatio = max(contract.longMarginRatio,
                                               old_contract.longMarginRatio)
                contract.shortMarginRatio = max(contract.shortMarginRatio,
                                                old_contract.shortMarginRatio)

        self.contractDict[contract.vtSymbol] = contract
        self.contractDict[contract.symbol] = contract  # 使用常规代码(不包括交易所)可能导致重复

    # ----------------------------------------------------------------------
    def getContract(self, vtSymbol):
        """查询合约对象"""
        try:
            if vtSymbol in self.contractDict.keys():
                return self.contractDict[vtSymbol]

            return None
        except Exception as ex:
            print(str(ex), file=sys.stderr)
            return None

    # ----------------------------------------------------------------------
    def getAllContracts(self):
        """查询所有合约对象(返回列表)"""
        return list(self.contractDict.values())

    # ----------------------------------------------------------------------
    def saveContracts(self):
        """保存所有合约对象到硬盘"""
        self.mainEngine.writeLog(u'持久化合约数据')
        f = shelve.open(self.contractFilePath)
        f['data'] = self.contractDict
        f.close()

    # ----------------------------------------------------------------------
    def loadContracts(self):
        """从硬盘读取合约对象"""
        print(u'load contract data from:{}'.format(self.contractFilePath))
        f = shelve.open(self.contractFilePath)
        if 'data' in f:
            d = f['data']
            for key, value in d.items():
                self.contractDict[key] = value
        f.close()

        c = Custom_Contract()
        self.custom_contract_setting = c.get_config()
        d = c.get_contracts()
        if len(d) > 0:
            print(u'更新本地定制合约')
            self.contractDict.update(d)

        # 将leg1,leg2合约对应的自定义spd合约映射
        for spd_name in self.custom_contract_setting.keys():
            setting = self.custom_contract_setting.get(spd_name)
            leg1_symbol = setting.get('leg1_symbol')
            leg2_symbol = setting.get('leg2_symbol')

            for symbol in [leg1_symbol, leg2_symbol]:
                spd_mapping_list = self.contract_spd_mapping.get(symbol, [])

                # 更新映射
                if spd_name not in spd_mapping_list:
                    spd_mapping_list.append(spd_name)
                    self.contract_spd_mapping.update(
                        {symbol: spd_mapping_list})

    # ----------------------------------------------------------------------
    def updateOrder(self, event):
        """更新委托数据"""
        order = event.dict_['data']
        self.orderDict[order.vtOrderID] = order

        # 如果订单的状态是全部成交或者撤销,则需要从workingOrderDict中移除
        if order.status in [
                STATUS_ALLTRADED, STATUS_REJECTED, STATUS_CANCELLED
        ]:
            if order.vtOrderID in self.workingOrderDict:
                del self.workingOrderDict[order.vtOrderID]
        # 否则则更新字典中的数据
        else:
            self.workingOrderDict[order.vtOrderID] = order

    def check_self_trade_risk(self, vtSymbol, direction, price, gatewayName):
        """
        检查自成交
        :param vtSymbol:
        :param direction:
        :param price:
        :return:True;有风险;False:无风险
        """
        if len(self.workingOrderDict) == 0:
            return False

        try:
            if direction == DIRECTION_LONG:
                for order in list(self.workingOrderDict.values()):
                    if order.vtSymbol == vtSymbol and order.direction == DIRECTION_SHORT and order.gatewayName == gatewayName and order.price <= price:
                        self.mainEngine.writeNotification(
                            u'存在反向委托单:id:{},{},gw:{},order.price:{}<{},有自成交风险'.
                            format(order.vtOrderID, order.direction,
                                   order.gatewayName, order.price, price))
                        return True
            elif direction == DIRECTION_SHORT:
                for order in list(self.workingOrderDict.values()):
                    if order.vtSymbol == vtSymbol and order.direction == DIRECTION_LONG and order.gatewayName == gatewayName and order.price >= price:
                        self.mainEngine.writeNotification(
                            u'存在反向委托单:id:{},{},gw:{},order.price:{}>{},有自成交风险'.
                            format(order.vtOrderID, order.direction,
                                   order.gatewayName, order.price, price))
                        return True

            return False
        except Exception as ex:
            self.mainEngine.writeCritical(
                u'DataEngine check_self_trade_risk Exception:{} /{}'.format(
                    str(ex), traceback.format_exc()))
            return False

    # ----------------------------------------------------------------------
    def getOrder(self, vtOrderID):
        """查询委托单(报单)"""
        try:
            return self.orderDict[vtOrderID]
        except KeyError:
            return None

    # ----------------------------------------------------------------------
    def getAllWorkingOrders(self):
        """查询所有活动委托(返回列表)"""
        return list(self.workingOrderDict.values())

    # ----------------------------------------------------------------------
    def registerEvent(self):
        """注册事件监听"""
        self.eventEngine.register(EVENT_CONTRACT, self.updateContract)
        self.eventEngine.register(EVENT_ORDER, self.updateOrder)
        self.eventEngine.register(EVENT_POSITION, self.updatePosition)

    def clearData(self):
        """清空数据"""

        self.orderDict = {}
        self.workingOrderDict = {}
        self.subscribedSymbols.clear()

    def updatePosition(self, event):
        """更新持仓信息"""
        # 1、在获取更新持仓信息时,自动订阅这个symbol

        position = event.dict_['data']
        symbol = position.symbol

        if symbol is None:
            return

        if len(symbol) == 0:
            return

        # 已存在,不做更新
        if symbol in self.subscribedSymbols:
            return

        self.subscribedSymbols.add(symbol)

        gatewayName = position.gatewayName
        contract = self.mainEngine.getContract(symbol)

        if not contract:
            self.mainEngine.writeLog(
                u'vtEngine.updatePosition()找不到合约{0}信息'.format(symbol))
            return

        # 订阅合约
        req = VtSubscribeReq()
        req.symbol = symbol
        req.exchange = contract.exchange
        req.currency = ''
        req.productClass = ''

        self.mainEngine.subscribe(req, gatewayName)

        self.mainEngine.writeLog(u'自动订阅合约{0}'.format(symbol))
示例#15
0
文件: vtEngine.py 项目: zion302/vnpy
class DataEngine(object):
    """数据引擎"""
    contractFileName = 'ContractData.vt'
    contractFilePath = getTempPath(contractFileName)

    #----------------------------------------------------------------------
    def __init__(self, eventEngine):
        """Constructor"""
        self.eventEngine = eventEngine
        
        # 保存合约详细信息的字典
        self.contractDict = {}
        
        # 保存委托数据的字典
        self.orderDict = {}
        
        # 保存活动委托数据的字典(即可撤销)
        self.workingOrderDict = {}
        
        # 读取保存在硬盘的合约数据
        self.loadContracts()
        
        # 注册事件监听
        self.registerEvent()
        
    #----------------------------------------------------------------------
    def updateContract(self, event):
        """更新合约数据"""
        contract = event.dict_['data']
        self.contractDict[contract.vtSymbol] = contract
        self.contractDict[contract.symbol] = contract       # 使用常规代码(不包括交易所)可能导致重复
        
    #----------------------------------------------------------------------
    def getContract(self, vtSymbol):
        """查询合约对象"""
        try:
            return self.contractDict[vtSymbol]
        except KeyError:
            return None
        
    #----------------------------------------------------------------------
    def getAllContracts(self):
        """查询所有合约对象(返回列表)"""
        return self.contractDict.values()
    
    #----------------------------------------------------------------------
    def saveContracts(self):
        """保存所有合约对象到硬盘"""
        f = shelve.open(self.contractFilePath)
        f['data'] = self.contractDict
        f.close()
    
    #----------------------------------------------------------------------
    def loadContracts(self):
        """从硬盘读取合约对象"""
        f = shelve.open(self.contractFilePath)
        if 'data' in f:
            d = f['data']
            for key, value in d.items():
                self.contractDict[key] = value
        f.close()
        
    #----------------------------------------------------------------------
    def updateOrder(self, event):
        """更新委托数据"""
        order = event.dict_['data']        
        self.orderDict[order.vtOrderID] = order
        
        # 如果订单的状态是全部成交或者撤销,则需要从workingOrderDict中移除
        if order.status in [STATUS_ALLTRADED, STATUS_REJECTED, STATUS_CANCELLED]:
            if order.vtOrderID in self.workingOrderDict:
                del self.workingOrderDict[order.vtOrderID]
        # 否则则更新字典中的数据        
        else:
            self.workingOrderDict[order.vtOrderID] = order
        
    #----------------------------------------------------------------------
    def getOrder(self, vtOrderID):
        """查询委托"""
        try:
            return self.orderDict[vtOrderID]
        except KeyError:
            return None
    
    #----------------------------------------------------------------------
    def getAllWorkingOrders(self):
        """查询所有活动委托(返回列表)"""
        return self.workingOrderDict.values()
    
    #----------------------------------------------------------------------
    def registerEvent(self):
        """注册事件监听"""
        self.eventEngine.register(EVENT_CONTRACT, self.updateContract)
        self.eventEngine.register(EVENT_ORDER, self.updateOrder)
示例#16
0
class DataEngine(object):
    """数据引擎"""
    contractFileName = 'ContractData.vt'
    contractFilePath = getTempPath(contractFileName)

    FINISHED_STATUS = [STATUS_ALLTRADED, STATUS_REJECTED, STATUS_CANCELLED]

    TIME_RECORD_ACCOUNT = time(15, 2)
    TIME_RECORD_ACCOUNT_END = time(15, 20)

    #----------------------------------------------------------------------
    def __init__(self, eventEngine):
        """Constructor"""
        self.eventEngine = eventEngine

        # 保存合约详细信息的字典
        self.contractDict = {}

        # 保存委托数据的字典
        self.orderDict = {}

        # 保存活动委托数据的字典(即可撤销)
        self.workingOrderDict = {}

        # 持仓细节相关
        self.detailDict = {}  # vtSymbol:PositionDetail
        self.tdPenaltyList = globalSetting['tdPenalty']  # 平今手续费惩罚的产品代码列表

        # 读取保存在硬盘的合约数据
        self.loadContracts()

        self.orderResTime = None  ##由于持仓查询有延迟,所以持仓查询必须在onorder ontrader 没有返回后的15分钟才有效

        self.mysqlClient = None  ##mysql引擎
        self.accountIsRecord = False

        # 注册事件监听
        self.registerEvent()

    def setMysqlClient(self, mysqlClient):
        self.mysqlClient = mysqlClient

    #----------------------------------------------------------------------
    def registerEvent(self):
        """注册事件监听"""
        self.eventEngine.register(EVENT_CONTRACT, self.processContractEvent)
        self.eventEngine.register(EVENT_ORDER, self.processOrderEvent)
        self.eventEngine.register(EVENT_TRADE, self.processTradeEvent)
        self.eventEngine.register(EVENT_POSITION, self.processPositionEvent)
        self.eventEngine.register(EVENT_ACCOUNT, self.processAccountEvent)

    def processAccountEvent(self, event):
        account = event.dict_['data']
        ##下午3.05记录账号信息
        nowTime = datetime.now().time()
        if nowTime > self.TIME_RECORD_ACCOUNT and nowTime < self.TIME_RECORD_ACCOUNT_END:
            if self.mysqlClient and self.accountIsRecord == False:
                self.accountIsRecord = True
                self.mysqlClient.dbInsert(SQL_TABLENAME_ACCOUNT, account)

    #----------------------------------------------------------------------
    def processContractEvent(self, event):
        """处理合约事件"""
        contract = event.dict_['data']
        self.contractDict[contract.vtSymbol] = contract
        self.contractDict[contract.symbol] = contract  # 使用常规代码(不包括交易所)可能导致重复

    #----------------------------------------------------------------------
    def processOrderEvent(self, event):
        """处理委托事件"""

        order = event.dict_['data']
        self.orderDict[order.vtOrderID] = order

        # 如果订单的状态是全部成交或者撤销,则需要从workingOrderDict中移除
        if order.status in self.FINISHED_STATUS:
            if order.vtOrderID in self.workingOrderDict:
                del self.workingOrderDict[order.vtOrderID]
        # 否则则更新字典中的数据
        else:
            self.workingOrderDict[order.vtOrderID] = order

        # 更新到持仓细节中
        detail = self.getPositionDetail(order.vtSymbol)
        detail.updateOrder(order)

    #----------------------------------------------------------------------
    def processTradeEvent(self, event):
        """处理成交事件"""

        self.orderResTime = datetime.now()

        trade = event.dict_['data']

        # 更新到持仓细节中
        detail = self.getPositionDetail(trade.vtSymbol)
        detail.updateTrade(trade)

    #----------------------------------------------------------------------
    def processPositionEvent(self, event):
        """处理持仓事件"""
        if self.orderResTime:
            now = datetime.now()
            last_time = self.orderResTime + timedelta(seconds=15)
            if last_time > now:  ##1分钟内不更新持仓, 用trader更新
                return

        pos = event.dict_['data']
        #print(pos)
        # 更新到持仓细节中
        detail = self.getPositionDetail(pos.vtSymbol)
        detail.updatePosition(pos)

    #----------------------------------------------------------------------
    def getContract(self, vtSymbol):
        """查询合约对象"""
        try:
            return self.contractDict[vtSymbol]
        except KeyError:
            return None

    #----------------------------------------------------------------------
    def getAllContracts(self):
        """查询所有合约对象(返回列表)"""
        return self.contractDict.values()

    #----------------------------------------------------------------------
    def saveContracts(self):
        """保存所有合约对象到硬盘"""
        f = shelve.open(self.contractFilePath)
        f['data'] = self.contractDict
        f.close()

    #----------------------------------------------------------------------
    def loadContracts(self):
        """从硬盘读取合约对象"""
        f = shelve.open(self.contractFilePath)
        if 'data' in f:
            d = f['data']
            for key, value in d.items():
                self.contractDict[key] = value
        f.close()

    #----------------------------------------------------------------------
    def getOrder(self, vtOrderID):
        """查询委托"""
        try:
            return self.orderDict[vtOrderID]
        except KeyError:
            return None

    #----------------------------------------------------------------------
    def getAllWorkingOrders(self):
        """查询所有活动委托(返回列表)"""
        return self.workingOrderDict.values()

    def getAllPositionDetail(self):
        return self.detailDict

    #----------------------------------------------------------------------
    def getPositionDetail(self, vtSymbol):
        """查询持仓细节"""
        if vtSymbol in self.detailDict:
            detail = self.detailDict[vtSymbol]
        else:
            contract = self.getContract(vtSymbol)
            detail = PositionDetail(vtSymbol, contract)

            if not contract:  ##contract为空的时候不加入detailDict
                return detail

            self.detailDict[vtSymbol] = detail

            # 设置持仓细节的委托转换模式
            #contract = self.getContract(vtSymbol)

            if contract:
                detail.exchange = contract.exchange

                # 上期所合约
                if contract.exchange == EXCHANGE_SHFE:
                    detail.mode = detail.MODE_SHFE

                # 检查是否有平今惩罚
                for productID in self.tdPenaltyList:
                    if str(productID) in contract.symbol:
                        detail.mode = detail.MODE_TDPENALTY

        return detail

    #----------------------------------------------------------------------
    def updateOrderReq(self, req, vtOrderID):
        """委托请求更新"""
        vtSymbol = req.vtSymbol

        detail = self.getPositionDetail(vtSymbol)
        detail.updateOrderReq(req, vtOrderID)

    #----------------------------------------------------------------------
    def convertOrderReq(self, req):
        """根据规则转换委托请求"""
        detail = self.detailDict.get(req.vtSymbol, None)
        if not detail:
            return [req]
        else:
            return detail.convertOrderReq(req)
示例#17
0
class TcManager(QtWidgets.QWidget):
    """"""
    REQ_ADDRESS = 'tcp://localhost:2015'
    SUB_ADDRESS = 'tcp://localhost:2018'   
    REP_ADDRESS = 'tcp://*:2015'
    PUB_ADDRESS = 'tcp://*:2018'
    COPY_RATIO = '1'
    INTERVAL = '1'
    
    settingFileName = 'TradeCopy.vt'
    settingFilePath = getTempPath(settingFileName)
    
    signal = QtCore.Signal(type(Event()))

    #----------------------------------------------------------------------
    def __init__(self, tcEngine, eventEngine, parent=None):
        """Constructor"""
        super(TcManager, self).__init__(parent)
        
        self.tcEngine = tcEngine
        self.eventEngine = eventEngine
        
        self.initUi()
        self.loadSetting()
        self.registerEvent()
        
        self.tcEngine.writeLog(u'欢迎使用TradeCopy交易复制模块')
    
    #----------------------------------------------------------------------
    def initUi(self):
        """"""
        self.setWindowTitle(u'交易复制')
        self.setMinimumWidth(700)
        self.setMinimumHeight(700)
        
        # 创建组件
        self.lineReqAddress = QtWidgets.QLineEdit(self.REQ_ADDRESS)
        self.lineSubAddress= QtWidgets.QLineEdit(self.SUB_ADDRESS)
        self.lineRepAddress = QtWidgets.QLineEdit(self.REP_ADDRESS)
        self.linePubAddress = QtWidgets.QLineEdit(self.PUB_ADDRESS)
        
        validator = QtGui.QDoubleValidator()
        validator.setBottom(0)
        self.lineCopyRatio = QtWidgets.QLineEdit()
        self.lineCopyRatio.setValidator(validator)
        self.lineCopyRatio.setText(self.COPY_RATIO)
        
        validator2 = QtGui.QIntValidator()
        validator2.setBottom(1)
        self.lineInterval = QtWidgets.QLineEdit()
        self.lineInterval.setValidator(validator2)
        self.lineInterval.setText(self.INTERVAL)
        
        self.buttonProvider = QtWidgets.QPushButton(u'启动发布者')
        self.buttonProvider.clicked.connect(self.startProvider)
        
        self.buttonSubscriber = QtWidgets.QPushButton(u'启动订阅者')
        self.buttonSubscriber.clicked.connect(self.startSubscriber)
        
        self.buttonStopEngine = QtWidgets.QPushButton(u'停止')
        self.buttonStopEngine.clicked.connect(self.stopEngine)
        self.buttonStopEngine.setEnabled(False)
        
        self.buttonResetAddress = QtWidgets.QPushButton(u'重置地址')
        self.buttonResetAddress.clicked.connect(self.resetAddress)
        
        self.logMonitor = QtWidgets.QTextEdit()
        self.logMonitor.setReadOnly(True)
        
        self.widgetList = [
            self.lineCopyRatio,
            self.lineInterval,
            self.linePubAddress,
            self.lineSubAddress,
            self.lineRepAddress,
            self.lineReqAddress,
            self.buttonProvider,
            self.buttonSubscriber,
            self.buttonResetAddress
        ]
        
        # 布局
        QLabel = QtWidgets.QLabel
        grid = QtWidgets.QGridLayout()
        
        grid.addWidget(QLabel(u'响应地址'), 0, 0)
        grid.addWidget(self.lineRepAddress, 0, 1)
        grid.addWidget(QLabel(u'请求地址'), 0, 2)
        grid.addWidget(self.lineReqAddress, 0, 3)
        
        grid.addWidget(QLabel(u'发布地址'), 1, 0)
        grid.addWidget(self.linePubAddress, 1, 1)
        grid.addWidget(QLabel(u'订阅地址'), 1, 2)
        grid.addWidget(self.lineSubAddress, 1, 3)
        
        grid.addWidget(QLabel(u'发布间隔(秒)'), 2, 0)
        grid.addWidget(self.lineInterval, 2, 1)
        grid.addWidget(QLabel(u'复制比例(倍)'), 2, 2)
        grid.addWidget(self.lineCopyRatio, 2, 3)
        
        grid.addWidget(self.buttonProvider, 3, 0, 1, 2)
        grid.addWidget(self.buttonSubscriber, 3, 2, 1, 2)
        grid.addWidget(self.buttonStopEngine, 4, 0, 1, 2)
        grid.addWidget(self.buttonResetAddress, 4, 2, 1, 2)
        
        grid.addWidget(self.logMonitor, 5, 0, 1, 4)
        
        self.setLayout(grid)
    
    #----------------------------------------------------------------------
    def saveSetting(self):
        """"""
        f = shelve.open(self.settingFilePath)
        f['repAddress'] = self.lineRepAddress.text()
        f['reqAddress'] = self.lineReqAddress.text()
        f['pubAddress'] = self.linePubAddress.text()
        f['subAddress'] = self.lineSubAddress.text()
        f['copyRatio'] = self.lineCopyRatio.text()
        f['interval'] = self.lineInterval.text()
        f.close()
    
    #----------------------------------------------------------------------
    def loadSetting(self):
        """"""
        f = shelve.open(self.settingFilePath)
        if f:
            self.lineRepAddress.setText(f['repAddress'])
            self.lineReqAddress.setText(f['reqAddress'])
            self.linePubAddress.setText(f['pubAddress'])
            self.lineSubAddress.setText(f['subAddress'])
            self.lineCopyRatio.setText(f['copyRatio'])
            self.lineInterval.setText(f['interval'])
        f.close()        
    
    #----------------------------------------------------------------------
    def resetAddress(self):
        """"""
        self.lineReqAddress.setText(self.REQ_ADDRESS)
        self.lineRepAddress.setText(self.REP_ADDRESS)
        self.linePubAddress.setText(self.PUB_ADDRESS)
        self.lineSubAddress.setText(self.SUB_ADDRESS)
    
    #----------------------------------------------------------------------
    def stopEngine(self):
        """"""
        self.tcEngine.stop()
        
        for widget in self.widgetList:
            widget.setEnabled(True)
        self.buttonStopEngine.setEnabled(False)

    #----------------------------------------------------------------------
    def registerEvent(self):
        """"""
        self.signal.connect(self.processLogEvent)
        self.eventEngine.register(EVENT_TC_LOG, self.signal.emit)
    
    #----------------------------------------------------------------------
    def processLogEvent(self, event):
        """"""
        log = event.dict_['data']
        txt = '%s:  %s' %(log.logTime, log.logContent)
        self.logMonitor.append(txt)
    
    #----------------------------------------------------------------------
    def startProvider(self):
        """"""
        repAddress = str(self.lineRepAddress.text())
        pubAddress = str(self.linePubAddress.text())
        interval = int(self.lineInterval.text())
        self.tcEngine.startProvider(repAddress, pubAddress, interval)
        
        for widget in self.widgetList:
            widget.setEnabled(False)
        self.buttonStopEngine.setEnabled(True)
        
    #----------------------------------------------------------------------
    def startSubscriber(self):
        """"""
        reqAddress = str(self.lineReqAddress.text())
        subAddress = str(self.lineSubAddress.text())
        copyRatio = float(self.lineCopyRatio.text())
        self.tcEngine.startSubscriber(reqAddress, subAddress, copyRatio)
    
        for widget in self.widgetList:
            widget.setEnabled(False)
        self.buttonStopEngine.setEnabled(True)
示例#18
0
class OmEngine(object):
    """期权主引擎"""
    impvFileName = 'PricingImpv.vt'
    impvFilePath = getTempPath(impvFileName)

    #----------------------------------------------------------------------
    def __init__(self, mainEngine, eventEngine):
        """Constructor"""
        self.mainEngine = mainEngine
        self.eventEngine = eventEngine

        # """持仓组合"""
        self.portfolio = None
        self.optionContractDict = {}  # symbol:contract

        self.registerEvent()

    #----------------------------------------------------------------------
    def registerEvent(self):
        """注册事件监听"""
        self.eventEngine.register(EVENT_CONTRACT, self.processContractEvent)

    #----------------------------------------------------------------------
    def processTickEvent(self, event):
        """行情事件"""
        tick = event.dict_['data']
        self.portfolio.newTick(tick)

    #----------------------------------------------------------------------
    def processTradeEvent(self, event):
        """成交事件"""
        trade = event.dict_['data']
        self.portfolio.newTrade(trade)

    #----------------------------------------------------------------------
    def processContractEvent(self, event):
        """合约事件"""
        contract = event.dict_['data']
        if contract.symbol and contract.productClass == PRODUCT_OPTION:
            self.optionContractDict[contract.symbol] = contract

    #----------------------------------------------------------------------
    def subscribeEvent(self, symbol):
        """订阅对应合约的事件"""
        contract = self.mainEngine.getContract(symbol)
        if not contract:
            self.writeLog(u'行情订阅失败,找不到合约:%s' % symbol)
            return

        vtSymbol = contract.vtSymbol

        # 订阅行情
        req = VtSubscribeReq()
        req.symbol = contract.symbol
        req.exchange = contract.exchange

        gateway = self.mainEngine.getGateway(contract.gatewayName)
        if gateway.mdConnected:
            self.mainEngine.subscribe(req, contract.gatewayName)
        else:
            self.mainEngine.subscribe(req, 'SEC')
            self.mainEngine.subscribe(req, 'CSHSHLP')

        # 订阅事件
        if req.symbol == '510050':
            #做这个处理是因为,中信接口没有行情接口,需要用其他的接口获取行情,但是有时候会出现vtSymbol对应不上的情况
            self.eventEngine.register(EVENT_TICK + req.symbol,
                                      self.processTickEvent)
            vtSymbol = '510050.SSE'
        self.eventEngine.register(EVENT_TICK + vtSymbol, self.processTickEvent)
        self.eventEngine.register(EVENT_TRADE + vtSymbol,
                                  self.processTradeEvent)

    #----------------------------------------------------------------------
    def initEngine(self, fileName):
        """初始化引擎"""
        if self.portfolio:
            return False

        f = file(fileName)
        setting = json.load(f)

        # 读取定价模型
        model = MODEL_DICT.get(setting['model'], None)
        if not model:
            self.writeLog(u'找不到定价模型%s' % setting['model'])
            return

        # 创建标的对象
        underlyingDict = OrderedDict()

        for underlyingSymbol in setting['underlying']:
            contract = self.mainEngine.getContract(underlyingSymbol)
            if not contract:
                self.writeLog(u'找不到标的物合约%s' % underlyingSymbol)
                continue

            detail = self.mainEngine.getPositionDetail(contract.vtSymbol)
            underlying = OmUnderlying(contract, detail)
            underlyingDict[underlyingSymbol] = underlying

        # 创建期权链对象并初始化
        chainList = []
        futureList = []
        for d in setting['chain']:
            chainSymbol = d['chainSymbol']
            futureSymbol = d['futureSymbol']
            #查找对应的期货合约
            futureContact = self.mainEngine.getContract(futureSymbol)
            if not futureContact:
                self.writeLog(u'找不到期货合约%s' % futureSymbol)
                return

            detail = self.mainEngine.getPositionDetail(futureContact.vtSymbol)
            future = OmUnderlying(futureContact, detail)
            futureList.append(future)

            # 利率
            r = d['r']

            # 锁定标的对象
            underlying = underlyingDict.get(d['underlyingSymbol'], None)

            if not underlying:
                self.writeLog(u'%s期权链的标的合约%s尚未创建,请检查配置文件' %
                              (chainSymbol, underlyingSymbol))
                continue

            # 创建期权对象并初始化
            callDict = {}
            putDict = {}

            for symbol, contract in self.optionContractDict.items():
                if contract.underlyingSymbol == d['chainSymbol']:
                    detail = self.mainEngine.getPositionDetail(
                        contract.vtSymbol)
                    option = OmOption(contract, detail, underlying, model, r)
                    if contract.optionType is OPTION_CALL:
                        if option.k in callDict:
                            callDict[option.k + 0.0001] = option
                        else:
                            callDict[option.k] = option

                    else:
                        if option.k in putDict:
                            putDict[option.k + 0.0001] = option
                        else:
                            putDict[option.k] = option

            # 期权排序
            strikeList = callDict.keys()
            strikeList.sort()
            callList = [callDict[k] for k in strikeList]
            putList = [putDict[k] for k in strikeList]

            # 创建期权链

            chain = OmChain(underlying, chainSymbol, callList, putList, future)
            chainList.append(chain)

            # 添加标的映射关系

            underlying.addChain(chain)

        # 创建持仓组合对象并初始化
        self.portfolio = OmPortfolio(self.mainEngine, self.eventEngine,
                                     setting['name'], model,
                                     underlyingDict.values(), chainList,
                                     futureList)

        # 载入波动率配置
        self.loadImpvSetting()

        # 订阅行情和事件

        for underlying in underlyingDict.values():
            self.subscribeEvent(underlying.vtSymbol)

        for chain in chainList:
            self.subscribeEvent(chain.future.vtSymbol)
            for option in chain.optionDict.values():
                self.subscribeEvent(option.vtSymbol)

        # 载入成功返回
        return True

    #----------------------------------------------------------------------
    def loadImpvSetting(self):
        """载入波动率配置"""
        f = shelve.open(self.impvFilePath)

        for chain in self.portfolio.chainDict.values():
            for option in chain.optionDict.values():
                option.pricingImpv = f.get(option.symbol, 0)

        f.close()

    #----------------------------------------------------------------------
    def saveImpvSetting(self):
        """保存波动率配置"""
        if not self.portfolio:
            return

        f = shelve.open(self.impvFilePath)

        for chain in self.portfolio.chainDict.values():
            for option in chain.optionDict.values():
                f[option.symbol] = option.pricingImpv

        f.close()

    #----------------------------------------------------------------------
    def stop(self):
        """关闭函数"""
        self.saveImpvSetting()

    #----------------------------------------------------------------------
    def writeLog(self, content):
        """发出日志 """
        log = VtLogData()
        log.logContent = content

        event = Event(EVENT_OM_LOG)
        event.dict_['data'] = log
        self.eventEngine.put(event)
示例#19
0
class DataCache(object):
    """数据引擎"""
    contractFileName = 'ContractData.vt'
    contractFilePath = getTempPath(contractFileName)
    
    FINISHED_STATUS = [STATUS_ALLTRADED, STATUS_REJECTED, STATUS_CANCELLED]

    #----------------------------------------------------------------------
    def getTick(self, vtSymbol):
        """查询行情对象"""
        try:
            return self._dickLatestTick[vtSymbol]
        except KeyError:
            return None        
    
    #----------------------------------------------------------------------
    def getContract(self, vtSymbol):
        """查询合约对象"""
        try:
            return self._dictLatestContract[vtSymbol]
        except KeyError:
            return None
        
    #----------------------------------------------------------------------
    def getAllContracts(self):
        """查询所有合约对象(返回列表)"""
        return self._dictLatestContract.values()
    
    #----------------------------------------------------------------------
    def saveContracts(self):
        """保存所有合约对象到硬盘"""
        f = shelve.open(self.contractFilePath)
        f['data'] = self._dictLatestContract
        f.close()
    
    #----------------------------------------------------------------------
    def loadContracts(self):
        """从硬盘读取合约对象"""
        f = shelve.open(self.contractFilePath)
        if 'data' in f:
            d = f['data']
            for key, value in d.items():
                self._dictLatestContract[key] = value
        f.close()
        
    #----------------------------------------------------------------------
    def getOrder(self, vtOrderID):
        """查询委托"""
        try:
            return self._dictLatestOrder[vtOrderID]
        except KeyError:
            return None
    
    #----------------------------------------------------------------------
    def getAllWorkingOrders(self):
        """查询所有活动委托(返回列表)"""
        return self._dictWorkingOrder.values()
    
    #----------------------------------------------------------------------
    def getAllOrders(self):
        """获取所有委托"""
        return self._dictLatestOrder.values()
    
    #----------------------------------------------------------------------
    def getAllTrades(self):
        """获取所有成交"""
        return self._dictTrade.values()
    
    #----------------------------------------------------------------------
    def getAllPositions(self):
        """获取所有持仓"""
        return self._dictPositions.values()
    
    #----------------------------------------------------------------------
    def getAllAccounts(self):
        """获取所有资金"""
        return self._dictAccounts.values()
    
    #----------------------------------------------------------------------
    def getPositionDetail(self, vtSymbol):
        """查询持仓细节"""
        if vtSymbol in self._dictDetails:
            detail = self._dictDetails[vtSymbol]
        else:
            contract = self.getContract(vtSymbol)
            detail = PositionDetail(vtSymbol, contract)
            self._dictDetails[vtSymbol] = detail
            
            # 设置持仓细节的委托转换模式
            contract = self.getContract(vtSymbol)
            
            if contract:
                detail.exchange = contract.exchange
                
                # 上期所合约
                if contract.exchange == EXCHANGE_SHFE:
                    detail.mode = detail.MODE_SHFE
                
                # 检查是否有平今惩罚
                for productID in self._lstTdPenalty:
                    if str(productID) in contract.symbol:
                        detail.mode = detail.MODE_TDPENALTY
                
        return detail
    
    #----------------------------------------------------------------------
    def getAllPositionDetails(self):
        """查询所有本地持仓缓存细节"""
        return self._dictDetails.values()
    
    #----------------------------------------------------------------------
    def updateOrderReq(self, req, vtOrderID):
        """委托请求更新"""
        vtSymbol = req.vtSymbol
            
        detail = self.getPositionDetail(vtSymbol)
        detail.updateOrderReq(req, vtOrderID)
    
    #----------------------------------------------------------------------
    def convertOrderReq(self, req):
        """根据规则转换委托请求"""
        detail = self._dictDetails.get(req.vtSymbol, None)
        if not detail:
            return [req]
        else:
            return detail.convertOrderReq(req)

    #----------------------------------------------------------------------
    def getLog(self):
        """获取日志"""
        return self._lstLogs
    
    #----------------------------------------------------------------------
    def getError(self):
        """获取错误"""
        return self._lstErrors
示例#20
0
class DataEngine(object):
    """数据引擎"""
    contractFileName = 'ContractData.vt'
    contractFilePath = getTempPath(contractFileName)

    FINISHED_STATUS = [STATUS_ALLTRADED, STATUS_REJECTED, STATUS_CANCELLED]

    #----------------------------------------------------------------------
    def __init__(self, eventEngine):
        """Constructor"""
        self.eventEngine = eventEngine

        # 保存数据的字典和列表
        self.tickDict = {}
        self.contractDict = {}
        self.orderDict = {}
        self.workingOrderDict = {}  # 可撤销委托
        self.tradeDict = {}
        self.accountDict = {}
        self.positionDict = {}
        self.logList = []
        self.errorList = []

        # 持仓细节相关
        # self.detailDict = {}                                # vtSymbol:PositionDetail
        self.tdPenaltyList = globalSetting['tdPenalty']  # 平今手续费惩罚的产品代码列表

        # 读取保存在硬盘的合约数据
        self.loadContracts()

        # 注册事件监听
        self.registerEvent()

    #----------------------------------------------------------------------
    def registerEvent(self):
        """注册事件监听"""
        self.eventEngine.register(EVENT_TICK, self.processTickEvent)
        self.eventEngine.register(EVENT_CONTRACT, self.processContractEvent)
        self.eventEngine.register(EVENT_ORDER, self.processOrderEvent)
        self.eventEngine.register(EVENT_TRADE, self.processTradeEvent)
        self.eventEngine.register(EVENT_POSITION, self.processPositionEvent)
        self.eventEngine.register(EVENT_ACCOUNT, self.processAccountEvent)
        self.eventEngine.register(EVENT_LOG, self.processLogEvent)
        self.eventEngine.register(EVENT_ERROR, self.processErrorEvent)

    #----------------------------------------------------------------------
    def processTickEvent(self, event):
        """处理成交事件"""
        tick = event.dict_['data']
        self.tickDict[tick.vtSymbol] = tick

    #----------------------------------------------------------------------
    def processContractEvent(self, event):
        """处理合约事件"""
        contract = event.dict_['data']
        self.contractDict[contract.vtSymbol] = contract
        self.contractDict[contract.symbol] = contract  # 使用常规代码(不包括交易所)可能导致重复

    #----------------------------------------------------------------------
    def processOrderEvent(self, event):
        """处理委托事件"""
        order = event.dict_['data']
        self.orderDict[order.vtOrderID] = order

        # 如果订单的状态是全部成交或者撤销,则需要从workingOrderDict中移除
        if order.status in self.FINISHED_STATUS:
            if order.vtOrderID in self.workingOrderDict:
                del self.workingOrderDict[order.vtOrderID]
        # 否则则更新字典中的数据
        else:
            self.workingOrderDict[order.vtOrderID] = order

        # 更新到持仓细节中
        # detail = self.getPositionDetail(order.vtSymbol)
        # detail.updateOrder(order)

    #----------------------------------------------------------------------
    def processTradeEvent(self, event):
        """处理成交事件"""
        trade = event.dict_['data']

        self.tradeDict[trade.vtTradeID] = trade

        # 更新到持仓细节中
        # detail = self.getPositionDetail(trade.vtSymbol)
        # detail.updateTrade(trade)

    #----------------------------------------------------------------------
    def processPositionEvent(self, event):
        """处理持仓事件"""
        pos = event.dict_['data']

        self.positionDict[pos.vtPositionName] = pos

        # 更新到持仓细节中
        # detail = self.getPositionDetail(pos.vtSymbol)
        # detail.updatePosition(pos)

    #----------------------------------------------------------------------
    def processAccountEvent(self, event):
        """处理账户事件"""
        account = event.dict_['data']
        self.accountDict[account.vtAccountID] = account

    #----------------------------------------------------------------------
    def processLogEvent(self, event):
        """处理日志事件"""
        log = event.dict_['data']
        self.logList.append(log)

    #----------------------------------------------------------------------
    def processErrorEvent(self, event):
        """处理错误事件"""
        error = event.dict_['data']
        self.errorList.append(error)

    #----------------------------------------------------------------------
    def getTick(self, vtSymbol):
        """查询行情对象"""
        try:
            return self.tickDict[vtSymbol]
        except KeyError:
            return None

    #----------------------------------------------------------------------
    def getContract(self, vtSymbol):
        """查询合约对象"""
        try:
            return self.contractDict[vtSymbol]
        except KeyError:
            return None

    #----------------------------------------------------------------------
    def getAllContracts(self):
        """查询所有合约对象(返回列表)"""
        return self.contractDict.values()

    #----------------------------------------------------------------------
    def saveContracts(self):
        """保存所有合约对象到硬盘"""
        f = shelve.open(self.contractFilePath)
        f['data'] = self.contractDict
        f.close()

    #----------------------------------------------------------------------
    def loadContracts(self):
        """从硬盘读取合约对象"""
        f = shelve.open(self.contractFilePath)
        if 'data' in f:
            d = f['data']
            for key, value in d.items():
                self.contractDict[key] = value
        f.close()

    #----------------------------------------------------------------------
    def getOrder(self, vtOrderID):
        """查询委托"""
        try:
            return self.orderDict[vtOrderID]
        except KeyError:
            return None

    #----------------------------------------------------------------------
    def getAllWorkingOrders(self):
        """查询所有活动委托(返回列表)"""
        return self.workingOrderDict.values()

    #----------------------------------------------------------------------
    def getAllOrders(self):
        """获取所有委托"""
        return self.orderDict.values()

    #----------------------------------------------------------------------
    def getAllTrades(self):
        """获取所有成交"""
        return self.tradeDict.values()

    #----------------------------------------------------------------------
    def getAllPositions(self):
        """获取所有持仓"""
        return self.positionDict.values()

    #----------------------------------------------------------------------
    def getAllAccounts(self):
        """获取所有资金"""
        return self.accountDict.values()

    # #----------------------------------------------------------------------
    # def getPositionDetail(self, vtSymbol):
    #     """查询持仓细节"""
    #     if vtSymbol in self.detailDict:
    #         detail = self.detailDict[vtSymbol]
    #     else:
    #         contract = self.getContract(vtSymbol)
    #         detail = PositionDetail(vtSymbol, contract)
    #         self.detailDict[vtSymbol] = detail

    #         # 设置持仓细节的委托转换模式
    #         contract = self.getContract(vtSymbol)

    #         if contract:
    #             detail.exchange = contract.exchange

    #             # 上期所合约
    #             if contract.exchange == EXCHANGE_SHFE:
    #                 detail.mode = detail.MODE_SHFE

    #             # 检查是否有平今惩罚
    #             for productID in self.tdPenaltyList:
    #                 if str(productID) in contract.symbol:
    #                     detail.mode = detail.MODE_TDPENALTY

    #     return detail

    #----------------------------------------------------------------------
    # def getAllPositionDetails(self):
    #     """查询所有本地持仓缓存细节"""
    #     return self.detailDict.values()

    # #----------------------------------------------------------------------
    # def updateOrderReq(self, req, vtOrderID):
    #     """委托请求更新"""
    #     vtSymbol = req.vtSymbol

    #     detail = self.getPositionDetail(vtSymbol)
    #     detail.updateOrderReq(req, vtOrderID)

    # #----------------------------------------------------------------------
    # def convertOrderReq(self, req):
    #     """根据规则转换委托请求"""
    #     detail = self.detailDict.get(req.vtSymbol, None)
    #     if not detail:
    #         return [req]
    #     else:
    #         return detail.convertOrderReq(req)

    #----------------------------------------------------------------------
    def getLog(self):
        """获取日志"""
        return self.logList

    #----------------------------------------------------------------------
    def getError(self):
        """获取错误"""
        return self.errorList
示例#21
0
class DataEngine(object):
    """数据引擎"""
    contractFileName = 'ContractData.vt'
    contractFilePath = getTempPath(contractFileName)

    # ----------------------------------------------------------------------
    def __init__(self, mainEngine, eventEngine):
        """Constructor"""
        self.mainEngine = mainEngine
        self.eventEngine = eventEngine

        # 保存合约详细信息的字典
        self.contractDict = {}

        # 保存委托数据的字典
        self.orderDict = {}

        # 保存活动委托数据的字典(即可撤销)
        self.workingOrderDict = {}

        # 读取保存在硬盘的合约数据
        self.loadContracts()

        # 注册事件监听
        self.registerEvent()

        # 已订阅合约代码
        self.subscribedSymbols = set()

    # ----------------------------------------------------------------------
    def updateContract(self, event):
        """更新合约数据"""
        contract = event.dict_['data']
        self.contractDict[contract.vtSymbol] = contract
        self.contractDict[contract.symbol] = contract  # 使用常规代码(不包括交易所)可能导致重复

    # ----------------------------------------------------------------------
    def getContract(self, vtSymbol):
        """查询合约对象"""
        try:
            return self.contractDict[vtSymbol]
        except KeyError:
            return None

    # ----------------------------------------------------------------------
    def getAllContracts(self):
        """查询所有合约对象(返回列表)"""
        return list(self.contractDict.values())

    # ----------------------------------------------------------------------
    def saveContracts(self):
        """保存所有合约对象到硬盘"""
        f = shelve.open(self.contractFilePath)
        f['data'] = self.contractDict
        f.close()

    # ----------------------------------------------------------------------
    def loadContracts(self):
        """从硬盘读取合约对象"""
        print(u'load contract data from:{}'.format(self.contractFilePath))
        f = shelve.open(self.contractFilePath)
        if 'data' in f:
            d = f['data']
            for key, value in d.items():
                self.contractDict[key] = value
        f.close()

    # ----------------------------------------------------------------------
    def updateOrder(self, event):
        """更新委托数据"""
        order = event.dict_['data']
        self.orderDict[order.vtOrderID] = order

        # 如果订单的状态是全部成交或者撤销,则需要从workingOrderDict中移除
        if order.status in [
                STATUS_ALLTRADED, STATUS_REJECTED, STATUS_CANCELLED
        ]:
            if order.vtOrderID in self.workingOrderDict:
                del self.workingOrderDict[order.vtOrderID]
        # 否则则更新字典中的数据
        else:
            self.workingOrderDict[order.vtOrderID] = order

    # ----------------------------------------------------------------------
    def getOrder(self, vtOrderID):
        """查询委托单(报单)"""
        try:
            return self.orderDict[vtOrderID]
        except KeyError:
            return None

    # ----------------------------------------------------------------------
    def getAllWorkingOrders(self):
        """查询所有活动委托(返回列表)"""
        return list(self.workingOrderDict.values())

    # ----------------------------------------------------------------------
    def registerEvent(self):
        """注册事件监听"""
        self.eventEngine.register(EVENT_CONTRACT, self.updateContract)
        self.eventEngine.register(EVENT_ORDER, self.updateOrder)
        self.eventEngine.register(EVENT_POSITION, self.updatePosition)

    def clearData(self):
        """清空数据"""

        self.orderDict = {}
        self.workingOrderDict = {}
        self.subscribedSymbols.clear()

    def updatePosition(self, event):
        """更新持仓信息"""
        # 在获取更新持仓信息时,自动订阅这个symbol
        # 目的:1、

        position = event.dict_['data']
        symbol = position.symbol

        if symbol is None:
            return

        if len(symbol) == 0:
            return

        # 已存在,不做更新
        if symbol in self.subscribedSymbols:
            return

        self.subscribedSymbols.add(symbol)

        gatewayName = position.gatewayName
        contract = self.mainEngine.getContract(symbol)

        if not contract:
            self.mainEngine.writeLog(
                u'vtEngine.updatePosition()找不到合约{0}信息'.format(symbol))
            return

        # 订阅合约
        req = VtSubscribeReq()
        req.symbol = symbol
        req.exchange = contract.exchange
        req.currency = ''
        req.productClass = ''

        self.mainEngine.subscribe(req, gatewayName)

        self.mainEngine.writeLog(u'自动订阅合约{0}'.format(symbol))
示例#22
0
class StAlgoEngine(object):
    """价差算法交易引擎"""
    algoFileName = 'SpreadTradingAlgo.vt'
    algoFilePath = getTempPath(algoFileName)

    #----------------------------------------------------------------------
    def __init__(self, dataEngine, mainEngine, eventEngine):
        """Constructor"""
        self.dataEngine = dataEngine
        self.mainEngine = mainEngine
        self.eventEngine = eventEngine

        self.algoDict = {}  # spreadName:algo
        self.vtSymbolAlgoDict = {}  # vtSymbol:algo

        self.registerEvent()

    #----------------------------------------------------------------------
    def registerEvent(self):
        """注册事件监听"""
        self.eventEngine.register(EVENT_SPREADTRADING_TICK,
                                  self.processSpreadTickEvent)
        self.eventEngine.register(EVENT_SPREADTRADING_POS,
                                  self.processSpreadPosEvent)
        self.eventEngine.register(EVENT_TRADE, self.processTradeEvent)
        self.eventEngine.register(EVENT_ORDER, self.processOrderEvent)
        self.eventEngine.register(EVENT_TIMER, self.processTimerEvent)

    #----------------------------------------------------------------------
    def processSpreadTickEvent(self, event):
        """处理价差行情事件"""
        spread = event.dict_['data']

        # 若价差的买卖价均为0,则意味着尚未初始化,直接返回
        if not spread.bidPrice and not spread.askPrice:
            return

        algo = self.algoDict.get(spread.name, None)
        if algo:
            algo.updateSpreadTick(spread)

    #----------------------------------------------------------------------
    def processSpreadPosEvent(self, event):
        """处理价差持仓事件"""
        spread = event.dict_['data']

        algo = self.algoDict.get(spread.name, None)
        if algo:
            algo.updateSpreadPos(spread)

    #----------------------------------------------------------------------
    def processTradeEvent(self, event):
        """处理成交事件"""
        trade = event.dict_['data']

        algo = self.vtSymbolAlgoDict.get(trade.vtSymbol, None)
        if algo:
            algo.updateTrade(trade)

    #----------------------------------------------------------------------
    def processOrderEvent(self, event):
        """处理委托事件"""
        order = event.dict_['data']
        algo = self.vtSymbolAlgoDict.get(order.vtSymbol, None)

        if algo:
            algo.updateOrder(order)

    #----------------------------------------------------------------------
    def processTimerEvent(self, event):
        """"""
        for algo in self.algoDict.values():
            algo.updateTimer()

    #----------------------------------------------------------------------
    def sendOrder(self, vtSymbol, direction, offset, price, volume, payup=0):
        """发单"""
        contract = self.mainEngine.getContract(vtSymbol)
        if not contract:
            return ''

        req = VtOrderReq()
        req.symbol = contract.symbol
        req.exchange = contract.exchange
        req.vtSymbol = contract.vtSymbol
        req.direction = direction
        req.offset = offset
        req.volume = int(volume)
        req.priceType = PRICETYPE_LIMITPRICE

        if direction == DIRECTION_LONG:
            req.price = price + payup * contract.priceTick
        else:
            req.price = price - payup * contract.priceTick

        # 委托转换
        reqList = self.mainEngine.convertOrderReq(req)
        vtOrderIDList = []

        for req in reqList:
            vtOrderID = self.mainEngine.sendOrder(req, contract.gatewayName)
            vtOrderIDList.append(vtOrderID)

        return vtOrderIDList

    #----------------------------------------------------------------------
    def cancelOrder(self, vtOrderID):
        """撤单"""
        order = self.mainEngine.getOrder(vtOrderID)
        if not order:
            return

        req = VtCancelOrderReq()
        req.symbol = order.symbol
        req.exchange = order.exchange
        req.frontID = order.frontID
        req.sessionID = order.sessionID
        req.orderID = order.orderID

        self.mainEngine.cancelOrder(req, order.gatewayName)

    #----------------------------------------------------------------------
    def buy(self, vtSymbol, price, volume, payup=0):
        """买入"""
        l = self.sendOrder(vtSymbol, DIRECTION_LONG, OFFSET_OPEN, price,
                           volume, payup)
        return l

    #----------------------------------------------------------------------
    def sell(self, vtSymbol, price, volume, payup=0):
        """卖出"""
        l = self.sendOrder(vtSymbol, DIRECTION_SHORT, OFFSET_CLOSE, price,
                           volume, payup)
        return l

    #----------------------------------------------------------------------
    def short(self, vtSymbol, price, volume, payup=0):
        """卖空"""
        l = self.sendOrder(vtSymbol, DIRECTION_SHORT, OFFSET_OPEN, price,
                           volume, payup)
        return l

    #----------------------------------------------------------------------
    def cover(self, vtSymbol, price, volume, payup=0):
        """平空"""
        l = self.sendOrder(vtSymbol, DIRECTION_LONG, OFFSET_CLOSE, price,
                           volume, payup)
        return l

    #----------------------------------------------------------------------
    def putAlgoEvent(self, algo):
        """发出算法状态更新事件"""
        event = Event(EVENT_SPREADTRADING_ALGO + algo.name)
        self.eventEngine.put(event)

    #----------------------------------------------------------------------
    def writeLog(self, content):
        """输出日志"""
        log = VtLogData()
        log.logContent = content

        event = Event(EVENT_SPREADTRADING_ALGOLOG)
        event.dict_['data'] = log

        self.eventEngine.put(event)

    #----------------------------------------------------------------------
    def saveSetting(self):
        """保存算法配置"""
        setting = {}
        for algo in self.algoDict.values():
            setting[algo.spreadName] = algo.getAlgoParams()

        f = shelve.open(self.algoFilePath)
        f['setting'] = setting
        f.close()

    #----------------------------------------------------------------------
    def loadSetting(self):
        """加载算法配置"""
        # 创建算法对象
        l = self.dataEngine.getAllSpreads()
        for spread in l:
            algo = SniperAlgo(self, spread)
            self.algoDict[spread.name] = algo

            # 保存腿代码和算法对象的映射
            for leg in spread.allLegs:
                self.vtSymbolAlgoDict[leg.vtSymbol] = algo

        # 加载配置
        f = shelve.open(self.algoFilePath)
        setting = f.get('setting', None)
        f.close()

        if not setting:
            return

        for algo in self.algoDict.values():
            if algo.spreadName in setting:
                d = setting[algo.spreadName]
                algo.setAlgoParams(d)

    #----------------------------------------------------------------------
    def stopAll(self):
        """停止全部算法"""
        for algo in self.algoDict.values():
            algo.stop()

    #----------------------------------------------------------------------
    def startAlgo(self, spreadName):
        """启动算法"""
        algo = self.algoDict[spreadName]
        algoActive = algo.start()
        return algoActive

    #----------------------------------------------------------------------
    def stopAlgo(self, spreadName):
        """停止算法"""
        algo = self.algoDict[spreadName]
        algoActive = algo.stop()
        return algoActive

    #----------------------------------------------------------------------
    def getAllAlgoParams(self):
        """获取所有算法的参数"""
        return [algo.getAlgoParams() for algo in self.algoDict.values()]

    #----------------------------------------------------------------------
    def setAlgoBuyPrice(self, spreadName, buyPrice):
        """设置算法买开价格"""
        algo = self.algoDict[spreadName]
        algo.setBuyPrice(buyPrice)

    #----------------------------------------------------------------------
    def setAlgoSellPrice(self, spreadName, sellPrice):
        """设置算法卖平价格"""
        algo = self.algoDict[spreadName]
        algo.setSellPrice(sellPrice)

    #----------------------------------------------------------------------
    def setAlgoShortPrice(self, spreadName, shortPrice):
        """设置算法卖开价格"""
        algo = self.algoDict[spreadName]
        algo.setShortPrice(shortPrice)

    #----------------------------------------------------------------------
    def setAlgoCoverPrice(self, spreadName, coverPrice):
        """设置算法买平价格"""
        algo = self.algoDict[spreadName]
        algo.setCoverPrice(coverPrice)

    #----------------------------------------------------------------------
    def setAlgoMode(self, spreadName, mode):
        """设置算法工作模式"""
        algo = self.algoDict[spreadName]
        algo.setMode(mode)

    #----------------------------------------------------------------------
    def setAlgoMaxOrderSize(self, spreadName, maxOrderSize):
        """设置算法单笔委托限制"""
        algo = self.algoDict[spreadName]
        algo.setMaxOrderSize(maxOrderSize)

    #----------------------------------------------------------------------
    def setAlgoMaxPosSize(self, spreadName, maxPosSize):
        """设置算法持仓限制"""
        algo = self.algoDict[spreadName]
        algo.setMaxPosSize(maxPosSize)
示例#23
0
class DataEngine(object):
    """数据引擎"""
    contractFileName = 'ContractData.vt'
    # 获取存放临时文件的路径
    contractFilePath = getTempPath(contractFileName)

    # ----------------------------------------------------------------------
    def __init__(self, mainEngine, eventEngine):
        """Constructor"""
        self.mainEngine = mainEngine
        self.eventEngine = eventEngine

        # 保存合约详细信息的字典
        self.contractDict = {}

        # 保存委托数据的字典
        self.orderDict = {}

        # 保存活动委托数据的字典(即可撤销)
        self.workingOrderDict = {}

        # 读取保存在硬盘的合约数据
        self.loadContracts()

        # 注册事件监听
        self.registerEvent()

        # 已订阅合约代码
        self.subscribedSymbols = set()

    # ----------------------------------------------------------------------
    def updateContract(self, event):
        """更新合约数据"""
        contract = event.dict_['data']
        self.contractDict[contract.vtSymbol] = contract
        self.contractDict[contract.symbol] = contract  # 使用常规代码(不包括交易所)可能导致重复

    # ----------------------------------------------------------------------
    def getContract(self, vtSymbol):
        """查询合约对象"""
        try:
            # 返回合约字典中的合约对象
            return self.contractDict[vtSymbol]
        except KeyError:
            return None

    # ----------------------------------------------------------------------
    def getAllContracts(self):
        """查询所有合约对象(返回列表)"""
        return list(self.contractDict.values())

    # ----------------------------------------------------------------------
    def saveContracts(self):
        """保存所有合约对象到硬盘"""
        self.mainEngine.writeLog(u'持久化合约数据')
        f = shelve.open(self.contractFilePath)
        f['data'] = self.contractDict
        f.close()

    # ----------------------------------------------------------------------
    def loadContracts(self):
        """从硬盘读取合约对象"""
        print(u'load contract data from:{}'.format(self.contractFilePath))
        f = shelve.open(self.contractFilePath)
        if 'data' in f:
            d = f['data']
            for key, value in d.items():
                self.contractDict[key] = value
        f.close()

    # ----------------------------------------------------------------------
    def updateOrder(self, event):
        """更新委托数据"""
        order = event.dict_['data']
        self.orderDict[order.vtOrderID] = order

        # 如果订单的状态是全部成交或者撤销,则需要从workingOrderDict中移除
        if order.status in [
                STATUS_ALLTRADED, STATUS_REJECTED, STATUS_CANCELLED
        ]:
            if order.vtOrderID in self.workingOrderDict:
                del self.workingOrderDict[order.vtOrderID]
        # 否则则更新字典中的数据
        else:
            self.workingOrderDict[order.vtOrderID] = order

    def check_self_trade_risk(self, vtSymbol, direction, price, gatewayName):
        """
        检查自成交
        :param vtSymbol:
        :param direction:
        :param price:
        :return:True;有风险;False:无风险
        """
        if len(self.workingOrderDict) == 0:
            return False

        try:
            if direction == DIRECTION_LONG:
                for order in list(self.workingOrderDict.values()):
                    if order.vtSymbol == vtSymbol and order.direction == DIRECTION_SHORT and order.gatewayName == gatewayName and order.price <= price:
                        self.mainEngine.writeNotification(
                            u'存在反向委托单:id:{},{},gw:{},order.price:{}<{},有自成交风险'.
                            format(order.vtOrderID, order.direction,
                                   order.gatewayName, order.price, price))
                        return True
            elif direction == DIRECTION_SHORT:
                for order in list(self.workingOrderDict.values()):
                    if order.vtSymbol == vtSymbol and order.direction == DIRECTION_LONG and order.gatewayName == gatewayName and order.price >= price:
                        self.mainEngine.writeNotification(
                            u'存在反向委托单:id:{},{},gw:{},order.price:{}>{},有自成交风险'.
                            format(order.vtOrderID, order.direction,
                                   order.gatewayName, order.price, price))
                        return True

            return False
        except Exception as ex:
            self.mainEngine.writeCritical(
                u'DataEngine check_self_trade_risk Exception:{} /{}'.format(
                    str(ex), traceback.format_exc()))
            return False

    # ----------------------------------------------------------------------
    def getOrder(self, vtOrderID):
        """查询委托单(报单)"""
        try:
            return self.orderDict[vtOrderID]
        except KeyError:
            return None

    # ----------------------------------------------------------------------
    def getAllWorkingOrders(self):
        """查询所有活动委托(返回列表)"""
        return list(self.workingOrderDict.values())

    # ----------------------------------------------------------------------
    def registerEvent(self):
        """注册事件监听"""
        self.eventEngine.register(EVENT_CONTRACT, self.updateContract)
        self.eventEngine.register(EVENT_ORDER, self.updateOrder)
        self.eventEngine.register(EVENT_POSITION, self.updatePosition)

    def clearData(self):
        """清空数据"""

        self.orderDict = {}
        self.workingOrderDict = {}
        self.subscribedSymbols.clear()

    def updatePosition(self, event):
        """更新持仓信息"""
        # 在获取更新持仓信息时,自动订阅这个symbol

        position = event.dict_['data']
        symbol = position.symbol

        if symbol is None:
            return

        if len(symbol) == 0:
            return

        # 已存在,不做更新
        if symbol in self.subscribedSymbols:
            return

        # 加入已订阅合约代码列表
        self.subscribedSymbols.add(symbol)

        gatewayName = position.gatewayName

        # 查询合约对象
        contract = self.mainEngine.getContract(symbol)

        if not contract:
            self.mainEngine.writeLog(
                u'vtEngine.updatePosition()找不到合约{0}信息'.format(symbol))
            return

        # 订阅合约
        req = VtSubscribeReq()
        req.symbol = symbol
        req.exchange = contract.exchange
        req.currency = ''
        req.productClass = ''

        # 订阅特定接口的行情
        self.mainEngine.subscribe(req, gatewayName)

        self.mainEngine.writeLog(u'自动订阅合约{0}'.format(symbol))
示例#24
0
class OmEngine(object):
    """期权主引擎"""
    impvFileName = 'PricingImpv.vt'
    impvFilePath = getTempPath(impvFileName)

    #----------------------------------------------------------------------
    def __init__(self, mainEngine, eventEngine):
        """Constructor"""
        self.mainEngine = mainEngine
        self.eventEngine = eventEngine

        self.portfolio = None
        self.optionContractDict = {}  # symbol:contract

        self.strategyEngine = OmStrategyEngine(self, eventEngine)

        self.registerEvent()

    #----------------------------------------------------------------------
    def registerEvent(self):
        """注册事件监听"""
        self.eventEngine.register(EVENT_CONTRACT, self.processContractEvent)

    #----------------------------------------------------------------------
    def processTickEvent(self, event):
        """行情事件"""
        tick = event.dict_['data']
        self.portfolio.newTick(tick)

    #----------------------------------------------------------------------
    def processTradeEvent(self, event):
        """成交事件"""
        trade = event.dict_['data']
        self.portfolio.newTrade(trade)

    #----------------------------------------------------------------------
    def processContractEvent(self, event):
        """合约事件"""
        contract = event.dict_['data']
        if contract.symbol and contract.productClass == PRODUCT_OPTION:
            self.optionContractDict[contract.symbol] = contract

    #----------------------------------------------------------------------
    def subscribeEvent(self, symbol):
        """订阅对应合约的事件"""
        contract = self.mainEngine.getContract(symbol)
        if not contract:
            self.writeLog(u'行情订阅失败,找不到合约:%s' % symbol)
            return

        vtSymbol = contract.vtSymbol

        # 订阅行情
        req = VtSubscribeReq()
        req.symbol = contract.symbol
        req.exchange = contract.exchange
        self.mainEngine.subscribe(req, contract.gatewayName)

        # 订阅事件
        self.eventEngine.register(EVENT_TICK + vtSymbol, self.processTickEvent)
        self.eventEngine.register(EVENT_TRADE + vtSymbol,
                                  self.processTradeEvent)

    #----------------------------------------------------------------------
    def initEngine(self, fileName):
        """初始化引擎"""
        if self.portfolio:
            return False

        f = open(fileName)
        setting = json.load(f)
        f.close()

        # 读取定价模型
        model = MODEL_DICT.get(setting['model'], None)
        if not model:
            self.writeLog(u'找不到定价模型%s' % setting['model'])
            return

        # 创建标的对象
        underlyingDict = OrderedDict()

        for underlyingSymbol in setting['underlying']:
            contract = self.mainEngine.getContract(underlyingSymbol)
            if not contract:
                self.writeLog(u'找不到标的物合约%s' % underlyingSymbol)
                continue

            detail = self.mainEngine.getPositionDetail(contract.vtSymbol)

            underlying = OmUnderlying(contract, detail)
            underlyingDict[underlyingSymbol] = underlying

        # 创建期权链对象并初始化
        chainList = []

        for d in setting['chain']:
            chainSymbol = d['chainSymbol']
            r = d['r']

            # 锁定标的对象
            underlying = underlyingDict.get(d['underlyingSymbol'], None)
            if not underlying:
                self.writeLog(u'%s期权链的标的合约%s尚未创建,请检查配置文件' %
                              (chainSymbol, underlyingSymbol))
                continue

            # 创建期权对象并初始化
            callDict = {}
            putDict = {}

            for symbol, contract in self.optionContractDict.items():
                if contract.underlyingSymbol == d['chainSymbol']:
                    detail = self.mainEngine.getPositionDetail(
                        contract.vtSymbol)
                    option = OmOption(contract, detail, underlying, model, r)

                    key = str(option.k)
                    if contract.optionType is OPTION_CALL:
                        if key in callDict:
                            key += 'a'
                        callDict[key] = option
                    else:
                        if key in putDict:
                            key += 'a'
                        putDict[key] = option

            # 期权排序
            strikeList = sorted(callDict.keys())
            callList = [callDict[k] for k in strikeList]
            putList = [putDict[k] for k in strikeList]

            # 创建期权链
            chain = OmChain(chainSymbol, callList, putList)
            chainList.append(chain)

            # 添加标的映射关系
            underlying.addChain(chain)

        # 创建持仓组合对象并初始化
        self.portfolio = OmPortfolio(setting['name'], model,
                                     underlyingDict.values(), chainList)

        # 载入波动率配置
        self.loadImpvSetting()

        # 订阅行情和事件
        for underlying in underlyingDict.values():
            self.subscribeEvent(underlying.vtSymbol)

        for chain in chainList:
            for option in chain.optionDict.values():
                self.subscribeEvent(option.vtSymbol)

        # 载入成功返回
        return True

    #----------------------------------------------------------------------
    def loadImpvSetting(self):
        """载入波动率配置"""
        f = shelve.open(self.impvFilePath)

        for chain in self.portfolio.chainDict.values():
            for option in chain.optionDict.values():
                option.pricingImpv = f.get(option.symbol, 0)

        f.close()

    #----------------------------------------------------------------------
    def saveImpvSetting(self):
        """保存波动率配置"""
        if not self.portfolio:
            return

        f = shelve.open(self.impvFilePath)

        for chain in self.portfolio.chainDict.values():
            for option in chain.optionDict.values():
                f[option.symbol] = option.pricingImpv

        f.close()

    #----------------------------------------------------------------------
    def stop(self):
        """关闭函数"""
        self.saveImpvSetting()

    #----------------------------------------------------------------------
    def writeLog(self, content):
        """发出日志 """
        log = VtLogData()
        log.logContent = content

        event = Event(EVENT_OM_LOG)
        event.dict_['data'] = log
        self.eventEngine.put(event)

    #----------------------------------------------------------------------
    def adjustR(self):
        """调整折现率"""
        if self.portfolio:
            self.portfolio.adjustR()

        for chain in self.portfolio.chainDict.values():
            self.writeLog(u'期权链%s的折现率r拟合为%.3f' % (chain.symbol, chain.r))
class DataEngine(object):
    """数据引擎"""
    contractFileName = 'ContractData.vt'
    contractFilePath = getTempPath(contractFileName)

    FINISHED_STATUS = [STATUS_ALLTRADED, STATUS_REJECTED, STATUS_CANCELLED]

    #----------------------------------------------------------------------
    def __init__(self, eventEngine):
        """Constructor"""
        self.eventEngine = eventEngine

        # 保存数据的字典和列表
        self.tickDict = {}
        self.contractDict = {}
        self.orderDict = {}
        self.workingOrderDict = {}  # 可撤销委托
        self.tradeDict = {}
        self.accountDict = {}
        self.positionDict = {}
        self.logList = []
        self.errorList = []

        # 持仓细节相关
        self.detailDict = {}  # vtSymbol:PositionDetail
        self.tdPenaltyList = globalSetting['tdPenalty']  # 平今手续费惩罚的产品代码列表

        # 读取保存在硬盘的合约数据
        self.loadContracts()
        self.posBufferDict = {}  #持仓缓存
        # 注册事件监听
        self.registerEvent()

    #----------------------------------------------------------------------
    def registerEvent(self):
        """注册事件监听"""
        self.eventEngine.register(EVENT_TICK, self.processTickEvent)
        self.eventEngine.register(EVENT_CONTRACT, self.processContractEvent)
        self.eventEngine.register(EVENT_ORDER, self.processOrderEvent)
        self.eventEngine.register(EVENT_TRADE, self.processTradeEvent)
        self.eventEngine.register(EVENT_POSITION, self.processPositionEvent)
        self.eventEngine.register(EVENT_ACCOUNT, self.processAccountEvent)

        self.eventEngine.register(EVENT_LOG, self.processLogEvent)
        self.eventEngine.register(EVENT_ERROR, self.processErrorEvent)

    #----------------------------------------------------------------------

    def putMsg(self, q):
        """处理账户事件"""
        q.put(self.accountDict, block=False)

    def putPos(self, q):
        """推送持仓"""

        q.put(self.detailDict, block=False)

    #----------------------------------------------------------------------
    def processTickEvent(self, event):
        """处理成交事件"""
        tick = event.dict_['data']
        print "tick: ", tick.vtSymbol, tick.askPrice1
        self.tickDict[tick.vtSymbol] = tick

    #----------------------------------------------------------------------
    def processContractEvent(self, event):
        """处理合约事件"""
        contract = event.dict_['data']
        self.contractDict[contract.vtSymbol] = contract
        self.contractDict[contract.symbol] = contract  # 使用常规代码(不包括交易所)可能导致重复

    #----------------------------------------------------------------------
    def processOrderEvent(self, event):
        """处理委托事件"""
        order = event.dict_['data']
        self.orderDict[order.vtOrderID] = order

        # 如果订单的状态是全部成交或者撤销,则需要从workingOrderDict中移除
        if order.status in self.FINISHED_STATUS:
            if order.vtOrderID in self.workingOrderDict:
                del self.workingOrderDict[order.vtOrderID]
        # 否则则更新字典中的数据
        else:
            self.workingOrderDict[order.vtOrderID] = order

        # 更新到持仓细节中
        detail = self.getPositionDetail(order.vtSymbol)
        detail.updateOrder(order)

    #----------------------------------------------------------------------
    def processTradeEvent(self, event):
        """处理成交事件"""
        trade = event.dict_['data']

        self.tradeDict[trade.vtTradeID] = trade

        # 更新到持仓细节中
        detail = self.getPositionDetail(trade.vtSymbol)
        detail.updateTrade(trade)
        ## 更新持仓缓存数据

        #posBuffer = self.posBufferDict.get(trade.vtSymbol, None)
        #if not posBuffer:
        #posBuffer = PositionBuffer()
        #posBuffer.vtSymbol = trade.vtSymbol
        #self.posBufferDict[trade.vtSymbol] = posBuffer
        #posBuffer.updateTradeData(trade)

    #----------------------------------------------------------------------
    def updateTradeData(self, trade):
        """更新成交数据"""
        if trade.direction == DIRECTION_LONG:
            # 多方开仓,则对应多头的持仓和今仓增加
            if trade.offset == OFFSET_OPEN:
                self.longPosition += trade.volume
                self.longToday += trade.volume
            # 多方平今,对应空头的持仓和今仓减少
            elif trade.offset == OFFSET_CLOSETODAY:
                self.shortPosition -= trade.volume
                self.shortToday -= trade.volume
            # 多方平昨,对应空头的持仓和昨仓减少
            else:
                self.shortPosition -= trade.volume
                self.shortYd -= trade.volume
        else:
            # 空头和多头相同
            if trade.offset == OFFSET_OPEN:
                self.shortPosition += trade.volume
                self.shortToday += trade.volume
            elif trade.offset == OFFSET_CLOSETODAY:
                self.longPosition -= trade.volume
                self.longToday -= trade.volume
            else:
                self.longPosition -= trade.volume
                self.longYd -= trade.volume

    #----------------------------------------------------------------------
    def processPositionEvent(self, event):
        """处理持仓事件"""
        pos = event.dict_['data']

        self.positionDict[pos.vtPositionName] = pos

        # 更新到持仓细节中
        detail = self.getPositionDetail(pos.vtSymbol)
        detail.updatePosition(pos)
        # 更新持仓缓存数据

        #posBuffer = self.posBufferDict.get(pos.vtSymbol, None)
        #if not posBuffer:
        #posBuffer = PositionBuffer()
        #posBuffer.vtSymbol = pos.vtSymbol
        #self.posBufferDict[pos.vtSymbol] = posBuffer
        #posBuffer.updatePositionData(pos)

#----------------------------------------------------------------------

    def updatePositionData(self, pos):
        """更新持仓数据"""
        if pos.direction == DIRECTION_LONG:
            self.longPosition = pos.position
            self.longYd = pos.ydPosition
            self.longToday = self.longPosition - self.longYd
        else:
            self.shortPosition = pos.position
            self.shortYd = pos.ydPosition
            self.shortToday = self.shortPosition - self.shortYd

    #----------------------------------------------------------------------
    def processAccountEvent(self, event):
        """处理账户事件"""
        account = event.dict_['data']
        self.accountDict[account.vtAccountID] = account
    # print account.vtAccountID , " banlance: ", account.balance

    #----------------------------------------------------------------------

    def processLogEvent(self, event):
        """处理日志事件"""
        log = event.dict_['data']
        self.logList.append(log)

    #----------------------------------------------------------------------
    def processErrorEvent(self, event):
        """处理错误事件"""
        error = event.dict_['data']
        self.errorList.append(error)

    #----------------------------------------------------------------------
    def getTick(self, vtSymbol):
        """查询行情对象"""
        try:
            return self.tickDict[vtSymbol]
        except KeyError:
            return None

    #----------------------------------------------------------------------
    def getContract(self, vtSymbol):
        """查询合约对象"""
        try:
            return self.contractDict[vtSymbol]
        except KeyError:
            return None

    #----------------------------------------------------------------------
    def getAllContracts(self):
        """查询所有合约对象(返回列表)"""
        return self.contractDict.values()

    #----------------------------------------------------------------------
    def saveContracts(self):
        """保存所有合约对象到硬盘"""
        f = shelve.open(self.contractFilePath)
        f['data'] = self.contractDict
        f.close()

    #----------------------------------------------------------------------
    def loadContracts(self):
        """从硬盘读取合约对象"""
        f = shelve.open(self.contractFilePath)
        if 'data' in f:
            d = f['data']
            for key, value in d.items():
                self.contractDict[key] = value
        f.close()

    #----------------------------------------------------------------------
    def getOrder(self, vtOrderID):
        """查询委托"""
        try:
            return self.orderDict[vtOrderID]
        except KeyError:
            return None

    #----------------------------------------------------------------------
    def getAllWorkingOrders(self):
        """查询所有活动委托(返回列表)"""
        return self.workingOrderDict.values()

    #-----------------------------------------r-----------------------------
    def getAllOrders(self):
        """获取所有委托"""
        return self.orderDict.values()

    #----------------------------------------------------------------------
    def getAllTrades(self):
        """获取所有成交"""
        return self.tradeDict.values()

    #----------------------------------------------------------------------
    def getAllPositions(self):
        """获取所有持仓"""
        return self.positionDict.values()

    #----------------------------------------------------------------------
    def getAllAccounts(self):
        """获取所有资金"""
        return self.accountDict.values()

    #----------------------------------------------------------------------
    def getPositionDetail(self, vtSymbol):
        """查询持仓细节"""
        if vtSymbol in self.detailDict:
            detail = self.detailDict[vtSymbol]
        else:
            contract = self.getContract(vtSymbol)
            detail = PositionDetail(vtSymbol, contract)
            self.detailDict[vtSymbol] = detail

            # 设置持仓细节的委托转换模式
            contract = self.getContract(vtSymbol)

            if contract:
                detail.exchange = contract.exchange

                # 上期所合约
                if contract.exchange == EXCHANGE_SHFE:
                    detail.mode = detail.MODE_SHFE

                # 检查是否有平今惩罚
                for productID in self.tdPenaltyList:
                    if str(productID) in contract.symbol:
                        detail.mode = detail.MODE_TDPENALTY

        return detail

    #----------------------------------------------------------------------
    def getAllPositionDetails(self):
        """查询所有本地持仓缓存细节"""
        return self.detailDict.values()

    #----------------------------------------------------------------------
    def updateOrderReq(self, req, vtOrderID):
        """委托请求更新"""
        vtSymbol = req.vtSymbol

        detail = self.getPositionDetail(vtSymbol)
        detail.updateOrderReq(req, vtOrderID)

    #----------------------------------------------------------------------
    def convertOrderReq(self, req):
        """根据规则转换委托请求"""
        detail = self.detailDict.get(req.vtSymbol, None)
        if not detail:
            return [req]
        else:
            return detail.convertOrderReq(req)

    #----------------------------------------------------------------------
    def getLog(self):
        """获取日志"""
        return self.logList

    #----------------------------------------------------------------------
    def getError(self):
        """获取错误"""
        return self.errorList