Merge pull request #252 from ares89/dev

风控模块增加单品种报撤单次数限制
This commit is contained in:
vn.py 2017-03-08 16:54:55 +08:00 committed by GitHub
commit 7f2c47f425
5 changed files with 105 additions and 58 deletions

View File

@ -4,5 +4,6 @@
"tradeLimit": 100, "tradeLimit": 100,
"orderSizeLimit": 10, "orderSizeLimit": 10,
"active": true, "active": true,
"orderFlowLimit": 10 "orderCountLimit": 400,
"orderFlowLimit": 50
} }

View File

@ -21,8 +21,8 @@ class RmEngine(object):
"""风控引擎""" """风控引擎"""
settingFileName = 'RM_setting.json' settingFileName = 'RM_setting.json'
path = os.path.abspath(os.path.dirname(__file__)) path = os.path.abspath(os.path.dirname(__file__))
settingFileName = os.path.join(path, settingFileName) settingFileName = os.path.join(path, settingFileName)
name = u'风控模块' name = u'风控模块'
#---------------------------------------------------------------------- #----------------------------------------------------------------------
@ -30,47 +30,53 @@ class RmEngine(object):
"""Constructor""" """Constructor"""
self.mainEngine = mainEngine self.mainEngine = mainEngine
self.eventEngine = eventEngine self.eventEngine = eventEngine
# 是否启动风控 # 是否启动风控
self.active = False self.active = False
# 流控相关 # 流控相关
self.orderFlowCount = EMPTY_INT # 单位时间内委托计数 self.orderFlowCount = EMPTY_INT # 单位时间内委托计数
self.orderFlowLimit = EMPTY_INT # 委托限制 self.orderFlowLimit = EMPTY_INT # 委托限制
self.orderFlowClear = EMPTY_INT # 计数清空时间(秒) self.orderFlowClear = EMPTY_INT # 计数清空时间(秒)
self.orderFlowTimer = EMPTY_INT # 计数清空时间计时 self.orderFlowTimer = EMPTY_INT # 计数清空时间计时
# 单笔委托相关 # 单笔委托相关
self.orderSizeLimit = EMPTY_INT # 单笔委托最大限制 self.orderSizeLimit = EMPTY_INT # 单笔委托最大限制
# 成交统计相关 # 成交统计相关
self.tradeCount = EMPTY_INT # 当日成交合约数量统计 self.tradeCount = EMPTY_INT # 当日成交合约数量统计
self.tradeLimit = EMPTY_INT # 当日成交合约数量限制 self.tradeLimit = EMPTY_INT # 当日成交合约数量限制
# 单品种报撤
self.orderCountLimit = 450
self.orderCount = {}
# 活动合约相关 # 活动合约相关
self.workingOrderLimit = EMPTY_INT # 活动合约最大限制 self.workingOrderLimit = EMPTY_INT # 活动合约最大限制
self.loadSetting() self.loadSetting()
self.registerEvent() self.registerEvent()
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def loadSetting(self): def loadSetting(self):
"""读取配置""" """读取配置"""
with open(self.settingFileName) as f: with open(self.settingFileName) as f:
d = json.load(f) d = json.load(f)
# 设置风控参数 # 设置风控参数
self.active = d['active'] self.active = d['active']
self.orderFlowLimit = d['orderFlowLimit'] self.orderFlowLimit = d['orderFlowLimit']
self.orderFlowClear = d['orderFlowClear'] self.orderFlowClear = d['orderFlowClear']
self.orderSizeLimit = d['orderSizeLimit'] self.orderSizeLimit = d['orderSizeLimit']
self.tradeLimit = d['tradeLimit'] self.tradeLimit = d['tradeLimit']
self.workingOrderLimit = d['workingOrderLimit'] self.workingOrderLimit = d['workingOrderLimit']
self.orderCountLimit = d['orderCountLimit']
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def saveSetting(self): def saveSetting(self):
"""保存风控参数""" """保存风控参数"""
@ -79,42 +85,55 @@ class RmEngine(object):
d = {} d = {}
d['active'] = self.active d['active'] = self.active
d['orderFlowLimit'] = self.orderFlowLimit d['orderFlowLimit'] = self.orderFlowLimit
d['orderFlowClear'] = self.orderFlowClear d['orderFlowClear'] = self.orderFlowClear
d['orderSizeLimit'] = self.orderSizeLimit d['orderSizeLimit'] = self.orderSizeLimit
d['tradeLimit'] = self.tradeLimit d['tradeLimit'] = self.tradeLimit
d['workingOrderLimit'] = self.workingOrderLimit d['workingOrderLimit'] = self.workingOrderLimit
d['orderCountLimit'] = self.orderCountLimit
# 写入json # 写入json
jsonD = json.dumps(d, indent=4) jsonD = json.dumps(d, indent=4)
f.write(jsonD) f.write(jsonD)
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def registerEvent(self): def registerEvent(self):
"""注册事件监听""" """注册事件监听"""
self.eventEngine.register(EVENT_TRADE, self.updateTrade) self.eventEngine.register(EVENT_TRADE, self.updateTrade)
self.eventEngine.register(EVENT_TIMER, self.updateTimer) self.eventEngine.register(EVENT_TIMER, self.updateTimer)
self.eventEngine.register(EVENT_ORDER, self.updateOrder)
def updateOrder(self, event):
"""更新成交数据"""
order = event.dict_['data']
if not self.orderCount.has_key(order.symbol):
self.orderCount[order.symbol] = 0
if order.status in [STATUS_NOTTRADED, STATUS_PARTTRADED, STATUS_ALLTRADED, STATUS_UNKNOWN]:
self.orderCount[order.symbol] += 1
elif order.status == STATUS_CANCELLED:
self.orderCount[order.symbol] += 2
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def updateTrade(self, event): def updateTrade(self, event):
"""更新成交数据""" """更新成交数据"""
trade = event.dict_['data'] trade = event.dict_['data']
self.tradeCount += trade.volume self.tradeCount += trade.volume
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def updateTimer(self, event): def updateTimer(self, event):
"""更新定时器""" """更新定时器"""
self.orderFlowTimer += 1 self.orderFlowTimer += 1
# 如果计时超过了流控清空的时间间隔,则执行清空 # 如果计时超过了流控清空的时间间隔,则执行清空
if self.orderFlowTimer >= self.orderFlowClear: if self.orderFlowTimer >= self.orderFlowClear:
self.orderFlowCount = 0 self.orderFlowCount = 0
self.orderFlowTimer = 0 self.orderFlowTimer = 0
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def writeRiskLog(self, content): def writeRiskLog(self, content):
"""快速发出日志事件""" """快速发出日志事件"""
@ -122,95 +141,105 @@ class RmEngine(object):
if platform.uname() == 'Windows': if platform.uname() == 'Windows':
import winsound import winsound
winsound.PlaySound("SystemHand", winsound.SND_ASYNC) winsound.PlaySound("SystemHand", winsound.SND_ASYNC)
# 发出日志事件 # 发出日志事件
log = VtLogData() log = VtLogData()
log.logContent = content log.logContent = content
log.gatewayName = self.name log.gatewayName = self.name
event = Event(type_=EVENT_LOG) event = Event(type_=EVENT_LOG)
event.dict_['data'] = log event.dict_['data'] = log
self.eventEngine.put(event) self.eventEngine.put(event)
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def checkRisk(self, orderReq): def checkRisk(self, orderReq):
"""检查风险""" """检查风险"""
# 如果没有启动风控检查,则直接返回成功 # 如果没有启动风控检查,则直接返回成功
if not self.active: if not self.active:
return True return RISK_OK
# 检查委托数量 # 检查委托数量
if orderReq.volume > self.orderSizeLimit: if orderReq.volume > self.orderSizeLimit:
self.writeRiskLog(u'单笔委托数量%s,超过限制%s' self.writeRiskLog(u'单笔委托数量%s,超过限制%s'
%(orderReq.volume, self.orderSizeLimit)) %(orderReq.volume, self.orderSizeLimit))
return False return RISK_ERROR_ORDER_SIZE
# 检查成交合约量 # 检查成交合约量
if self.tradeCount >= self.tradeLimit: if self.tradeCount >= self.tradeLimit:
self.writeRiskLog(u'今日总成交合约数量%s,超过限制%s' self.writeRiskLog(u'今日总成交合约数量%s,超过限制%s'
%(self.tradeCount, self.tradeLimit)) %(self.tradeCount, self.tradeLimit))
return False return RISK_ERROR_TRADE_COUNT
# 检查流控 # 检查流控
if self.orderFlowCount >= self.orderFlowLimit: if self.orderFlowCount >= self.orderFlowLimit:
self.writeRiskLog(u'委托流数量%s,超过限制每%s%s' self.writeRiskLog(u'委托流数量%s,超过限制每%s%s'
%(self.orderFlowCount, self.orderFlowClear, self.orderFlowLimit)) %(self.orderFlowCount, self.orderFlowClear, self.orderFlowLimit))
return False return RISK_ERROR_ORDER_FLOW_COUNT
# 检查总活动合约 # 检查总活动合约
workingOrderCount = len(self.mainEngine.getAllWorkingOrders()) workingOrderCount = len(self.mainEngine.getAllWorkingOrders())
if workingOrderCount >= self.workingOrderLimit: if workingOrderCount >= self.workingOrderLimit:
self.writeRiskLog(u'当前活动委托数量%s,超过限制%s' self.writeRiskLog(u'当前活动委托数量%s,超过限制%s'
%(workingOrderCount, self.workingOrderLimit)) %(workingOrderCount, self.workingOrderLimit))
return False return RISK_ERROR_WORKING_ORDER
if self.orderCount.has_key(orderReq.symbol) and self.orderCount[orderReq.symbol] > self.orderCountLimit:
self.writeRiskLog(u'%s当日报撤%s,超过限制%s'
% (orderReq.symbol, self.orderCount[orderReq.symbol], self.orderCountLimit))
return RISK_ERROR_ORDER_SEND
# 对于通过风控的委托,增加流控计数 # 对于通过风控的委托,增加流控计数
self.orderFlowCount += 1 self.orderFlowCount += 1
return True return RISK_OK
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def clearOrderFlowCount(self): def clearOrderFlowCount(self):
"""清空流控计数""" """清空流控计数"""
self.orderFlowCount = 0 self.orderFlowCount = 0
self.writeRiskLog(u'清空流控计数') self.writeRiskLog(u'清空流控计数')
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def clearTradeCount(self): def clearTradeCount(self):
"""清空成交数量计数""" """清空成交数量计数"""
self.tradeCount = 0 self.tradeCount = 0
self.writeRiskLog(u'清空总成交计数') self.writeRiskLog(u'清空总成交计数')
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def setOrderFlowLimit(self, n): def setOrderFlowLimit(self, n):
"""设置流控限制""" """设置流控限制"""
self.orderFlowLimit = n self.orderFlowLimit = n
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def setOrderFlowClear(self, n): def setOrderFlowClear(self, n):
"""设置流控清空时间""" """设置流控清空时间"""
self.orderFlowClear = n self.orderFlowClear = n
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def setOrderSizeLimit(self, n): def setOrderSizeLimit(self, n):
"""设置委托最大限制""" """设置委托最大限制"""
self.orderSizeLimit = n self.orderSizeLimit = n
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def setTradeLimit(self, n): def setTradeLimit(self, n):
"""设置成交限制""" """设置成交限制"""
self.tradeLimit = n self.tradeLimit = n
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def setWorkingOrderLimit(self, n): def setWorkingOrderLimit(self, n):
"""设置活动合约限制""" """设置活动合约限制"""
self.workingOrderLimit = n self.workingOrderLimit = n
#----------------------------------------------------------------------
def setOrderCountLimit(self, n):
"""设置单品种报撤次数上限"""
self.orderCountLimit = n
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def switchEngineStatus(self): def switchEngineStatus(self):
"""开关风控引擎""" """开关风控引擎"""
self.active = not self.active self.active = not self.active
if self.active: if self.active:
self.writeRiskLog(u'风险管理功能启动') self.writeRiskLog(u'风险管理功能启动')
else: else:

View File

@ -68,6 +68,7 @@ class RmEngineManager(QtGui.QWidget):
self.spinOrderSizeLimit = RmSpinBox(self.rmEngine.orderSizeLimit) self.spinOrderSizeLimit = RmSpinBox(self.rmEngine.orderSizeLimit)
self.spinTradeLimit = RmSpinBox(self.rmEngine.tradeLimit) self.spinTradeLimit = RmSpinBox(self.rmEngine.tradeLimit)
self.spinWorkingOrderLimit = RmSpinBox(self.rmEngine.workingOrderLimit) self.spinWorkingOrderLimit = RmSpinBox(self.rmEngine.workingOrderLimit)
self.spinOrderCountLimit = RmSpinBox(self.rmEngine.orderCountLimit)
buttonClearOrderFlowCount = QtGui.QPushButton(u'清空流控计数') buttonClearOrderFlowCount = QtGui.QPushButton(u'清空流控计数')
buttonClearTradeCount = QtGui.QPushButton(u'清空总成交计数') buttonClearTradeCount = QtGui.QPushButton(u'清空总成交计数')
@ -91,6 +92,8 @@ class RmEngineManager(QtGui.QWidget):
grid.addWidget(RmLine(), 8, 0, 1, 2) grid.addWidget(RmLine(), 8, 0, 1, 2)
grid.addWidget(Label(u'活动订单上限'), 9, 0) grid.addWidget(Label(u'活动订单上限'), 9, 0)
grid.addWidget(self.spinWorkingOrderLimit, 9, 1) grid.addWidget(self.spinWorkingOrderLimit, 9, 1)
grid.addWidget(Label(u'单品种报撤次数上限'), 10, 0)
grid.addWidget(self.spinOrderCountLimit, 10, 1)
hbox = QtGui.QHBoxLayout() hbox = QtGui.QHBoxLayout()
hbox.addWidget(buttonClearOrderFlowCount) hbox.addWidget(buttonClearOrderFlowCount)
@ -109,7 +112,8 @@ class RmEngineManager(QtGui.QWidget):
self.spinOrderSizeLimit.valueChanged.connect(self.rmEngine.setOrderSizeLimit) self.spinOrderSizeLimit.valueChanged.connect(self.rmEngine.setOrderSizeLimit)
self.spinTradeLimit.valueChanged.connect(self.rmEngine.setTradeLimit) self.spinTradeLimit.valueChanged.connect(self.rmEngine.setTradeLimit)
self.spinWorkingOrderLimit.valueChanged.connect(self.rmEngine.setWorkingOrderLimit) self.spinWorkingOrderLimit.valueChanged.connect(self.rmEngine.setWorkingOrderLimit)
self.spinOrderCountLimit.valueChanged.connect(self.rmEngine.setOrderCountLimit)
self.buttonSwitchEngineStatus.clicked.connect(self.switchEngineSatus) self.buttonSwitchEngineStatus.clicked.connect(self.switchEngineSatus)
buttonClearOrderFlowCount.clicked.connect(self.rmEngine.clearOrderFlowCount) buttonClearOrderFlowCount.clicked.connect(self.rmEngine.clearOrderFlowCount)
buttonClearTradeCount.clicked.connect(self.rmEngine.clearTradeCount) buttonClearTradeCount.clicked.connect(self.rmEngine.clearTradeCount)

View File

@ -6,6 +6,18 @@ EMPTY_UNICODE = u''
EMPTY_INT = 0 EMPTY_INT = 0
EMPTY_FLOAT = 0.0 EMPTY_FLOAT = 0.0
# 风控常量
RISK_OK = 0 # 风控正常
RISK_ERROR_ORDER_SIZE = 1 # 单笔委托数量超限
RISK_ERROR_TRADE_COUNT = 2 # 今日总成交合约数量超限
RISK_ERROR_ORDER_FLOW_COUNT = 3 # 委托流数量超限
RISK_ERROR_WORKING_ORDER = 4 # 当前活动委托数量超限
RISK_ERROR_ORDER_SEND = 5 # 当日单品种报撤次数超限
RISK_MESSAGE = {RISK_ERROR_ORDER_SIZE: u'单笔委托数量超限', RISK_ERROR_TRADE_COUNT: u'今日总成交合约数量超限',
RISK_ERROR_ORDER_FLOW_COUNT: u'委托流数量超限', RISK_ERROR_WORKING_ORDER: u'当前活动委托数量超限',
RISK_ERROR_ORDER_SEND: u'当日单品种报撤次数超限'}
# 方向常量 # 方向常量
DIRECTION_NONE = u'无方向' DIRECTION_NONE = u'无方向'
DIRECTION_LONG = u'' DIRECTION_LONG = u''

View File

@ -188,9 +188,10 @@ class MainEngine(object):
def sendOrder(self, orderReq, gatewayName): def sendOrder(self, orderReq, gatewayName):
"""对特定接口发单""" """对特定接口发单"""
# 如果风控检查失败则不发单 # 如果风控检查失败则不发单
if not self.rmEngine.checkRisk(orderReq): riskResult = self.rmEngine.checkRisk(orderReq)
return '' if riskResult != RISK_OK:
return riskResult
if gatewayName in self.gatewayDict: if gatewayName in self.gatewayDict:
gateway = self.gatewayDict[gatewayName] gateway = self.gatewayDict[gatewayName]
return gateway.sendOrder(orderReq) return gateway.sendOrder(orderReq)