Ejemplo n.º 1
0
    def __init__(self, eventEngine, gatewayName=''):
        """Constructor"""
        super(BinanceGateway, self).__init__(eventEngine, gatewayName)

        self.api = GatewayApi(self)

        self.qryEnabled = False         # 是否要启动循环查询

        self.fileName = self.gatewayName + '_connect.json'
        self.filePath = getJsonPath(self.fileName, __file__)
Ejemplo n.º 2
0
    def __init__(self, eventEngine, mdEngine, gatewayName='BITMEX'):
        """Constructor"""
        super(BitmexGateway, self).__init__(eventEngine, mdEngine, gatewayName)

        self.localID = 100

        self.accountDict = {}
        self.orderDict = {}
        self.localOrderDict = {}
        self.orderLocalDict = {}

        self.restApi = BitmexFutureRestApi(self)
        self.marketWsApi = BitmexFutureMarketWsApi(self)

        self.qryEnabled = False  # 是否要启动循环查询

        self.fileName = 'c:\dxTrader\connection.json'
        self.filePath = getJsonPath(self.fileName, __file__)
Ejemplo n.º 3
0
class StrEngine(object):
    """Str trading engine"""
    settingFileName = 'str_setting.json'
    settingFilePath = getJsonPath(settingFileName, __file__)

    STATUS_FINISHED = set(
        [STATUS_REJECTED, STATUS_CANCELLED, STATUS_ALLTRADED])

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

        # 当前日期
        self.today = todayDate()

        # 保存策略实例的字典
        # key为策略名称,value为策略实例,注意策略名称不允许重复
        self.strategyDict = {}

        # 保存vtSymbol和策略实例映射的字典(用于推送tick数据)
        # 由于可能多个strategy交易同一个vtSymbol,因此key为vtSymbol
        # value为包含所有相关strategy对象的list
        self.tickStrategyDict = {}

        # 保存vtOrderID和strategy对象映射的字典(用于推送order和trade数据)
        # key为vtOrderID,value为strategy对象
        self.orderStrategyDict = {}

        # 本地停止单编号计数
        self.stopOrderCount = 0
        # stopOrderID = STOPORDERPREFIX + str(stopOrderCount)

        # 本地停止单字典
        # key为stopOrderID,value为stopOrder对象
        self.stopOrderDict = {}  # 停止单撤销后不会从本字典中删除
        self.workingStopOrderDict = {}  # 停止单撤销后会从本字典中删除

        # 保存策略名称和委托号列表的字典
        # key为name,value为保存orderID(限价+本地停止)的集合
        self.strategyOrderDict = {}

        # 成交号集合,用来过滤已经收到过的成交推送
        self.tradeSet = set()

        # 引擎类型为实盘
        self.engineType = ENGINETYPE_TRADING

        # RQData数据服务
        self.rq = None

        # RQData能获取的合约代码列表
        self.rqSymbolSet = set()

        # 初始化RQData服务
        #self.initRqData()

        # 注册日式事件类型
        self.mainEngine.registerLogEvent(EVENT_STR_LOG)

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

    #----------------------------------------------------------------------
    def sendOrder(self,
                  symbol,
                  orderType,
                  price,
                  volume,
                  priceType,
                  stopLossPx=None,
                  takeProfPx=None,
                  strategy=None):
        """发单"""
        contract = self.mainEngine.getContract(symbol)

        req = VtOrderReq()
        req.symbol = contract.symbol
        req.exchange = contract.exchange
        req.vtSymbol = contract.vtSymbol
        req.price = self.roundToPriceTick(contract.priceTick, price)
        req.volume = volume

        req.productClass = contract.productClass
        #req.currency = contract.currency

        # 设计为CTA引擎发出的委托只允许使用限价单
        req.priceType = priceType

        # CTA委托类型映射
        if orderType == STR_ORDER_BUY:
            req.direction = DIRECTION_LONG
            #req.offset = OFFSET_OPEN

        elif orderType == STR_ORDER_SELL:
            req.direction = DIRECTION_SHORT
            #req.offset = OFFSET_CLOSE

        #elif order['type'] == CTAORDER_SHORT:
        #req.direction = DIRECTION_SHORT
        ##req.offset = OFFSET_OPEN

        #elif order['type'] == CTAORDER_COVER:
        #req.direction = DIRECTION_LONG
        #req.offset = OFFSET_CLOSE

        # order converter
        if stopLossPx:
            req.stopLossPx = stopLossPx
            #req.priceType = PRICETYPE_STOPLIMIT

        if takeProfPx:
            req.takeProfPx = takeProfPx

        #reqList = self.convertOrderReq(req, stopLossPx, takeProfPx)
        #vtOrderIDList = []

        #if not reqList:
        #return vtOrderIDList

        #for convertedReq in reqList:
        vtOrderIDList = self.mainEngine.sendOrder(req,
                                                  contract.gatewayName)  # 发单
        for vtOrderID in vtOrderIDList:
            self.orderStrategyDict[vtOrderID] = strategy  # 保存vtOrderID和策略的映射关系
            self.strategyOrderDict[strategy.name].add(vtOrderID)  # 添加到策略委托号集合中
        #vtOrderIDList.append(vtOrderID)

        #self.writeStrLog(u'策略%s发送委托,%s,%s,%s@%s'
        #%(strategy.name, vtSymbol, req.direction, volume, price))

        return vtOrderIDList

    #----------------------------------------------------------------------
    def convertOrderReq(req, stopLossPx, takeProfPx):
        if req.exchange == EXCHANGE_BITMEX:
            pass
        elif req.exchange in [
                EXCHANGE_DERIBIT,
        ]:  # exchanges do not support bulk orders.
            pass
            #slReq = deepcopy(req)
            #slReq.price = stopLossPx
            #slReq.direction = directionRevMap.get(req.direction)

            #spReq = deepcopy(req)
            #spReq.price = takeProfPx
            #spReq.direction = directionRevMap.get(req.direction)

            #return [req, slReq, spReq]

    #----------------------------------------------------------------------
    def qryBar(self, strategy, interval='1m', limit=1000):
        gwList = []
        for vtSymbol in strategy.vtSymbols:
            contract = self.mainEngine.getContract(vtSymbol)
            self.mainEngine.qryBar(contract.gatewayName, contract.symbol,
                                   interval, limit)

    #----------------------------------------------------------------------
    def qryOrder(self, strategy, openOnly=False):
        gwList = []
        for vtSymbol in strategy.vtSymbols:
            gatewayName = self.mainEngine.getContract(vtSymbol).gatewayName

            if gatewayName not in gwList:
                self.mainEngine.qryOrder(gatewayName, openOnly)
                gwList.append(gatewayName)

    #----------------------------------------------------------------------
    def qryPosition(self, strategy):
        gwList = []
        for vtSymbol in strategy.vtSymbols:
            gatewayName = self.mainEngine.getContract(vtSymbol).gatewayName

            if gatewayName not in gwList:
                self.mainEngine.qryPosition(gatewayName)
                gwList.append(gatewayName)

    #----------------------------------------------------------------------
    def cancelOrder(self, vtOrderID):
        """撤单"""
        # 查询报单对象
        order = self.mainEngine.getOrder(vtOrderID)

        # 如果查询成功
        if order:
            # 检查是否报单还有效,只有有效时才发出撤单指令
            orderFinished = (order.status == STATUS_ALLTRADED
                             or order.status == STATUS_CANCELLED)
            if not orderFinished:
                req = VtCancelOrderReq()
                req.symbol = order.symbol
                req.exchange = order.exchange
                req.frontID = order.frontID
                req.sessionID = order.sessionID
                req.orderID = order.orderSysID  # use the sys id
                self.mainEngine.cancelOrder(req, order.gatewayName)

    #----------------------------------------------------------------------
    def sendStopOrder(self, vtSymbol, orderType, price, volume, strategy):
        """发停止单(本地实现)"""
        self.stopOrderCount += 1
        stopOrderID = STOPORDERPREFIX + str(self.stopOrderCount)

        so = StopOrder()
        so.vtSymbol = vtSymbol
        so.orderType = orderType
        so.price = price
        so.volume = volume
        so.strategy = strategy
        so.stopOrderID = stopOrderID
        so.status = STOPORDER_WAITING

        if orderType == STR_ORDER_BUY:
            so.direction = DIRECTION_LONG
            so.offset = OFFSET_OPEN
        elif orderType == STR_ORDER_SELL:
            so.direction = DIRECTION_SHORT
            so.offset = OFFSET_CLOSE
        elif orderType == STR_ORDER_SHORT:
            so.direction = DIRECTION_SHORT
            so.offset = OFFSET_OPEN
        elif orderType == STR_ORDER_COVER:
            so.direction = DIRECTION_LONG
            so.offset = OFFSET_CLOSE

        # 保存stopOrder对象到字典中
        self.stopOrderDict[stopOrderID] = so
        self.workingStopOrderDict[stopOrderID] = so

        # 保存stopOrderID到策略委托号集合中
        self.strategyOrderDict[strategy.name].add(stopOrderID)

        # 推送停止单状态
        strategy.onStopOrder(so)

        return [stopOrderID]

    #----------------------------------------------------------------------
    def cancelStopOrder(self, stopOrderID):
        """撤销停止单"""
        # 检查停止单是否存在
        if stopOrderID in self.workingStopOrderDict:
            so = self.workingStopOrderDict[stopOrderID]
            strategy = so.strategy

            # 更改停止单状态为已撤销
            so.status = STOPORDER_CANCELLED

            # 从活动停止单字典中移除
            del self.workingStopOrderDict[stopOrderID]

            # 从策略委托号集合中移除
            s = self.strategyOrderDict[strategy.name]
            if stopOrderID in s:
                s.remove(stopOrderID)

            # 通知策略
            strategy.onStopOrder(so)

    #----------------------------------------------------------------------
    def processStopOrder(self, tick):
        """收到行情后处理本地停止单(检查是否要立即发出)"""
        vtSymbol = tick.vtSymbol

        # 首先检查是否有策略交易该合约
        if vtSymbol in self.tickStrategyDict:
            # 遍历等待中的停止单,检查是否会被触发
            for so in self.workingStopOrderDict.values():
                if so.vtSymbol == vtSymbol:
                    longTriggered = so.direction == DIRECTION_LONG and tick.lastPrice >= so.price  # 多头停止单被触发
                    shortTriggered = so.direction == DIRECTION_SHORT and tick.lastPrice <= so.price  # 空头停止单被触发

                    if longTriggered or shortTriggered:
                        # 买入和卖出分别以涨停跌停价发单(模拟市价单)
                        # 对于没有涨跌停价格的市场则使用5档报价
                        if so.direction == DIRECTION_LONG:
                            if tick.upperLimit:
                                price = tick.upperLimit
                            else:
                                price = tick.askPrice5
                        else:
                            if tick.lowerLimit:
                                price = tick.lowerLimit
                            else:
                                price = tick.bidPrice5

                        # 发出市价委托
                        vtOrderID = self.sendOrder(so.vtSymbol, so.orderType,
                                                   price, so.volume,
                                                   so.strategy)

                        # 检查因为风控流控等原因导致的委托失败(无委托号)
                        if vtOrderID:
                            # 从活动停止单字典中移除该停止单
                            del self.workingStopOrderDict[so.stopOrderID]

                            # 从策略委托号集合中移除
                            s = self.strategyOrderDict[so.strategy.name]
                            if so.stopOrderID in s:
                                s.remove(so.stopOrderID)

                            # 更新停止单状态,并通知策略
                            so.status = STOPORDER_TRIGGERED
                            so.strategy.onStopOrder(so)

    #----------------------------------------------------------------------
    def processTickEvent(self, event):
        """处理行情推送"""
        tick = event.dict_['data']
        tick = copy(tick)

        # 收到tick行情后,先处理本地停止单(检查是否要立即发出)
        self.processStopOrder(tick)

        # 推送tick到对应的策略实例进行处理
        if tick.vtSymbol in self.tickStrategyDict:

            # 逐个推送到策略实例中
            l = self.tickStrategyDict[tick.vtSymbol]
            for strategy in l:
                if strategy.inited:
                    self.callStrategyFunc(strategy, strategy.onTick, tick)

        #----------------------------------------------------------------------
    def processBarEvent(self, event):
        """处理行情推送"""
        bar = event.dict_['data']
        bar = copy(bar)

        # 推送bar到对应的策略实例进行处理
        if bar.vtSymbol in self.tickStrategyDict:

            # 逐个推送到策略实例中
            l = self.tickStrategyDict[bar.vtSymbol]
            for strategy in l:
                self.callStrategyFunc(strategy, strategy.onBar, bar)

    #----------------------------------------------------------------------
    def processMarketTradeEvent(self, event):
        mt = event.dict_['data']
        mt = copy(mt)

        # 推送tick到对应的策略实例进行处理
        if mt.vtSymbol in self.tickStrategyDict:

            l = self.tickStrategyDict[mt.vtSymbol]
            for strategy in l:
                if strategy.inited:
                    self.callStrategyFunc(strategy, strategy.onMarketTrade, mt)

    #----------------------------------------------------------------------
    def processOrderEvent(self, event):
        """处理委托推送"""
        order = event.dict_['data']

        vtOrderID = order.vtOrderID

        if vtOrderID in self.orderStrategyDict:
            strategy = self.orderStrategyDict[vtOrderID]

            # 如果委托已经完成(拒单、撤销、全成),则从活动委托集合中移除
            if order.status in self.STATUS_FINISHED:
                s = self.strategyOrderDict[strategy.name]
                if vtOrderID in s:
                    s.remove(vtOrderID)

            self.callStrategyFunc(strategy, strategy.onOrder, order)
        else:

            for strategy in self.strategyDict.values():
                if order.vtSymbol in strategy.vtSymbols:
                    self.callStrategyFunc(strategy, strategy.onOrder, order)

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

        # 过滤已经收到过的成交回报
        if trade.vtTradeID in self.tradeSet:
            return
        self.tradeSet.add(trade.vtTradeID)

        # 将成交推送到策略对象中
        if trade.vtOrderID in self.orderStrategyDict:
            strategy = self.orderStrategyDict[trade.vtOrderID]

            # 计算策略持仓
            #if trade.direction == DIRECTION_LONG:
            #strategy.pos += trade.volume
            #else:
            #strategy.pos -= trade.volume

            self.callStrategyFunc(strategy, strategy.onTrade, trade)

            # 保存策略持仓到数据库
            #self.saveSyncData(strategy)

    #----------------------------------------------------------------------
    def processPosEvent(self, event):
        position = event.dict_['data']

        for strategy in self.strategyDict.values():
            if position.vtSymbol in strategy.vtSymbols:
                self.callStrategyFunc(strategy, strategy.onPosition, position)

    #----------------------------------------------------------------------
    def processTimerEvent(self, event):
        """"""
        for strategy in self.strategyDict.values():
            self.callStrategyFunc(strategy, strategy.onTimer)

    #----------------------------------------------------------------------
    def registerEvent(self):
        """注册事件监听"""
        self.eventEngine.register(EVENT_TICK, self.processTickEvent)
        self.eventEngine.register(EVENT_BAR, self.processBarEvent)
        self.eventEngine.register(EVENT_MARKETTRADE,
                                  self.processMarketTradeEvent)
        self.eventEngine.register(EVENT_ORDER, self.processOrderEvent)
        self.eventEngine.register(EVENT_TRADE, self.processTradeEvent)
        self.eventEngine.register(EVENT_POSITION, self.processPosEvent)
        self.eventEngine.register(EVENT_TIMER, self.processTimerEvent)

    #----------------------------------------------------------------------
    def insertData(self, dbName, collectionName, data):
        """插入数据到数据库(这里的data可以是VtTickData或者VtBarData)"""
        self.mainEngine.dbInsert(dbName, collectionName, data.__dict__)

    #----------------------------------------------------------------------
    def loadBar(self, dbName, collectionName, days):
        """从数据库中读取Bar数据,startDate是datetime对象"""
        # 优先尝试从RQData获取数据
        if dbName == MINUTE_DB_NAME and collectionName.upper(
        ) in self.rqSymbolSet:
            l = self.loadRqBar(collectionName, days)
            return l

        # 如果没有则从数据库中读取数据
        startDate = self.today - timedelta(days)

        d = {'datetime': {'$gte': startDate}}
        barData = self.mainEngine.dbQuery(dbName, collectionName, d,
                                          'datetime')

        l = []
        for d in barData:
            bar = VtBarData()
            bar.__dict__ = d
            l.append(bar)
        return l

    #----------------------------------------------------------------------
    def loadTick(self, dbName, collectionName, days):
        """从数据库中读取Tick数据,startDate是datetime对象"""
        startDate = self.today - timedelta(days)

        d = {'datetime': {'$gte': startDate}}
        tickData = self.mainEngine.dbQuery(dbName, collectionName, d,
                                           'datetime')

        l = []
        for d in tickData:
            tick = VtTickData()
            tick.__dict__ = d
            l.append(tick)
        return l

    #----------------------------------------------------------------------
    def writeStrLog(self, content):
        """快速发出模块日志事件"""
        log = VtLogData()
        log.logContent = content
        log.gatewayName = 'STR_TRADING'
        event = Event(type_=EVENT_STR_LOG)
        event.dict_['data'] = log
        self.eventEngine.put(event)

    #----------------------------------------------------------------------
    def loadStrategy(self, setting):
        """载入策略"""
        try:
            name = setting['name']
            className = setting['className']
        except Exception:
            msg = traceback.format_exc()
            self.writeStrLog(u'Load Strategy Error:%s' % msg)
            return

        # 获取策略类
        strategyClass = STRATEGY_CLASS.get(className, None)
        if not strategyClass:
            self.writeStrLog(u'Cannot Find Strategy Class:%s' % className)
            return

        # 防止策略重名
        if name in self.strategyDict:
            self.writeStrLog(u'Duplicated Strategy Name:%s' % name)
        else:
            # 创建策略实例
            strategy = strategyClass(self, setting)
            self.strategyDict[name] = strategy

            # 创建委托号列表
            self.strategyOrderDict[name] = set()

            # 保存Tick映射关系
            for vtSymbol in strategy.vtSymbols:
                if vtSymbol in self.tickStrategyDict:
                    self.tickStrategyDict[vtSymbol]
                else:
                    self.tickStrategyDict[vtSymbol] = []
                self.tickStrategyDict[vtSymbol].append(strategy)

    #----------------------------------------------------------------------
    def subscribeMarketData(self, strategy):
        """订阅行情"""
        # 订阅合约
        for vtSymbol in strategy.vtSymbols:
            contract = self.mainEngine.getContract(vtSymbol)
            if contract:
                req = VtSubscribeReq()
                req.symbol = contract.symbol
                req.exchange = contract.exchange
                req.productClass = contract.productClass

                self.mainEngine.subscribe(req, contract.gatewayName)
            else:
                self.writeStrLog(u'%s Instrument Info %s Not Found' %
                                 (strategy.name, vtSymbol))

    #----------------------------------------------------------------------
    def initStrategy(self, name):
        """初始化策略"""
        if name in self.strategyDict:
            strategy = self.strategyDict[name]

            if not strategy.inited:
                #strategy.inited = True
                self.callStrategyFunc(strategy, strategy.onInit)

                self.loadSyncData(strategy)  # 初始化完成后加载同步数据
                self.subscribeMarketData(strategy)  # 加载同步数据后再订阅行情
            else:
                self.writeStrLog(u'Strategy Has Already Been Initilized:%s' %
                                 name)
        else:
            self.writeStrLog(u'Strategy Instance Does Not Exist:%s' % name)

    #---------------------------------------------------------------------
    def startStrategy(self, name):
        """启动策略"""
        if name in self.strategyDict:
            strategy = self.strategyDict[name]

            if strategy.inited and not strategy.trading:
                strategy.trading = True
                self.callStrategyFunc(strategy, strategy.onStart)
        else:
            self.writeStrLog(u'Strategy Instance Does Not Exist:%s' % name)

    #----------------------------------------------------------------------
    def stopStrategy(self, name):
        """停止策略"""
        if name in self.strategyDict:
            strategy = self.strategyDict[name]

            if strategy.trading:
                strategy.trading = False
                self.callStrategyFunc(strategy, strategy.onStop)

                # 对该策略发出的所有限价单进行撤单
                for vtOrderID, s in self.orderStrategyDict.items():
                    if s is strategy:
                        self.cancelOrder(vtOrderID)

                # 对该策略发出的所有本地停止单撤单
                #for stopOrderID, so in self.workingStopOrderDict.items():
                #if so.strategy is strategy:
                #self.cancelStopOrder(stopOrderID)
        else:
            self.writeStrLog(u'Strategy Instance Does Not Exist:%s' % name)

    #----------------------------------------------------------------------
    def initAll(self):
        """全部初始化"""
        for name in self.strategyDict.keys():
            self.initStrategy(name)

    #----------------------------------------------------------------------
    def startAll(self):
        """全部启动"""
        for name in self.strategyDict.keys():
            self.startStrategy(name)

    #----------------------------------------------------------------------
    def stopAll(self):
        """全部停止"""
        for name in self.strategyDict.keys():
            self.stopStrategy(name)

    #----------------------------------------------------------------------
    def saveSetting(self):
        """保存策略配置"""
        with open(self.settingFilePath, 'w') as f:
            l = []

            for strategy in self.strategyDict.values():
                setting = {}
                for param in strategy.paramList:
                    setting[param] = strategy.__getattribute__(param)
                l.append(setting)

            jsonL = json.dumps(l, indent=4)
            f.write(jsonL)

    #----------------------------------------------------------------------
    def loadSetting(self):
        """读取策略配置"""
        with open(self.settingFilePath) as f:
            l = json.load(f)

            for setting in l:
                self.loadStrategy(setting)

    #----------------------------------------------------------------------
    def getStrategyVar(self, name):
        """获取策略当前的变量字典"""
        if name in self.strategyDict:
            strategy = self.strategyDict[name]
            varDict = OrderedDict()

            for key in strategy.varList:
                varDict[key] = strategy.__getattribute__(key)

            return varDict
        else:
            self.writeStrLog(u'Strategy Instance Does Not Exist:' + name)
            return None

    #----------------------------------------------------------------------
    def getStrategyParam(self, name):
        """获取策略的参数字典"""
        if name in self.strategyDict:
            strategy = self.strategyDict[name]
            paramDict = OrderedDict()

            for key in strategy.paramList:
                paramDict[key] = strategy.__getattribute__(key)

            return paramDict
        else:
            self.writeStrLog(u'Strategy Instance Does Not Exist:' + name)
            return None

    #----------------------------------------------------------------------
    def getStrategyNames(self):
        """查询所有策略名称"""
        return self.strategyDict.keys()

    #----------------------------------------------------------------------
    def putStrategyEvent(self, name):
        """触发策略状态变化事件(通常用于通知GUI更新)"""
        strategy = self.strategyDict[name]
        d = {k: strategy.__getattribute__(k) for k in strategy.varList}

        event = Event(EVENT_STRATEGY + name)
        event.dict_['data'] = d
        self.eventEngine.put(event)

        d2 = {k: str(v) for k, v in d.items()}
        d2['name'] = name
        event2 = Event(EVENT_STRATEGY)
        event2.dict_['data'] = d2
        self.eventEngine.put(event2)

    #----------------------------------------------------------------------
    def callStrategyFunc(self, strategy, func, params=None):
        """调用策略的函数,若触发异常则捕捉"""
        try:
            if params:
                func(params)
            else:
                func()
        except Exception:
            # 停止策略,修改状态为未初始化
            strategy.trading = False
            strategy.inited = False

            # 发出日志
            content = '\n'.join(
                [u'策略%s触发异常已停止' % strategy.name,
                 traceback.format_exc()])
            self.writeStrLog(content)

    #----------------------------------------------------------------------
    def saveSyncData(self, strategy):
        """保存策略的持仓情况到数据库"""
        flt = {'name': strategy.name, 'vtSymbol': strategy.vtSymbol}

        d = copy(flt)
        for key in strategy.syncList:
            d[key] = strategy.__getattribute__(key)

        self.mainEngine.dbUpdate(POSITION_DB_NAME, strategy.className, d, flt,
                                 True)

        content = u'策略%s同步数据保存成功,当前持仓%s' % (strategy.name, strategy.pos)
        self.writeStrLog(content)

    #----------------------------------------------------------------------
    def loadSyncData(self, strategy):
        """从数据库载入策略的持仓情况"""
        flt = {'name': strategy.name, 'vtSymbol': strategy.vtSymbols}
        syncData = self.mainEngine.dbQuery(POSITION_DB_NAME,
                                           strategy.className, flt)

        if not syncData:
            return

        d = syncData[0]

        for key in strategy.syncList:
            if key in d:
                strategy.__setattr__(key, d[key])

    #----------------------------------------------------------------------
    def roundToPriceTick(self, priceTick, price):
        """取整价格到合约最小价格变动"""
        if not priceTick:
            return price

        newPrice = round(price / priceTick, 0) * priceTick
        return newPrice

    #----------------------------------------------------------------------
    def stop(self):
        """停止"""
        pass

    #----------------------------------------------------------------------
    def cancelAll(self, name):
        """全部撤单"""
        s = self.strategyOrderDict[name]

        # 遍历列表,全部撤单
        # 这里不能直接遍历集合s,因为撤单时会修改s中的内容,导致出错
        for orderID in list(s):
            if STOPORDERPREFIX in orderID:
                self.cancelStopOrder(orderID)
            else:
                self.cancelOrder(orderID)

    #----------------------------------------------------------------------
    def getPriceTick(self, vtSymbol):
        """获取最小价格变动"""
        contract = self.mainEngine.getContract(vtSymbol)
        if contract:
            return contract.priceTick
        return 0

    #----------------------------------------------------------------------
    def initRqData(self):
        """初始化RQData客户端"""
        # 检查是否填写了RQData配置
        username = globalSetting.get('rqUsername', None)
        password = globalSetting.get('rqPassword', None)
        if not username or not password:
            return

        # 加载RQData
        try:
            import rqdatac as rq
        except ImportError:
            return

        # 登录RQData
        self.rq = rq
        self.rq.init(username, password)

        # 获取本日可交易合约代码
        try:
            df = self.rq.all_instruments(type='Future', date=datetime.now())
            for ix, row in df.iterrows():
                self.rqSymbolSet.add(row['order_book_id'])
        except RuntimeError:
            pass

    #----------------------------------------------------------------------
    def loadRqBar(self, symbol, days):
        """从RQData加载K线数据"""
        endDate = datetime.now()
        startDate = endDate - timedelta(days)

        df = self.rq.get_price(
            symbol.upper(),
            frequency='1m',
            fields=['open', 'high', 'low', 'close', 'volume'],
            start_date=startDate,
            end_date=endDate)

        l = []

        for ix, row in df.iterrows():
            bar = VtBarData()
            bar.symbol = symbol
            bar.vtSymbol = symbol
            bar.open = row['open']
            bar.high = row['high']
            bar.low = row['low']
            bar.close = row['close']
            bar.volume = row['volume']
            bar.datetime = row.name
            bar.date = bar.datetime.strftime("%Y%m%d")
            bar.time = bar.datetime.strftime("%H:%M:%S")

            l.append(bar)

        return l
Ejemplo n.º 4
0
class JsEngine(object):
    """JAQS服务引擎"""
    settingFileName = 'JS_setting.json'
    settingfilePath = getJsonPath(settingFileName, __file__)

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

        self.server = None  # RPC服务器
        self.cbDict = {}  # 回调函数字典
        self.account = None  # 账户对象

        # 注册日志事件类型
        self.mainEngine.registerLogEvent(EVENT_JS_LOG)

        # 初始化
        self.initCallback()
        self.initServer()
        self.registerEvent()

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

    #----------------------------------------------------------------------
    def initCallback(self):
        """初始化回调函数映射"""
        self.cbDict['.sys.heartbeat'] = self.onHeartbeat
        self.cbDict['auth.login'] = self.onLogin
        self.cbDict['auth.use_strategy'] = self.onUseStrategy
        self.cbDict['oms.query_position'] = self.onQueryPosition
        self.cbDict['oms.query_order'] = self.onQueryOrder
        self.cbDict['oms.place_order'] = self.onPlaceOrder
        self.cbDict['oms.cancel_order'] = self.onCancelOrder
        self.cbDict['oms.query_account'] = self.onQueryAccount
        self.cbDict['oms.query_universe'] = self.onQueryUniverse

    #----------------------------------------------------------------------
    def initServer(self):
        """初始化"""
        with open(self.settingfilePath) as f:
            setting = json.load(f)
            host = setting['host']
            port = setting['port']
            addr = "tcp://%s:%s" % (host, port)

            # 初始化RPC服务器
            self.server = jrpc_server.JRpcServer()
            self.server.on_call = self.onCall
            self.server.listen(addr)

            self.writeLog(u'Jaqs服务器启动成功')

    #----------------------------------------------------------------------
    def onCall(self, clientId, req):
        """RPC服务回调函数"""
        method = req['method']
        cb = self.cbDict.get(method, None)
        if not cb:
            self.writeLog(u'无法找到方法%s对应的回调函数' % method)
            return

        self.writeLog(u'收到请求:%s' % req)

        cb(clientId, req)

    #----------------------------------------------------------------------
    def onHeartbeat(self, clientId, req):
        """心跳"""
        pass

    #----------------------------------------------------------------------
    def onLogin(self, clientId, req):
        """登录"""
        params = req['params']

        result = {
            'username': params['username'],
            'name': params['username'],
            'strategies': [1],
            'broker_strategies': [1]
        }

        error = [0, '']

        self.server.send_rsp(clientId, req, result, error)

        self.writeLog(u'发出响应:%s' % result)

    #----------------------------------------------------------------------
    def onUseStrategy(self, clientId, req):
        """使用策略"""
        result = req['params']['account_id']
        error = [0, '']
        self.server.send_rsp(clientId, req, result, error)

        self.writeLog(u'发出响应:%s' % result)

    #----------------------------------------------------------------------
    def onQueryPosition(self, clientId, req):
        """查询持仓"""
        l = self.mainEngine.getAllPositionDetails()

        result = defaultdict(list)
        for detail in l:
            security = self.converSymbol(detail.vtSymbol)

            # 多头
            if detail.longPos:
                result['security'].append(security)
                result['side'].append('Long')

                result['cost_price'].append(0)
                result['float_pnl'].append(0)
                result['close_pnl'].append(0)
                result['trading_pnl'].append(0)
                result['holding_pnl'].append(0)
                result['commission'].append(0)
                result['init_size'].append(0)
                result['current_size'].append(detail.longPos)
                result['enable_size'].append(detail.longPos -
                                             detail.longPosFrozen)
                result['frozen_size'].append(detail.longPosFrozen)
                result['uncome_size'].append(0)
                result['pre_size'].append(detail.longYd)
                result['today_size'].append(detail.longTd)

            # 空头
            if detail.shortPos:
                result['security'].append(security)
                result['side'].append('Short')

                result['cost_price'].append(0)
                result['float_pnl'].append(0)
                result['close_pnl'].append(0)
                result['trading_pnl'].append(0)
                result['holding_pnl'].append(0)
                result['commission'].append(0)
                result['init_size'].append(0)
                result['current_size'].append(detail.shortPos)
                result['enable_size'].append(detail.shortPos -
                                             detail.shortPosFrozen)
                result['frozen_size'].append(detail.shortPosFrozen)
                result['uncome_size'].append(0)
                result['pre_size'].append(detail.shortYd)
                result['today_size'].append(detail.shortTd)

        error = [0, '']

        self.server.send_rsp(clientId, req, result, error)

        self.writeLog(u'发出响应:%s' % result)

    #----------------------------------------------------------------------
    def onQueryOrder(self, clientId, req):
        """查询委托"""
        l = self.mainEngine.getAllOrders()

        result = defaultdict(list)
        for order in l:
            result['task_id'].append(order.vtOrderID)
            result['entrust_no'].append(order.vtOrderID)

            result['entrust_price'].append(order.price)
            result['entrust_size'].append(order.totalVolume)
            result['sub_seq'].append(0)
            result['sub_total'].append(0)
            result['batch_no'].append(0)

            result['fill_price'].append(order.price)
            result['fill_size'].append(order.tradedVolume)
            result['algo'].append('')
            result['entrust_action'].append(
                ACTION_MAP_REVERSE[(order.direction, order.offset)])
            result['order_status'].append(STATUS_MAP_REVERSE[order.status])
            result['security'].append(self.converSymbol(order.vtSymbol))

            hh, mm, ss = order.orderTime.split(':')
            result['entrust_time'].append(
                int(hh) * 10000000 + int(mm) * 100000 + int(ss) * 1000)

        error = [0, '']

        self.server.send_rsp(clientId, req, result, error)

        self.writeLog(u'发出响应:%s' % result)

    #----------------------------------------------------------------------
    def onPlaceOrder(self, clientId, req):
        """委托"""
        params = req['params']
        s, e = params['security'].split('.')

        contract = self.mainEngine.getContract(s)

        if not contract:
            vtOrderID = ''
            error = [-1, u'委托失败,找不到合约%s' % params['security']]
        else:
            vor = VtOrderReq()
            vor.symbol = s
            vor.exchange = EXCHANGE_MAP[e]
            vor.direction, vor.offset = ACTION_MAP[params['action']]
            vor.price = float(params['price'])
            vor.volume = int(params['size'])
            vor.priceType = PRICETYPE_LIMITPRICE

            vtOrderID = self.mainEngine.sendOrder(vor, contract.gatewayName)
            error = [0, '']

        self.server.send_rsp(clientId, req, vtOrderID, error)

        self.writeLog(u'发出响应:%s' % vtOrderID)

    #----------------------------------------------------------------------
    def onCancelOrder(self, clientId, req):
        """撤单"""
        params = req['params']
        vtOrderID = params['task_id']
        gatewayName, orderID = vtOrderID.split('.')

        vcor = VtCancelOrderReq()
        vcor.orderID = vtOrderID
        self.mainEngine.cancelOrder(vcor, gatewayName)

        error = [0, '']
        self.server.send_rsp(clientId, req, 'successful', error)

        self.writeLog(u'发出响应:%s' % result)

    #----------------------------------------------------------------------
    def onQueryAccount(self, clientId, req):
        """查询账户"""
        params = req['params']

        account = self.account

        result = defaultdict(list)
        result['id'].append(account.accountID)
        result['init_balance'].append(account.preBalance)
        result['enable_balance'].append(account.available)
        result['margin'].append(account.margin)
        result['float_pnl'].append(0.0)
        result['close_pnl'].append(account.closeProfit)
        result['holding_pnl'].append(0.0)
        result['trading_pnl'].append(0.0)
        result['type'].append('BA')

        error = [0, '']
        self.server.send_rsp(clientId, req, result, error)

        self.writeLog(u'发出响应:%s' % result)

    #----------------------------------------------------------------------
    def onQueryUniverse(self, clientId, req):
        """查询账户"""
        params = req['params']

        l = self.mainEngine.getAllContracts()

        result = defaultdict(list)
        for contract in l:
            result['ba_id'].append(1000)
            result['security'].append(self.converSymbol(contract.vtSymbol))

        error = [0, '']
        self.server.send_rsp(clientId, req, result, error)

        self.writeLog(u'发出响应:%s' % result)

    #----------------------------------------------------------------------
    def writeLog(self, content):
        """发出日志事件"""
        log = VtLogData()
        log.logContent = content
        log.gatewayName = 'JAQS_SERVICE'
        event = Event(type_=EVENT_JS_LOG)
        event.dict_['data'] = log
        self.eventEngine.put(event)

    #----------------------------------------------------------------------
    def converSymbol(self, vtSymbol):
        """转换合约代码"""
        contract = self.mainEngine.getContract(vtSymbol)
        if not contract:
            return ''

        e = EXCHANGE_MAP_REVERSE.get(contract.exchange, contract.exchange)
        return '.'.join([contract.symbol, e])

    #----------------------------------------------------------------------
    def processAccountEvent(self, event):
        """账户资金更新"""
        self.account = event.dict_['data']
Ejemplo n.º 5
0
class RtdEngine(object):
    """RTD引擎"""
    ENGINE_NAME = 'RTD'

    settingFileName = 'RTD_setting.json'
    settingfilePath = getJsonPath(settingFileName, __file__)

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

        self.server = None
        self.eventTypeDict = {}  # key:事件类型,value:键

        self.loadSetting()
        self.registerEvent()

    #----------------------------------------------------------------------
    def loadSetting(self):
        """读取配置"""
        with open(self.settingfilePath) as f:
            d = json.load(f)

            repAddress = d['repAddress']
            pubAddress = d['pubAddress']

            self.server = RtdServer(repAddress, pubAddress)

            self.eventTypeDict = d['eventType']

    #----------------------------------------------------------------------
    def registerEvent(self):
        """注册事件监听"""
        for eventType in self.eventTypeDict.keys():
            self.eventEngine.register(eventType, self.processDataEvent)

    #----------------------------------------------------------------------
    def processDataEvent(self, event):
        """处理数据事件"""
        if not self.server:
            return

        data = event.dict_['data']
        d = data.__dict__
        keyname = self.eventTypeDict[event.type_]  # 获取数据标识用的名称
        d["key"] = d[keyname]

        self.server.publish(event.type_, d)

        self.writeLog(u'发布数据,类型%s,内容%s' % (event.type_, str(d)))

    #----------------------------------------------------------------------
    def writeLog(self, content):
        """记录日志"""
        log = VtLogData()
        log.logContent = content
        log.gatewayName = self.ENGINE_NAME

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

    #----------------------------------------------------------------------
    def stop(self):
        """停止"""
        pass
Ejemplo n.º 6
0
class OmStrategyEngine(object):
    """策略引擎"""
    settingFileName = 'strategy_setting.json'
    settingfilePath = getJsonPath(settingFileName, __file__)

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

        self.portfolio = None

        self.strategyDict = {}  # name: strategy
        self.symbolStrategyDict = {}  # vtSymbol:strategy list
        self.orderStrategyDict = {}  # vtOrderID: strategy

        self.registerEvent()

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

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

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

    #----------------------------------------------------------------------
    def callStrategyFunc(self, strategy, func, params=None):
        """调用策略的函数,若触发异常则捕捉"""
        try:
            if params:
                func(params)
            else:
                func()
        except Exception:
            # 停止策略,修改状态为未初始化
            strategy.trading = False
            strategy.inited = False

            # 发出日志
            content = '\n'.join(
                [u'策略%s触发异常已停止' % strategy.name,
                 traceback.format_exc()])
            self.writeLog(content)

    #----------------------------------------------------------------------
    def processTickEvent(self, event):
        """处理行情事件"""
        tick = event.dict_['data']
        l = self.symbolStrategyDict.get(tick.vtSymbol, None)
        if l:
            for strategy in l:
                self.callStrategyFunc(strategy, strategy.onTick, tick)

    #----------------------------------------------------------------------
    def processTradeEvent(self, event):
        """处理成交事件"""
        trade = event.dict_['data']
        strategy = self.orderStrategyDict.get(trade.vtOrderID, None)
        if strategy:
            self.callStrategyFunc(strategy, strategy.onTrade, trade)

    #----------------------------------------------------------------------
    def processOrderEvent(self, event):
        """处理委托事件"""
        order = event.dict_['data']
        strategy = self.orderStrategyDict.get(order.vtOrderID, None)
        if strategy:
            self.callStrategyFunc(strategy, strategy.onOrder, order)

    #----------------------------------------------------------------------
    def processTimerEvent(self, event):
        """处理定时事件"""
        for strategy in self.strategyDict.values():
            self.callStrategyFunc(strategy, strategy.onTimer)

    #----------------------------------------------------------------------
    def loadSetting(self):
        """加载配置"""
        self.portfolio = self.omEngine.portfolio

        with open(self.settingfilePath) as f:
            l = json.load(f)

            for setting in l:
                self.loadStrategy(setting)

    #----------------------------------------------------------------------
    def loadStrategy(self, setting):
        """加载策略"""
        try:
            name = setting['name']
            className = setting['className']
        except Exception:
            msg = traceback.format_exc()
            self.writeLog(u'载入策略出错:%s' % msg)
            return

        # 获取策略类
        strategyClass = STRATEGY_CLASS.get(className, None)
        if not strategyClass:
            self.writeLog(u'找不到策略类:%s' % className)
            return

        # 防止策略重名
        if name in self.strategyDict:
            self.writeLog(u'策略实例重名:%s' % name)
        else:
            # 创建策略实例
            strategy = strategyClass(self, setting)
            self.strategyDict[name] = strategy

            # 保存Tick映射关系
            for vtSymbol in strategy.vtSymbols:
                l = self.symbolStrategyDict.setdefault(vtSymbol, [])
                l.append(strategy)

    #----------------------------------------------------------------------
    def initStrategy(self, name):
        """初始化策略"""
        strategy = self.strategyDict[name]
        self.callStrategyFunc(strategy, strategy.onInit)

    #----------------------------------------------------------------------
    def startStrategy(self, name):
        """启动策略"""
        strategy = self.strategyDict[name]
        self.callStrategyFunc(strategy, strategy.onStart)

    #----------------------------------------------------------------------
    def stopStrategy(self, name):
        """停止策略"""
        strategy = self.strategyDict[name]
        self.callStrategyFunc(strategy, strategy.onStop)

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

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

        return self.mainEngine.sendOrder(req, contract.gatewayName)

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

        req = VtCancelOrderReq()
        req.symbol = order.symbol
        req.exchange = order.exchange
        req.orderID = order.orderID
        req.symbol = order.symbol
        req.vtSymbol = order.vtSymbo

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

    #----------------------------------------------------------------------
    def buy(self, vtSymbol, price, volume):
        """开多"""
        return self.sendOrder(vtSymbol, DIRECTION_LONG, OFFSET_OPEN, price,
                              volume)

    #----------------------------------------------------------------------
    def short(self, vtSymbol, price, volume):
        """开空"""
        return self.sendOrder(vtSymbol, DIRECTION_SHORT, OFFSET_OPEN, price,
                              volume)

    #----------------------------------------------------------------------
    def sell(self, vtSymbol, price, volume):
        """平多"""
        return self.sendOrder(vtSymbol, DIRECTION_SHORT, OFFSET_CLOSE, price,
                              volume)

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

    #----------------------------------------------------------------------
    def dbQuery(self, collectionName, flt):
        """查询数据"""
        return self.mainEngine.dbQuery(OM_DB_NAME, collectionName, flt)

    #----------------------------------------------------------------------
    def dbUpdate(self, collectionName, d, flt):
        """更新数据"""
        self.mainEngine.dbUpdate(OM_DB_NAME, collectionName, d, flt, True)

    #----------------------------------------------------------------------
    def getOption(self, vtSymbol):
        """获取期权信息"""
        return self.portfolio.optionDict.get(vtSymbol, None)

    #----------------------------------------------------------------------
    def getUnderlying(self, vtSymbol):
        """获取标的信息"""
        return self.portfolio.underlyingDict.get(vtSymbol, None)

    #----------------------------------------------------------------------
    def getChain(self, symbol):
        """获取期权链信息"""
        return self.portfolio.chainDict.get(symbol, None)

    #----------------------------------------------------------------------
    def getPortfolio(self):
        """获取持仓组合信息"""
        return self.portfolio

    #----------------------------------------------------------------------
    def putStrategyEvent(self, name):
        """触发策略状态变化事件(通常用于通知GUI更新)"""
        event = Event(EVENT_OM_STRATEGY + name)
        self.eventEngine.put(event)

    #----------------------------------------------------------------------
    def setStrategyParam(self, name, key, value):
        """设置策略变量"""
        if name in self.strategyDict:
            strategy = self.strategyDict[name]
            strategy.__setattr__(key, value)
            self.writeLog(u'策略%s参数%s已修改为%s' % (name, key, value))
        else:
            self.writeLog(u'策略实例不存在:' + name)
            return None

    #----------------------------------------------------------------------
    def getStrategyVar(self, name):
        """获取策略当前的变量字典"""
        if name in self.strategyDict:
            strategy = self.strategyDict[name]
            varDict = OrderedDict()

            for key in strategy.varList:
                varDict[key] = strategy.__getattribute__(key)

            return varDict
        else:
            self.writeLog(u'策略实例不存在:' + name)
            return None

    #----------------------------------------------------------------------
    def getStrategyParam(self, name):
        """获取策略的参数字典"""
        if name in self.strategyDict:
            strategy = self.strategyDict[name]
            paramDict = OrderedDict()

            for key in strategy.paramList:
                paramDict[key] = strategy.__getattribute__(key)

            return paramDict
        else:
            self.writeLog(u'策略实例不存在:' + name)
            return None

    #----------------------------------------------------------------------
    def initAll(self):
        """全部初始化"""
        for name in self.strategyDict.keys():
            self.initStrategy(name)

    #----------------------------------------------------------------------
    def startAll(self):
        """全部启动"""
        for name in self.strategyDict.keys():
            self.startStrategy(name)

    #----------------------------------------------------------------------
    def stopAll(self):
        """全部停止"""
        for name in self.strategyDict.keys():
            self.stopStrategy(name)