commit
d8dae9e680
@ -121,7 +121,7 @@ never-returning-functions=sys.exit
|
||||
|
||||
# Regular expression matching correct argument names. Overrides argument-
|
||||
# naming-style.
|
||||
argument-rgx=[a-z][a-z0-9_]*
|
||||
argument-rgx=^[a-z][a-z0-9_]*$
|
||||
|
||||
# Naming style matching correct attribute names.
|
||||
attr-naming-style=snake_case
|
||||
|
@ -262,7 +262,7 @@ class FutuGateway(BaseGateway):
|
||||
orderid = str(row["order_id"])
|
||||
|
||||
order = req.create_order_data(orderid, self.gateway_name)
|
||||
self.gateway.on_order(order)
|
||||
self.on_order(order)
|
||||
return order.vt_orderid
|
||||
|
||||
def cancel_order(self, req):
|
||||
|
@ -182,21 +182,21 @@ class IbApi(EWrapper):
|
||||
self.client = IbClient(self)
|
||||
self.thread = Thread(target=self.client.run)
|
||||
|
||||
def connectAck(self):
|
||||
def connectAck(self): # pylint: disable=invalid-name
|
||||
"""
|
||||
Callback when connection is established.
|
||||
"""
|
||||
self.status = True
|
||||
self.gateway.write_log("IB TWS连接成功")
|
||||
|
||||
def connectionClosed(self):
|
||||
def connectionClosed(self): # pylint: disable=invalid-name
|
||||
"""
|
||||
Callback when connection is closed.
|
||||
"""
|
||||
self.status = False
|
||||
self.gateway.write_log("IB TWS连接断开")
|
||||
|
||||
def nextValidId(self, orderId: int):
|
||||
def nextValidId(self, orderId: int): # pylint: disable=invalid-name
|
||||
"""
|
||||
Callback of next valid orderid.
|
||||
"""
|
||||
@ -204,7 +204,7 @@ class IbApi(EWrapper):
|
||||
|
||||
self.orderid = orderId
|
||||
|
||||
def currentTime(self, time: int):
|
||||
def currentTime(self, time: int): # pylint: disable=invalid-name
|
||||
"""
|
||||
Callback of current server time of IB.
|
||||
"""
|
||||
@ -216,7 +216,7 @@ class IbApi(EWrapper):
|
||||
msg = f"服务器时间: {time_string}"
|
||||
self.gateway.write_log(msg)
|
||||
|
||||
def error(self, reqId: TickerId, errorCode: int, errorString: str):
|
||||
def error(self, reqId: TickerId, errorCode: int, errorString: str): # pylint: disable=invalid-name
|
||||
"""
|
||||
Callback of error caused by specific request.
|
||||
"""
|
||||
@ -225,7 +225,7 @@ class IbApi(EWrapper):
|
||||
msg = f"信息通知,代码:{errorCode},内容: {errorString}"
|
||||
self.gateway.write_log(msg)
|
||||
|
||||
def tickPrice(
|
||||
def tickPrice( # pylint: disable=invalid-name
|
||||
self,
|
||||
reqId: TickerId,
|
||||
tickType: TickType,
|
||||
@ -257,7 +257,7 @@ class IbApi(EWrapper):
|
||||
tick.datetime = datetime.now()
|
||||
self.gateway.on_tick(copy(tick))
|
||||
|
||||
def tickSize(self, reqId: TickerId, tickType: TickType, size: int):
|
||||
def tickSize(self, reqId: TickerId, tickType: TickType, size: int): # pylint: disable=invalid-name
|
||||
"""
|
||||
Callback of tick volume update.
|
||||
"""
|
||||
@ -272,7 +272,7 @@ class IbApi(EWrapper):
|
||||
|
||||
self.gateway.on_tick(copy(tick))
|
||||
|
||||
def tickString(self, reqId: TickerId, tickType: TickType, value: str):
|
||||
def tickString(self, reqId: TickerId, tickType: TickType, value: str): # pylint: disable=invalid-name
|
||||
"""
|
||||
Callback of tick string update.
|
||||
"""
|
||||
@ -286,7 +286,7 @@ class IbApi(EWrapper):
|
||||
|
||||
self.gateway.on_tick(copy(tick))
|
||||
|
||||
def orderStatus(
|
||||
def orderStatus( # pylint: disable=invalid-name
|
||||
self,
|
||||
orderId: OrderId,
|
||||
status: str,
|
||||
@ -325,7 +325,7 @@ class IbApi(EWrapper):
|
||||
|
||||
self.gateway.on_order(copy(order))
|
||||
|
||||
def openOrder(
|
||||
def openOrder( # pylint: disable=invalid-name
|
||||
self,
|
||||
orderId: OrderId,
|
||||
ib_contract: Contract,
|
||||
@ -354,7 +354,7 @@ class IbApi(EWrapper):
|
||||
self.orders[orderid] = order
|
||||
self.gateway.on_order(copy(order))
|
||||
|
||||
def updateAccountValue(
|
||||
def updateAccountValue( # pylint: disable=invalid-name
|
||||
self,
|
||||
key: str,
|
||||
val: str,
|
||||
@ -381,7 +381,7 @@ class IbApi(EWrapper):
|
||||
name = ACCOUNTFIELD_IB2VT[key]
|
||||
setattr(account, name, float(val))
|
||||
|
||||
def updatePortfolio(
|
||||
def updatePortfolio( # pylint: disable=invalid-name
|
||||
self,
|
||||
contract: Contract,
|
||||
position: float,
|
||||
@ -419,7 +419,7 @@ class IbApi(EWrapper):
|
||||
)
|
||||
self.gateway.on_position(pos)
|
||||
|
||||
def updateAccountTime(self, timeStamp: str):
|
||||
def updateAccountTime(self, timeStamp: str): # pylint: disable=invalid-name
|
||||
"""
|
||||
Callback of account update time.
|
||||
"""
|
||||
@ -427,7 +427,7 @@ class IbApi(EWrapper):
|
||||
for account in self.accounts.values():
|
||||
self.gateway.on_account(copy(account))
|
||||
|
||||
def contractDetails(self, reqId: int, contractDetails: ContractDetails):
|
||||
def contractDetails(self, reqId: int, contractDetails: ContractDetails): # pylint: disable=invalid-name
|
||||
"""
|
||||
Callback of contract data update.
|
||||
"""
|
||||
@ -456,7 +456,7 @@ class IbApi(EWrapper):
|
||||
|
||||
self.contracts[contract.vt_symbol] = contract
|
||||
|
||||
def execDetails(self, reqId: int, contract: Contract, execution: Execution):
|
||||
def execDetails(self, reqId: int, contract: Contract, execution: Execution): # pylint: disable=invalid-name
|
||||
"""
|
||||
Callback of trade data update.
|
||||
"""
|
||||
@ -479,7 +479,7 @@ class IbApi(EWrapper):
|
||||
|
||||
self.gateway.on_trade(trade)
|
||||
|
||||
def managedAccounts(self, accountsList: str):
|
||||
def managedAccounts(self, accountsList: str): # pylint: disable=invalid-name
|
||||
"""
|
||||
Callback of all sub accountid.
|
||||
"""
|
||||
|
@ -11,8 +11,15 @@ from PyQt5 import QtWidgets, QtGui, QtCore
|
||||
from vnpy.event import EventEngine, Event
|
||||
from ..constant import Direction, Offset, PriceType, Exchange
|
||||
from ..engine import MainEngine
|
||||
from ..event import (EVENT_TICK, EVENT_ORDER, EVENT_TRADE, EVENT_ACCOUNT,
|
||||
EVENT_POSITION, EVENT_CONTRACT, EVENT_LOG)
|
||||
from ..event import (
|
||||
EVENT_TICK,
|
||||
EVENT_ORDER,
|
||||
EVENT_TRADE,
|
||||
EVENT_ACCOUNT,
|
||||
EVENT_POSITION,
|
||||
EVENT_CONTRACT,
|
||||
EVENT_LOG
|
||||
)
|
||||
from ..object import SubscribeRequest, OrderRequest, CancelRequest
|
||||
from ..utility import load_setting, save_setting
|
||||
|
||||
@ -63,7 +70,7 @@ class EnumCell(BaseCell):
|
||||
"""
|
||||
if content:
|
||||
super(EnumCell, self).set_content(content.value, data)
|
||||
|
||||
|
||||
|
||||
class DirectionCell(EnumCell):
|
||||
"""
|
||||
@ -282,7 +289,8 @@ class BaseMonitor(QtWidgets.QTableWidget):
|
||||
Resize all columns according to contents.
|
||||
"""
|
||||
self.horizontalHeader().resizeSections(
|
||||
QtWidgets.QHeaderView.ResizeToContents)
|
||||
QtWidgets.QHeaderView.ResizeToContents
|
||||
)
|
||||
|
||||
def save_csv(self):
|
||||
"""
|
||||
@ -308,12 +316,12 @@ class BaseMonitor(QtWidgets.QTableWidget):
|
||||
else:
|
||||
row_data.append("")
|
||||
writer.writerow(row_data)
|
||||
|
||||
|
||||
def contextMenuEvent(self, event):
|
||||
"""
|
||||
Show menu with right click.
|
||||
"""
|
||||
self.menu.popup(QtGui.QCursor.pos())
|
||||
self.menu.popup(QtGui.QCursor.pos())
|
||||
|
||||
|
||||
class TickMonitor(BaseMonitor):
|
||||
@ -664,7 +672,7 @@ class ConnectDialog(QtWidgets.QDialog):
|
||||
"""
|
||||
Start connection of a certain gateway.
|
||||
"""
|
||||
|
||||
|
||||
def __init__(self, main_engine: MainEngine, gateway_name: str):
|
||||
""""""
|
||||
super(ConnectDialog, self).__init__()
|
||||
@ -676,17 +684,19 @@ class ConnectDialog(QtWidgets.QDialog):
|
||||
self.widgets = {}
|
||||
|
||||
self.init_ui()
|
||||
|
||||
|
||||
def init_ui(self):
|
||||
""""""
|
||||
self.setWindowTitle(f"连接{self.gateway_name}")
|
||||
|
||||
# Default setting provides field name, field data type and field default value.
|
||||
default_setting = self.main_engine.get_default_setting(self.gateway_name)
|
||||
default_setting = self.main_engine.get_default_setting(
|
||||
self.gateway_name
|
||||
)
|
||||
|
||||
# Saved setting provides field data used last time.
|
||||
loaded_setting = load_setting(self.file_name)
|
||||
|
||||
|
||||
# Initialize line edits and form layout based on setting.
|
||||
form = QtWidgets.QFormLayout()
|
||||
|
||||
@ -729,13 +739,12 @@ class ConnectDialog(QtWidgets.QDialog):
|
||||
else:
|
||||
field_value = field_type(widget.text())
|
||||
setting[field_name] = field_value
|
||||
|
||||
|
||||
self.main_engine.connect(setting, self.gateway_name)
|
||||
|
||||
|
||||
save_setting(self.file_name, setting)
|
||||
|
||||
self.accept()
|
||||
|
||||
|
||||
|
||||
class TradingWidget(QtWidgets.QWidget):
|
||||
@ -744,7 +753,7 @@ class TradingWidget(QtWidgets.QWidget):
|
||||
"""
|
||||
|
||||
signal_tick = QtCore.pyqtSignal(Event)
|
||||
|
||||
|
||||
def __init__(self, main_engine: MainEngine, event_engine: EventEngine):
|
||||
""""""
|
||||
super(TradingWidget, self).__init__()
|
||||
@ -756,7 +765,7 @@ class TradingWidget(QtWidgets.QWidget):
|
||||
|
||||
self.init_ui()
|
||||
self.register_event()
|
||||
|
||||
|
||||
def init_ui(self):
|
||||
""""""
|
||||
self.setFixedWidth(300)
|
||||
@ -772,20 +781,22 @@ class TradingWidget(QtWidgets.QWidget):
|
||||
self.name_line.setReadOnly(True)
|
||||
|
||||
self.direction_combo = QtWidgets.QComboBox()
|
||||
self.direction_combo.addItems([
|
||||
Direction.LONG.value,
|
||||
Direction.SHORT.value
|
||||
])
|
||||
self.direction_combo.addItems(
|
||||
[Direction.LONG.value,
|
||||
Direction.SHORT.value]
|
||||
)
|
||||
|
||||
self.offset_combo = QtWidgets.QComboBox()
|
||||
self.offset_combo.addItems([offset.value for offset in Offset])
|
||||
|
||||
self.price_type_combo = QtWidgets.QComboBox()
|
||||
self.price_type_combo.addItems([price_type.value for price_type in PriceType])
|
||||
self.price_type_combo.addItems(
|
||||
[price_type.value for price_type in PriceType]
|
||||
)
|
||||
|
||||
double_validator = QtGui.QDoubleValidator()
|
||||
double_validator.setBottom(0)
|
||||
|
||||
|
||||
self.price_line = QtWidgets.QLineEdit()
|
||||
self.price_line.setValidator(double_validator)
|
||||
|
||||
@ -817,18 +828,33 @@ class TradingWidget(QtWidgets.QWidget):
|
||||
# Market depth display area
|
||||
bid_color = "rgb(255,174,201)"
|
||||
ask_color = "rgb(160,255,160)"
|
||||
|
||||
|
||||
self.bp1_label = self.create_label(bid_color)
|
||||
self.bp2_label = self.create_label(bid_color)
|
||||
self.bp3_label = self.create_label(bid_color)
|
||||
self.bp4_label = self.create_label(bid_color)
|
||||
self.bp5_label = self.create_label(bid_color)
|
||||
|
||||
self.bv1_label = self.create_label(bid_color, alignment=QtCore.Qt.AlignRight)
|
||||
self.bv2_label = self.create_label(bid_color, alignment=QtCore.Qt.AlignRight)
|
||||
self.bv3_label = self.create_label(bid_color, alignment=QtCore.Qt.AlignRight)
|
||||
self.bv4_label = self.create_label(bid_color, alignment=QtCore.Qt.AlignRight)
|
||||
self.bv5_label = self.create_label(bid_color, alignment=QtCore.Qt.AlignRight)
|
||||
self.bv1_label = self.create_label(
|
||||
bid_color,
|
||||
alignment=QtCore.Qt.AlignRight
|
||||
)
|
||||
self.bv2_label = self.create_label(
|
||||
bid_color,
|
||||
alignment=QtCore.Qt.AlignRight
|
||||
)
|
||||
self.bv3_label = self.create_label(
|
||||
bid_color,
|
||||
alignment=QtCore.Qt.AlignRight
|
||||
)
|
||||
self.bv4_label = self.create_label(
|
||||
bid_color,
|
||||
alignment=QtCore.Qt.AlignRight
|
||||
)
|
||||
self.bv5_label = self.create_label(
|
||||
bid_color,
|
||||
alignment=QtCore.Qt.AlignRight
|
||||
)
|
||||
|
||||
self.ap1_label = self.create_label(ask_color)
|
||||
self.ap2_label = self.create_label(ask_color)
|
||||
@ -836,11 +862,26 @@ class TradingWidget(QtWidgets.QWidget):
|
||||
self.ap4_label = self.create_label(ask_color)
|
||||
self.ap5_label = self.create_label(ask_color)
|
||||
|
||||
self.av1_label = self.create_label(ask_color, alignment=QtCore.Qt.AlignRight)
|
||||
self.av2_label = self.create_label(ask_color, alignment=QtCore.Qt.AlignRight)
|
||||
self.av3_label = self.create_label(ask_color, alignment=QtCore.Qt.AlignRight)
|
||||
self.av4_label = self.create_label(ask_color, alignment=QtCore.Qt.AlignRight)
|
||||
self.av5_label = self.create_label(ask_color, alignment=QtCore.Qt.AlignRight)
|
||||
self.av1_label = self.create_label(
|
||||
ask_color,
|
||||
alignment=QtCore.Qt.AlignRight
|
||||
)
|
||||
self.av2_label = self.create_label(
|
||||
ask_color,
|
||||
alignment=QtCore.Qt.AlignRight
|
||||
)
|
||||
self.av3_label = self.create_label(
|
||||
ask_color,
|
||||
alignment=QtCore.Qt.AlignRight
|
||||
)
|
||||
self.av4_label = self.create_label(
|
||||
ask_color,
|
||||
alignment=QtCore.Qt.AlignRight
|
||||
)
|
||||
self.av5_label = self.create_label(
|
||||
ask_color,
|
||||
alignment=QtCore.Qt.AlignRight
|
||||
)
|
||||
|
||||
self.lp_label = self.create_label()
|
||||
self.return_label = self.create_label(alignment=QtCore.Qt.AlignRight)
|
||||
@ -857,14 +898,18 @@ class TradingWidget(QtWidgets.QWidget):
|
||||
form2.addRow(self.bp3_label, self.bv3_label)
|
||||
form2.addRow(self.bp4_label, self.bv4_label)
|
||||
form2.addRow(self.bp5_label, self.bv5_label)
|
||||
|
||||
|
||||
# Overall layout
|
||||
vbox = QtWidgets.QVBoxLayout()
|
||||
vbox.addLayout(form1)
|
||||
vbox.addLayout(form2)
|
||||
self.setLayout(vbox)
|
||||
|
||||
def create_label(self, color: str = "", alignment: int = QtCore.Qt.AlignLeft):
|
||||
|
||||
def create_label(
|
||||
self,
|
||||
color: str = "",
|
||||
alignment: int = QtCore.Qt.AlignLeft
|
||||
):
|
||||
"""
|
||||
Create label with certain font color.
|
||||
"""
|
||||
@ -873,12 +918,12 @@ class TradingWidget(QtWidgets.QWidget):
|
||||
label.setStyleSheet(f"color:{color}")
|
||||
label.setAlignment(alignment)
|
||||
return label
|
||||
|
||||
|
||||
def register_event(self):
|
||||
""""""
|
||||
self.signal_tick.connect(self.process_tick_event)
|
||||
self.event_engine.register(EVENT_TICK, self.signal_tick.emit)
|
||||
|
||||
|
||||
def process_tick_event(self, event: Event):
|
||||
""""""
|
||||
tick = event.data
|
||||
@ -894,8 +939,8 @@ class TradingWidget(QtWidgets.QWidget):
|
||||
if tick.pre_close:
|
||||
r = (tick.last_price / tick.pre_close - 1) * 100
|
||||
self.return_label.setText(f"{r:.2f}%")
|
||||
|
||||
if tick.bid_price_2:
|
||||
|
||||
if tick.bid_price_2:
|
||||
self.bp2_label.setText(str(tick.bid_price_2))
|
||||
self.bv2_label.setText(str(tick.bid_volume_2))
|
||||
self.ap2_label.setText(str(tick.ask_price_2))
|
||||
@ -948,10 +993,7 @@ class TradingWidget(QtWidgets.QWidget):
|
||||
self.clear_label_text()
|
||||
|
||||
# Subscribe tick data
|
||||
req = SubscribeRequest(
|
||||
symbol=symbol,
|
||||
exchange=Exchange(exchange_value)
|
||||
)
|
||||
req = SubscribeRequest(symbol=symbol, exchange=Exchange(exchange_value))
|
||||
|
||||
self.main_engine.subscribe(req, gateway_name)
|
||||
|
||||
@ -992,21 +1034,15 @@ class TradingWidget(QtWidgets.QWidget):
|
||||
"""
|
||||
symbol = str(self.symbol_line.text())
|
||||
if not symbol:
|
||||
QtWidgets.QMessageBox.critical(
|
||||
"委托失败",
|
||||
"请输入合约代码"
|
||||
)
|
||||
QtWidgets.QMessageBox.critical("委托失败", "请输入合约代码")
|
||||
return
|
||||
|
||||
volume_text = str(self.volume_line.text())
|
||||
if not volume_text:
|
||||
QtWidgets.QMessageBox.critical(
|
||||
"委托失败",
|
||||
"请输入委托数量"
|
||||
)
|
||||
QtWidgets.QMessageBox.critical("委托失败", "请输入委托数量")
|
||||
return
|
||||
volume = float(volume_text)
|
||||
|
||||
|
||||
price_text = str(self.price_line.text())
|
||||
if not price_text:
|
||||
price = 0
|
||||
@ -1026,7 +1062,7 @@ class TradingWidget(QtWidgets.QWidget):
|
||||
gateway_name = str(self.gateway_combo.currentText())
|
||||
|
||||
self.main_engine.send_order(req, gateway_name)
|
||||
|
||||
|
||||
def cancel_all(self):
|
||||
"""
|
||||
Cancel all active orders.
|
||||
@ -1051,7 +1087,7 @@ class ActiveOrderMonitor(OrderMonitor):
|
||||
order = event.data
|
||||
row_cells = self.cells[order.vt_orderid]
|
||||
row = self.row(row_cells["volume"])
|
||||
|
||||
|
||||
if order.is_active():
|
||||
self.showRow(row)
|
||||
else:
|
||||
@ -1081,7 +1117,7 @@ class ContractManager(QtWidgets.QWidget):
|
||||
self.event_engine = event_engine
|
||||
|
||||
self.init_ui()
|
||||
|
||||
|
||||
def init_ui(self):
|
||||
""""""
|
||||
self.setWindowTitle("合约查询")
|
||||
@ -1108,13 +1144,13 @@ class ContractManager(QtWidgets.QWidget):
|
||||
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
|
||||
@ -1123,7 +1159,10 @@ class ContractManager(QtWidgets.QWidget):
|
||||
|
||||
all_contracts = self.main_engine.get_all_contracts()
|
||||
if flt:
|
||||
contracts = [contract for contract in all_contracts if flt in contract.vt_symbol]
|
||||
contracts = [
|
||||
contract for contract in all_contracts
|
||||
if flt in contract.vt_symbol
|
||||
]
|
||||
else:
|
||||
contracts = all_contracts
|
||||
|
||||
@ -1155,7 +1194,7 @@ class AboutDialog(QtWidgets.QDialog):
|
||||
self.event_engine = event_engine
|
||||
|
||||
self.init_ui()
|
||||
|
||||
|
||||
def init_ui(self):
|
||||
""""""
|
||||
self.setWindowTitle(f"关于VN Trader")
|
||||
|
Loading…
Reference in New Issue
Block a user