Merge pull request #1764 from 1122455801/rm_engine_01
[Add] UI for RiskManagerApp
This commit is contained in:
commit
9f8dd2ebd7
14
vnpy/app/risk_manager/__init__.py
Normal file
14
vnpy/app/risk_manager/__init__.py
Normal file
@ -0,0 +1,14 @@
|
||||
from pathlib import Path
|
||||
from vnpy.trader.app import BaseApp
|
||||
from .engine import RiskManagerEngine, APP_NAME
|
||||
|
||||
|
||||
class RiskManagerApp(BaseApp):
|
||||
""""""
|
||||
app_name = APP_NAME
|
||||
app_module = __module__
|
||||
app_path = Path(__file__).parent
|
||||
display_name = "风险控制"
|
||||
engine_class = RiskManagerEngine
|
||||
widget_name = "RiskManager"
|
||||
icon_name = "risk_manager.ico"
|
@ -1,6 +1,7 @@
|
||||
""""""
|
||||
|
||||
from collections import defaultdict
|
||||
from vnpy.trader.object import OrderRequest
|
||||
from vnpy.trader.object import OrderRequest, LogData
|
||||
from vnpy.event import Event, EventEngine, EVENT_TIMER
|
||||
from vnpy.trader.engine import BaseEngine, MainEngine
|
||||
from vnpy.trader.event import EVENT_TRADE, EVENT_ORDER, EVENT_LOG
|
||||
@ -12,15 +13,16 @@ APP_NAME = "RiskManager"
|
||||
|
||||
|
||||
class RiskManagerEngine(BaseEngine):
|
||||
"""风控引擎"""
|
||||
""""""
|
||||
setting_filename = "risk_manager_setting.json"
|
||||
|
||||
def __init__(self, main_engine: MainEngine, event_engine: EventEngine):
|
||||
""""""
|
||||
super().__init__(main_engine, event_engine, APP_NAME)
|
||||
|
||||
self.main_engine = main_engine
|
||||
self.event_engine = event_engine
|
||||
main_engine.rmEngine = self
|
||||
|
||||
|
||||
self.active = False
|
||||
self.order_flow_count = 0
|
||||
self.order_flow_limit = 50
|
||||
@ -31,22 +33,34 @@ class RiskManagerEngine(BaseEngine):
|
||||
self.trade_limit = 1000
|
||||
self.order_cancel_limit = 10
|
||||
self.order_cancel_counts = defaultdict(int)
|
||||
self.active_order_limit = 20
|
||||
self.active_order_limit = 20
|
||||
|
||||
# Patch send order function of MainEngine
|
||||
self._send_order = self.main_engine.send_order
|
||||
self.main_engine.send_order = self.send_order
|
||||
|
||||
self.load_setting()
|
||||
self.registerEvent()
|
||||
self.register_event()
|
||||
|
||||
def send_order(self, req: OrderRequest, gateway_name: str):
|
||||
""""""
|
||||
result = self.check_risk(req, gateway_name)
|
||||
if not result:
|
||||
return ""
|
||||
|
||||
return self._send_order(req, gateway_name)
|
||||
|
||||
def load_setting(self):
|
||||
""""""
|
||||
setting = load_json(self.setting_filename)
|
||||
|
||||
self.active = setting["active"]
|
||||
self.order_flow_limit = setting["order_flow_limit"]
|
||||
self.order_flow_clear = setting["order_flow_clear"]
|
||||
self.order_size_limit = setting["order_size_limit"]
|
||||
self.trade_limit = setting["trade_limit"]
|
||||
self.active_order_limit = setting["active_order_limit"]
|
||||
self.order_cancel_limit = setting["order_cancel_limit"]
|
||||
self.active = setting.get("active", self.active)
|
||||
self.order_flow_limit = setting.get("order_flow_limit", self.order_flow_count)
|
||||
self.order_flow_clear = setting.get("order_flow_clear", self.order_flow_clear)
|
||||
self.order_size_limit = setting.get("order_size_limit", self.order_size_limit)
|
||||
self.trade_limit = setting.get("trade_limit", self.trade_limit)
|
||||
self.active_order_limit = setting.get("active_order_limit", self.active_order_limit)
|
||||
self.order_cancel_limit = setting.get("order_cancel_limit", self.order_cancel_limit)
|
||||
|
||||
def save_setting(self):
|
||||
""""""
|
||||
@ -89,11 +103,9 @@ class RiskManagerEngine(BaseEngine):
|
||||
self.order_flow_timer = 0
|
||||
|
||||
def write_risk_log(self, msg: str):
|
||||
""""""
|
||||
event = Event(
|
||||
EVENT_LOG,
|
||||
msg
|
||||
)
|
||||
""""""
|
||||
log = LogData(msg=msg, gateway_name="RiskManager")
|
||||
event = Event(type=EVENT_LOG, data=log)
|
||||
self.event_engine.put(event)
|
||||
|
||||
def check_risk(self, req: OrderRequest, gateway_name: str):
|
||||
@ -117,17 +129,17 @@ class RiskManagerEngine(BaseEngine):
|
||||
|
||||
# Check flow count
|
||||
if self.order_flow_count >= self.order_flow_limit:
|
||||
self.write_risk_log(f"委托流数量{self.order_flow_count},超过限制每{self.order_flow_clear}秒{self.order_flow_limit}")
|
||||
self.write_risk_log(f"委托流数量{self.order_flow_count},超过限制每{self.order_flow_clear}秒{self.order_flow_limit}次")
|
||||
return False
|
||||
|
||||
# Check all active orders
|
||||
active_order_count = len(self.main_engine.get_all_active_orders())
|
||||
if active_order_count >= self.active_order_limit:
|
||||
self.write_risk_log(f"当前活动委托数量{active_order_count},超过限制{self.active_order_limit}")
|
||||
self.write_risk_log(f"当前活动委托次数{active_order_count},超过限制{self.active_order_limit}")
|
||||
return False
|
||||
|
||||
# Check order cancel counts
|
||||
if req.symbol in self.order_cancel_counts and self.order_cancel_counts[req.symbol] >= self.order_cancel_limit:
|
||||
if req.symbol in self.order_cancel_counts and self.order_cancel_counts[req.symbol] >= self.order_cancel_limit:
|
||||
self.write_risk_log(f"当日{req.symbol}撤单次数{self.order_cancel_counts[req.symbol]},超过限制{self.order_cancel_limit}")
|
||||
return False
|
||||
|
||||
@ -181,4 +193,3 @@ class RiskManagerEngine(BaseEngine):
|
||||
def stop(self):
|
||||
""""""
|
||||
self.save_setting()
|
||||
|
||||
|
1
vnpy/app/risk_manager/ui/__init__.py
Normal file
1
vnpy/app/risk_manager/ui/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from .widget import RiskManager
|
BIN
vnpy/app/risk_manager/ui/risk_manager.ico
Normal file
BIN
vnpy/app/risk_manager/ui/risk_manager.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 66 KiB |
116
vnpy/app/risk_manager/ui/widget.py
Normal file
116
vnpy/app/risk_manager/ui/widget.py
Normal file
@ -0,0 +1,116 @@
|
||||
from vnpy.event import EventEngine
|
||||
from vnpy.trader.engine import MainEngine
|
||||
from vnpy.trader.ui import QtWidgets
|
||||
from ..engine import APP_NAME
|
||||
|
||||
|
||||
class RiskManager(QtWidgets.QWidget):
|
||||
""""""
|
||||
|
||||
def __init__(self, main_engine: MainEngine, event_engine: EventEngine):
|
||||
""""""
|
||||
super().__init__()
|
||||
|
||||
self.main_engine = main_engine
|
||||
self.event_engine = event_engine
|
||||
self.risk_manager_engine = main_engine.get_engine(APP_NAME)
|
||||
|
||||
self.init_ui()
|
||||
self.update_engine_status()
|
||||
|
||||
def init_ui(self):
|
||||
""""""
|
||||
self.setWindowTitle("风险控制")
|
||||
|
||||
# SpinBox
|
||||
self.order_flow_limit = RiskManagerSpinBox(0)
|
||||
self.order_flow_clear = RiskManagerSpinBox(0)
|
||||
self.order_size_limit = RiskManagerSpinBox(0)
|
||||
self.trade_limit = RiskManagerSpinBox(0)
|
||||
self.active_order_limit = RiskManagerSpinBox(0)
|
||||
self.order_cancel_limit = RiskManagerSpinBox(0)
|
||||
|
||||
# Button
|
||||
self.switch_button = QtWidgets.QPushButton("风控模块未启动")
|
||||
clear_order_count_button = QtWidgets.QPushButton("清空流控计数")
|
||||
clear_trade_count_button = QtWidgets.QPushButton("清空总成交计数")
|
||||
save_setting_button = QtWidgets.QPushButton("保存设置")
|
||||
|
||||
# Grid layout
|
||||
Label = QtWidgets.QLabel
|
||||
grid = QtWidgets.QGridLayout()
|
||||
grid.addWidget(Label("工作状态"), 0, 0)
|
||||
grid.addWidget(self.switch_button, 0, 1)
|
||||
grid.addWidget(Label("流控上限"), 1, 0)
|
||||
grid.addWidget(self.order_flow_limit, 1, 1)
|
||||
grid.addWidget(Label("流控清空(秒)"), 2, 0)
|
||||
grid.addWidget(self.order_flow_clear, 2, 1)
|
||||
grid.addWidget(Label("单笔委托上限"), 3, 0)
|
||||
grid.addWidget(self.order_size_limit, 3, 1)
|
||||
grid.addWidget(Label("总成交上限"), 4, 0)
|
||||
grid.addWidget(self.trade_limit, 4, 1)
|
||||
grid.addWidget(Label("活动订单上限"), 5, 0)
|
||||
grid.addWidget(self.active_order_limit, 5, 1)
|
||||
grid.addWidget(Label("单合约撤单上限"), 6, 0)
|
||||
grid.addWidget(self.order_cancel_limit, 6, 1)
|
||||
|
||||
# Horizontal box layout
|
||||
hbox = QtWidgets.QHBoxLayout()
|
||||
hbox.addWidget(clear_order_count_button)
|
||||
hbox.addWidget(clear_trade_count_button)
|
||||
hbox.addWidget(save_setting_button)
|
||||
|
||||
# Vertical box layout
|
||||
vbox = QtWidgets.QVBoxLayout()
|
||||
vbox.addLayout(grid)
|
||||
vbox.addLayout(hbox)
|
||||
self.setLayout(vbox)
|
||||
|
||||
# Connect signal to SpinBox
|
||||
self.order_flow_limit.valueChanged.connect(self.risk_manager_engine.set_order_flow_limit)
|
||||
self.order_flow_clear.valueChanged.connect(self.risk_manager_engine.set_order_flow_clear)
|
||||
self.order_size_limit.valueChanged.connect(self.risk_manager_engine.set_order_size_limit)
|
||||
self.trade_limit.valueChanged.connect(self.risk_manager_engine.set_trade_limit)
|
||||
self.active_order_limit.valueChanged.connect(self.risk_manager_engine.set_active_order_limit)
|
||||
self.order_cancel_limit.valueChanged.connect(self.risk_manager_engine.set_order_cancel_limit)
|
||||
|
||||
# Connect signal to button
|
||||
self.switch_button.clicked.connect(self.switch_engine_status)
|
||||
clear_order_count_button.clicked.connect(self.risk_manager_engine.clear_order_flow_count)
|
||||
clear_trade_count_button.clicked.connect(self.risk_manager_engine.clear_trade_count)
|
||||
save_setting_button.clicked.connect(self.risk_manager_engine.save_setting)
|
||||
|
||||
# Set Fix Size
|
||||
self.setFixedSize(self.sizeHint())
|
||||
|
||||
def switch_engine_status(self):
|
||||
""""""
|
||||
self.risk_manager_engine.switch_engine_status()
|
||||
self.update_engine_status()
|
||||
|
||||
def update_engine_status(self):
|
||||
""""""
|
||||
if self.risk_manager_engine.active:
|
||||
self.switch_button.setText("风控模块运行中")
|
||||
self.order_flow_limit.setValue(self.risk_manager_engine.order_flow_limit)
|
||||
self.order_flow_clear.setValue(self.risk_manager_engine.order_flow_clear)
|
||||
self.order_size_limit.setValue(self.risk_manager_engine.order_size_limit)
|
||||
self.trade_limit.setValue(self.risk_manager_engine.trade_limit)
|
||||
self.active_order_limit.setValue(self.risk_manager_engine.active_order_limit)
|
||||
self.order_cancel_limit.setValue(self.risk_manager_engine.order_cancel_limit)
|
||||
else:
|
||||
self.switch_button.setText("风控模块未启动")
|
||||
|
||||
self.risk_manager_engine.save_setting()
|
||||
|
||||
|
||||
class RiskManagerSpinBox(QtWidgets.QSpinBox):
|
||||
""""""
|
||||
|
||||
def __init__(self, value):
|
||||
""""""
|
||||
super(RiskManagerSpinBox, self).__init__()
|
||||
|
||||
self.setMinimum(0)
|
||||
self.setMaximum(1000000)
|
||||
self.setValue(value)
|
Loading…
Reference in New Issue
Block a user