From 7b96029cfeffb2ddf5855871332ecc06ba3e6955 Mon Sep 17 00:00:00 2001 From: "ares89@wind" Date: Fri, 3 Feb 2017 17:56:52 +0800 Subject: [PATCH 01/13] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=88=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vn.trader/uiBasicWidget.py | 319 +++++++++++++++++++------------------ 1 file changed, 162 insertions(+), 157 deletions(-) diff --git a/vn.trader/uiBasicWidget.py b/vn.trader/uiBasicWidget.py index e551f7f1..f97431a1 100644 --- a/vn.trader/uiBasicWidget.py +++ b/vn.trader/uiBasicWidget.py @@ -16,9 +16,9 @@ from vtGateway import * def loadFont(): """载入字体设置""" fileName = 'VT_setting.json' - path = os.path.abspath(os.path.dirname(__file__)) - fileName = os.path.join(path, fileName) - + path = os.path.abspath(os.path.dirname(__file__)) + fileName = os.path.join(path, fileName) + try: f = file(fileName) setting = json.load(f) @@ -43,7 +43,7 @@ class BasicCell(QtGui.QTableWidgetItem): self.data = None if text: self.setContent(text) - + #---------------------------------------------------------------------- def setContent(self, text): """设置内容""" @@ -64,7 +64,7 @@ class NumCell(QtGui.QTableWidgetItem): self.data = None if text: self.setContent(text) - + #---------------------------------------------------------------------- def setContent(self, text): """设置内容""" @@ -76,7 +76,7 @@ class NumCell(QtGui.QTableWidgetItem): self.setData(QtCore.Qt.DisplayRole, num) except ValueError: self.setText(text) - + ######################################################################## class DirectionCell(QtGui.QTableWidgetItem): @@ -89,7 +89,7 @@ class DirectionCell(QtGui.QTableWidgetItem): self.data = None if text: self.setContent(text) - + #---------------------------------------------------------------------- def setContent(self, text): """设置内容""" @@ -108,20 +108,20 @@ class NameCell(QtGui.QTableWidgetItem): def __init__(self, text=None, mainEngine=None): """Constructor""" super(NameCell, self).__init__() - + self.mainEngine = mainEngine self.data = None - + if text: self.setContent(text) - + #---------------------------------------------------------------------- def setContent(self, text): """设置内容""" if self.mainEngine: # 首先尝试正常获取合约对象 contract = self.mainEngine.getContract(text) - + # 如果能读取合约信息 if contract: self.setText(contract.name) @@ -139,10 +139,10 @@ class BidCell(QtGui.QTableWidgetItem): self.setForeground(QtGui.QColor('black')) self.setBackground(QtGui.QColor(255,174,201)) - + if text: self.setContent(text) - + #---------------------------------------------------------------------- def setContent(self, text): """设置内容""" @@ -161,10 +161,10 @@ class AskCell(QtGui.QTableWidgetItem): self.setForeground(QtGui.QColor('black')) self.setBackground(QtGui.QColor(160,255,160)) - + if text: self.setContent(text) - + #---------------------------------------------------------------------- def setContent(self, text): """设置内容""" @@ -175,10 +175,10 @@ class AskCell(QtGui.QTableWidgetItem): class BasicMonitor(QtGui.QTableWidget): """ 基础监控 - + headerDict中的值对应的字典格式如下 {'chinese': u'中文名', 'cellType': BasicCell} - + """ signal = QtCore.pyqtSignal(type(Event())) @@ -186,79 +186,79 @@ class BasicMonitor(QtGui.QTableWidget): def __init__(self, mainEngine=None, eventEngine=None, parent=None): """Constructor""" super(BasicMonitor, self).__init__(parent) - + self.mainEngine = mainEngine self.eventEngine = eventEngine - + # 保存表头标签用 self.headerDict = OrderedDict() # 有序字典,key是英文名,value是对应的配置字典 self.headerList = [] # 对应self.headerDict.keys() - + # 保存相关数据用 self.dataDict = {} # 字典,key是字段对应的数据,value是保存相关单元格的字典 self.dataKey = '' # 字典键对应的数据字段 - + # 监控的事件类型 self.eventType = '' - + # 字体 self.font = None - + # 保存数据对象到单元格 self.saveData = False - + # 默认不允许根据表头进行排序,需要的组件可以开启 self.sorting = False - + # 初始化右键菜单 self.initMenu() - + #---------------------------------------------------------------------- def setHeaderDict(self, headerDict): """设置表头有序字典""" self.headerDict = headerDict self.headerList = headerDict.keys() - + #---------------------------------------------------------------------- def setDataKey(self, dataKey): """设置数据字典的键""" self.dataKey = dataKey - + #---------------------------------------------------------------------- def setEventType(self, eventType): """设置监控的事件类型""" self.eventType = eventType - + #---------------------------------------------------------------------- def setFont(self, font): """设置字体""" self.font = font - + #---------------------------------------------------------------------- def setSaveData(self, saveData): """设置是否要保存数据到单元格""" self.saveData = saveData - + #---------------------------------------------------------------------- def initTable(self): """初始化表格""" # 设置表格的列数 col = len(self.headerDict) self.setColumnCount(col) - + # 设置列表头 labels = [d['chinese'] for d in self.headerDict.values()] self.setHorizontalHeaderLabels(labels) - + # 关闭左边的垂直表头 self.verticalHeader().setVisible(False) - + # 设为不可编辑 self.setEditTriggers(self.NoEditTriggers) - + # 设为行交替颜色 self.setAlternatingRowColors(True) - + # 设置允许排序 self.setSortingEnabled(self.sorting) @@ -267,38 +267,38 @@ class BasicMonitor(QtGui.QTableWidget): """注册GUI更新相关的事件监听""" self.signal.connect(self.updateEvent) self.eventEngine.register(self.eventType, self.signal.emit) - + #---------------------------------------------------------------------- def updateEvent(self, event): """收到事件更新""" data = event.dict_['data'] self.updateData(data) - + #---------------------------------------------------------------------- def updateData(self, data): """将数据更新到表格中""" # 如果允许了排序功能,则插入数据前必须关闭,否则插入新的数据会变乱 if self.sorting: self.setSortingEnabled(False) - + # 如果设置了dataKey,则采用存量更新模式 if self.dataKey: key = data.__getattribute__(self.dataKey) # 如果键在数据字典中不存在,则先插入新的一行,并创建对应单元格 if key not in self.dataDict: - self.insertRow(0) + self.insertRow(0) d = {} - for n, header in enumerate(self.headerList): + for n, header in enumerate(self.headerList): content = safeUnicode(data.__getattribute__(header)) cellType = self.headerDict[header]['cellType'] cell = cellType(content, self.mainEngine) - + if self.font: cell.setFont(self.font) # 如果设置了特殊字体,则进行单元格设置 - + if self.saveData: # 如果设置了保存数据对象,则进行对象保存 cell.data = data - + self.setItem(0, n, cell) d[header] = cell self.dataDict[key] = d @@ -309,48 +309,48 @@ class BasicMonitor(QtGui.QTableWidget): content = safeUnicode(data.__getattribute__(header)) cell = d[header] cell.setContent(content) - + if self.saveData: # 如果设置了保存数据对象,则进行对象保存 - cell.data = data + cell.data = data # 否则采用增量更新模式 else: - self.insertRow(0) + self.insertRow(0) for n, header in enumerate(self.headerList): content = safeUnicode(data.__getattribute__(header)) cellType = self.headerDict[header]['cellType'] cell = cellType(content, self.mainEngine) - + if self.font: cell.setFont(self.font) if self.saveData: - cell.data = data + cell.data = data + + self.setItem(0, n, cell) - self.setItem(0, n, cell) - # 调整列宽 self.resizeColumns() - + # 重新打开排序 if self.sorting: self.setSortingEnabled(True) - + #---------------------------------------------------------------------- def resizeColumns(self): """调整各列的大小""" - self.horizontalHeader().resizeSections(QtGui.QHeaderView.ResizeToContents) - + self.horizontalHeader().resizeSections(QtGui.QHeaderView.ResizeToContents) + #---------------------------------------------------------------------- def setSorting(self, sorting): """设置是否允许根据表头排序""" self.sorting = sorting - + #---------------------------------------------------------------------- def saveToCsv(self): """保存表格内容到CSV文件""" # 先隐藏右键菜单 self.menu.close() - + # 获取想要保存的文件名 path = QtGui.QFileDialog.getSaveFileName(self, '保存数据', '', 'CSV(*.csv)') @@ -358,11 +358,11 @@ class BasicMonitor(QtGui.QTableWidget): if not path.isEmpty(): with open(unicode(path), 'wb') as f: writer = csv.writer(f) - + # 保存标签 headers = [header.encode('gbk') for header in self.headerList] writer.writerow(headers) - + # 保存每行内容 for row in range(self.rowCount()): rowdata = [] @@ -373,24 +373,24 @@ class BasicMonitor(QtGui.QTableWidget): unicode(item.text()).encode('gbk')) else: rowdata.append('') - writer.writerow(rowdata) + writer.writerow(rowdata) except IOError: pass #---------------------------------------------------------------------- def initMenu(self): """初始化右键菜单""" - self.menu = QtGui.QMenu(self) - + self.menu = QtGui.QMenu(self) + saveAction = QtGui.QAction(u'保存内容', self) saveAction.triggered.connect(self.saveToCsv) - + self.menu.addAction(saveAction) - + #---------------------------------------------------------------------- def contextMenuEvent(self, event): """右键点击事件""" - self.menu.popup(QtGui.QCursor.pos()) + self.menu.popup(QtGui.QCursor.pos()) ######################################################################## @@ -401,7 +401,7 @@ class MarketMonitor(BasicMonitor): def __init__(self, mainEngine, eventEngine, parent=None): """Constructor""" super(MarketMonitor, self).__init__(mainEngine, eventEngine, parent) - + # 设置表头有序字典 d = OrderedDict() d['symbol'] = {'chinese':u'合约代码', 'cellType':BasicCell} @@ -420,22 +420,22 @@ class MarketMonitor(BasicMonitor): d['time'] = {'chinese':u'时间', 'cellType':BasicCell} d['gatewayName'] = {'chinese':u'接口', 'cellType':BasicCell} self.setHeaderDict(d) - + # 设置数据键 self.setDataKey('vtSymbol') - + # 设置监控事件类型 self.setEventType(EVENT_TICK) - + # 设置字体 self.setFont(BASIC_FONT) - + # 设置允许排序 self.setSorting(True) - + # 初始化表格 self.initTable() - + # 注册事件监听 self.registerEvent() @@ -448,15 +448,15 @@ class LogMonitor(BasicMonitor): def __init__(self, mainEngine, eventEngine, parent=None): """Constructor""" super(LogMonitor, self).__init__(mainEngine, eventEngine, parent) - - d = OrderedDict() + + d = OrderedDict() d['logTime'] = {'chinese':u'时间', 'cellType':BasicCell} d['logContent'] = {'chinese':u'内容', 'cellType':BasicCell} d['gatewayName'] = {'chinese':u'接口', 'cellType':BasicCell} self.setHeaderDict(d) - + self.setEventType(EVENT_LOG) - self.setFont(BASIC_FONT) + self.setFont(BASIC_FONT) self.initTable() self.registerEvent() @@ -469,14 +469,14 @@ class ErrorMonitor(BasicMonitor): def __init__(self, mainEngine, eventEngine, parent=None): """Constructor""" super(ErrorMonitor, self).__init__(mainEngine, eventEngine, parent) - - d = OrderedDict() + + d = OrderedDict() d['errorTime'] = {'chinese':u'错误时间', 'cellType':BasicCell} d['errorID'] = {'chinese':u'错误代码', 'cellType':BasicCell} d['errorMsg'] = {'chinese':u'错误信息', 'cellType':BasicCell} d['gatewayName'] = {'chinese':u'接口', 'cellType':BasicCell} self.setHeaderDict(d) - + self.setEventType(EVENT_ERROR) self.setFont(BASIC_FONT) self.initTable() @@ -491,7 +491,7 @@ class TradeMonitor(BasicMonitor): def __init__(self, mainEngine, eventEngine, parent=None): """Constructor""" super(TradeMonitor, self).__init__(mainEngine, eventEngine, parent) - + d = OrderedDict() d['tradeID'] = {'chinese':u'成交编号', 'cellType':NumCell} d['orderID'] = {'chinese':u'委托编号', 'cellType':NumCell} @@ -504,11 +504,11 @@ class TradeMonitor(BasicMonitor): d['tradeTime'] = {'chinese':u'成交时间', 'cellType':BasicCell} d['gatewayName'] = {'chinese':u'接口', 'cellType':BasicCell} self.setHeaderDict(d) - + self.setEventType(EVENT_TRADE) self.setFont(BASIC_FONT) self.setSorting(True) - + self.initTable() self.registerEvent() @@ -523,7 +523,7 @@ class OrderMonitor(BasicMonitor): super(OrderMonitor, self).__init__(mainEngine, eventEngine, parent) self.mainEngine = mainEngine - + d = OrderedDict() d['orderID'] = {'chinese':u'委托编号', 'cellType':NumCell} d['symbol'] = {'chinese':u'合约代码', 'cellType':BasicCell} @@ -540,28 +540,28 @@ class OrderMonitor(BasicMonitor): d['sessionID'] = {'chinese':u'会话编号', 'cellType':BasicCell} d['gatewayName'] = {'chinese':u'接口', 'cellType':BasicCell} self.setHeaderDict(d) - + self.setDataKey('vtOrderID') self.setEventType(EVENT_ORDER) self.setFont(BASIC_FONT) self.setSaveData(True) self.setSorting(True) - + self.initTable() self.registerEvent() self.connectSignal() - + #---------------------------------------------------------------------- def connectSignal(self): """连接信号""" # 双击单元格撤单 - self.itemDoubleClicked.connect(self.cancelOrder) - + self.itemDoubleClicked.connect(self.cancelOrder) + #---------------------------------------------------------------------- def cancelOrder(self, cell): """根据单元格的数据撤单""" order = cell.data - + req = VtCancelOrderReq() req.symbol = order.symbol req.exchange = order.exchange @@ -578,7 +578,7 @@ class PositionMonitor(BasicMonitor): def __init__(self, mainEngine, eventEngine, parent=None): """Constructor""" super(PositionMonitor, self).__init__(mainEngine, eventEngine, parent) - + d = OrderedDict() d['symbol'] = {'chinese':u'合约代码', 'cellType':BasicCell} d['vtSymbol'] = {'chinese':u'名称', 'cellType':NameCell} @@ -589,16 +589,16 @@ class PositionMonitor(BasicMonitor): d['price'] = {'chinese':u'价格', 'cellType':BasicCell} d['gatewayName'] = {'chinese':u'接口', 'cellType':BasicCell} self.setHeaderDict(d) - + self.setDataKey('vtPositionName') self.setEventType(EVENT_POSITION) self.setFont(BASIC_FONT) self.setSaveData(True) - + self.initTable() self.registerEvent() - - + + ######################################################################## class AccountMonitor(BasicMonitor): """账户监控""" @@ -607,7 +607,7 @@ class AccountMonitor(BasicMonitor): def __init__(self, mainEngine, eventEngine, parent=None): """Constructor""" super(AccountMonitor, self).__init__(mainEngine, eventEngine, parent) - + d = OrderedDict() d['accountID'] = {'chinese':u'账户', 'cellType':BasicCell} d['preBalance'] = {'chinese':u'昨结', 'cellType':BasicCell} @@ -619,7 +619,7 @@ class AccountMonitor(BasicMonitor): d['positionProfit'] = {'chinese':u'持仓盈亏', 'cellType':BasicCell} d['gatewayName'] = {'chinese':u'接口', 'cellType':BasicCell} self.setHeaderDict(d) - + self.setDataKey('vtAccountID') self.setEventType(EVENT_ACCOUNT) self.setFont(BASIC_FONT) @@ -631,7 +631,7 @@ class AccountMonitor(BasicMonitor): class TradingWidget(QtGui.QFrame): """简单交易组件""" signal = QtCore.pyqtSignal(type(Event())) - + directionList = [DIRECTION_LONG, DIRECTION_SHORT] @@ -639,12 +639,12 @@ class TradingWidget(QtGui.QFrame): OFFSET_CLOSE, OFFSET_CLOSEYESTERDAY, OFFSET_CLOSETODAY] - + priceTypeList = [PRICETYPE_LIMITPRICE, PRICETYPE_MARKETPRICE, PRICETYPE_FAK, PRICETYPE_FOK] - + exchangeList = [EXCHANGE_NONE, EXCHANGE_CFFEX, EXCHANGE_SHFE, @@ -661,18 +661,18 @@ class TradingWidget(QtGui.QFrame): EXCHANGE_NYMEX, EXCHANGE_GLOBEX, EXCHANGE_IDEALPRO] - + currencyList = [CURRENCY_NONE, CURRENCY_CNY, CURRENCY_HKD, CURRENCY_USD] - + productClassList = [PRODUCT_NONE, PRODUCT_EQUITY, PRODUCT_FUTURES, PRODUCT_OPTION, PRODUCT_FOREX] - + gatewayList = [''] #---------------------------------------------------------------------- @@ -681,9 +681,9 @@ class TradingWidget(QtGui.QFrame): super(TradingWidget, self).__init__(parent) self.mainEngine = mainEngine self.eventEngine = eventEngine - + self.symbol = '' - + # 添加交易接口 self.gatewayList.extend(mainEngine.getAllGatewayNames()) @@ -696,7 +696,7 @@ class TradingWidget(QtGui.QFrame): self.setWindowTitle(u'交易') self.setMaximumWidth(400) self.setFrameShape(self.Box) # 设置边框 - self.setLineWidth(1) + self.setLineWidth(1) # 左边部分 labelSymbol = QtGui.QLabel(u'代码') @@ -707,7 +707,7 @@ class TradingWidget(QtGui.QFrame): self.checkFixed = QtGui.QCheckBox(u'') # 价格固定选择框 labelVolume = QtGui.QLabel(u'数量') labelPriceType = QtGui.QLabel(u'价格类型') - labelExchange = QtGui.QLabel(u'交易所') + labelExchange = QtGui.QLabel(u'交易所') labelCurrency = QtGui.QLabel(u'货币') labelProductClass = QtGui.QLabel(u'产品类型') labelGateway = QtGui.QLabel(u'交易接口') @@ -732,18 +732,18 @@ class TradingWidget(QtGui.QFrame): self.comboPriceType = QtGui.QComboBox() self.comboPriceType.addItems(self.priceTypeList) - + self.comboExchange = QtGui.QComboBox() - self.comboExchange.addItems(self.exchangeList) - + self.comboExchange.addItems(self.exchangeList) + self.comboCurrency = QtGui.QComboBox() self.comboCurrency.addItems(self.currencyList) - + self.comboProductClass = QtGui.QComboBox() - self.comboProductClass.addItems(self.productClassList) - + self.comboProductClass.addItems(self.productClassList) + self.comboGateway = QtGui.QComboBox() - self.comboGateway.addItems(self.gatewayList) + self.comboGateway.addItems(self.gatewayList) gridleft = QtGui.QGridLayout() gridleft.addWidget(labelSymbol, 0, 0) @@ -755,9 +755,9 @@ class TradingWidget(QtGui.QFrame): gridleft.addWidget(labelPriceType, 6, 0) gridleft.addWidget(labelExchange, 7, 0) gridleft.addWidget(labelCurrency, 8, 0) - gridleft.addWidget(labelProductClass, 9, 0) + gridleft.addWidget(labelProductClass, 9, 0) gridleft.addWidget(labelGateway, 10, 0) - + gridleft.addWidget(self.lineSymbol, 0, 1, 1, -1) gridleft.addWidget(self.lineName, 1, 1, 1, -1) gridleft.addWidget(self.comboDirection, 2, 1, 1, -1) @@ -793,7 +793,7 @@ class TradingWidget(QtGui.QFrame): self.labelBidVolume2 = QtGui.QLabel() self.labelBidVolume3 = QtGui.QLabel() self.labelBidVolume4 = QtGui.QLabel() - self.labelBidVolume5 = QtGui.QLabel() + self.labelBidVolume5 = QtGui.QLabel() self.labelAskPrice1 = QtGui.QLabel() self.labelAskPrice2 = QtGui.QLabel() @@ -804,7 +804,7 @@ class TradingWidget(QtGui.QFrame): self.labelAskVolume2 = QtGui.QLabel() self.labelAskVolume3 = QtGui.QLabel() self.labelAskVolume4 = QtGui.QLabel() - self.labelAskVolume5 = QtGui.QLabel() + self.labelAskVolume5 = QtGui.QLabel() labelLast = QtGui.QLabel(u'最新') self.labelLastPrice = QtGui.QLabel() @@ -836,7 +836,7 @@ class TradingWidget(QtGui.QFrame): gridRight.addWidget(self.labelBidPrice2, 7, 1) gridRight.addWidget(self.labelBidPrice3, 8, 1) gridRight.addWidget(self.labelBidPrice4, 9, 1) - gridRight.addWidget(self.labelBidPrice5, 10, 1) + gridRight.addWidget(self.labelBidPrice5, 10, 1) gridRight.addWidget(self.labelAskVolume5, 0, 2) gridRight.addWidget(self.labelAskVolume4, 1, 2) @@ -853,7 +853,7 @@ class TradingWidget(QtGui.QFrame): # 发单按钮 buttonSendOrder = QtGui.QPushButton(u'发单') buttonCancelAll = QtGui.QPushButton(u'全撤') - + size = buttonSendOrder.sizeHint() buttonSendOrder.setMinimumHeight(size.height()*2) # 把按钮高度设为默认两倍 buttonCancelAll.setMinimumHeight(size.height()*2) @@ -883,23 +883,23 @@ class TradingWidget(QtGui.QFrame): symbol = str(self.lineSymbol.text()) exchange = unicode(self.comboExchange.currentText()) currency = unicode(self.comboCurrency.currentText()) - productClass = unicode(self.comboProductClass.currentText()) + productClass = unicode(self.comboProductClass.currentText()) gatewayName = unicode(self.comboGateway.currentText()) - + # 查询合约 if exchange: vtSymbol = '.'.join([symbol, exchange]) contract = self.mainEngine.getContract(vtSymbol) else: vtSymbol = symbol - contract = self.mainEngine.getContract(symbol) - + contract = self.mainEngine.getContract(symbol) + if contract: vtSymbol = contract.vtSymbol gatewayName = contract.gatewayName self.lineName.setText(contract.name) exchange = contract.exchange # 保证有交易所代码 - + # 清空价格数量 self.spinPrice.setValue(0) self.spinVolume.setValue(0) @@ -914,7 +914,7 @@ class TradingWidget(QtGui.QFrame): self.labelBidVolume2.setText('') self.labelBidVolume3.setText('') self.labelBidVolume4.setText('') - self.labelBidVolume5.setText('') + self.labelBidVolume5.setText('') self.labelAskPrice1.setText('') self.labelAskPrice2.setText('') self.labelAskPrice3.setText('') @@ -959,30 +959,30 @@ class TradingWidget(QtGui.QFrame): self.labelAskPrice1.setText(str(tick.askPrice1)) self.labelBidVolume1.setText(str(tick.bidVolume1)) self.labelAskVolume1.setText(str(tick.askVolume1)) - + if tick.bidPrice2: self.labelBidPrice2.setText(str(tick.bidPrice2)) self.labelBidPrice3.setText(str(tick.bidPrice3)) self.labelBidPrice4.setText(str(tick.bidPrice4)) self.labelBidPrice5.setText(str(tick.bidPrice5)) - + self.labelAskPrice2.setText(str(tick.askPrice2)) self.labelAskPrice3.setText(str(tick.askPrice3)) self.labelAskPrice4.setText(str(tick.askPrice4)) self.labelAskPrice5.setText(str(tick.askPrice5)) - + self.labelBidVolume2.setText(str(tick.bidVolume2)) self.labelBidVolume3.setText(str(tick.bidVolume3)) self.labelBidVolume4.setText(str(tick.bidVolume4)) self.labelBidVolume5.setText(str(tick.bidVolume5)) - + self.labelAskVolume2.setText(str(tick.askVolume2)) self.labelAskVolume3.setText(str(tick.askVolume3)) self.labelAskVolume4.setText(str(tick.askVolume4)) - self.labelAskVolume5.setText(str(tick.askVolume5)) + self.labelAskVolume5.setText(str(tick.askVolume5)) self.labelLastPrice.setText(str(tick.lastPrice)) - + if tick.preClosePrice: rt = (tick.lastPrice/tick.preClosePrice)-1 self.labelReturn.setText(('%.2f' %(rt*100))+'%') @@ -1000,8 +1000,8 @@ class TradingWidget(QtGui.QFrame): symbol = str(self.lineSymbol.text()) exchange = unicode(self.comboExchange.currentText()) currency = unicode(self.comboCurrency.currentText()) - productClass = unicode(self.comboProductClass.currentText()) - gatewayName = unicode(self.comboGateway.currentText()) + productClass = unicode(self.comboProductClass.currentText()) + gatewayName = unicode(self.comboGateway.currentText()) # 查询合约 if exchange: @@ -1010,11 +1010,11 @@ class TradingWidget(QtGui.QFrame): else: vtSymbol = symbol contract = self.mainEngine.getContract(symbol) - + if contract: gatewayName = contract.gatewayName exchange = contract.exchange # 保证有交易所代码 - + req = VtOrderReq() req.symbol = symbol req.exchange = exchange @@ -1025,9 +1025,9 @@ class TradingWidget(QtGui.QFrame): req.offset = unicode(self.comboOffset.currentText()) req.currency = currency req.productClass = productClass - + self.mainEngine.sendOrder(req, gatewayName) - + #---------------------------------------------------------------------- def cancelAll(self): """一键撤销所有委托""" @@ -1040,18 +1040,18 @@ class TradingWidget(QtGui.QFrame): req.sessionID = order.sessionID req.orderID = order.orderID self.mainEngine.cancelOrder(req, order.gatewayName) - + #---------------------------------------------------------------------- def closePosition(self, cell): """根据持仓信息自动填写交易组件""" # 读取持仓数据,cell是一个表格中的单元格对象 pos = cell.data symbol = pos.symbol - + # 更新交易组件的显示合约 self.lineSymbol.setText(symbol) self.updateSymbol() - + # 自动填写信息 self.comboPriceType.setCurrentIndex(self.priceTypeList.index(PRICETYPE_LIMITPRICE)) self.comboOffset.setCurrentIndex(self.offsetList.index(OFFSET_CLOSE)) @@ -1073,9 +1073,9 @@ class ContractMonitor(BasicMonitor): def __init__(self, mainEngine, parent=None): """Constructor""" super(ContractMonitor, self).__init__(parent=parent) - + self.mainEngine = mainEngine - + d = OrderedDict() d['symbol'] = {'chinese':u'合约代码', 'cellType':BasicCell} d['exchange'] = {'chinese':u'交易所', 'cellType':BasicCell} @@ -1084,13 +1084,16 @@ class ContractMonitor(BasicMonitor): d['productClass'] = {'chinese':u'合约类型', 'cellType':BasicCell} d['size'] = {'chinese':u'大小', 'cellType':BasicCell} d['priceTick'] = {'chinese':u'最小价格变动', 'cellType':BasicCell} + d['tick'] = {'chinese':u'tick', 'cellType':BasicCell} + d['bar'] = {'chinese':u'bar', 'cellType':BasicCell} + d['main'] = {'chinese':u'主力合约', 'cellType':BasicCell} #d['strikePrice'] = {'chinese':u'期权行权价', 'cellType':BasicCell} #d['underlyingSymbol'] = {'chinese':u'期权标的物', 'cellType':BasicCell} - #d['optionType'] = {'chinese':u'期权类型', 'cellType':BasicCell} + #d['optionType'] = {'chinese':u'期权类型', 'cellType':BasicCell} self.setHeaderDict(d) - + self.initUi() - + #---------------------------------------------------------------------- def initUi(self): """初始化界面""" @@ -1099,7 +1102,7 @@ class ContractMonitor(BasicMonitor): self.setFont(BASIC_FONT) self.initTable() self.addMenuAction() - + #---------------------------------------------------------------------- def showAllContracts(self): """显示所有合约数据""" @@ -1110,22 +1113,24 @@ class ContractMonitor(BasicMonitor): self.setRowCount(len(l2)) row = 0 - + for key in l2: contract = d[key] - + for n, header in enumerate(self.headerList): + if(not hasattr(contract,header)): + break content = safeUnicode(contract.__getattribute__(header)) cellType = self.headerDict[header]['cellType'] cell = cellType(content) - + if self.font: cell.setFont(self.font) # 如果设置了特殊字体,则进行单元格设置 - + self.setItem(row, n, cell) - + row = row + 1 - + #---------------------------------------------------------------------- def refresh(self): """刷新""" @@ -1133,19 +1138,19 @@ class ContractMonitor(BasicMonitor): self.clearContents() self.setRowCount(0) self.showAllContracts() - + #---------------------------------------------------------------------- def addMenuAction(self): """增加右键菜单内容""" refreshAction = QtGui.QAction(u'刷新', self) refreshAction.triggered.connect(self.refresh) - + self.menu.addAction(refreshAction) - + #---------------------------------------------------------------------- def show(self): """显示""" super(ContractMonitor, self).show() self.refresh() - - + + From 3ad2fa5159df82a2e80c35ae04c5174a647a38b4 Mon Sep 17 00:00:00 2001 From: "sunlit@home" Date: Fri, 3 Feb 2017 22:59:42 +0800 Subject: [PATCH 02/13] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BA=86checkbox?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vn.trader/dataRecorder/DR_setting.json | 110 +++++++++++++++++++------ vn.trader/uiBasicWidget.py | 29 +++++-- 2 files changed, 108 insertions(+), 31 deletions(-) diff --git a/vn.trader/dataRecorder/DR_setting.json b/vn.trader/dataRecorder/DR_setting.json index f7c297c5..cbc5d6b0 100644 --- a/vn.trader/dataRecorder/DR_setting.json +++ b/vn.trader/dataRecorder/DR_setting.json @@ -1,31 +1,91 @@ { - "working": false, - - "tick": - [ - ["m1609", "XSPEED"], - ["IF1606", "SGIT"], - ["IH1606", "SGIT"], - ["IH1606", "SGIT"], - ["IC1606", "SGIT"], - ["IC1606", "SGIT"], - ["600036", "LTS", "SZSE"], - ["EUR.USD", "IB", "IDEALPRO", "USD", "外汇"] + "working": true, + "tick": [ + [ + "au1706", + "CTP" + ], + [ + "a1705", + "CTP" + ], + [ + "m1705", + "CTP" + ], + [ + "bu1706", + "CTP" + ], + [ + "SR705", + "CTP" + ], + [ + "TA705", + "CTP" + ], + [ + "MA705", + "CTP" + ], + [ + "RM705", + "CTP" + ], + [ + "FG705", + "CTP" + ], + [ + "OI705", + "CTP" + ] ], - - "bar": - [ - ["IF1605", "SGIT"], - ["IF1606", "SGIT"], - ["IH1606", "SGIT"], - ["IH1606", "SGIT"], - ["IC1606", "SGIT"], - ["IC1606", "SGIT"] + "bar": [ + [ + "au1706", + "CTP" + ], + [ + "a1705", + "CTP" + ], + [ + "m1705", + "CTP" + ], + [ + "bu1706", + "CTP" + ], + [ + "SR705", + "CTP" + ], + [ + "TA705", + "CTP" + ], + [ + "MA705", + "CTP" + ], + [ + "RM705", + "CTP" + ], + [ + "FG705", + "CTP" + ], + [ + "OI705", + "CTP" + ] ], - - "active": - { - "IF0000": "IF1605", + "active": { + "IF0000": "IF1605", "IH0000": "IH1605", "IC0000": "IC1605" } diff --git a/vn.trader/uiBasicWidget.py b/vn.trader/uiBasicWidget.py index f97431a1..9ba0ab93 100644 --- a/vn.trader/uiBasicWidget.py +++ b/vn.trader/uiBasicWidget.py @@ -6,6 +6,7 @@ import os from collections import OrderedDict from PyQt4 import QtGui, QtCore +from PyQt4.QtCore import Qt from eventEngine import * from vtFunction import * @@ -53,6 +54,22 @@ class BasicCell(QtGui.QTableWidgetItem): self.setText(text) +######################################################################## +class CheckBoxCell(QtGui.QTableWidgetItem): + """用来显示复选框的单元格""" + + def __init__(self, isChecked=False, mainEngine=None): + """Constructor""" + super(CheckBoxCell, self).__init__() + self.setFlags(QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled) + self.setStauts(isChecked) + + def setStauts(self, isChecked=False): + if not isChecked: + self.setCheckState(Qt.Unchecked) + else: + self.setCheckState(Qt.Checked) + ######################################################################## class NumCell(QtGui.QTableWidgetItem): """用来显示数字的单元格""" @@ -1084,9 +1101,9 @@ class ContractMonitor(BasicMonitor): d['productClass'] = {'chinese':u'合约类型', 'cellType':BasicCell} d['size'] = {'chinese':u'大小', 'cellType':BasicCell} d['priceTick'] = {'chinese':u'最小价格变动', 'cellType':BasicCell} - d['tick'] = {'chinese':u'tick', 'cellType':BasicCell} - d['bar'] = {'chinese':u'bar', 'cellType':BasicCell} - d['main'] = {'chinese':u'主力合约', 'cellType':BasicCell} + d['tick'] = {'chinese':u'tick', 'cellType':CheckBoxCell} + d['bar'] = {'chinese':u'bar', 'cellType':CheckBoxCell} + d['main'] = {'chinese':u'主力合约', 'cellType':CheckBoxCell} #d['strikePrice'] = {'chinese':u'期权行权价', 'cellType':BasicCell} #d['underlyingSymbol'] = {'chinese':u'期权标的物', 'cellType':BasicCell} #d['optionType'] = {'chinese':u'期权类型', 'cellType':BasicCell} @@ -1118,10 +1135,10 @@ class ContractMonitor(BasicMonitor): contract = d[key] for n, header in enumerate(self.headerList): - if(not hasattr(contract,header)): - break - content = safeUnicode(contract.__getattribute__(header)) cellType = self.headerDict[header]['cellType'] + content = None + if (hasattr(contract, header)): + content = safeUnicode(contract.__getattribute__(header)) cell = cellType(content) if self.font: From 615b4c69ba8a2d48901961734753c66f8fe45a07 Mon Sep 17 00:00:00 2001 From: "sunlit@home" Date: Mon, 6 Feb 2017 21:54:35 +0800 Subject: [PATCH 03/13] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BA=86=E8=AE=A2?= =?UTF-8?q?=E9=98=85=E5=90=88=E7=BA=A6=E7=BC=96=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vn.trader/dataRecorder/uiDrEdit.py | 58 ++++++++++++++++++++++++++++ vn.trader/dataRecorder/uiDrWidget.py | 23 ++++++----- 2 files changed, 71 insertions(+), 10 deletions(-) create mode 100644 vn.trader/dataRecorder/uiDrEdit.py diff --git a/vn.trader/dataRecorder/uiDrEdit.py b/vn.trader/dataRecorder/uiDrEdit.py new file mode 100644 index 00000000..be7f6800 --- /dev/null +++ b/vn.trader/dataRecorder/uiDrEdit.py @@ -0,0 +1,58 @@ +# encoding: UTF-8 + +''' +行情记录模块相关的GUI控制组件 +''' +from PyQt4.QtCore import QDir +from PyQt4.QtGui import QFileSystemModel +from PyQt4.QtGui import QTreeView + +from uiBasicWidget import QtGui, QtCore +from eventEngine import * + +from eventType import EVENT_CONTRACT + + +class DrEditWidget(QtGui.QWidget): + """行情数据记录引擎管理组件""" + signal = QtCore.pyqtSignal(type(Event())) + + def __init__(self, drEngine, eventEngine, parent=None): + """Constructor""" + super(DrEditWidget, self).__init__(parent) + + self.drEngine = drEngine + self.eventEngine = eventEngine + + # 保存合约详细信息的字典 + self.contractDict = {} + + self.initUi() + self.updateSetting() + self.registerEvent() + + def initUi(self): + self.qTreeView = QTreeView() + model = QFileSystemModel() + model.setRootPath(QDir.currentPath()) + self.qTreeView.setModel(model) + self.qTreeView.setRootIndex(model.index(QDir.currentPath())) + + vbox = QtGui.QVBoxLayout() + vbox.addWidget(self.qTreeView) + self.setLayout(vbox) + + def updateSetting(self): + pass + + def updateContract(self, event): + """更新合约数据""" + contract = event.dict_['data'] + self.contractDict[contract.vtSymbol] = contract + self.contractDict[contract.symbol] = contract # 使用常规代码(不包括交易所)可能导致重复 + + # ---------------------------------------------------------------------- + def registerEvent(self): + """注册事件监听""" + self.signal.connect(self.updateContract) + self.eventEngine.register(EVENT_CONTRACT, self.signal.emit) diff --git a/vn.trader/dataRecorder/uiDrWidget.py b/vn.trader/dataRecorder/uiDrWidget.py index b9a21190..649c4ec6 100644 --- a/vn.trader/dataRecorder/uiDrWidget.py +++ b/vn.trader/dataRecorder/uiDrWidget.py @@ -6,6 +6,7 @@ import json +from dataRecorder.uiDrEdit import DrEditWidget from uiBasicWidget import QtGui, QtCore from eventEngine import * @@ -95,13 +96,18 @@ class DrEngineManager(QtGui.QWidget): grid.addWidget(activeLabel, 0, 2) grid.addWidget(self.tickTable, 1, 0) grid.addWidget(self.barTable, 1, 1) - grid.addWidget(self.activeTable, 1, 2) - + grid.addWidget(self.activeTable, 1, 2) + + btn = QtGui.QPushButton(u'编辑', self) + vbox = QtGui.QVBoxLayout() vbox.addLayout(grid) + vbox.addWidget(btn) vbox.addWidget(self.logMonitor) self.setLayout(vbox) + btn.clicked.connect(self.openDr) + #---------------------------------------------------------------------- def updateLog(self, event): """更新日志""" @@ -144,12 +150,9 @@ class DrEngineManager(QtGui.QWidget): self.activeTable.insertRow(0) self.activeTable.setItem(0, 0, TableCell(activeSymbol)) self.activeTable.setItem(0, 1, TableCell(symbol)) - - - - - - - - \ No newline at end of file + # ---------------------------------------------------------------------- + def openDr(self): + """打开行情数据记录组件""" + self.mDrEditWidget = DrEditWidget(self.drEngine, self.eventEngine) + self.mDrEditWidget.showMaximized() From 659c43fee10c4c8386c2d18a529c09223e692caa Mon Sep 17 00:00:00 2001 From: "ares89@wind" Date: Tue, 7 Feb 2017 19:32:55 +0800 Subject: [PATCH 04/13] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=88=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vn.trader/dataRecorder/uiDrEdit.py | 236 +++++++++++++++++++++++++---- 1 file changed, 203 insertions(+), 33 deletions(-) diff --git a/vn.trader/dataRecorder/uiDrEdit.py b/vn.trader/dataRecorder/uiDrEdit.py index be7f6800..5ca32560 100644 --- a/vn.trader/dataRecorder/uiDrEdit.py +++ b/vn.trader/dataRecorder/uiDrEdit.py @@ -7,52 +7,222 @@ from PyQt4.QtCore import QDir from PyQt4.QtGui import QFileSystemModel from PyQt4.QtGui import QTreeView +from dataRecorder.drEngine import DrEngine from uiBasicWidget import QtGui, QtCore from eventEngine import * from eventType import EVENT_CONTRACT +class TreeItem(object): + def __init__(self, data, parent=None): + self.parentItem = parent + self.itemData = data + self.childItems = [] + + def appendChild(self, item): + self.childItems.append(item) + + def extendChild(self, item): + self.childItems.extend(item) + + def child(self, row): + return self.childItems[row] + + def childCount(self): + return len(self.childItems) + + def columnCount(self): + return len(self.itemData) + + def data(self, column): + try: + return self.itemData[column] + except IndexError: + return None + + def parent(self): + return self.parentItem + + def row(self): + if self.parentItem: + return self.parentItem.childItems.index(self) + + return 0 + + +class TreeModel(QtCore.QAbstractItemModel): + def __init__(self, parent=None): + super(TreeModel, self).__init__(parent) + self.rootItem = TreeItem((u"合约", u"tick", u"bar", u"主力")) + + def rootItem(self): + return self.rootItem + + def setDataSource(self, data): + self.rootItem.extendChild(data) + + def columnCount(self, parent): + if parent.isValid(): + return parent.internalPointer().columnCount() + else: + return self.rootItem.columnCount() + + # def setData(self, index, value, role=None): + # item = index.internalPointer() + # if index.column != 0 and role == QtCore.Qt.CheckStateRole: + # if value: + # item.setCheckState(QtCore.Qt.checked) + # else: + # item.setCheckState(QtCore.Qt.Unchecked) + # else: + # pass + # return True + + def data(self, index, role): + if not index.isValid(): + return None + + item = index.internalPointer() + + if role == QtCore.Qt.CheckStateRole and index.column() != 0: + return QtCore.Qt.Checked if item.data(index.column()) == True else QtCore.Qt.Unchecked + + if role != QtCore.Qt.DisplayRole: + return None + + return item.data(index.column()) + + def flags(self, index): + if not index.isValid(): + return QtCore.Qt.NoItemFlags + + if index.column() == 0 or index.row() == 0: + return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable + + return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsUserCheckable + + def headerData(self, section, orientation, role): + if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole: + return self.rootItem.data(section) + + return None + + def index(self, row, column, parent): + if not self.hasIndex(row, column, parent): + return QtCore.QModelIndex() + + if not parent.isValid(): + parentItem = self.rootItem + else: + parentItem = parent.internalPointer() + + childItem = parentItem.child(row) + if childItem: + return self.createIndex(row, column, childItem) + else: + return QtCore.QModelIndex() + + def parent(self, index): + if not index.isValid(): + return QtCore.QModelIndex() + + childItem = index.internalPointer() + parentItem = childItem.parent() + + if parentItem == self.rootItem: + return QtCore.QModelIndex() + + return self.createIndex(parentItem.row(), 0, parentItem) + + def rowCount(self, parent): + if parent.column() > 0: + return 0 + + if not parent.isValid(): + parentItem = self.rootItem + else: + parentItem = parent.internalPointer() + + return parentItem.childCount() + + class DrEditWidget(QtGui.QWidget): - """行情数据记录引擎管理组件""" - signal = QtCore.pyqtSignal(type(Event())) + """行情数据记录引擎管理组件""" + signal = QtCore.pyqtSignal(type(Event())) - def __init__(self, drEngine, eventEngine, parent=None): - """Constructor""" - super(DrEditWidget, self).__init__(parent) + def __init__(self, drEngine, eventEngine, parent=None): + """Constructor""" + super(DrEditWidget, self).__init__(parent) - self.drEngine = drEngine - self.eventEngine = eventEngine + self.drEngine = drEngine + self.eventEngine = eventEngine - # 保存合约详细信息的字典 - self.contractDict = {} + # 保存合约详细信息的字典 + self.contractDict = {} - self.initUi() - self.updateSetting() - self.registerEvent() + self.initUi() + self.updateSetting() + self.registerEvent() - def initUi(self): - self.qTreeView = QTreeView() - model = QFileSystemModel() - model.setRootPath(QDir.currentPath()) - self.qTreeView.setModel(model) - self.qTreeView.setRootIndex(model.index(QDir.currentPath())) + def initUi(self): + self.qTreeView = QTreeView() - vbox = QtGui.QVBoxLayout() - vbox.addWidget(self.qTreeView) - self.setLayout(vbox) + model = TreeModel() - def updateSetting(self): - pass + self.qTreeView.setModel(model) + # self.qTreeView.setRootIndex(model.index()) - def updateContract(self, event): - """更新合约数据""" - contract = event.dict_['data'] - self.contractDict[contract.vtSymbol] = contract - self.contractDict[contract.symbol] = contract # 使用常规代码(不包括交易所)可能导致重复 + child = [] + yumi = TreeItem((u"玉米", False, False, False), model.rootItem) + yumi.appendChild(TreeItem((u"c1705", False, False, False), yumi)) + yumi.appendChild(TreeItem((u"c1703", False, False, False), yumi)) + yumi.appendChild(TreeItem((u"c1707", False, False, False), yumi)) + yumi.appendChild(TreeItem((u"c1709", False, False, False), yumi)) + dianfen = TreeItem((u"淀粉", False, False, False), model.rootItem) + dianfen.appendChild(TreeItem((u"d1705", False, False, False), dianfen)) + dianfen.appendChild(TreeItem((u"d1703", False, False, False), dianfen)) + dianfen.appendChild(TreeItem((u"d1707", False, False, False), dianfen)) + dianfen.appendChild(TreeItem((u"d1709", False, False, False), dianfen)) - # ---------------------------------------------------------------------- - def registerEvent(self): - """注册事件监听""" - self.signal.connect(self.updateContract) - self.eventEngine.register(EVENT_CONTRACT, self.signal.emit) + child.append(yumi) + child.append(dianfen) + model.setDataSource(child) + + vbox = QtGui.QVBoxLayout() + + vline = QtGui.QHBoxLayout() + vline.setSpacing(2) + btnTickAll = QtGui.QPushButton(u"全部记录tick", self) + btnBarAll = QtGui.QPushButton(u'全部记录bar', self) + vline.addWidget(btnTickAll) + vline.addWidget(btnBarAll) + vbox.addLayout(vline) + vbox.addWidget(self.qTreeView) + self.setLayout(vbox) + + def updateSetting(self): + pass + + def updateContract(self, event): + """更新合约数据""" + contract = event.dict_['data'] + self.contractDict[contract.vtSymbol] = contract + self.contractDict[contract.symbol] = contract # 使用常规代码(不包括交易所)可能导致重复 + + # ---------------------------------------------------------------------- + def registerEvent(self): + """注册事件监听""" + self.signal.connect(self.updateContract) + + # self.eventEngine.register(EVENT_CONTRACT, self.signal.emit) + + +if __name__ == '__main__': + import sys + + app = QtGui.QApplication(sys.argv) + + view = DrEditWidget(DrEngine, EventEngine) + view.showMaximized() + sys.exit(app.exec_()) From e5ce000a7dd97536d4dd2bcb7b0f1629ff594472 Mon Sep 17 00:00:00 2001 From: "ares89@wind" Date: Wed, 8 Feb 2017 11:41:28 +0800 Subject: [PATCH 05/13] =?UTF-8?q?=E7=95=8C=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vn.trader/dataRecorder/uiDrEdit.py | 135 ++++++++++++++++++++--------- 1 file changed, 94 insertions(+), 41 deletions(-) diff --git a/vn.trader/dataRecorder/uiDrEdit.py b/vn.trader/dataRecorder/uiDrEdit.py index 5ca32560..7df09e88 100644 --- a/vn.trader/dataRecorder/uiDrEdit.py +++ b/vn.trader/dataRecorder/uiDrEdit.py @@ -3,15 +3,11 @@ ''' 行情记录模块相关的GUI控制组件 ''' -from PyQt4.QtCore import QDir -from PyQt4.QtGui import QFileSystemModel from PyQt4.QtGui import QTreeView from dataRecorder.drEngine import DrEngine -from uiBasicWidget import QtGui, QtCore from eventEngine import * - -from eventType import EVENT_CONTRACT +from uiBasicWidget import QtGui, QtCore class TreeItem(object): @@ -50,11 +46,19 @@ class TreeItem(object): return 0 + def setData(self, column, value): + if column < 0 or column >= len(self.itemData): + return False + + self.itemData[column] = value + + return True + class TreeModel(QtCore.QAbstractItemModel): def __init__(self, parent=None): super(TreeModel, self).__init__(parent) - self.rootItem = TreeItem((u"合约", u"tick", u"bar", u"主力")) + self.rootItem = TreeItem([u"合约", u"Tick", u"Bar", u"主力"]) def rootItem(self): return self.rootItem @@ -68,16 +72,28 @@ class TreeModel(QtCore.QAbstractItemModel): else: return self.rootItem.columnCount() - # def setData(self, index, value, role=None): - # item = index.internalPointer() - # if index.column != 0 and role == QtCore.Qt.CheckStateRole: - # if value: - # item.setCheckState(QtCore.Qt.checked) - # else: - # item.setCheckState(QtCore.Qt.Unchecked) - # else: - # pass - # return True + def setData(self, index, value, role=None): + if index.column() != 0 and role == QtCore.Qt.CheckStateRole: + item = index.internalPointer() + if item is None: + return False + result = item.setData(index.column(), True if value == QtCore.Qt.Checked else False) + if result: + self.dataChanged.emit(index, index) + + # 如果第一条 + if item.parentItem == self.rootItem: + for row in range(item.childCount()): + childIndex = self.index(row, index.column(), index) + self.setData(childIndex, value, QtCore.Qt.CheckStateRole) + + if value == QtCore.Qt.Checked and index.column() == 3: + for row in range(item.parentItem.childCount()): + if row != index.row(): + siblingIndex = self.index(row, index.column(), index.parent()) + self.setData(siblingIndex, QtCore.Qt.Unchecked, QtCore.Qt.CheckStateRole) + + return True def data(self, index, role): if not index.isValid(): @@ -88,6 +104,9 @@ class TreeModel(QtCore.QAbstractItemModel): if role == QtCore.Qt.CheckStateRole and index.column() != 0: return QtCore.Qt.Checked if item.data(index.column()) == True else QtCore.Qt.Unchecked + if index.column() == 3 and item.parentItem == self.rootItem: + return None + if role != QtCore.Qt.DisplayRole: return None @@ -97,9 +116,13 @@ class TreeModel(QtCore.QAbstractItemModel): if not index.isValid(): return QtCore.Qt.NoItemFlags - if index.column() == 0 or index.row() == 0: + if index.column() == 0: return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable + item = index.internalPointer() + if index.column() == 3 and item.parentItem == self.rootItem: + return QtCore.Qt.NoItemFlags + return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsUserCheckable def headerData(self, section, orientation, role): @@ -112,7 +135,7 @@ class TreeModel(QtCore.QAbstractItemModel): if not self.hasIndex(row, column, parent): return QtCore.QModelIndex() - if not parent.isValid(): + if parent is None or not parent.isValid(): parentItem = self.rootItem else: parentItem = parent.internalPointer() @@ -146,6 +169,11 @@ class TreeModel(QtCore.QAbstractItemModel): return parentItem.childCount() + def hasIndex(self, row, column, parentIndex=None, *args, **kwargs): + if row < 0 or column > 4: + return False + return True + class DrEditWidget(QtGui.QWidget): """行情数据记录引擎管理组件""" @@ -163,31 +191,10 @@ class DrEditWidget(QtGui.QWidget): self.initUi() self.updateSetting() + self.loadData() self.registerEvent() def initUi(self): - self.qTreeView = QTreeView() - - model = TreeModel() - - self.qTreeView.setModel(model) - # self.qTreeView.setRootIndex(model.index()) - - child = [] - yumi = TreeItem((u"玉米", False, False, False), model.rootItem) - yumi.appendChild(TreeItem((u"c1705", False, False, False), yumi)) - yumi.appendChild(TreeItem((u"c1703", False, False, False), yumi)) - yumi.appendChild(TreeItem((u"c1707", False, False, False), yumi)) - yumi.appendChild(TreeItem((u"c1709", False, False, False), yumi)) - dianfen = TreeItem((u"淀粉", False, False, False), model.rootItem) - dianfen.appendChild(TreeItem((u"d1705", False, False, False), dianfen)) - dianfen.appendChild(TreeItem((u"d1703", False, False, False), dianfen)) - dianfen.appendChild(TreeItem((u"d1707", False, False, False), dianfen)) - dianfen.appendChild(TreeItem((u"d1709", False, False, False), dianfen)) - - child.append(yumi) - child.append(dianfen) - model.setDataSource(child) vbox = QtGui.QVBoxLayout() @@ -195,12 +202,57 @@ class DrEditWidget(QtGui.QWidget): vline.setSpacing(2) btnTickAll = QtGui.QPushButton(u"全部记录tick", self) btnBarAll = QtGui.QPushButton(u'全部记录bar', self) + btnTickAll.clicked.connect(self.selectAllTick) + btnBarAll.clicked.connect(self.selectAllBar) + vline.addWidget(btnTickAll) vline.addWidget(btnBarAll) + vbox.addLayout(vline) + + self.qTreeView = QTreeView() + self.model = TreeModel() + self.qTreeView.setModel(self.model) + vbox.addWidget(self.qTreeView) self.setLayout(vbox) + def loadData(self): + child = [] + yumi = TreeItem([u"玉米", False, False, False], self.model.rootItem) + yumi.appendChild(TreeItem([u"c1705", False, False, False], yumi)) + yumi.appendChild(TreeItem([u"c1703", False, False, False], yumi)) + yumi.appendChild(TreeItem([u"c1707", False, False, False], yumi)) + yumi.appendChild(TreeItem([u"c1709", False, False, False], yumi)) + dianfen = TreeItem([u"淀粉", False, False, False], self.model.rootItem) + dianfen.appendChild(TreeItem([u"d1705", False, False, False], dianfen)) + dianfen.appendChild(TreeItem([u"d1703", False, False, False], dianfen)) + dianfen.appendChild(TreeItem([u"d1707", False, False, False], dianfen)) + dianfen.appendChild(TreeItem([u"d1709", False, False, False], dianfen)) + + child.append(yumi) + child.append(dianfen) + self.model.setDataSource(child) + self.qTreeView.expandAll() + + def selectAllTick(self): + self.selectAll(True, False, True) + + def selectAllBar(self): + self.selectAll(False, True, True) + + def selectAll(self, tick=False, bar=False, select=False): + column = None + if tick: + column = 1 + if bar: + column = 2 + + for row in range(self.model.rootItem.childCount()): + childIndex = self.model.index(row, column, None) + self.model.setData(childIndex, QtCore.Qt.Unchecked if select == False else QtCore.Qt.Checked, + QtCore.Qt.CheckStateRole) + def updateSetting(self): pass @@ -224,5 +276,6 @@ if __name__ == '__main__': app = QtGui.QApplication(sys.argv) view = DrEditWidget(DrEngine, EventEngine) - view.showMaximized() + view.setFixedSize(500, 500) + view.show() sys.exit(app.exec_()) From 4e49f0624667ed071be2f84b86d059b8e25e31e9 Mon Sep 17 00:00:00 2001 From: "ares89@wind" Date: Wed, 8 Feb 2017 15:40:28 +0800 Subject: [PATCH 06/13] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vn.trader/dataRecorder/uiDrEdit.py | 74 +++++++++++++++++++--------- vn.trader/dataRecorder/uiDrWidget.py | 14 +++--- vn.trader/uiBasicWidget.py | 6 --- vn.trader/uiMainWindow.py | 4 +- 4 files changed, 61 insertions(+), 37 deletions(-) diff --git a/vn.trader/dataRecorder/uiDrEdit.py b/vn.trader/dataRecorder/uiDrEdit.py index 7df09e88..0756f69c 100644 --- a/vn.trader/dataRecorder/uiDrEdit.py +++ b/vn.trader/dataRecorder/uiDrEdit.py @@ -3,12 +3,18 @@ ''' 行情记录模块相关的GUI控制组件 ''' +import re +import sys + from PyQt4.QtGui import QTreeView from dataRecorder.drEngine import DrEngine from eventEngine import * from uiBasicWidget import QtGui, QtCore +reload(sys) +sys.setdefaultencoding("utf8") + class TreeItem(object): def __init__(self, data, parent=None): @@ -58,7 +64,7 @@ class TreeItem(object): class TreeModel(QtCore.QAbstractItemModel): def __init__(self, parent=None): super(TreeModel, self).__init__(parent) - self.rootItem = TreeItem([u"合约", u"Tick", u"Bar", u"主力"]) + self.rootItem = TreeItem([u"合约", u"Tick", u"Bar", u"主力", u"交易所", u"接口"]) def rootItem(self): return self.rootItem @@ -73,7 +79,7 @@ class TreeModel(QtCore.QAbstractItemModel): return self.rootItem.columnCount() def setData(self, index, value, role=None): - if index.column() != 0 and role == QtCore.Qt.CheckStateRole: + if index.column() in [1, 2, 3] and role == QtCore.Qt.CheckStateRole: item = index.internalPointer() if item is None: return False @@ -101,13 +107,11 @@ class TreeModel(QtCore.QAbstractItemModel): item = index.internalPointer() - if role == QtCore.Qt.CheckStateRole and index.column() != 0: + if role == QtCore.Qt.CheckStateRole and ( + index.column() in [1, 2] or index.column() == 3 and item.parentItem != self.rootItem): return QtCore.Qt.Checked if item.data(index.column()) == True else QtCore.Qt.Unchecked - if index.column() == 3 and item.parentItem == self.rootItem: - return None - - if role != QtCore.Qt.DisplayRole: + if role != QtCore.Qt.DisplayRole or index.column() == 3 and item.parentItem == self.rootItem: return None return item.data(index.column()) @@ -116,12 +120,12 @@ class TreeModel(QtCore.QAbstractItemModel): if not index.isValid(): return QtCore.Qt.NoItemFlags - if index.column() == 0: + if index.column() in [0, 4, 5]: return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable item = index.internalPointer() if index.column() == 3 and item.parentItem == self.rootItem: - return QtCore.Qt.NoItemFlags + return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsUserCheckable @@ -170,7 +174,7 @@ class TreeModel(QtCore.QAbstractItemModel): return parentItem.childCount() def hasIndex(self, row, column, parentIndex=None, *args, **kwargs): - if row < 0 or column > 4: + if row < 0 or column > self.rootItem.columnCount(): return False return True @@ -179,11 +183,11 @@ class DrEditWidget(QtGui.QWidget): """行情数据记录引擎管理组件""" signal = QtCore.pyqtSignal(type(Event())) - def __init__(self, drEngine, eventEngine, parent=None): + def __init__(self, mainEngine, eventEngine, parent=None): """Constructor""" super(DrEditWidget, self).__init__(parent) - self.drEngine = drEngine + self.mainEngine = mainEngine self.eventEngine = eventEngine # 保存合约详细信息的字典 @@ -217,18 +221,42 @@ class DrEditWidget(QtGui.QWidget): vbox.addWidget(self.qTreeView) self.setLayout(vbox) + def getContractChineseName(self, str): + line = str.strip().decode('utf-8', 'ignore') # 处理前进行相关的处理,包括转换成Unicode等 + p2 = re.compile(ur'[^\u4e00-\u9fa5]') # 中文的编码范围是:\u4e00到\u9fa5 + zh = " ".join(p2.split(line)).strip() + zh = ",".join(zh.split()) + outStr = zh # 经过相关处理后得到中文的文本 + return outStr + def loadData(self): child = [] - yumi = TreeItem([u"玉米", False, False, False], self.model.rootItem) - yumi.appendChild(TreeItem([u"c1705", False, False, False], yumi)) - yumi.appendChild(TreeItem([u"c1703", False, False, False], yumi)) - yumi.appendChild(TreeItem([u"c1707", False, False, False], yumi)) - yumi.appendChild(TreeItem([u"c1709", False, False, False], yumi)) - dianfen = TreeItem([u"淀粉", False, False, False], self.model.rootItem) - dianfen.appendChild(TreeItem([u"d1705", False, False, False], dianfen)) - dianfen.appendChild(TreeItem([u"d1703", False, False, False], dianfen)) - dianfen.appendChild(TreeItem([u"d1707", False, False, False], dianfen)) - dianfen.appendChild(TreeItem([u"d1709", False, False, False], dianfen)) + + contractDict = {} + # contracts = self.mainEngine.getAllContracts() + # for contract in contracts: + # contractName = self.getContractChineseName(contract.name) + # if contractDict.has_key(contractName): + # parentItem = contractDict[contractName] + # item = TreeItem([contract.symbol, False, False, False, contract.exchange, "CTP"], parentItem) + # parentItem.appendChild(item) + # else: + # item = TreeItem([contractName, False, False, False, contract.exchange, "CTP"], self.model.rootItem) + # contractDict[contractName] = item + # child.append(item) + # subItem = TreeItem([contract.symbol, False, False, False, contract.exchange, "CTP"], item) + # item.appendChild(subItem) + + yumi = TreeItem([u"玉米", False, False, False, "SH", "CTP"], self.model.rootItem) + yumi.appendChild(TreeItem([u"c1705", False, False, False, "SH", "CTP"], yumi)) + yumi.appendChild(TreeItem([u"c1703", False, False, False, "SH", "CTP"], yumi)) + yumi.appendChild(TreeItem([u"c1707", False, False, False, "SH", "CTP"], yumi)) + yumi.appendChild(TreeItem([u"c1709", False, False, False, "SH", "CTP"], yumi)) + dianfen = TreeItem([u"淀粉", False, False, False, "SH", "CTP"], self.model.rootItem) + dianfen.appendChild(TreeItem([u"d1705", False, False, False, "SH", "CTP"], dianfen)) + dianfen.appendChild(TreeItem([u"d1703", False, False, False, "SH", "CTP"], dianfen)) + dianfen.appendChild(TreeItem([u"d1707", False, False, False, "SH", "CTP"], dianfen)) + dianfen.appendChild(TreeItem([u"d1709", False, False, False, "SH", "CTP"], dianfen)) child.append(yumi) child.append(dianfen) @@ -276,6 +304,6 @@ if __name__ == '__main__': app = QtGui.QApplication(sys.argv) view = DrEditWidget(DrEngine, EventEngine) - view.setFixedSize(500, 500) + view.setFixedSize(650, 500) view.show() sys.exit(app.exec_()) diff --git a/vn.trader/dataRecorder/uiDrWidget.py b/vn.trader/dataRecorder/uiDrWidget.py index 649c4ec6..06ffd80c 100644 --- a/vn.trader/dataRecorder/uiDrWidget.py +++ b/vn.trader/dataRecorder/uiDrWidget.py @@ -7,8 +7,8 @@ import json from dataRecorder.uiDrEdit import DrEditWidget -from uiBasicWidget import QtGui, QtCore from eventEngine import * +from uiBasicWidget import QtGui, QtCore ######################################################################## @@ -39,11 +39,12 @@ class DrEngineManager(QtGui.QWidget): signal = QtCore.pyqtSignal(type(Event())) #---------------------------------------------------------------------- - def __init__(self, drEngine, eventEngine, parent=None): + def __init__(self, mainEngine, eventEngine, parent=None): """Constructor""" super(DrEngineManager, self).__init__(parent) - - self.drEngine = drEngine + + self.mainEngine = mainEngine + self.drEngine = mainEngine.drEngine self.eventEngine = eventEngine self.initUi() @@ -154,5 +155,6 @@ class DrEngineManager(QtGui.QWidget): # ---------------------------------------------------------------------- def openDr(self): """打开行情数据记录组件""" - self.mDrEditWidget = DrEditWidget(self.drEngine, self.eventEngine) - self.mDrEditWidget.showMaximized() + self.mDrEditWidget = DrEditWidget(self.mainEngine, self.eventEngine) + self.mDrEditWidget.setFixedSize(500, 500) + self.mDrEditWidget.show() diff --git a/vn.trader/uiBasicWidget.py b/vn.trader/uiBasicWidget.py index 9ba0ab93..48b7c5c4 100644 --- a/vn.trader/uiBasicWidget.py +++ b/vn.trader/uiBasicWidget.py @@ -1,14 +1,11 @@ # encoding: UTF-8 -import json import csv -import os from collections import OrderedDict from PyQt4 import QtGui, QtCore from PyQt4.QtCore import Qt -from eventEngine import * from vtFunction import * from vtGateway import * @@ -1101,9 +1098,6 @@ class ContractMonitor(BasicMonitor): d['productClass'] = {'chinese':u'合约类型', 'cellType':BasicCell} d['size'] = {'chinese':u'大小', 'cellType':BasicCell} d['priceTick'] = {'chinese':u'最小价格变动', 'cellType':BasicCell} - d['tick'] = {'chinese':u'tick', 'cellType':CheckBoxCell} - d['bar'] = {'chinese':u'bar', 'cellType':CheckBoxCell} - d['main'] = {'chinese':u'主力合约', 'cellType':CheckBoxCell} #d['strikePrice'] = {'chinese':u'期权行权价', 'cellType':BasicCell} #d['underlyingSymbol'] = {'chinese':u'期权标的物', 'cellType':BasicCell} #d['optionType'] = {'chinese':u'期权类型', 'cellType':BasicCell} diff --git a/vn.trader/uiMainWindow.py b/vn.trader/uiMainWindow.py index 348ed439..06b3f85d 100644 --- a/vn.trader/uiMainWindow.py +++ b/vn.trader/uiMainWindow.py @@ -2,10 +2,10 @@ import psutil -from uiBasicWidget import * from ctaAlgo.uiCtaWidget import CtaEngineManager from dataRecorder.uiDrWidget import DrEngineManager from riskManager.uiRmWidget import RmEngineManager +from uiBasicWidget import * ######################################################################## class MainWindow(QtGui.QMainWindow): @@ -194,7 +194,7 @@ class MainWindow(QtGui.QMainWindow): try: self.widgetDict['drM'].showMaximized() except KeyError: - self.widgetDict['drM'] = DrEngineManager(self.mainEngine.drEngine, self.eventEngine) + self.widgetDict['drM'] = DrEngineManager(self.mainEngine, self.eventEngine) self.widgetDict['drM'].showMaximized() #---------------------------------------------------------------------- From 2ee300ad2bb4193a178b257f58bd82566f1111f0 Mon Sep 17 00:00:00 2001 From: "ares89@wind" Date: Wed, 8 Feb 2017 17:55:38 +0800 Subject: [PATCH 07/13] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vn.trader/dataRecorder/drEngine.py | 23 ++++---- vn.trader/dataRecorder/uiDrEdit.py | 79 +++++++++++++++++++--------- vn.trader/dataRecorder/uiDrWidget.py | 26 +++++++-- 3 files changed, 90 insertions(+), 38 deletions(-) diff --git a/vn.trader/dataRecorder/drEngine.py b/vn.trader/dataRecorder/drEngine.py index c4565fc4..fbcdc92a 100644 --- a/vn.trader/dataRecorder/drEngine.py +++ b/vn.trader/dataRecorder/drEngine.py @@ -6,18 +6,15 @@ 使用DR_setting.json来配置需要收集的合约,以及主力合约代码。 ''' +import copy import json import os -import copy -from collections import OrderedDict -from datetime import datetime, timedelta -from Queue import Queue -from threading import Thread +from datetime import datetime -from eventEngine import * -from vtGateway import VtSubscribeReq, VtLogData from drBase import * +from eventEngine import * from vtFunction import todayDate +from vtGateway import VtSubscribeReq, VtLogData ######################################################################## @@ -53,6 +50,14 @@ class DrEngine(object): # 载入设置,订阅行情 self.loadSetting() + + def saveSetting(self, setting): + """保存设置""" + setting['working'] = self.working + with open(self.settingFileName, 'w') as f: + str = json.dumps(setting) + f.write(str) + return True #---------------------------------------------------------------------- def loadSetting(self): @@ -61,8 +66,8 @@ class DrEngine(object): drSetting = json.load(f) # 如果working设为False则不启动行情记录功能 - working = drSetting['working'] - if not working: + self.working = drSetting['working'] + if not self.working: return if 'tick' in drSetting: diff --git a/vn.trader/dataRecorder/uiDrEdit.py b/vn.trader/dataRecorder/uiDrEdit.py index 0756f69c..b04a1749 100644 --- a/vn.trader/dataRecorder/uiDrEdit.py +++ b/vn.trader/dataRecorder/uiDrEdit.py @@ -206,11 +206,14 @@ class DrEditWidget(QtGui.QWidget): vline.setSpacing(2) btnTickAll = QtGui.QPushButton(u"全部记录tick", self) btnBarAll = QtGui.QPushButton(u'全部记录bar', self) + btnSaveAll = QtGui.QPushButton(u'保存设置', self) btnTickAll.clicked.connect(self.selectAllTick) btnBarAll.clicked.connect(self.selectAllBar) + btnSaveAll.clicked.connect(self.saveSetting) vline.addWidget(btnTickAll) vline.addWidget(btnBarAll) + vline.addWidget(btnSaveAll) vbox.addLayout(vline) @@ -233,36 +236,60 @@ class DrEditWidget(QtGui.QWidget): child = [] contractDict = {} - # contracts = self.mainEngine.getAllContracts() - # for contract in contracts: - # contractName = self.getContractChineseName(contract.name) - # if contractDict.has_key(contractName): - # parentItem = contractDict[contractName] - # item = TreeItem([contract.symbol, False, False, False, contract.exchange, "CTP"], parentItem) - # parentItem.appendChild(item) - # else: - # item = TreeItem([contractName, False, False, False, contract.exchange, "CTP"], self.model.rootItem) - # contractDict[contractName] = item - # child.append(item) - # subItem = TreeItem([contract.symbol, False, False, False, contract.exchange, "CTP"], item) - # item.appendChild(subItem) + contracts = self.mainEngine.getAllContracts() + for contract in contracts: + contractName = self.getContractChineseName(contract.name) + if contractDict.has_key(contractName): + parentItem = contractDict[contractName] + item = TreeItem([contract.symbol, False, False, False, contract.exchange, "CTP"], parentItem) + parentItem.appendChild(item) + else: + item = TreeItem([contractName, False, False, False, contract.exchange, "CTP"], self.model.rootItem) + contractDict[contractName] = item + child.append(item) + subItem = TreeItem([contract.symbol, False, False, False, contract.exchange, "CTP"], item) + item.appendChild(subItem) - yumi = TreeItem([u"玉米", False, False, False, "SH", "CTP"], self.model.rootItem) - yumi.appendChild(TreeItem([u"c1705", False, False, False, "SH", "CTP"], yumi)) - yumi.appendChild(TreeItem([u"c1703", False, False, False, "SH", "CTP"], yumi)) - yumi.appendChild(TreeItem([u"c1707", False, False, False, "SH", "CTP"], yumi)) - yumi.appendChild(TreeItem([u"c1709", False, False, False, "SH", "CTP"], yumi)) - dianfen = TreeItem([u"淀粉", False, False, False, "SH", "CTP"], self.model.rootItem) - dianfen.appendChild(TreeItem([u"d1705", False, False, False, "SH", "CTP"], dianfen)) - dianfen.appendChild(TreeItem([u"d1703", False, False, False, "SH", "CTP"], dianfen)) - dianfen.appendChild(TreeItem([u"d1707", False, False, False, "SH", "CTP"], dianfen)) - dianfen.appendChild(TreeItem([u"d1709", False, False, False, "SH", "CTP"], dianfen)) - - child.append(yumi) - child.append(dianfen) + # yumi = TreeItem([u"玉米", False, False, False, "SH", "CTP"], self.model.rootItem) + # yumi.appendChild(TreeItem([u"c1705", False, False, False, "SH", "CTP"], yumi)) + # yumi.appendChild(TreeItem([u"c1703", False, False, False, "SH", "CTP"], yumi)) + # yumi.appendChild(TreeItem([u"c1707", False, False, False, "SH", "CTP"], yumi)) + # yumi.appendChild(TreeItem([u"c1709", False, False, False, "SH", "CTP"], yumi)) + # dianfen = TreeItem([u"淀粉", False, False, False, "SH", "CTP"], self.model.rootItem) + # dianfen.appendChild(TreeItem([u"d1705", False, False, False, "SH", "CTP"], dianfen)) + # dianfen.appendChild(TreeItem([u"d1703", False, False, False, "SH", "CTP"], dianfen)) + # dianfen.appendChild(TreeItem([u"d1707", False, False, False, "SH", "CTP"], dianfen)) + # dianfen.appendChild(TreeItem([u"d1709", False, False, False, "SH", "CTP"], dianfen)) + # + # child.append(yumi) + # child.append(dianfen) self.model.setDataSource(child) self.qTreeView.expandAll() + def saveSetting(self): + setting = {} + setting["tick"] = [] + setting["bar"] = [] + setting["active"] = {} + queue = Queue() + queue.put(self.model.rootItem) + while queue.qsize() > 0: + item = queue.get() + for child in item.childItems: + queue.put(child) + if item.parentItem is not None and item.parentItem != self.model.rootItem: + name = item.data(0) + interface = item.data(5) + if item.data(1): + setting["tick"].append([name, interface]) + if item.data(2): + setting["bar"].append([name, interface]) + if item.data(3): + setting["active"][item.parentItem.data(0)] = name + if self.mainEngine.drEngine.saveSetting(setting): + self.close() + + def selectAllTick(self): self.selectAll(True, False, True) diff --git a/vn.trader/dataRecorder/uiDrWidget.py b/vn.trader/dataRecorder/uiDrWidget.py index 06ffd80c..41ba66ea 100644 --- a/vn.trader/dataRecorder/uiDrWidget.py +++ b/vn.trader/dataRecorder/uiDrWidget.py @@ -6,6 +6,9 @@ import json +from PyQt4.QtCore import QObject + +from dataRecorder.drEngine import DrEngine from dataRecorder.uiDrEdit import DrEditWidget from eventEngine import * from uiBasicWidget import QtGui, QtCore @@ -99,15 +102,22 @@ class DrEngineManager(QtGui.QWidget): grid.addWidget(self.barTable, 1, 1) grid.addWidget(self.activeTable, 1, 2) - btn = QtGui.QPushButton(u'编辑', self) + btnEdit = QtGui.QPushButton(u'编辑', self) + btnRestart = QtGui.QPushButton(u'更新数据', self) vbox = QtGui.QVBoxLayout() vbox.addLayout(grid) - vbox.addWidget(btn) + + vline = QtGui.QHBoxLayout() + vline.addWidget(btnEdit) + vline.addWidget(btnRestart) + + vbox.addLayout(vline) vbox.addWidget(self.logMonitor) self.setLayout(vbox) - btn.clicked.connect(self.openDr) + btnEdit.clicked.connect(self.openDr) + btnRestart.clicked.connect(self.restart) #---------------------------------------------------------------------- def updateLog(self, event): @@ -125,6 +135,11 @@ class DrEngineManager(QtGui.QWidget): #---------------------------------------------------------------------- def updateSetting(self): """显示引擎行情记录配置""" + + self.tickTable.clearContents() + self.barTable.clearContents() + self.activeTable.clearContents() + with open(self.drEngine.settingFileName) as f: drSetting = json.load(f) @@ -158,3 +173,8 @@ class DrEngineManager(QtGui.QWidget): self.mDrEditWidget = DrEditWidget(self.mainEngine, self.eventEngine) self.mDrEditWidget.setFixedSize(500, 500) self.mDrEditWidget.show() + QObject.connect(self.mDrEditWidget, QtCore.SIGNAL('closed()'), self, QtCore.SIGNAL('restart()')) + + def restart(self): + self.updateSetting() + self.mainEngine.drEngine = DrEngine(self.mainEngine, self.mainEngine.eventEngine) From 359504b16c7ff409def82830ef867293f2e8ae85 Mon Sep 17 00:00:00 2001 From: "sunlit@home" Date: Wed, 8 Feb 2017 23:05:33 +0800 Subject: [PATCH 08/13] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BA=86=E8=AE=A2?= =?UTF-8?q?=E9=98=85=E5=90=88=E7=BA=A6=E7=BC=96=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vn.trader/dataRecorder/uiDrEdit.py | 16 +++++---- vn.trader/dataRecorder/uiDrWidget.py | 49 +++++++++++++++------------- vn.trader/uiBasicWidget.py | 2 +- vn.trader/uiMainWindow.py | 2 +- 4 files changed, 38 insertions(+), 31 deletions(-) diff --git a/vn.trader/dataRecorder/uiDrEdit.py b/vn.trader/dataRecorder/uiDrEdit.py index b04a1749..64f6b2f6 100644 --- a/vn.trader/dataRecorder/uiDrEdit.py +++ b/vn.trader/dataRecorder/uiDrEdit.py @@ -183,12 +183,13 @@ class DrEditWidget(QtGui.QWidget): """行情数据记录引擎管理组件""" signal = QtCore.pyqtSignal(type(Event())) - def __init__(self, mainEngine, eventEngine, parent=None): + def __init__(self, drWidget, mainEngine, eventEngine, parent=None): """Constructor""" super(DrEditWidget, self).__init__(parent) - + self.drWidget = drWidget self.mainEngine = mainEngine self.eventEngine = eventEngine + self.hasChanged = False # 保存合约详细信息的字典 self.contractDict = {} @@ -198,6 +199,10 @@ class DrEditWidget(QtGui.QWidget): self.loadData() self.registerEvent() + def closeEvent(self, QCloseEvent): + if self.hasChanged: + self.drWidget.restart() + def initUi(self): vbox = QtGui.QVBoxLayout() @@ -287,9 +292,9 @@ class DrEditWidget(QtGui.QWidget): if item.data(3): setting["active"][item.parentItem.data(0)] = name if self.mainEngine.drEngine.saveSetting(setting): + self.hasChanged = True self.close() - def selectAllTick(self): self.selectAll(True, False, True) @@ -321,8 +326,7 @@ class DrEditWidget(QtGui.QWidget): def registerEvent(self): """注册事件监听""" self.signal.connect(self.updateContract) - - # self.eventEngine.register(EVENT_CONTRACT, self.signal.emit) + self.eventEngine.register(EVENT_CONTRACT, self.signal.emit) if __name__ == '__main__': @@ -330,7 +334,7 @@ if __name__ == '__main__': app = QtGui.QApplication(sys.argv) - view = DrEditWidget(DrEngine, EventEngine) + view = DrEditWidget(None, DrEngine, EventEngine) view.setFixedSize(650, 500) view.show() sys.exit(app.exec_()) diff --git a/vn.trader/dataRecorder/uiDrWidget.py b/vn.trader/dataRecorder/uiDrWidget.py index 41ba66ea..654fffa7 100644 --- a/vn.trader/dataRecorder/uiDrWidget.py +++ b/vn.trader/dataRecorder/uiDrWidget.py @@ -49,16 +49,16 @@ class DrEngineManager(QtGui.QWidget): self.mainEngine = mainEngine self.drEngine = mainEngine.drEngine self.eventEngine = eventEngine - + self.initUi() self.updateSetting() - self.registerEvent() - + self.registerEvent() + #---------------------------------------------------------------------- def initUi(self): """初始化界面""" self.setWindowTitle(u'行情数据记录工具') - + # 记录合约配置监控 tickLabel = QtGui.QLabel(u'Tick记录') self.tickTable = QtGui.QTableWidget() @@ -68,14 +68,14 @@ class DrEngineManager(QtGui.QWidget): self.tickTable.horizontalHeader().setResizeMode(QtGui.QHeaderView.Stretch) self.tickTable.setAlternatingRowColors(True) self.tickTable.setHorizontalHeaderLabels([u'合约代码', u'接口']) - + barLabel = QtGui.QLabel(u'Bar记录') self.barTable = QtGui.QTableWidget() self.barTable.setColumnCount(2) self.barTable.verticalHeader().setVisible(False) self.barTable.setEditTriggers(QtGui.QTableWidget.NoEditTriggers) self.barTable.horizontalHeader().setResizeMode(QtGui.QHeaderView.Stretch) - self.barTable.setAlternatingRowColors(True) + self.barTable.setAlternatingRowColors(True) self.barTable.setHorizontalHeaderLabels([u'合约代码', u'接口']) activeLabel = QtGui.QLabel(u'主力合约') @@ -84,17 +84,17 @@ class DrEngineManager(QtGui.QWidget): self.activeTable.verticalHeader().setVisible(False) self.activeTable.setEditTriggers(QtGui.QTableWidget.NoEditTriggers) self.activeTable.horizontalHeader().setResizeMode(QtGui.QHeaderView.Stretch) - self.activeTable.setAlternatingRowColors(True) + self.activeTable.setAlternatingRowColors(True) self.activeTable.setHorizontalHeaderLabels([u'主力代码', u'合约代码']) # 日志监控 self.logMonitor = QtGui.QTextEdit() self.logMonitor.setReadOnly(True) self.logMonitor.setMinimumHeight(600) - + # 设置布局 grid = QtGui.QGridLayout() - + grid.addWidget(tickLabel, 0, 0) grid.addWidget(barLabel, 0, 1) grid.addWidget(activeLabel, 0, 2) @@ -125,43 +125,46 @@ class DrEngineManager(QtGui.QWidget): log = event.dict_['data'] content = '\t'.join([log.logTime, log.logContent]) self.logMonitor.append(content) - + #---------------------------------------------------------------------- def registerEvent(self): """注册事件监听""" self.signal.connect(self.updateLog) self.eventEngine.register(EVENT_DATARECORDER_LOG, self.signal.emit) - + #---------------------------------------------------------------------- def updateSetting(self): """显示引擎行情记录配置""" self.tickTable.clearContents() + self.tickTable.setRowCount(0) self.barTable.clearContents() + self.barTable.setRowCount(0) self.activeTable.clearContents() + self.activeTable.setRowCount(0) with open(self.drEngine.settingFileName) as f: drSetting = json.load(f) - + if 'tick' in drSetting: l = drSetting['tick'] - + for setting in l: self.tickTable.insertRow(0) self.tickTable.setItem(0, 0, TableCell(setting[0])) self.tickTable.setItem(0, 1, TableCell(setting[1])) - + if 'bar' in drSetting: l = drSetting['bar'] - + for setting in l: self.barTable.insertRow(0) self.barTable.setItem(0, 0, TableCell(setting[0])) - self.barTable.setItem(0, 1, TableCell(setting[1])) - + self.barTable.setItem(0, 1, TableCell(setting[1])) + if 'active' in drSetting: d = drSetting['active'] - + for activeSymbol, symbol in d.items(): self.activeTable.insertRow(0) self.activeTable.setItem(0, 0, TableCell(activeSymbol)) @@ -170,11 +173,11 @@ class DrEngineManager(QtGui.QWidget): # ---------------------------------------------------------------------- def openDr(self): """打开行情数据记录组件""" - self.mDrEditWidget = DrEditWidget(self.mainEngine, self.eventEngine) - self.mDrEditWidget.setFixedSize(500, 500) + self.mDrEditWidget = DrEditWidget(self,self.mainEngine, self.eventEngine) + self.mDrEditWidget.setFixedSize(800,800) self.mDrEditWidget.show() - QObject.connect(self.mDrEditWidget, QtCore.SIGNAL('closed()'), self, QtCore.SIGNAL('restart()')) def restart(self): - self.updateSetting() - self.mainEngine.drEngine = DrEngine(self.mainEngine, self.mainEngine.eventEngine) + self.drEngine.stop() + self.updateSetting() + self.mainEngine.drEngine = DrEngine(self.mainEngine, self.mainEngine.eventEngine) diff --git a/vn.trader/uiBasicWidget.py b/vn.trader/uiBasicWidget.py index 48b7c5c4..879e120d 100644 --- a/vn.trader/uiBasicWidget.py +++ b/vn.trader/uiBasicWidget.py @@ -445,7 +445,7 @@ class MarketMonitor(BasicMonitor): self.setFont(BASIC_FONT) # 设置允许排序 - self.setSorting(True) + self.setSorting(False) # 初始化表格 self.initTable() diff --git a/vn.trader/uiMainWindow.py b/vn.trader/uiMainWindow.py index 06b3f85d..66924bf8 100644 --- a/vn.trader/uiMainWindow.py +++ b/vn.trader/uiMainWindow.py @@ -194,7 +194,7 @@ class MainWindow(QtGui.QMainWindow): try: self.widgetDict['drM'].showMaximized() except KeyError: - self.widgetDict['drM'] = DrEngineManager(self.mainEngine, self.eventEngine) + self.widgetDict['drM'] = DrEngineManager(self.mainEngine, self.eventEngine) self.widgetDict['drM'].showMaximized() #---------------------------------------------------------------------- From 1e2799933f6d60d83716b997aa875cda64ec736d Mon Sep 17 00:00:00 2001 From: "ares89@wind" Date: Thu, 9 Feb 2017 16:33:33 +0800 Subject: [PATCH 09/13] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=A4=8D=E9=80=89?= =?UTF-8?q?=E6=A1=86=E7=9A=84=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vn.trader/dataRecorder/uiDrEdit.py | 6 +- vn.trader/util/UiUtil.py | 96 ++++++++++++++++++++++++++++++ vn.trader/util/__init__.py | 0 3 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 vn.trader/util/UiUtil.py create mode 100644 vn.trader/util/__init__.py diff --git a/vn.trader/dataRecorder/uiDrEdit.py b/vn.trader/dataRecorder/uiDrEdit.py index 64f6b2f6..f0a5f23f 100644 --- a/vn.trader/dataRecorder/uiDrEdit.py +++ b/vn.trader/dataRecorder/uiDrEdit.py @@ -11,6 +11,7 @@ from PyQt4.QtGui import QTreeView from dataRecorder.drEngine import DrEngine from eventEngine import * from uiBasicWidget import QtGui, QtCore +from util.UiUtil import CheckBoxDelegate reload(sys) sys.setdefaultencoding("utf8") @@ -127,7 +128,7 @@ class TreeModel(QtCore.QAbstractItemModel): if index.column() == 3 and item.parentItem == self.rootItem: return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable - return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsUserCheckable + return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEditable def headerData(self, section, orientation, role): if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole: @@ -225,6 +226,9 @@ class DrEditWidget(QtGui.QWidget): self.qTreeView = QTreeView() self.model = TreeModel() self.qTreeView.setModel(self.model) + self.qTreeView.setItemDelegateForColumn(1, CheckBoxDelegate(self)) + self.qTreeView.setItemDelegateForColumn(2, CheckBoxDelegate(self)) + self.qTreeView.setItemDelegateForColumn(3, CheckBoxDelegate(self)) vbox.addWidget(self.qTreeView) self.setLayout(vbox) diff --git a/vn.trader/util/UiUtil.py b/vn.trader/util/UiUtil.py new file mode 100644 index 00000000..8efcc41a --- /dev/null +++ b/vn.trader/util/UiUtil.py @@ -0,0 +1,96 @@ +from PyQt4 import QtCore +from PyQt4.QtGui import QStyle, QStyledItemDelegate, QStyleOptionButton, QApplication, QItemDelegate + + +class CheckBoxDelegate(QStyledItemDelegate): + """ + A delegate that places a fully functioning QCheckBox in every + cell of the column to which it's applied + """ + + def __init__(self, parent): + QItemDelegate.__init__(self, parent) + + def createEditor(self, parent, option, index): + ''' + Important, otherwise an editor is created if the user clicks in this cell. + ** Need to hook up a signal to the model + ''' + return None + + def paint(self, painter, option, index): + ''' + Paint a checkbox without the label. + ''' + data = index.model().data(index, QtCore.Qt.CheckStateRole) + if not data in [QtCore.Qt.Unchecked, QtCore.Qt.Checked]: + return + checked = data == QtCore.Qt.Checked + check_box_style_option = QStyleOptionButton() + + if index.flags() & QtCore.Qt.ItemIsEditable == QtCore.Qt.ItemIsEditable: + check_box_style_option.state |= QStyle.State_Enabled + else: + check_box_style_option.state |= QStyle.State_ReadOnly + + if checked: + check_box_style_option.state |= QStyle.State_On + else: + check_box_style_option.state |= QStyle.State_Off + + check_box_style_option.rect = self.getCheckBoxRect(option) + + # this will not run - hasFlag does not exist + # if not index.model().hasFlag(index, QtCore.Qt.ItemIsEditable): + # check_box_style_option.state |= QStyle.State_ReadOnly + + # check_box_style_option.state |= QStyle.State_Enabled + + QApplication.style().drawControl(QStyle.CE_CheckBox, check_box_style_option, painter) + + def editorEvent(self, event, model, option, index): + ''' + Change the data in the model and the state of the checkbox + if the user presses the left mousebutton or presses + Key_Space or Key_Select and this cell is editable. Otherwise do nothing. + ''' + # print 'Check Box editor Event detected : ' + if index.flags() & QtCore.Qt.ItemIsEditable != QtCore.Qt.ItemIsEditable: + return False + + # print 'Check Box edior Event detected : passed first check' + # Do not change the checkbox-state + if event.type() == QtCore.QEvent.MouseButtonRelease or event.type() == QtCore.QEvent.MouseButtonDblClick: + if event.button() != QtCore.Qt.LeftButton or not self.getCheckBoxRect(option).contains(event.pos()): + return False + if event.type() == QtCore.QEvent.MouseButtonDblClick: + return True + elif event.type() == QtCore.QEvent.KeyPress: + if event.key() != QtCore.Qt.Key_Space and event.key() != QtCore.Qt.Key_Select: + return False + else: + return False + + # Change the checkbox-state + self.setModelData(None, model, index) + return True + + def setModelData(self, editor, model, index): + ''' + The user wanted to change the old state in the opposite. + ''' + # print 'SetModelData' + newValue = not index.data().toBool() + # print 'New Value : {0}'.format(newValue) + model.setData(index, QtCore.Qt.Checked if newValue else QtCore.Qt.Unchecked, QtCore.Qt.CheckStateRole) + + def getCheckBoxRect(self, option): + check_box_style_option = QStyleOptionButton() + check_box_rect = QApplication.style().subElementRect(QStyle.SE_CheckBoxIndicator, check_box_style_option, None) + check_box_point = QtCore.QPoint(option.rect.x() + + option.rect.width() / 2 - + check_box_rect.width() / 2, + option.rect.y() + + option.rect.height() / 2 - + check_box_rect.height() / 2) + return QtCore.QRect(check_box_point, check_box_rect.size()) diff --git a/vn.trader/util/__init__.py b/vn.trader/util/__init__.py new file mode 100644 index 00000000..e69de29b From 2605103b9fc5ed13d3d14eaf1e7d731d5d647567 Mon Sep 17 00:00:00 2001 From: "ares89@wind" Date: Thu, 9 Feb 2017 19:31:14 +0800 Subject: [PATCH 10/13] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=A4=8D=E9=80=89?= =?UTF-8?q?=E6=A1=86=E7=9A=84=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vn.trader/dataRecorder/uiDrEdit.py | 55 +++++++++++++++++++++++----- vn.trader/dataRecorder/uiDrWidget.py | 10 ++--- vn.trader/util/UiUtil.py | 50 ++++++++++++++++++++++++- 3 files changed, 99 insertions(+), 16 deletions(-) diff --git a/vn.trader/dataRecorder/uiDrEdit.py b/vn.trader/dataRecorder/uiDrEdit.py index f0a5f23f..3592ced1 100644 --- a/vn.trader/dataRecorder/uiDrEdit.py +++ b/vn.trader/dataRecorder/uiDrEdit.py @@ -3,6 +3,7 @@ ''' 行情记录模块相关的GUI控制组件 ''' +import json import re import sys @@ -11,7 +12,7 @@ from PyQt4.QtGui import QTreeView from dataRecorder.drEngine import DrEngine from eventEngine import * from uiBasicWidget import QtGui, QtCore -from util.UiUtil import CheckBoxDelegate +from util.UiUtil import CheckBoxDelegate, GateWayListItemEditorCreator reload(sys) sys.setdefaultencoding("utf8") @@ -112,7 +113,7 @@ class TreeModel(QtCore.QAbstractItemModel): index.column() in [1, 2] or index.column() == 3 and item.parentItem != self.rootItem): return QtCore.Qt.Checked if item.data(index.column()) == True else QtCore.Qt.Unchecked - if role != QtCore.Qt.DisplayRole or index.column() == 3 and item.parentItem == self.rootItem: + if role != QtCore.Qt.DisplayRole or index.column() in [3, 4] and item.parentItem == self.rootItem: return None return item.data(index.column()) @@ -121,9 +122,12 @@ class TreeModel(QtCore.QAbstractItemModel): if not index.isValid(): return QtCore.Qt.NoItemFlags - if index.column() in [0, 4, 5]: + if index.column() in [0, 4]: return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable + if index.column() in [5]: + return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable + item = index.internalPointer() if index.column() == 3 and item.parentItem == self.rootItem: return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable @@ -210,9 +214,9 @@ class DrEditWidget(QtGui.QWidget): vline = QtGui.QHBoxLayout() vline.setSpacing(2) - btnTickAll = QtGui.QPushButton(u"全部记录tick", self) - btnBarAll = QtGui.QPushButton(u'全部记录bar', self) - btnSaveAll = QtGui.QPushButton(u'保存设置', self) + btnTickAll = QtGui.QPushButton(u"全部记录Tick", self) + btnBarAll = QtGui.QPushButton(u'全部记录Bar', self) + btnSaveAll = QtGui.QPushButton(u'保存设置(重启后生效)', self) btnTickAll.clicked.connect(self.selectAllTick) btnBarAll.clicked.connect(self.selectAllBar) btnSaveAll.clicked.connect(self.saveSetting) @@ -230,6 +234,10 @@ class DrEditWidget(QtGui.QWidget): self.qTreeView.setItemDelegateForColumn(2, CheckBoxDelegate(self)) self.qTreeView.setItemDelegateForColumn(3, CheckBoxDelegate(self)) + factory = QtGui.QItemEditorFactory() + factory.registerEditor(QtCore.QVariant.Line, GateWayListItemEditorCreator()) + QtGui.QItemEditorFactory.setDefaultFactory(factory) + vbox.addWidget(self.qTreeView) self.setLayout(vbox) @@ -244,19 +252,48 @@ class DrEditWidget(QtGui.QWidget): def loadData(self): child = [] + tick = {} + bar = {} + active = [] + with open(self.mainEngine.drEngine.settingFileName) as f: + drSetting = json.load(f) + if 'tick' in drSetting: + l = drSetting['tick'] + + for setting in l: + tick[setting[0]] = setting[1] + + if 'bar' in drSetting: + l = drSetting['bar'] + + for setting in l: + bar[setting[0]] = setting[1] + + if 'active' in drSetting: + d = drSetting['active'] + + for activeSymbol, symbol in d.items(): + active.append(symbol) + contractDict = {} contracts = self.mainEngine.getAllContracts() for contract in contracts: contractName = self.getContractChineseName(contract.name) + gateWayName = contract.gatewayName + hasTick = tick.has_key(contract.symbol) + hasBar = bar.has_key(contract.symbol) + hasActive = contract.symbol in active if contractDict.has_key(contractName): parentItem = contractDict[contractName] - item = TreeItem([contract.symbol, False, False, False, contract.exchange, "CTP"], parentItem) + item = TreeItem([contract.symbol, hasTick, hasBar, hasActive, contract.exchange, gateWayName], + parentItem) parentItem.appendChild(item) else: - item = TreeItem([contractName, False, False, False, contract.exchange, "CTP"], self.model.rootItem) + item = TreeItem([contractName, False, False, False, contract.exchange, gateWayName], + self.model.rootItem) contractDict[contractName] = item child.append(item) - subItem = TreeItem([contract.symbol, False, False, False, contract.exchange, "CTP"], item) + subItem = TreeItem([contract.symbol, hasTick, hasBar, hasActive, contract.exchange, gateWayName], item) item.appendChild(subItem) # yumi = TreeItem([u"玉米", False, False, False, "SH", "CTP"], self.model.rootItem) diff --git a/vn.trader/dataRecorder/uiDrWidget.py b/vn.trader/dataRecorder/uiDrWidget.py index 654fffa7..f1506686 100644 --- a/vn.trader/dataRecorder/uiDrWidget.py +++ b/vn.trader/dataRecorder/uiDrWidget.py @@ -6,9 +6,6 @@ import json -from PyQt4.QtCore import QObject - -from dataRecorder.drEngine import DrEngine from dataRecorder.uiDrEdit import DrEditWidget from eventEngine import * from uiBasicWidget import QtGui, QtCore @@ -178,6 +175,7 @@ class DrEngineManager(QtGui.QWidget): self.mDrEditWidget.show() def restart(self): - self.drEngine.stop() - self.updateSetting() - self.mainEngine.drEngine = DrEngine(self.mainEngine, self.mainEngine.eventEngine) + pass + # self.drEngine.stop() + # self.updateSetting() + # self.mainEngine.drEngine = DrEngine(self.mainEngine, self.mainEngine.eventEngine) diff --git a/vn.trader/util/UiUtil.py b/vn.trader/util/UiUtil.py index 8efcc41a..caf63887 100644 --- a/vn.trader/util/UiUtil.py +++ b/vn.trader/util/UiUtil.py @@ -1,5 +1,6 @@ from PyQt4 import QtCore -from PyQt4.QtGui import QStyle, QStyledItemDelegate, QStyleOptionButton, QApplication, QItemDelegate +from PyQt4.QtGui import QStyle, QStyledItemDelegate, QStyleOptionButton, QApplication, QItemDelegate, QComboBox, \ + QItemEditorCreatorBase class CheckBoxDelegate(QStyledItemDelegate): @@ -94,3 +95,50 @@ class CheckBoxDelegate(QStyledItemDelegate): option.rect.height() / 2 - check_box_rect.height() / 2) return QtCore.QRect(check_box_point, check_box_rect.size()) + + +class ComboDelegate(QItemDelegate): + def __init__(self, parent, dataList=[]): + QItemDelegate.__init__(self, parent) + self.dataList = dataList + + def createEditor(self, parent, option, index): + combo = QComboBox(parent) + + return combo + + def setEditorData(self, editor, index): + text = index.data().toString() + index = editor.findText(text) + editor.setCurrentIndex(index) + + def setModelData(self, editor, model, index): + model.setData(index, editor.itemText(editor.currentIndex())) + + def updateEditorGeometry(self, editor, option, index): + print option, option.rect + editor.setGeometry(option.rect) + + +class GateWayListEditor(QComboBox): + def __init__(self, widget=None, dataList=[]): + super(GateWayListEditor, self).__init__(widget) + self.dataList = dataList + self.populateList() + + def getGateWay(self): + gateWay = self.itemData(self.currentIndex(), QtCore.Qt.DisplayRole) + return gateWay + + def setGateWay(self, gateWay): + self.setCurrentIndex(self.findData(gateWay, QtCore.Qt.DisplayRole)) + + def populateList(self): + for i, gateWayName in enumerate(self.dataList): + self.insertItem(i, gateWayName) + self.setItemData(i, gateWayName, QtCore.Qt.DisplayRole) + + +class GateWayListItemEditorCreator(QItemEditorCreatorBase): + def createWidget(self, parent): + return GateWayListEditor(parent, ["CTP", "LTS", "XTP", "FEMAS", "XSPEED", "QDP", "KSOTP", "KSGOLD", "SGIT"]) From cd47994617a9769a3359bb154e9b02e8d0531ffd Mon Sep 17 00:00:00 2001 From: "ares89@wind" Date: Fri, 10 Feb 2017 10:19:39 +0800 Subject: [PATCH 11/13] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vn.trader/dataRecorder/drEngine.py | 7 ++++-- vn.trader/dataRecorder/uiDrEdit.py | 37 ++++++++++++++++++++++-------- vn.trader/util/UiUtil.py | 4 ++-- 3 files changed, 34 insertions(+), 14 deletions(-) diff --git a/vn.trader/dataRecorder/drEngine.py b/vn.trader/dataRecorder/drEngine.py index fbcdc92a..bd296e89 100644 --- a/vn.trader/dataRecorder/drEngine.py +++ b/vn.trader/dataRecorder/drEngine.py @@ -55,8 +55,11 @@ class DrEngine(object): """保存设置""" setting['working'] = self.working with open(self.settingFileName, 'w') as f: - str = json.dumps(setting) - f.write(str) + try: + str = json.dumps(setting) + f.write(str) + except: + pass return True #---------------------------------------------------------------------- diff --git a/vn.trader/dataRecorder/uiDrEdit.py b/vn.trader/dataRecorder/uiDrEdit.py index 3592ced1..0a0c20c7 100644 --- a/vn.trader/dataRecorder/uiDrEdit.py +++ b/vn.trader/dataRecorder/uiDrEdit.py @@ -12,7 +12,7 @@ from PyQt4.QtGui import QTreeView from dataRecorder.drEngine import DrEngine from eventEngine import * from uiBasicWidget import QtGui, QtCore -from util.UiUtil import CheckBoxDelegate, GateWayListItemEditorCreator +from util.UiUtil import CheckBoxDelegate, ComboDelegate reload(sys) sys.setdefaultencoding("utf8") @@ -81,16 +81,27 @@ class TreeModel(QtCore.QAbstractItemModel): return self.rootItem.columnCount() def setData(self, index, value, role=None): + item = index.internalPointer() + if item is None: + return False + + if index.column() == 5: + result = item.setData(index.column(), value) + if result: + self.dataChanged.emit(index, index) + # 如果第一条 + if item.parentItem == self.rootItem: + for row in range(item.childCount()): + childIndex = self.index(row, index.column(), index) + self.setData(childIndex, value, QtCore.Qt.DisplayRole) + if index.column() in [1, 2, 3] and role == QtCore.Qt.CheckStateRole: - item = index.internalPointer() - if item is None: - return False result = item.setData(index.column(), True if value == QtCore.Qt.Checked else False) if result: self.dataChanged.emit(index, index) # 如果第一条 - if item.parentItem == self.rootItem: + if item.parentItem == self.rootItem and index.column() in [1, 2]: for row in range(item.childCount()): childIndex = self.index(row, index.column(), index) self.setData(childIndex, value, QtCore.Qt.CheckStateRole) @@ -109,6 +120,9 @@ class TreeModel(QtCore.QAbstractItemModel): item = index.internalPointer() + if role == QtCore.Qt.TextAlignmentRole: + return QtCore.Qt.AlignCenter + if role == QtCore.Qt.CheckStateRole and ( index.column() in [1, 2] or index.column() == 3 and item.parentItem != self.rootItem): return QtCore.Qt.Checked if item.data(index.column()) == True else QtCore.Qt.Unchecked @@ -230,13 +244,12 @@ class DrEditWidget(QtGui.QWidget): self.qTreeView = QTreeView() self.model = TreeModel() self.qTreeView.setModel(self.model) + self.qTreeView.setSelectionMode(QtGui.QAbstractItemView.NoSelection) self.qTreeView.setItemDelegateForColumn(1, CheckBoxDelegate(self)) self.qTreeView.setItemDelegateForColumn(2, CheckBoxDelegate(self)) self.qTreeView.setItemDelegateForColumn(3, CheckBoxDelegate(self)) - - factory = QtGui.QItemEditorFactory() - factory.registerEditor(QtCore.QVariant.Line, GateWayListItemEditorCreator()) - QtGui.QItemEditorFactory.setDefaultFactory(factory) + self.qTreeView.setItemDelegateForColumn(5, ComboDelegate(self, ["CTP", "LTS", "XTP", "FEMAS", "XSPEED", "QDP", + "KSOTP", "KSGOLD", "SGIT"])) vbox.addWidget(self.qTreeView) self.setLayout(vbox) @@ -279,10 +292,14 @@ class DrEditWidget(QtGui.QWidget): contracts = self.mainEngine.getAllContracts() for contract in contracts: contractName = self.getContractChineseName(contract.name) - gateWayName = contract.gatewayName + gateWayName = u"CTP" hasTick = tick.has_key(contract.symbol) hasBar = bar.has_key(contract.symbol) hasActive = contract.symbol in active + if hasTick: + gateWayName = tick[contract.symbol] + elif hasBar: + gateWayName = bar[contract.symbol] if contractDict.has_key(contractName): parentItem = contractDict[contractName] item = TreeItem([contract.symbol, hasTick, hasBar, hasActive, contract.exchange, gateWayName], diff --git a/vn.trader/util/UiUtil.py b/vn.trader/util/UiUtil.py index caf63887..33eab6ac 100644 --- a/vn.trader/util/UiUtil.py +++ b/vn.trader/util/UiUtil.py @@ -104,7 +104,7 @@ class ComboDelegate(QItemDelegate): def createEditor(self, parent, option, index): combo = QComboBox(parent) - + combo.addItems(self.dataList) return combo def setEditorData(self, editor, index): @@ -113,7 +113,7 @@ class ComboDelegate(QItemDelegate): editor.setCurrentIndex(index) def setModelData(self, editor, model, index): - model.setData(index, editor.itemText(editor.currentIndex())) + model.setData(index, str(editor.itemText(editor.currentIndex()))) def updateEditorGeometry(self, editor, option, index): print option, option.rect From 819d54e5d7370471b0d6c9b554f2a98071f7f05c Mon Sep 17 00:00:00 2001 From: "ares89@wind" Date: Fri, 10 Feb 2017 13:47:32 +0800 Subject: [PATCH 12/13] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vn.trader/dataRecorder/drEngine.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vn.trader/dataRecorder/drEngine.py b/vn.trader/dataRecorder/drEngine.py index bd296e89..8d209504 100644 --- a/vn.trader/dataRecorder/drEngine.py +++ b/vn.trader/dataRecorder/drEngine.py @@ -56,7 +56,7 @@ class DrEngine(object): setting['working'] = self.working with open(self.settingFileName, 'w') as f: try: - str = json.dumps(setting) + str = json.dumps(setting, indent=2) f.write(str) except: pass From 8bf76922676b4b032042493191c5e0bb4ddcacbd Mon Sep 17 00:00:00 2001 From: "sunlit@home" Date: Sun, 12 Feb 2017 19:38:03 +0800 Subject: [PATCH 13/13] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vn.trader/dataRecorder/uiDrEdit.py | 8 +++++--- vn.trader/dataRecorder/uiDrWidget.py | 8 +++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/vn.trader/dataRecorder/uiDrEdit.py b/vn.trader/dataRecorder/uiDrEdit.py index 0a0c20c7..1242a225 100644 --- a/vn.trader/dataRecorder/uiDrEdit.py +++ b/vn.trader/dataRecorder/uiDrEdit.py @@ -149,9 +149,11 @@ class TreeModel(QtCore.QAbstractItemModel): return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEditable def headerData(self, section, orientation, role): - if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole: - return self.rootItem.data(section) - + if orientation == QtCore.Qt.Horizontal: + if role == QtCore.Qt.DisplayRole: + return self.rootItem.data(section) + elif role == QtCore.Qt.TextAlignmentRole: + return QtCore.Qt.AlignCenter return None def index(self, row, column, parent): diff --git a/vn.trader/dataRecorder/uiDrWidget.py b/vn.trader/dataRecorder/uiDrWidget.py index f1506686..869f7e1a 100644 --- a/vn.trader/dataRecorder/uiDrWidget.py +++ b/vn.trader/dataRecorder/uiDrWidget.py @@ -100,21 +100,18 @@ class DrEngineManager(QtGui.QWidget): grid.addWidget(self.activeTable, 1, 2) btnEdit = QtGui.QPushButton(u'编辑', self) - btnRestart = QtGui.QPushButton(u'更新数据', self) vbox = QtGui.QVBoxLayout() vbox.addLayout(grid) vline = QtGui.QHBoxLayout() vline.addWidget(btnEdit) - vline.addWidget(btnRestart) vbox.addLayout(vline) vbox.addWidget(self.logMonitor) self.setLayout(vbox) btnEdit.clicked.connect(self.openDr) - btnRestart.clicked.connect(self.restart) #---------------------------------------------------------------------- def updateLog(self, event): @@ -171,11 +168,12 @@ class DrEngineManager(QtGui.QWidget): def openDr(self): """打开行情数据记录组件""" self.mDrEditWidget = DrEditWidget(self,self.mainEngine, self.eventEngine) + self.mDrEditWidget.setWindowTitle(u"编辑订阅") self.mDrEditWidget.setFixedSize(800,800) self.mDrEditWidget.show() def restart(self): - pass - # self.drEngine.stop() + pass + # self.drEngine.stop() # self.updateSetting() # self.mainEngine.drEngine = DrEngine(self.mainEngine, self.mainEngine.eventEngine)