From 9b2b0561b142459e502f5f5c57d620c1a88d4252 Mon Sep 17 00:00:00 2001 From: "vn.py" Date: Fri, 11 Jan 2019 12:21:55 +0800 Subject: [PATCH] [Add] Add active order monitor and contract manager --- vnpy/trader/engine.py | 3 +- vnpy/trader/object.py | 2 +- vnpy/trader/ui/mainwindow.py | 28 +++++++++- vnpy/trader/ui/widget.py | 104 ++++++++++++++++++++++++++++++++++- 4 files changed, 133 insertions(+), 4 deletions(-) diff --git a/vnpy/trader/engine.py b/vnpy/trader/engine.py index 6d05c96c..b473e33c 100644 --- a/vnpy/trader/engine.py +++ b/vnpy/trader/engine.py @@ -263,6 +263,7 @@ class OmsEngine(BaseEngine): self.main_engine.get_all_trades = self.get_all_trades self.main_engine.get_all_positions = self.get_all_positions self.main_engine.get_all_accounts = self.get_all_accounts + self.main_engine.get_all_contracts = self.get_all_contracts self.main_engine.get_all_active_orders = self.get_all_active_orders def register_event(self): @@ -285,7 +286,7 @@ class OmsEngine(BaseEngine): self.orders[order.vt_orderid] = order # If order is active, then update data in dict. - if order.check_active(): + if order.is_active(): self.active_orders[order.vt_orderid] = order # Otherwise, pop inactive order from in dict elif order.vt_orderid in self.active_orders: diff --git a/vnpy/trader/object.py b/vnpy/trader/object.py index f0e63936..2d36405f 100644 --- a/vnpy/trader/object.py +++ b/vnpy/trader/object.py @@ -114,7 +114,7 @@ class OrderData(BaseData): self.vt_symbol = f"{self.symbol}.{self.exchange}" self.vt_orderid = f"{self.gateway_name}.{self.orderid}" - def check_active(self): + def is_active(self): """ Check if the order is active. """ diff --git a/vnpy/trader/ui/mainwindow.py b/vnpy/trader/ui/mainwindow.py index 19b30ec2..9d091a0f 100644 --- a/vnpy/trader/ui/mainwindow.py +++ b/vnpy/trader/ui/mainwindow.py @@ -17,7 +17,9 @@ from .widget import ( AccountMonitor, LogMonitor, ConnectDialog, - TradingWidget + TradingWidget, + ActiveOrderMonitor, + ContractManager ) @@ -48,11 +50,14 @@ class MainWindow(QtWidgets.QMainWindow): trading_widget, trading_dock = self.create_dock(TradingWidget, "交易", QtCore.Qt.LeftDockWidgetArea) tick_widget, tick_dock = self.create_dock(TickMonitor, "行情", QtCore.Qt.RightDockWidgetArea) order_widget, order_dock = self.create_dock(OrderMonitor, "委托", QtCore.Qt.RightDockWidgetArea) + active_widget, active_dock = self.create_dock(ActiveOrderMonitor, "活动", QtCore.Qt.RightDockWidgetArea) trade_widget, trade_dock = self.create_dock(TradeMonitor, "成交", QtCore.Qt.RightDockWidgetArea) log_widget, log_dock = self.create_dock(LogMonitor, "日志", QtCore.Qt.BottomDockWidgetArea) account_widget, account_dock = self.create_dock(AccountMonitor, "资金", QtCore.Qt.BottomDockWidgetArea) position_widget, position_dock = self.create_dock(PositionMonitor, "持仓", QtCore.Qt.BottomDockWidgetArea) + self.tabifyDockWidget(active_dock, order_dock) + def init_menu(self): """""" bar = self.menuBar() @@ -61,6 +66,7 @@ class MainWindow(QtWidgets.QMainWindow): app_menu = bar.addMenu("功能") help_menu = bar.addMenu("帮助") + # System menu gateway_names = self.main_engine.get_all_gateway_names() for name in gateway_names: func = partial(self.connect, name) @@ -72,6 +78,16 @@ class MainWindow(QtWidgets.QMainWindow): sys_menu.addAction(action) + # App menu + + # Help menu + contract_action = QtWidgets.QAction("查询合约", self) + contract_action.triggered.connect(self.open_contract) + contract_icon = QtGui.QIcon(get_icon_path(__file__, "contract.ico")) + contract_action.setIcon(contract_icon) + + help_menu.addAction(contract_action) + def create_dock( self, widget_class: QtWidgets.QWidget, @@ -121,3 +137,13 @@ class MainWindow(QtWidgets.QMainWindow): event.accept() else: event.ignore() + + def open_contract(self): + """ + Open contract manager. + """ + widget = self.widgets.get("contract", None) + if not widget: + widget = ContractManager(self.main_engine, self.event_engine) + self.widgets["contract"] = widget + widget.show() \ No newline at end of file diff --git a/vnpy/trader/ui/widget.py b/vnpy/trader/ui/widget.py index 7e417295..5266e19f 100644 --- a/vnpy/trader/ui/widget.py +++ b/vnpy/trader/ui/widget.py @@ -958,4 +958,106 @@ class TradingWidget(QtWidgets.QWidget): order_list = self.main_engine.get_all_active_orders() for order in order_list: req = order.create_cancel_request() - self.main_engine.cancel_order(req, order.gateway_name) \ No newline at end of file + self.main_engine.cancel_order(req, order.gateway_name) + + +class ActiveOrderMonitor(OrderMonitor): + """ + Monitor which shows active order only. + """ + + def process_event(self, event): + """ + Hides the row if order is not active. + """ + super(ActiveOrderMonitor, self).process_event(event) + + order = event.data + row_cells = self.cells[order.vt_orderid] + row = self.row(row_cells["volume"]) + + if order.is_active(): + self.showRow(row) + else: + self.hideRow(row) + + +class ContractManager(QtWidgets.QWidget): + """ + Query contract data available to trade in system. + """ + + headers = { + "vt_symbol": "本地代码", + "symbol": "代码", + "exchange": "交易所", + "name": "名称", + "product": "合约分类", + "size": "合约乘数", + "pricetick": "价格跳动", + "gateway_name": "交易接口" + } + + def __init__(self, main_engine, event_engine): + super(ContractManager, self).__init__() + + self.main_engine = main_engine + self.event_engine = event_engine + + self.init_ui() + + def init_ui(self): + """""" + self.setWindowTitle("合约查询") + self.resize(1000, 600) + + self.filter_line = QtWidgets.QLineEdit() + self.filter_line.setPlaceholderText("输入合约代码或者交易所,留空则查询所有合约") + + self.button_show = QtWidgets.QPushButton("查询") + self.button_show.clicked.connect(self.show_contracts) + + labels = [] + for name, display in self.headers.items(): + label = f"{display}\n{name}" + labels.append(label) + + self.contract_table = QtWidgets.QTableWidget() + self.contract_table.setColumnCount(len(self.headers)) + self.contract_table.setHorizontalHeaderLabels(labels) + self.contract_table.verticalHeader().setVisible(False) + self.contract_table.setEditTriggers(self.contract_table.NoEditTriggers) + self.contract_table.setAlternatingRowColors(True) + + hbox = QtWidgets.QHBoxLayout() + hbox.addWidget(self.filter_line) + hbox.addWidget(self.button_show) + + vbox = QtWidgets.QVBoxLayout() + vbox.addLayout(hbox) + vbox.addWidget(self.contract_table) + + self.setLayout(vbox) + + def show_contracts(self): + """ + Show contracts by symbol + """ + flt = str(self.filter_line.text()) + + all_contracts = self.main_engine.get_all_contracts() + if flt: + contracts = [contract for contract in all_contracts if flt in contract.vt_symbol] + else: + contracts = all_contracts + + self.contract_table.clearContents() + self.contract_table.setRowCount(len(contracts)) + + for row, contract in enumerate(contracts): + for column, name in enumerate(self.headers.keys()): + cell = BaseCell(getattr(contract, name), contract) + self.contract_table.setItem(row, column, cell) + + self.contract_table.resizeColumnsToContents() +