[Mod] change RiskManager to use QDialog

This commit is contained in:
vn.py 2019-06-02 14:51:15 +08:00
parent 6311bb510e
commit 41bcf7b605
7 changed files with 152 additions and 176 deletions

View File

@ -25,6 +25,7 @@ from vnpy.app.csv_loader import CsvLoaderApp
from vnpy.app.algo_trading import AlgoTradingApp from vnpy.app.algo_trading import AlgoTradingApp
from vnpy.app.cta_backtester import CtaBacktesterApp from vnpy.app.cta_backtester import CtaBacktesterApp
from vnpy.app.data_recorder import DataRecorderApp from vnpy.app.data_recorder import DataRecorderApp
from vnpy.app.risk_manager import RiskManagerApp
def main(): def main():
@ -55,6 +56,7 @@ def main():
main_engine.add_app(CsvLoaderApp) main_engine.add_app(CsvLoaderApp)
main_engine.add_app(AlgoTradingApp) main_engine.add_app(AlgoTradingApp)
main_engine.add_app(DataRecorderApp) main_engine.add_app(DataRecorderApp)
main_engine.add_app(RiskManagerApp)
main_window = MainWindow(main_engine, event_engine) main_window = MainWindow(main_engine, event_engine)
main_window.showMaximized() main_window.showMaximized()

View File

@ -8,7 +8,7 @@ class RiskManagerApp(BaseApp):
app_name = APP_NAME app_name = APP_NAME
app_module = __module__ app_module = __module__
app_path = Path(__file__).parent app_path = Path(__file__).parent
display_name = "" display_name = "交易风控"
engine_class = RiskManagerEngine engine_class = RiskManagerEngine
widget_name = "RiskManager" widget_name = "RiskManager"
icon_name = "risk_manager.ico" icon_name = "rm.ico"

View File

@ -15,32 +15,42 @@ APP_NAME = "RiskManager"
class RiskManagerEngine(BaseEngine): class RiskManagerEngine(BaseEngine):
"""""" """"""
setting_filename = "risk_manager_setting.json" setting_filename = "risk_manager_setting.json"
def __init__(self, main_engine: MainEngine, event_engine: EventEngine): def __init__(self, main_engine: MainEngine, event_engine: EventEngine):
"""""" """"""
super().__init__(main_engine, event_engine, APP_NAME) super().__init__(main_engine, event_engine, APP_NAME)
self.main_engine = main_engine self.main_engine = main_engine
self.event_engine = event_engine self.event_engine = event_engine
self.active = False self.active = False
self.order_flow_count = 0
self.order_flow_limit = 50 self.order_flow_count = 0
self.order_flow_clear = 1 self.order_flow_limit = 50
self.order_flow_timer = 0
self.order_size_limit = 100 self.order_flow_clear = 1
self.trade_count = 0 self.order_flow_timer = 0
self.trade_limit = 1000
self.order_cancel_limit = 10 self.order_size_limit = 100
self.order_cancel_counts = defaultdict(int)
self.active_order_limit = 20 self.trade_count = 0
self.trade_limit = 1000
# Patch send order function of MainEngine
self._send_order = self.main_engine.send_order self.order_cancel_limit = 500
self.main_engine.send_order = self.send_order self.order_cancel_counts = defaultdict(int)
self.active_order_limit = 50
self.load_setting() self.load_setting()
self.register_event() self.register_event()
self.patch_send_order()
def patch_send_order(self):
"""
Patch send order function of MainEngine.
"""
self._send_order = self.main_engine.send_order
self.main_engine.send_order = self.send_order
def send_order(self, req: OrderRequest, gateway_name: str): def send_order(self, req: OrderRequest, gateway_name: str):
"""""" """"""
@ -49,20 +59,23 @@ class RiskManagerEngine(BaseEngine):
return "" return ""
return self._send_order(req, gateway_name) return self._send_order(req, gateway_name)
def load_setting(self):
""""""
setting = load_json(self.setting_filename)
self.active = setting.get("active", self.active) def update_setting(self, setting: dict):
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.active = setting["active"]
self.order_size_limit = setting.get("order_size_limit", self.order_size_limit) self.order_flow_limit = setting["order_flow_limit"]
self.trade_limit = setting.get("trade_limit", self.trade_limit) self.order_flow_clear = setting["order_flow_clear"]
self.active_order_limit = setting.get("active_order_limit", self.active_order_limit) self.order_size_limit = setting["order_size_limit"]
self.order_cancel_limit = setting.get("order_cancel_limit", self.order_cancel_limit) self.trade_limit = setting["trade_limit"]
self.active_order_limit = setting["active_order_limit"]
def save_setting(self): self.order_cancel_limit = setting["order_cancel_limit"]
if self.active:
self.write_log("交易风控功能启动")
else:
self.write_log("交易风控功能停止")
def get_setting(self):
"""""" """"""
setting = { setting = {
"active": self.active, "active": self.active,
@ -73,27 +86,39 @@ class RiskManagerEngine(BaseEngine):
"active_order_limit": self.active_order_limit, "active_order_limit": self.active_order_limit,
"order_cancel_limit": self.order_cancel_limit, "order_cancel_limit": self.order_cancel_limit,
} }
return setting
def load_setting(self):
""""""
setting = load_json(self.setting_filename)
if not setting:
return
self.update_setting(setting)
def save_setting(self):
""""""
setting = self.get_setting()
save_json(self.setting_filename, setting) save_json(self.setting_filename, setting)
def register_event(self): def register_event(self):
"""""" """"""
self.event_engine.register(EVENT_TRADE, self.process_trade_event) self.event_engine.register(EVENT_TRADE, self.process_trade_event)
self.event_engine.register(EVENT_TIMER, self.process_timer_event) self.event_engine.register(EVENT_TIMER, self.process_timer_event)
self.event_engine.register(EVENT_ORDER, self.process_order_event) self.event_engine.register(EVENT_ORDER, self.process_order_event)
def process_order_event(self, event: Event): def process_order_event(self, event: Event):
"""""" """"""
order = event.data order = event.data
if order.status != Status.CANCELLED: if order.status != Status.CANCELLED:
return return
self.order_cancel_counts[order.symbol] += 1 self.order_cancel_counts[order.symbol] += 1
def process_trade_event(self, event: Event): def process_trade_event(self, event: Event):
"""""" """"""
trade = event.data trade = event.data
self.trade_count += trade.volume self.trade_count += trade.volume
def process_timer_event(self, event: Event): def process_timer_event(self, event: Event):
"""""" """"""
self.order_flow_timer += 1 self.order_flow_timer += 1
@ -101,9 +126,9 @@ class RiskManagerEngine(BaseEngine):
if self.order_flow_timer >= self.order_flow_clear: if self.order_flow_timer >= self.order_flow_clear:
self.order_flow_count = 0 self.order_flow_count = 0
self.order_flow_timer = 0 self.order_flow_timer = 0
def write_risk_log(self, msg: str): def write_log(self, msg: str):
"""""" """"""
log = LogData(msg=msg, gateway_name="RiskManager") log = LogData(msg=msg, gateway_name="RiskManager")
event = Event(type=EVENT_LOG, data=log) event = Event(type=EVENT_LOG, data=log)
self.event_engine.put(event) self.event_engine.put(event)
@ -115,81 +140,39 @@ class RiskManagerEngine(BaseEngine):
# Check order volume # Check order volume
if req.volume <= 0: if req.volume <= 0:
self.write_risk_log("委托数量必须大于0") self.write_log("委托数量必须大于0")
return False return False
if req.volume > self.order_size_limit: if req.volume > self.order_size_limit:
self.write_risk_log(f"单笔委托数量{req.volume},超过限制{self.order_size_limit}") self.write_log(
f"单笔委托数量{req.volume},超过限制{self.order_size_limit}")
return False return False
# Check trade volume # Check trade volume
if self.trade_count >= self.trade_limit: if self.trade_count >= self.trade_limit:
self.write_risk_log(f"今日总成交合约数量{self.trade_count},超过限制{self.trade_limit}") self.write_log(
f"今日总成交合约数量{self.trade_count},超过限制{self.trade_limit}")
return False return False
# Check flow count # Check flow count
if self.order_flow_count >= self.order_flow_limit: 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_log(
f"委托流数量{self.order_flow_count},超过限制每{self.order_flow_clear}{self.order_flow_limit}")
return False return False
# Check all active orders # Check all active orders
active_order_count = len(self.main_engine.get_all_active_orders()) active_order_count = len(self.main_engine.get_all_active_orders())
if active_order_count >= self.active_order_limit: if active_order_count >= self.active_order_limit:
self.write_risk_log(f"当前活动委托次数{active_order_count},超过限制{self.active_order_limit}") self.write_log(
f"当前活动委托次数{active_order_count},超过限制{self.active_order_limit}")
return False return False
# Check order cancel counts # 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}") self.write_log(
f"当日{req.symbol}撤单次数{self.order_cancel_counts[req.symbol]},超过限制{self.order_cancel_limit}")
return False return False
# Add flow count if pass all checks # Add flow count if pass all checks
self.order_flow_count += 1 self.order_flow_count += 1
return True return True
def clear_order_flow_count(self):
""""""
self.order_flow_count = 0
self.write_risk_log("清空流控计数")
def clear_trade_count(self):
""""""
self.trade_count = 0
self.write_risk_log("清空总成交计数")
def set_order_flow_limit(self, n):
""""""
self.order_flow_limit = n
def set_order_flow_clear(self, n):
""""""
self.order_flow_clear = n
def set_order_size_limit(self, n):
""""""
self.order_size_limit = n
def set_trade_limit(self, n):
""""""
self.trade_limit = n
def set_active_order_limit(self, n):
""""""
self.active_order_limit = n
def set_order_cancel_limit(self, n):
""""""
self.order_cancel_limit = n
def switch_engine_status(self):
""""""
self.active = not self.active
if self.active:
self.write_risk_log("风险管理功能启动")
else:
self.write_risk_log("风险管理功能停止")
def stop(self):
""""""
self.save_setting()

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

View File

@ -4,7 +4,7 @@ from vnpy.trader.ui import QtWidgets
from ..engine import APP_NAME from ..engine import APP_NAME
class RiskManager(QtWidgets.QWidget): class RiskManager(QtWidgets.QDialog):
"""""" """"""
def __init__(self, main_engine: MainEngine, event_engine: EventEngine): def __init__(self, main_engine: MainEngine, event_engine: EventEngine):
@ -13,104 +13,95 @@ class RiskManager(QtWidgets.QWidget):
self.main_engine = main_engine self.main_engine = main_engine
self.event_engine = event_engine self.event_engine = event_engine
self.risk_manager_engine = main_engine.get_engine(APP_NAME) self.rm_engine = main_engine.get_engine(APP_NAME)
self.init_ui() self.init_ui()
self.update_engine_status()
def init_ui(self): def init_ui(self):
"""""" """"""
self.setWindowTitle("") self.setWindowTitle("交易风控")
# SpinBox # Create widgets
self.order_flow_limit = RiskManagerSpinBox(0) self.active_combo = QtWidgets.QComboBox()
self.order_flow_clear = RiskManagerSpinBox(0) self.active_combo.addItems(["停止", "启动"])
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.flow_limit_spin = RiskManagerSpinBox()
self.switch_button = QtWidgets.QPushButton("风控模块未启动") self.flow_clear_spin = RiskManagerSpinBox()
clear_order_count_button = QtWidgets.QPushButton("清空流控计数") self.size_limit_spin = RiskManagerSpinBox()
clear_trade_count_button = QtWidgets.QPushButton("清空总成交计数") self.trade_limit_spin = RiskManagerSpinBox()
save_setting_button = QtWidgets.QPushButton("保存设置") self.active_limit_spin = RiskManagerSpinBox()
self.cancel_limit_spin = RiskManagerSpinBox()
# Grid layout save_button = QtWidgets.QPushButton("保存")
Label = QtWidgets.QLabel save_button.clicked.connect(self.save_setting)
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 # Form layout
hbox = QtWidgets.QHBoxLayout() form = QtWidgets.QFormLayout()
hbox.addWidget(clear_order_count_button) form.addRow("风控运行状态", self.active_combo)
hbox.addWidget(clear_trade_count_button) form.addRow("委托流控上限(笔)", self.flow_limit_spin)
hbox.addWidget(save_setting_button) form.addRow("委托流控清空(秒)", self.flow_clear_spin)
form.addRow("单笔委托上限(数量)", self.size_limit_spin)
form.addRow("总成交上限(笔)", self.trade_limit_spin)
form.addRow("活动委托上限(笔)", self.active_limit_spin)
form.addRow("合约撤单上限(笔)", self.cancel_limit_spin)
form.addRow(save_button)
# Vertical box layout self.setLayout(form)
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 # Set Fix Size
self.setFixedSize(self.sizeHint()) hint = self.sizeHint()
self.setFixedSize(hint.width() * 1.2, hint.height())
def switch_engine_status(self): def save_setting(self):
"""""" """"""
self.risk_manager_engine.switch_engine_status() active_text = self.active_combo.currentText()
self.update_engine_status() if active_text == "启动":
active = True
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: else:
self.switch_button.setText("风控模块未启动") active = False
self.risk_manager_engine.save_setting() setting = {
"active": active,
"order_flow_limit": self.flow_limit_spin.value(),
"order_flow_clear": self.flow_clear_spin.value(),
"order_size_limit": self.size_limit_spin.value(),
"trade_limit": self.trade_limit_spin.value(),
"active_order_limit": self.active_limit_spin.value(),
"order_cancel_limit": self.cancel_limit_spin.value(),
}
self.rm_engine.update_setting(setting)
self.rm_engine.save_setting()
self.close()
def update_setting(self):
""""""
setting = self.rm_engine.get_setting()
if setting["active"]:
self.active_combo.setCurrentIndex(1)
else:
self.active_combo.setCurrentIndex(0)
self.flow_limit_spin.setValue(setting["order_flow_limit"])
self.flow_clear_spin.setValue(setting["order_flow_clear"])
self.size_limit_spin.setValue(setting["order_size_limit"])
self.trade_limit_spin.setValue(setting["trade_limit"])
self.active_limit_spin.setValue(setting["active_order_limit"])
self.cancel_limit_spin.setValue(setting["order_cancel_limit"])
def exec_(self):
""""""
self.update_setting()
super().exec_()
class RiskManagerSpinBox(QtWidgets.QSpinBox): class RiskManagerSpinBox(QtWidgets.QSpinBox):
"""""" """"""
def __init__(self, value): def __init__(self, value: int = 0):
"""""" """"""
super(RiskManagerSpinBox, self).__init__() super().__init__()
self.setMinimum(0) self.setMinimum(0)
self.setMaximum(1000000) self.setMaximum(1000000)
self.setValue(value) self.setValue(value)

View File

@ -187,7 +187,7 @@ class MainWindow(QtWidgets.QMainWindow):
if not dialog: if not dialog:
dialog = ConnectDialog(self.main_engine, gateway_name) dialog = ConnectDialog(self.main_engine, gateway_name)
dialog.exec() dialog.exec_()
def closeEvent(self, event): def closeEvent(self, event):
""" """
@ -222,7 +222,7 @@ class MainWindow(QtWidgets.QMainWindow):
self.widgets[name] = widget self.widgets[name] = widget
if isinstance(widget, QtWidgets.QDialog): if isinstance(widget, QtWidgets.QDialog):
widget.exec() widget.exec_()
else: else:
widget.show() widget.show()