commit
f2dba02243
@ -1,30 +1,90 @@
|
|||||||
{
|
{
|
||||||
"working": false,
|
"working": true,
|
||||||
|
"tick": [
|
||||||
"tick":
|
|
||||||
[
|
[
|
||||||
["m1609", "XSPEED"],
|
"au1706",
|
||||||
["IF1606", "SGIT"],
|
"CTP"
|
||||||
["IH1606", "SGIT"],
|
|
||||||
["IH1606", "SGIT"],
|
|
||||||
["IC1606", "SGIT"],
|
|
||||||
["IC1606", "SGIT"],
|
|
||||||
["600036", "LTS", "SZSE"],
|
|
||||||
["EUR.USD", "IB", "IDEALPRO", "USD", "外汇"]
|
|
||||||
],
|
],
|
||||||
|
|
||||||
"bar":
|
|
||||||
[
|
[
|
||||||
["IF1605", "SGIT"],
|
"a1705",
|
||||||
["IF1606", "SGIT"],
|
"CTP"
|
||||||
["IH1606", "SGIT"],
|
|
||||||
["IH1606", "SGIT"],
|
|
||||||
["IC1606", "SGIT"],
|
|
||||||
["IC1606", "SGIT"]
|
|
||||||
],
|
],
|
||||||
|
[
|
||||||
"active":
|
"m1705",
|
||||||
{
|
"CTP"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"bu1706",
|
||||||
|
"CTP"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"SR705",
|
||||||
|
"CTP"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"TA705",
|
||||||
|
"CTP"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"MA705",
|
||||||
|
"CTP"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"RM705",
|
||||||
|
"CTP"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"FG705",
|
||||||
|
"CTP"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"OI705",
|
||||||
|
"CTP"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"bar": [
|
||||||
|
[
|
||||||
|
"au1706",
|
||||||
|
"CTP"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"a1705",
|
||||||
|
"CTP"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"m1705",
|
||||||
|
"CTP"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"bu1706",
|
||||||
|
"CTP"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"SR705",
|
||||||
|
"CTP"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"TA705",
|
||||||
|
"CTP"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"MA705",
|
||||||
|
"CTP"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"RM705",
|
||||||
|
"CTP"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"FG705",
|
||||||
|
"CTP"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"OI705",
|
||||||
|
"CTP"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"active": {
|
||||||
"IF0000": "IF1605",
|
"IF0000": "IF1605",
|
||||||
"IH0000": "IH1605",
|
"IH0000": "IH1605",
|
||||||
"IC0000": "IC1605"
|
"IC0000": "IC1605"
|
||||||
|
@ -6,18 +6,15 @@
|
|||||||
使用DR_setting.json来配置需要收集的合约,以及主力合约代码。
|
使用DR_setting.json来配置需要收集的合约,以及主力合约代码。
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
import copy
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import copy
|
from datetime import datetime
|
||||||
from collections import OrderedDict
|
|
||||||
from datetime import datetime, timedelta
|
|
||||||
from Queue import Queue
|
|
||||||
from threading import Thread
|
|
||||||
|
|
||||||
from eventEngine import *
|
|
||||||
from vtGateway import VtSubscribeReq, VtLogData
|
|
||||||
from drBase import *
|
from drBase import *
|
||||||
|
from eventEngine import *
|
||||||
from vtFunction import todayDate
|
from vtFunction import todayDate
|
||||||
|
from vtGateway import VtSubscribeReq, VtLogData
|
||||||
|
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
@ -54,6 +51,17 @@ class DrEngine(object):
|
|||||||
# 载入设置,订阅行情
|
# 载入设置,订阅行情
|
||||||
self.loadSetting()
|
self.loadSetting()
|
||||||
|
|
||||||
|
def saveSetting(self, setting):
|
||||||
|
"""保存设置"""
|
||||||
|
setting['working'] = self.working
|
||||||
|
with open(self.settingFileName, 'w') as f:
|
||||||
|
try:
|
||||||
|
str = json.dumps(setting, indent=2)
|
||||||
|
f.write(str)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
return True
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def loadSetting(self):
|
def loadSetting(self):
|
||||||
"""载入设置"""
|
"""载入设置"""
|
||||||
@ -61,8 +69,8 @@ class DrEngine(object):
|
|||||||
drSetting = json.load(f)
|
drSetting = json.load(f)
|
||||||
|
|
||||||
# 如果working设为False则不启动行情记录功能
|
# 如果working设为False则不启动行情记录功能
|
||||||
working = drSetting['working']
|
self.working = drSetting['working']
|
||||||
if not working:
|
if not self.working:
|
||||||
return
|
return
|
||||||
|
|
||||||
if 'tick' in drSetting:
|
if 'tick' in drSetting:
|
||||||
|
400
vn.trader/dataRecorder/uiDrEdit.py
Normal file
400
vn.trader/dataRecorder/uiDrEdit.py
Normal file
@ -0,0 +1,400 @@
|
|||||||
|
# encoding: UTF-8
|
||||||
|
|
||||||
|
'''
|
||||||
|
行情记录模块相关的GUI控制组件
|
||||||
|
'''
|
||||||
|
import json
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from PyQt4.QtGui import QTreeView
|
||||||
|
|
||||||
|
from dataRecorder.drEngine import DrEngine
|
||||||
|
from eventEngine import *
|
||||||
|
from uiBasicWidget import QtGui, QtCore
|
||||||
|
from util.UiUtil import CheckBoxDelegate, ComboDelegate
|
||||||
|
|
||||||
|
reload(sys)
|
||||||
|
sys.setdefaultencoding("utf8")
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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"主力", u"交易所", 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 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:
|
||||||
|
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 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)
|
||||||
|
|
||||||
|
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():
|
||||||
|
return None
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
if role != QtCore.Qt.DisplayRole or index.column() in [3, 4] and item.parentItem == self.rootItem:
|
||||||
|
return None
|
||||||
|
|
||||||
|
return item.data(index.column())
|
||||||
|
|
||||||
|
def flags(self, index):
|
||||||
|
if not index.isValid():
|
||||||
|
return QtCore.Qt.NoItemFlags
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEditable
|
||||||
|
|
||||||
|
def headerData(self, section, orientation, role):
|
||||||
|
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):
|
||||||
|
if not self.hasIndex(row, column, parent):
|
||||||
|
return QtCore.QModelIndex()
|
||||||
|
|
||||||
|
if parent is None or 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()
|
||||||
|
|
||||||
|
def hasIndex(self, row, column, parentIndex=None, *args, **kwargs):
|
||||||
|
if row < 0 or column > self.rootItem.columnCount():
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
class DrEditWidget(QtGui.QWidget):
|
||||||
|
"""行情数据记录引擎管理组件"""
|
||||||
|
signal = QtCore.pyqtSignal(type(Event()))
|
||||||
|
|
||||||
|
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 = {}
|
||||||
|
|
||||||
|
self.initUi()
|
||||||
|
self.updateSetting()
|
||||||
|
self.loadData()
|
||||||
|
self.registerEvent()
|
||||||
|
|
||||||
|
def closeEvent(self, QCloseEvent):
|
||||||
|
if self.hasChanged:
|
||||||
|
self.drWidget.restart()
|
||||||
|
|
||||||
|
def initUi(self):
|
||||||
|
|
||||||
|
vbox = QtGui.QVBoxLayout()
|
||||||
|
|
||||||
|
vline = QtGui.QHBoxLayout()
|
||||||
|
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)
|
||||||
|
|
||||||
|
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))
|
||||||
|
self.qTreeView.setItemDelegateForColumn(5, ComboDelegate(self, ["CTP", "LTS", "XTP", "FEMAS", "XSPEED", "QDP",
|
||||||
|
"KSOTP", "KSGOLD", "SGIT"]))
|
||||||
|
|
||||||
|
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 = []
|
||||||
|
|
||||||
|
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 = 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],
|
||||||
|
parentItem)
|
||||||
|
parentItem.appendChild(item)
|
||||||
|
else:
|
||||||
|
item = TreeItem([contractName, False, False, False, contract.exchange, gateWayName],
|
||||||
|
self.model.rootItem)
|
||||||
|
contractDict[contractName] = item
|
||||||
|
child.append(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)
|
||||||
|
# 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.hasChanged = True
|
||||||
|
self.close()
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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(None, DrEngine, EventEngine)
|
||||||
|
view.setFixedSize(650, 500)
|
||||||
|
view.show()
|
||||||
|
sys.exit(app.exec_())
|
@ -6,8 +6,9 @@
|
|||||||
|
|
||||||
import json
|
import json
|
||||||
|
|
||||||
from uiBasicWidget import QtGui, QtCore
|
from dataRecorder.uiDrEdit import DrEditWidget
|
||||||
from eventEngine import *
|
from eventEngine import *
|
||||||
|
from uiBasicWidget import QtGui, QtCore
|
||||||
|
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
@ -38,11 +39,12 @@ class DrEngineManager(QtGui.QWidget):
|
|||||||
signal = QtCore.pyqtSignal(type(Event()))
|
signal = QtCore.pyqtSignal(type(Event()))
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def __init__(self, drEngine, eventEngine, parent=None):
|
def __init__(self, mainEngine, eventEngine, parent=None):
|
||||||
"""Constructor"""
|
"""Constructor"""
|
||||||
super(DrEngineManager, self).__init__(parent)
|
super(DrEngineManager, self).__init__(parent)
|
||||||
|
|
||||||
self.drEngine = drEngine
|
self.mainEngine = mainEngine
|
||||||
|
self.drEngine = mainEngine.drEngine
|
||||||
self.eventEngine = eventEngine
|
self.eventEngine = eventEngine
|
||||||
|
|
||||||
self.initUi()
|
self.initUi()
|
||||||
@ -97,11 +99,20 @@ class DrEngineManager(QtGui.QWidget):
|
|||||||
grid.addWidget(self.barTable, 1, 1)
|
grid.addWidget(self.barTable, 1, 1)
|
||||||
grid.addWidget(self.activeTable, 1, 2)
|
grid.addWidget(self.activeTable, 1, 2)
|
||||||
|
|
||||||
|
btnEdit = QtGui.QPushButton(u'编辑', self)
|
||||||
|
|
||||||
vbox = QtGui.QVBoxLayout()
|
vbox = QtGui.QVBoxLayout()
|
||||||
vbox.addLayout(grid)
|
vbox.addLayout(grid)
|
||||||
|
|
||||||
|
vline = QtGui.QHBoxLayout()
|
||||||
|
vline.addWidget(btnEdit)
|
||||||
|
|
||||||
|
vbox.addLayout(vline)
|
||||||
vbox.addWidget(self.logMonitor)
|
vbox.addWidget(self.logMonitor)
|
||||||
self.setLayout(vbox)
|
self.setLayout(vbox)
|
||||||
|
|
||||||
|
btnEdit.clicked.connect(self.openDr)
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def updateLog(self, event):
|
def updateLog(self, event):
|
||||||
"""更新日志"""
|
"""更新日志"""
|
||||||
@ -118,6 +129,14 @@ class DrEngineManager(QtGui.QWidget):
|
|||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def updateSetting(self):
|
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:
|
with open(self.drEngine.settingFileName) as f:
|
||||||
drSetting = json.load(f)
|
drSetting = json.load(f)
|
||||||
|
|
||||||
@ -145,11 +164,16 @@ class DrEngineManager(QtGui.QWidget):
|
|||||||
self.activeTable.setItem(0, 0, TableCell(activeSymbol))
|
self.activeTable.setItem(0, 0, TableCell(activeSymbol))
|
||||||
self.activeTable.setItem(0, 1, TableCell(symbol))
|
self.activeTable.setItem(0, 1, TableCell(symbol))
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
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()
|
||||||
|
# self.updateSetting()
|
||||||
|
# self.mainEngine.drEngine = DrEngine(self.mainEngine, self.mainEngine.eventEngine)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
# encoding: UTF-8
|
# encoding: UTF-8
|
||||||
|
|
||||||
import json
|
|
||||||
import csv
|
import csv
|
||||||
import os
|
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
from PyQt4 import QtGui, QtCore
|
from PyQt4 import QtGui, QtCore
|
||||||
|
from PyQt4.QtCore import Qt
|
||||||
|
|
||||||
from eventEngine import *
|
|
||||||
from vtFunction import *
|
from vtFunction import *
|
||||||
from vtGateway import *
|
from vtGateway import *
|
||||||
|
|
||||||
@ -53,6 +51,22 @@ class BasicCell(QtGui.QTableWidgetItem):
|
|||||||
self.setText(text)
|
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):
|
class NumCell(QtGui.QTableWidgetItem):
|
||||||
"""用来显示数字的单元格"""
|
"""用来显示数字的单元格"""
|
||||||
@ -431,7 +445,7 @@ class MarketMonitor(BasicMonitor):
|
|||||||
self.setFont(BASIC_FONT)
|
self.setFont(BASIC_FONT)
|
||||||
|
|
||||||
# 设置允许排序
|
# 设置允许排序
|
||||||
self.setSorting(True)
|
self.setSorting(False)
|
||||||
|
|
||||||
# 初始化表格
|
# 初始化表格
|
||||||
self.initTable()
|
self.initTable()
|
||||||
@ -1116,8 +1130,10 @@ class ContractMonitor(BasicMonitor):
|
|||||||
contract = d[key]
|
contract = d[key]
|
||||||
|
|
||||||
for n, header in enumerate(self.headerList):
|
for n, header in enumerate(self.headerList):
|
||||||
content = safeUnicode(contract.__getattribute__(header))
|
|
||||||
cellType = self.headerDict[header]['cellType']
|
cellType = self.headerDict[header]['cellType']
|
||||||
|
content = None
|
||||||
|
if (hasattr(contract, header)):
|
||||||
|
content = safeUnicode(contract.__getattribute__(header))
|
||||||
cell = cellType(content)
|
cell = cellType(content)
|
||||||
|
|
||||||
if self.font:
|
if self.font:
|
||||||
|
@ -2,10 +2,10 @@
|
|||||||
|
|
||||||
import psutil
|
import psutil
|
||||||
|
|
||||||
from uiBasicWidget import *
|
|
||||||
from ctaAlgo.uiCtaWidget import CtaEngineManager
|
from ctaAlgo.uiCtaWidget import CtaEngineManager
|
||||||
from dataRecorder.uiDrWidget import DrEngineManager
|
from dataRecorder.uiDrWidget import DrEngineManager
|
||||||
from riskManager.uiRmWidget import RmEngineManager
|
from riskManager.uiRmWidget import RmEngineManager
|
||||||
|
from uiBasicWidget import *
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
class MainWindow(QtGui.QMainWindow):
|
class MainWindow(QtGui.QMainWindow):
|
||||||
@ -197,7 +197,7 @@ class MainWindow(QtGui.QMainWindow):
|
|||||||
try:
|
try:
|
||||||
self.widgetDict['drM'].showMaximized()
|
self.widgetDict['drM'].showMaximized()
|
||||||
except KeyError:
|
except KeyError:
|
||||||
self.widgetDict['drM'] = DrEngineManager(self.mainEngine.drEngine, self.eventEngine)
|
self.widgetDict['drM'] = DrEngineManager(self.mainEngine, self.eventEngine)
|
||||||
self.widgetDict['drM'].showMaximized()
|
self.widgetDict['drM'].showMaximized()
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
|
144
vn.trader/util/UiUtil.py
Normal file
144
vn.trader/util/UiUtil.py
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
from PyQt4 import QtCore
|
||||||
|
from PyQt4.QtGui import QStyle, QStyledItemDelegate, QStyleOptionButton, QApplication, QItemDelegate, QComboBox, \
|
||||||
|
QItemEditorCreatorBase
|
||||||
|
|
||||||
|
|
||||||
|
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())
|
||||||
|
|
||||||
|
|
||||||
|
class ComboDelegate(QItemDelegate):
|
||||||
|
def __init__(self, parent, dataList=[]):
|
||||||
|
QItemDelegate.__init__(self, parent)
|
||||||
|
self.dataList = dataList
|
||||||
|
|
||||||
|
def createEditor(self, parent, option, index):
|
||||||
|
combo = QComboBox(parent)
|
||||||
|
combo.addItems(self.dataList)
|
||||||
|
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, str(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"])
|
0
vn.trader/util/__init__.py
Normal file
0
vn.trader/util/__init__.py
Normal file
Loading…
Reference in New Issue
Block a user