diff --git a/vn.trader/ctaAlgo/ctaEngine.py b/vn.trader/ctaAlgo/ctaEngine.py index 775ce3e9..57e40ac6 100644 --- a/vn.trader/ctaAlgo/ctaEngine.py +++ b/vn.trader/ctaAlgo/ctaEngine.py @@ -97,9 +97,14 @@ class CtaEngine(object): req.price = price # 价格 req.volume = volume # 数量 - req.productClass = strategy.productClass - req.currency = strategy.currency - + if strategy: + req.productClass = strategy.productClass + req.currency = strategy.currency + else: + req.productClass = '' + req.currency = '' + + # 设计为CTA引擎发出的委托只允许使用限价单 req.priceType = PRICETYPE_LIMITPRICE # 价格类型 @@ -165,11 +170,14 @@ class CtaEngine(object): vtOrderID = self.mainEngine.sendOrder(req, contract.gatewayName) # 发单 - self.orderStrategyDict[vtOrderID] = strategy # 保存vtOrderID和策略的映射关系 + if strategy: + self.orderStrategyDict[vtOrderID] = strategy # 保存vtOrderID和策略的映射关系 - self.writeCtaLog(u'策略%s发送委托,%s, %s,%s,%s@%s' + self.writeCtaLog(u'策略%s发送委托,%s, %s,%s,%s@%s' %(strategy.name, vtSymbol, req.offset, req.direction, volume, price)) - + else: + self.writeCtaLog(u'%s发送委托,%s, %s,%s,%s@%s' + % ('CtaEngine', vtSymbol, req.offset, req.direction, volume, price)) return vtOrderID # ---------------------------------------------------------------------- @@ -413,13 +421,14 @@ class CtaEngine(object): pos = event.dict_['data'] # 更新持仓缓存数据 - if pos.vtSymbol in self.tickStrategyDict: - posBuffer = self.posBufferDict.get(pos.vtSymbol, None) - if not posBuffer: - posBuffer = PositionBuffer() - posBuffer.vtSymbol = pos.vtSymbol - self.posBufferDict[pos.vtSymbol] = posBuffer - posBuffer.updatePositionData(pos) + #if pos.vtSymbol in self.tickStrategyDict: + + 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 registerEvent(self): @@ -440,6 +449,60 @@ class CtaEngine(object): # 注册定时器事件 self.eventEngine.register(EVENT_TIMER, self.processTimerEvent) + # 注册强制止损事件 + self.eventEngine.register(EVENT_ACCOUNT_LOSS, self.processAccoutLossEvent) + + def processAccoutLossEvent(self,event): + """处理止损时间""" + balance = event.dict_['data'] + self.writeCtaLog(u'净值{0}低于止损线,执行强制止损'.format(balance)) + self.mainEngine.writeLog(u'净值{0}低于止损线,执行强制止损'.format(balance)) + + self.cancelOrders(symbol=EMPTY_STRING) + + for posBuffer in self.posBufferDict.values(): + + if posBuffer.shortYd > 0: + self.writeCtaLog(u'{0}合约持有昨空单{1}手,强平'.format(posBuffer.vtSymbol,posBuffer.shortYd)) + tick = self.tickDict.get(posBuffer.vtSymbol, None) + + if not tick: + self.writeCtaLog(u'找不对{0}的最新Tick数据'.format(posBuffer.vtSymbol)) + continue + + self.sendOrder(posBuffer.vtSymbol, orderType=CTAORDER_COVER, price=tick.upperLimit, volume=posBuffer.shortYd,strategy=None) + + if posBuffer.shortToday > 0: + self.writeCtaLog(u'{0}合约持有今空单{1}手,强平'.format(posBuffer.vtSymbol,posBuffer.shortToday)) + tick = self.tickDict.get(posBuffer.vtSymbol, None) + + if not tick: + self.writeCtaLog(u'找不对{0}的最新Tick数据'.format(posBuffer.vtSymbol)) + continue + + self.sendOrder(posBuffer.vtSymbol, orderType=CTAORDER_COVER, price=tick.upperLimit, volume=posBuffer.shortToday,strategy=None) + + if posBuffer.longYd > 0: + self.writeCtaLog(u'{0}合约持有昨多单{1}手,强平'.format(posBuffer.vtSymbol,posBuffer.longYd)) + tick = self.tickDict.get(posBuffer.vtSymbol, None) + + if not tick: + self.writeCtaLog(u'找不对{0}的最新Tick数据'.format(posBuffer.vtSymbol)) + continue + + self.sendOrder(posBuffer.vtSymbol, orderType=CTAORDER_SELL, price=tick.lowerLimit, volume=posBuffer.longYd,strategy=None) + + if posBuffer.longToday > 0: + self.writeCtaLog(u'{0}合约持有今多单{1}手,强平'.format(posBuffer.vtSymbol,posBuffer.longToday)) + tick = self.tickDict.get(posBuffer.vtSymbol, None) + + if not tick: + self.writeCtaLog(u'找不对{0}的最新Tick数据'.format(posBuffer.vtSymbol)) + continue + + self.sendOrder(posBuffer.vtSymbol, orderType=CTAORDER_SELL, price=tick.lowerLimit, volume=posBuffer.longToday,strategy=None) + + def processTimerEvent(self, event): """定时器事件""" diff --git a/vn.trader/riskManager/uiRmWidget.py b/vn.trader/riskManager/uiRmWidget.py index 1c4c6074..d01ca6ab 100644 --- a/vn.trader/riskManager/uiRmWidget.py +++ b/vn.trader/riskManager/uiRmWidget.py @@ -68,7 +68,7 @@ class RmEngineManager(QtGui.QWidget): self.spinPercentLimit = RmSpinBox(self.rmEngine.percentLimit) # 最大净值止损比例,满足后强制止损 - self.spinLossPercentLimit = RmSpinBox(self.rmEngine.lossPercentLimit) + self.spinLossLimit = RmSpinBox(self.rmEngine.lossLimit) buttonClearOrderFlowCount = QtGui.QPushButton(u'清空流控计数') buttonClearTradeCount = QtGui.QPushButton(u'清空总成交计数') @@ -96,8 +96,8 @@ class RmEngineManager(QtGui.QWidget): grid.addWidget(RmLine(), 10, 0, 1, 2) grid.addWidget(Label(u'仓位上限(1~100)'), 11, 0) grid.addWidget(self.spinPercentLimit, 11, 1) - grid.addWidget(Label(u'强制止损比例'), 12, 0) - grid.addWidget(self.spinLossPercentLimit, 12, 1) + grid.addWidget(Label(u'强制止损净值'), 12, 0) + grid.addWidget(self.spinLossLimit, 12, 1) hbox = QtGui.QHBoxLayout() hbox.addWidget(buttonClearOrderFlowCount) @@ -117,7 +117,7 @@ class RmEngineManager(QtGui.QWidget): self.spinTradeLimit.valueChanged.connect(self.rmEngine.setTradeLimit) self.spinWorkingOrderLimit.valueChanged.connect(self.rmEngine.setWorkingOrderLimit) self.spinPercentLimit.valueChanged.connect(self.rmEngine.setAccountPercentLimit) - self.spinLossPercentLimit.valueChanged.connect(self.rmEngine.setLossPercentLimit) + self.spinLossLimit.valueChanged.connect(self.rmEngine.setLossLimit) self.buttonSwitchEngineStatus.clicked.connect(self.switchEngineSatus) buttonClearOrderFlowCount.clicked.connect(self.rmEngine.clearOrderFlowCount) diff --git a/vn.trader/vtEngine.py b/vn.trader/vtEngine.py index 38e8937d..5d143405 100644 --- a/vn.trader/vtEngine.py +++ b/vn.trader/vtEngine.py @@ -417,9 +417,14 @@ class DataEngine(object): # 目的:1、 position = event.dict_['data'] - symbol = position.symbol + if symbol is None: + return + + if len(symbol) == 0: + return + # 已存在,不做更新 if symbol in self.subscribedSymbols: return