增加风控功能,资金净值低于设定的止损线,强制全仓止损。

This commit is contained in:
msincenselee 2016-12-04 20:44:55 +08:00
parent c7f6e1e9a5
commit 23f8d1c6f3
3 changed files with 86 additions and 18 deletions

View File

@ -97,8 +97,13 @@ 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):
"""定时器事件"""

View File

@ -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)

View File

@ -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