From 027750362a82e8128eae11dec20301a51a7e91cb Mon Sep 17 00:00:00 2001 From: msincenselee Date: Tue, 17 Oct 2017 19:56:32 +0800 Subject: [PATCH] sync 1.7 --- vnpy/trader/uiBasicWidget.py | 306 ++++++++++++++++++++++++----------- vnpy/trader/uiQt.py | 50 +++--- vnpy/trader/util_sina.py | 6 +- vnpy/trader/vtEngine.py | 69 ++++++-- vnpy/trader/vtEvent.py | 2 + vnpy/trader/vtMain.py | 53 +++--- vnpy/trader/vtObject.py | 13 ++ 7 files changed, 340 insertions(+), 159 deletions(-) diff --git a/vnpy/trader/uiBasicWidget.py b/vnpy/trader/uiBasicWidget.py index 53a61b2d..999f1981 100644 --- a/vnpy/trader/uiBasicWidget.py +++ b/vnpy/trader/uiBasicWidget.py @@ -3,22 +3,23 @@ import json import csv import os +import platform from collections import OrderedDict -#from PyQt4 import QtGui, QtCore - from vnpy.trader.vtEvent import * from vnpy.trader.vtFunction import * from vnpy.trader.vtGateway import * import vtText -from vnpy.trader.uiQt import QtGui, QtCore, BASIC_FONT +from vnpy.trader.uiQt import QtWidgets, QtGui, QtCore, BASIC_FONT + +if str(platform.system()) == 'Windows': + import winsound QCOLOR_RED = QtGui.QColor('red') QCOLOR_GREEN = QtGui.QColor('green') - ######################################################################## -class BasicCell(QtGui.QTableWidgetItem): +class BasicCell(QtWidgets.QTableWidgetItem): """基础的单元格""" #---------------------------------------------------------------------- @@ -39,7 +40,7 @@ class BasicCell(QtGui.QTableWidgetItem): ######################################################################## -class NumCell(QtGui.QTableWidgetItem): +class NumCell(QtWidgets.QTableWidgetItem): """用来显示数字的单元格""" # ---------------------------------------------------------------------- @@ -64,7 +65,7 @@ class NumCell(QtGui.QTableWidgetItem): ######################################################################## -class DirectionCell(QtGui.QTableWidgetItem): +class DirectionCell(QtWidgets.QTableWidgetItem): """用来显示买卖方向的单元格""" #---------------------------------------------------------------------- @@ -84,10 +85,8 @@ class DirectionCell(QtGui.QTableWidgetItem): self.setForeground(QtGui.QColor('green')) self.setText(text) - - ######################################################################## -class NameCell(QtGui.QTableWidgetItem): +class NameCell(QtWidgets.QTableWidgetItem): """用来显示合约中文的单元格""" #---------------------------------------------------------------------- @@ -114,7 +113,7 @@ class NameCell(QtGui.QTableWidgetItem): ######################################################################## -class BidCell(QtGui.QTableWidgetItem): +class BidCell(QtWidgets.QTableWidgetItem): """买价单元格""" #---------------------------------------------------------------------- @@ -136,7 +135,7 @@ class BidCell(QtGui.QTableWidgetItem): ######################################################################## -class AskCell(QtGui.QTableWidgetItem): +class AskCell(QtWidgets.QTableWidgetItem): """买价单元格""" #---------------------------------------------------------------------- @@ -157,7 +156,7 @@ class AskCell(QtGui.QTableWidgetItem): self.setText(text) ######################################################################## -class PnlCell(QtGui.QTableWidgetItem): +class PnlCell(QtWidgets.QTableWidgetItem): """显示盈亏的单元格""" # ---------------------------------------------------------------------- @@ -185,7 +184,7 @@ class PnlCell(QtGui.QTableWidgetItem): except ValueError: pass ######################################################################## -class BasicMonitor(QtGui.QTableWidget): +class BasicMonitor(QtWidgets.QTableWidget): """ 基础监控 @@ -193,7 +192,7 @@ class BasicMonitor(QtGui.QTableWidget): {'chinese': u'中文名', 'cellType': BasicCell} """ - signal = QtCore.pyqtSignal(type(Event())) + signal = QtCore.Signal(type(Event())) #---------------------------------------------------------------------- def __init__(self, mainEngine=None, eventEngine=None, parent=None): @@ -351,7 +350,7 @@ class BasicMonitor(QtGui.QTableWidget): #---------------------------------------------------------------------- def resizeColumns(self): """调整各列的大小""" - self.horizontalHeader().resizeSections(QtGui.QHeaderView.ResizeToContents) + self.horizontalHeader().resizeSections(QtWidgets.QHeaderView.ResizeToContents) #---------------------------------------------------------------------- def setSorting(self, sorting): @@ -368,7 +367,7 @@ class BasicMonitor(QtGui.QTableWidget): self.menu.close() # 获取想要保存的文件名 - path = QtGui.QFileDialog.getSaveFileName(self, vtText.SAVE_DATA, '', 'CSV(*.csv)') + path = QtWidgets.QFileDialog.getSaveFileName(self, vtText.SAVE_DATA, '', 'CSV(*.csv)') log = VtLogData() log.gatewayName = u'-' @@ -406,9 +405,9 @@ class BasicMonitor(QtGui.QTableWidget): #---------------------------------------------------------------------- def initMenu(self): """初始化右键菜单""" - self.menu = QtGui.QMenu(self) + self.menu = QtWidgets.QMenu(self) - saveAction = QtGui.QAction(vtText.SAVE_DATA, self) + saveAction = QtWidgets.QAction(vtText.SAVE_DATA, self) saveAction.triggered.connect(self.saveToCsv) self.menu.addAction(saveAction) @@ -514,6 +513,14 @@ class ErrorMonitor(BasicMonitor): self.initTable() self.registerEvent() + self.eventEngine.register(EVENT_TRADE, self.play_trade) + + def play_trade(self, event): + """播放交易声音""" + + # 1.获取事件的Trade数据 + trade = event.dict_['data'] + winsound.PlaySound('warn.wav', winsound.SND_ASYNC) ######################################################################## class TradeMonitor(BasicMonitor): @@ -536,7 +543,8 @@ class TradeMonitor(BasicMonitor): d['tradeTime'] = {'chinese':vtText.TRADE_TIME, 'cellType':BasicCell} d['gatewayName'] = {'chinese':vtText.GATEWAY, 'cellType':BasicCell} self.setHeaderDict(d) - + + self.setDataKey('vtTradeID') self.setEventType(EVENT_TRADE) self.setFont(BASIC_FONT) self.setSorting(True) @@ -544,6 +552,16 @@ class TradeMonitor(BasicMonitor): self.initTable() self.registerEvent() + self.eventEngine.register( EVENT_TRADE, self.play_trade) + + + def play_trade(self, event): + """播放交易声音""" + + # 1.获取事件的Trade数据 + trade = event.dict_['data'] + winsound.PlaySound('match.wav', winsound.SND_ASYNC) + ######################################################################## class OrderMonitor(BasicMonitor): @@ -666,9 +684,9 @@ class AccountMonitor(BasicMonitor): self.registerEvent() ######################################################################## -class TradingWidget(QtGui.QFrame): +class TradingWidget(QtWidgets.QFrame): """简单交易组件""" - signal = QtCore.pyqtSignal(type(Event())) + signal = QtCore.Signal(type(Event())) directionList = [DIRECTION_LONG, DIRECTION_SHORT] @@ -737,55 +755,53 @@ class TradingWidget(QtGui.QFrame): self.setLineWidth(1) # 左边部分 - labelSymbol = QtGui.QLabel(vtText.CONTRACT_SYMBOL) - labelName = QtGui.QLabel(vtText.CONTRACT_NAME) - labelDirection = QtGui.QLabel(vtText.DIRECTION) - labelOffset = QtGui.QLabel(vtText.OFFSET) - labelPrice = QtGui.QLabel(vtText.PRICE) - self.checkFixed = QtGui.QCheckBox(u'') # 价格固定选择框 - labelVolume = QtGui.QLabel(vtText.VOLUME) - labelPriceType = QtGui.QLabel(vtText.PRICE_TYPE) - labelExchange = QtGui.QLabel(vtText.EXCHANGE) - labelCurrency = QtGui.QLabel(vtText.CURRENCY) - labelProductClass = QtGui.QLabel(vtText.PRODUCT_CLASS) - labelGateway = QtGui.QLabel(vtText.GATEWAY) + labelSymbol = QtWidgets.QLabel(vtText.CONTRACT_SYMBOL) + labelName = QtWidgets.QLabel(vtText.CONTRACT_NAME) + labelDirection = QtWidgets.QLabel(vtText.DIRECTION) + labelOffset = QtWidgets.QLabel(vtText.OFFSET) + labelPrice = QtWidgets.QLabel(vtText.PRICE) + self.checkFixed = QtWidgets.QCheckBox(u'') # 价格固定选择框 + labelVolume = QtWidgets.QLabel(vtText.VOLUME) + labelPriceType = QtWidgets.QLabel(vtText.PRICE_TYPE) + labelExchange = QtWidgets.QLabel(vtText.EXCHANGE) + labelCurrency = QtWidgets.QLabel(vtText.CURRENCY) + labelProductClass = QtWidgets.QLabel(vtText.PRODUCT_CLASS) + labelGateway = QtWidgets.QLabel(vtText.GATEWAY) - self.lineSymbol = QtGui.QLineEdit() - self.lineName = QtGui.QLineEdit() + self.lineSymbol = QtWidgets.QLineEdit() + self.lineName = QtWidgets.QLineEdit() - self.comboDirection = QtGui.QComboBox() + self.comboDirection = QtWidgets.QComboBox() self.comboDirection.addItems(self.directionList) - self.comboOffset = QtGui.QComboBox() + self.comboOffset = QtWidgets.QComboBox() self.comboOffset.addItems(self.offsetList) - self.spinPrice = QtGui.QDoubleSpinBox() + self.spinPrice = QtWidgets.QDoubleSpinBox() self.spinPrice.setDecimals(4) self.spinPrice.setMinimum(-10000) # 原来是0,为支持套利,改为-10000 self.spinPrice.setMaximum(100000) - self.spinVolume = QtGui.QSpinBox() + self.spinVolume = QtWidgets.QSpinBox() self.spinVolume.setMinimum(0) self.spinVolume.setMaximum(1000000) - self.comboPriceType = QtGui.QComboBox() + self.comboPriceType = QtWidgets.QComboBox() self.comboPriceType.addItems(self.priceTypeList) - self.comboExchange = QtGui.QComboBox() + self.comboExchange = QtWidgets.QComboBox() self.comboExchange.addItems(self.exchangeList) - self.comboCurrency = QtGui.QComboBox() + self.comboCurrency = QtWidgets.QComboBox() self.comboCurrency.addItems(self.currencyList) - self.comboProductClass = QtGui.QComboBox() + self.comboProductClass = QtWidgets.QComboBox() self.comboProductClass.addItems(self.productClassList) - self.comboGateway = QtGui.QComboBox() + self.comboGateway = QtWidgets.QComboBox() self.comboGateway.addItems(self.gatewayList) - #self.lineOrder = QtGui.QLineEdit() - - gridleft = QtGui.QGridLayout() + gridleft = QtWidgets.QGridLayout() gridleft.addWidget(labelSymbol, 0, 0) gridleft.addWidget(labelName, 1, 0) gridleft.addWidget(labelDirection, 2, 0) @@ -813,48 +829,48 @@ class TradingWidget(QtGui.QFrame): gridleft.addWidget(self.comboGateway, 10, 1, 1, -1) # 右边部分 - labelBid1 = QtGui.QLabel(vtText.BID_1) - labelBid2 = QtGui.QLabel(vtText.BID_2) - labelBid3 = QtGui.QLabel(vtText.BID_3) - labelBid4 = QtGui.QLabel(vtText.BID_4) - labelBid5 = QtGui.QLabel(vtText.BID_5) + labelBid1 = QtWidgets.QLabel(vtText.BID_1) + labelBid2 = QtWidgets.QLabel(vtText.BID_2) + labelBid3 = QtWidgets.QLabel(vtText.BID_3) + labelBid4 = QtWidgets.QLabel(vtText.BID_4) + labelBid5 = QtWidgets.QLabel(vtText.BID_5) - labelAsk1 = QtGui.QLabel(vtText.ASK_1) - labelAsk2 = QtGui.QLabel(vtText.ASK_2) - labelAsk3 = QtGui.QLabel(vtText.ASK_3) - labelAsk4 = QtGui.QLabel(vtText.ASK_4) - labelAsk5 = QtGui.QLabel(vtText.ASK_5) + labelAsk1 = QtWidgets.QLabel(vtText.ASK_1) + labelAsk2 = QtWidgets.QLabel(vtText.ASK_2) + labelAsk3 = QtWidgets.QLabel(vtText.ASK_3) + labelAsk4 = QtWidgets.QLabel(vtText.ASK_4) + labelAsk5 = QtWidgets.QLabel(vtText.ASK_5) - self.labelBidPrice1 = QtGui.QLabel() - self.labelBidPrice2 = QtGui.QLabel() - self.labelBidPrice3 = QtGui.QLabel() - self.labelBidPrice4 = QtGui.QLabel() - self.labelBidPrice5 = QtGui.QLabel() - self.labelBidVolume1 = QtGui.QLabel() - self.labelBidVolume2 = QtGui.QLabel() - self.labelBidVolume3 = QtGui.QLabel() - self.labelBidVolume4 = QtGui.QLabel() - self.labelBidVolume5 = QtGui.QLabel() + self.labelBidPrice1 = QtWidgets.QLabel() + self.labelBidPrice2 = QtWidgets.QLabel() + self.labelBidPrice3 = QtWidgets.QLabel() + self.labelBidPrice4 = QtWidgets.QLabel() + self.labelBidPrice5 = QtWidgets.QLabel() + self.labelBidVolume1 = QtWidgets.QLabel() + self.labelBidVolume2 = QtWidgets.QLabel() + self.labelBidVolume3 = QtWidgets.QLabel() + self.labelBidVolume4 = QtWidgets.QLabel() + self.labelBidVolume5 = QtWidgets.QLabel() - self.labelAskPrice1 = QtGui.QLabel() - self.labelAskPrice2 = QtGui.QLabel() - self.labelAskPrice3 = QtGui.QLabel() - self.labelAskPrice4 = QtGui.QLabel() - self.labelAskPrice5 = QtGui.QLabel() - self.labelAskVolume1 = QtGui.QLabel() - self.labelAskVolume2 = QtGui.QLabel() - self.labelAskVolume3 = QtGui.QLabel() - self.labelAskVolume4 = QtGui.QLabel() - self.labelAskVolume5 = QtGui.QLabel() + self.labelAskPrice1 = QtWidgets.QLabel() + self.labelAskPrice2 = QtWidgets.QLabel() + self.labelAskPrice3 = QtWidgets.QLabel() + self.labelAskPrice4 = QtWidgets.QLabel() + self.labelAskPrice5 = QtWidgets.QLabel() + self.labelAskVolume1 = QtWidgets.QLabel() + self.labelAskVolume2 = QtWidgets.QLabel() + self.labelAskVolume3 = QtWidgets.QLabel() + self.labelAskVolume4 = QtWidgets.QLabel() + self.labelAskVolume5 = QtWidgets.QLabel() - labelLast = QtGui.QLabel(vtText.LAST) - self.labelLastPrice = QtGui.QLabel() - self.labelReturn = QtGui.QLabel() + labelLast = QtWidgets.QLabel(vtText.LAST) + self.labelLastPrice = QtWidgets.QLabel() + self.labelReturn = QtWidgets.QLabel() self.labelLastPrice.setMinimumWidth(60) self.labelReturn.setMinimumWidth(60) - gridRight = QtGui.QGridLayout() + gridRight = QtWidgets.QGridLayout() gridRight.addWidget(labelAsk5, 0, 0) gridRight.addWidget(labelAsk4, 1, 0) gridRight.addWidget(labelAsk3, 2, 0) @@ -892,19 +908,19 @@ class TradingWidget(QtGui.QFrame): gridRight.addWidget(self.labelBidVolume5, 10, 2) # 发单按钮 - buttonSendOrder = QtGui.QPushButton(vtText.SEND_ORDER) - buttonCancelAll = QtGui.QPushButton(vtText.CANCEL_ALL) + buttonSendOrder = QtWidgets.QPushButton(vtText.SEND_ORDER) + buttonCancelAll = QtWidgets.QPushButton(vtText.CANCEL_ALL) size = buttonSendOrder.sizeHint() buttonSendOrder.setMinimumHeight(size.height()*2) # 把按钮高度设为默认两倍 buttonCancelAll.setMinimumHeight(size.height()*2) # 整合布局 - hbox = QtGui.QHBoxLayout() + hbox = QtWidgets.QHBoxLayout() hbox.addLayout(gridleft) hbox.addLayout(gridRight) - vbox = QtGui.QVBoxLayout() + vbox = QtWidgets.QVBoxLayout() vbox.addLayout(hbox) vbox.addWidget(buttonSendOrder) vbox.addWidget(buttonCancelAll) @@ -1202,7 +1218,7 @@ class ContractMonitor(BasicMonitor): #---------------------------------------------------------------------- def addMenuAction(self): """增加右键菜单内容""" - refreshAction = QtGui.QAction(vtText.REFRESH, self) + refreshAction = QtWidgets.QAction(vtText.REFRESH, self) refreshAction.triggered.connect(self.refresh) self.menu.addAction(refreshAction) @@ -1220,7 +1236,7 @@ class ContractMonitor(BasicMonitor): ######################################################################## -class ContractManager(QtGui.QWidget): +class ContractManager(QtWidgets.QWidget): """合约管理组件""" #---------------------------------------------------------------------- @@ -1237,18 +1253,18 @@ class ContractManager(QtGui.QWidget): """初始化界面""" self.setWindowTitle(vtText.CONTRACT_SEARCH) - self.lineFilter = QtGui.QLineEdit() - self.buttonFilter = QtGui.QPushButton(vtText.SEARCH) + self.lineFilter = QtWidgets.QLineEdit() + self.buttonFilter = QtWidgets.QPushButton(vtText.SEARCH) self.buttonFilter.clicked.connect(self.filterContract) self.monitor = ContractMonitor(self.mainEngine) self.monitor.refresh() - hbox = QtGui.QHBoxLayout() + hbox = QtWidgets.QHBoxLayout() hbox.addWidget(self.lineFilter) hbox.addWidget(self.buttonFilter) hbox.addStretch() - vbox = QtGui.QVBoxLayout() + vbox = QtWidgets.QVBoxLayout() vbox.addLayout(hbox) vbox.addWidget(self.monitor) @@ -1261,4 +1277,110 @@ class ContractManager(QtGui.QWidget): self.monitor.setFilterContent(content) self.monitor.refresh() +######################################################################## +class WorkingOrderMonitor(OrderMonitor): + """活动委托监控""" + STATUS_COMPLETED = [STATUS_ALLTRADED, STATUS_CANCELLED, STATUS_REJECTED] + + # ---------------------------------------------------------------------- + def __init__(self, mainEngine, eventEngine, parent=None): + """Constructor""" + super(WorkingOrderMonitor, self).__init__(mainEngine, eventEngine, parent) + + # ---------------------------------------------------------------------- + def updateData(self, data): + """更新数据""" + super(WorkingOrderMonitor, self).updateData(data) + + # 如果该委托已完成,则隐藏该行 + if data.status in self.STATUS_COMPLETED: + vtOrderID = data.vtOrderID + cellDict = self.dataDict[vtOrderID] + cell = cellDict['status'] + row = self.row(cell) + self.hideRow(row) + + +######################################################################## +class SettingEditor(QtWidgets.QWidget): + """配置编辑器""" + + # ---------------------------------------------------------------------- + def __init__(self, mainEngine, parent=None): + """Constructor""" + super(SettingEditor, self).__init__(parent) + + self.mainEngine = mainEngine + self.currentFileName = '' + + self.initUi() + + # ---------------------------------------------------------------------- + def initUi(self): + """初始化界面""" + self.setWindowTitle(vtText.EDIT_SETTING) + + self.comboFileName = QtWidgets.QComboBox() + self.comboFileName.addItems(jsonPathDict.keys()) + + buttonLoad = QtWidgets.QPushButton(vtText.LOAD) + buttonSave = QtWidgets.QPushButton(vtText.SAVE) + buttonLoad.clicked.connect(self.loadSetting) + buttonSave.clicked.connect(self.saveSetting) + + self.editSetting = QtWidgets.QTextEdit() + self.labelPath = QtWidgets.QLabel() + + hbox = QtWidgets.QHBoxLayout() + hbox.addWidget(self.comboFileName) + hbox.addWidget(buttonLoad) + hbox.addWidget(buttonSave) + hbox.addStretch() + + vbox = QtWidgets.QVBoxLayout() + vbox.addLayout(hbox) + vbox.addWidget(self.editSetting) + vbox.addWidget(self.labelPath) + + self.setLayout(vbox) + + # ---------------------------------------------------------------------- + def loadSetting(self): + """加载配置""" + self.currentFileName = str(self.comboFileName.currentText()) + filePath = jsonPathDict[self.currentFileName] + self.labelPath.setText(filePath) + + with open(filePath) as f: + self.editSetting.clear() + + for line in f: + line = line.replace('\n', '') # 移除换行符号 + line = line.decode('UTF-8') + self.editSetting.append(line) + + # ---------------------------------------------------------------------- + def saveSetting(self): + """保存配置""" + if not self.currentFileName: + return + + filePath = jsonPathDict[self.currentFileName] + + with open(filePath, 'w') as f: + content = self.editSetting.toPlainText() + content = content.encode('UTF-8') + f.write(content) + + # ---------------------------------------------------------------------- + def show(self): + """显示""" + # 更新配置文件下拉框 + self.comboFileName.clear() + self.comboFileName.addItems(jsonPathDict.keys()) + + # 显示界面 + super(SettingEditor, self).show() + + diff --git a/vnpy/trader/uiQt.py b/vnpy/trader/uiQt.py index 3efd3d69..ad28b19d 100644 --- a/vnpy/trader/uiQt.py +++ b/vnpy/trader/uiQt.py @@ -2,35 +2,43 @@ import platform -from PyQt4 import QtGui, QtCore +from qtpy import QtWidgets, QtGui, QtCore from vnpy.trader.vtGlobal import globalSetting from vnpy.trader.vtFunction import loadIconPath -# 创建Qt应用对象 -qApp = QtGui.QApplication([]) - -# 设置Qt的皮肤 -if globalSetting['darkStyle']: - try: - import qdarkstyle - qApp.setStyleSheet(qdarkstyle.load_stylesheet(pyside=False)) - except ImportError: - pass - -# 设置Windows底部任务栏图标 -if 'Windows' in platform.uname(): - import ctypes - ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID('vn.trader') - -# 设置Qt字体 +BASIC_FONT = None try: family = globalSetting['fontFamily'] size = globalSetting['fontSize'] BASIC_FONT = QtGui.QFont(family, size) except: BASIC_FONT = QtGui.QFont(u'微软雅黑', 12) -qApp.setFont(BASIC_FONT) -# 设置Qt图标 -qApp.setWindowIcon(QtGui.QIcon(loadIconPath('vnpy.ico'))) \ No newline at end of file +#---------------------------------------------------------------------- +def createQApp(): + """创建PyQt应用对象""" + # 创建Qt应用对象 + qApp = QtWidgets.QApplication([]) + + # 设置Qt的皮肤 + if globalSetting['darkStyle']: + try: + import qdarkstyle + qApp.setStyleSheet(qdarkstyle.load_stylesheet(pyside=False)) + except ImportError: + pass + + # 设置Windows底部任务栏图标 + if 'Windows' in platform.uname(): + import ctypes + ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID('vn.trader') + + # 设置Qt字体 + qApp.setFont(BASIC_FONT) + + # 设置Qt图标 + qApp.setWindowIcon(QtGui.QIcon(loadIconPath('vnpy.ico'))) + + # 返回创建好的QApp对象 + return qApp \ No newline at end of file diff --git a/vnpy/trader/util_sina.py b/vnpy/trader/util_sina.py index cfba904b..0faa6fcd 100644 --- a/vnpy/trader/util_sina.py +++ b/vnpy/trader/util_sina.py @@ -372,13 +372,13 @@ if __name__ == '__main__': sina = UtilSinaClient(t) - #rt=sina.getDayBars(symbol='RB1705', callback=t.addBar) + rt=sina.getDayBars(symbol='RB1710', callback=t.addBar) - #rt = sina.getMinBars(symbol='RB1705',minute = 5, callback=t.addBar) + rt = sina.getMinBars(symbol='RB1710',minute = 60, callback=t.addBar) #rt = sina.getTicks(symbol='RB1705', callback=t.addTick) #rt = sina.getTicks2(symbol='TF1706', callback=t.addTick) #rt = sina.getTicks3(symbol='TF1709', callback=t.addTick) - rt = sina.getMinBars2(symbol='TF1709',minute=60, callback=t.addBar) \ No newline at end of file + #rt = sina.getMinBars2(symbol='TF1709',minute=60, callback=t.addBar) \ No newline at end of file diff --git a/vnpy/trader/vtEngine.py b/vnpy/trader/vtEngine.py index a8efceae..f0637133 100644 --- a/vnpy/trader/vtEngine.py +++ b/vnpy/trader/vtEngine.py @@ -11,9 +11,9 @@ from pymongo.errors import ConnectionFailure from vnpy.trader.vtEvent import Event as vn_event from vnpy.trader.language import text -from vnpy.trader.app.ctaStrategy.ctaEngine import CtaEngine -from vnpy.trader.app.dataRecorder.drEngine import DrEngine -from vnpy.trader.app.riskManager.rmEngine import RmEngine +#from vnpy.trader.app.ctaStrategy.ctaEngine import CtaEngine +#from vnpy.trader.app.dataRecorder.drEngine import DrEngine +#from vnpy.trader.app.riskManager.rmEngine import RmEngine from vnpy.trader.vtFunction import loadMongoSetting from vnpy.trader.vtGateway import * @@ -27,13 +27,13 @@ class MainEngine(object): """主引擎""" #---------------------------------------------------------------------- - def __init__(self): + def __init__(self, eventEngine): """Constructor""" # 记录今日日期 self.todayDate = datetime.now().strftime('%Y%m%d') # 创建事件引擎 - self.eventEngine = EventEngine2() + self.eventEngine = eventEngine self.eventEngine.start() # 创建数据引擎 @@ -51,9 +51,9 @@ class MainEngine(object): self.appDetailList = [] # 扩展模块 - self.ctaEngine = CtaEngine(self, self.eventEngine) # cta策略运行模块 - self.drEngine = DrEngine(self, self.eventEngine) # 数据记录模块 - self.rmEngine = RmEngine(self, self.eventEngine) # 风险管理模块 + self.ctaEngine = None # CtaEngine(self, self.eventEngine) # cta策略运行模块 + self.drEngine = None # DrEngine(self, self.eventEngine) # 数据记录模块 + self.rmEngine = None # RmEngine(self, self.eventEngine) # 风险管理模块 self.connected_gw_name = u'' # ---------------------------------------------------------------------- @@ -75,8 +75,8 @@ class MainEngine(object): # 保存接口详细信息 d = { - 'gatewayName': gatewayModule.gatewayName, - 'gatewayDisplayName': gatewayModule.gatewayDisplayName, + 'gatewayName': gatewayName, #gatewayModule.gatewayName, + 'gatewayDisplayName': gatewayName, #gatewayModule.gatewayDisplayName, 'gatewayType': gatewayModule.gatewayType } self.gatewayDetailList.append(d) @@ -84,6 +84,26 @@ class MainEngine(object): if gateway_name != self.connected_gw_name: self.connected_gw_name = gateway_name + # ---------------------------------------------------------------------- + def addApp(self, appModule): + """添加上层应用""" + appName = appModule.appName + + # 创建应用实例 + self.appDict[appName] = appModule.appEngine(self, self.eventEngine) + + # 将应用引擎实例添加到主引擎的属性中 + self.__dict__[appName] = self.appDict[appName] + + # 保存应用信息 + d = { + 'appName': appModule.appName, + 'appDisplayName': appModule.appDisplayName, + 'appWidget': appModule.appWidget, + 'appIco': appModule.appIco + } + self.appDetailList.append(d) + # ---------------------------------------------------------------------- def connect(self, gatewayName): """连接特定名称的接口""" @@ -96,11 +116,9 @@ class MainEngine(object): # 接口连接后自动执行数据库连接的任务 self.dbConnect() - return True else: self.writeLog(text.GATEWAY_NOT_EXIST.format(gateway=gatewayName)) - return False def checkGatewayStatus(self,gatewayName): @@ -150,7 +168,7 @@ class MainEngine(object): def sendOrder(self, orderReq, gatewayName): """对特定接口发单""" # 如果风控检查失败则不发单 - if not self.rmEngine.checkRisk(orderReq): + if self.rmEngine and not self.rmEngine.checkRisk(orderReq): self.writeCritical(u'风控检查不通过') return '' @@ -183,8 +201,12 @@ class MainEngine(object): # Added by IncenseLee 仅支持一个账号。不支持多账号 以后支持跨市场套利才更新吧。 + return 当前账号的权益、可用资金、当前仓位比例, 投资仓位比例上限 """ - return self.rmEngine.getAccountInfo() + if self.rmEngine: + return self.rmEngine.getAccountInfo() + else: + return 0, 0, 0, 0 # ---------------------------------------------------------------------- def qryPosition(self, gatewayName): @@ -206,7 +228,8 @@ class MainEngine(object): self.eventEngine.stop() # 停止数据记录引擎 - self.drEngine.stop() + if self.drEngine: + self.drEngine.stop() # 保存数据引擎里的合约数据到硬盘 self.dataEngine.saveContracts() @@ -400,6 +423,22 @@ class MainEngine(object): def getAllGatewayNames(self): """查询引擎中所有可用接口的名称""" return self.gatewayDict.keys() + # ---------------------------------------------------------------------- + + def getAllGatewayDetails(self): + """查询引擎中所有底层接口的信息""" + return self.gatewayDetailList + + # ---------------------------------------------------------------------- + + def getAllAppDetails(self): + """查询引擎中所有上层应用的信息""" + return self.appDetailList + + # ---------------------------------------------------------------------- + def getApp(self, appName): + """获取APP引擎对象""" + return self.appDict[appName] def clearData(self): """清空数据引擎的数据""" diff --git a/vnpy/trader/vtEvent.py b/vnpy/trader/vtEvent.py index 8e9a7f40..63af6a04 100644 --- a/vnpy/trader/vtEvent.py +++ b/vnpy/trader/vtEvent.py @@ -35,6 +35,8 @@ EVENT_ON_BAR = 'eOnBar' # OnBar事件 EVENT_WARNING = 'eWarning' # 全局告警信息 EVENT_CRITICAL = 'eCritical' # 全局严重信息 EVENT_NOTIFICATION = 'eNotification' # 全局通知 +EVENT_SIGNAL = 'eSignal' # 信号通知 +EVENT_STATUS = 'eStatus' # 服务状态 # CTA模块相关 EVENT_CTA_LOG = 'eCtaLog' # CTA相关的日志事件 diff --git a/vnpy/trader/vtMain.py b/vnpy/trader/vtMain.py index 2661ec40..5bf63eac 100644 --- a/vnpy/trader/vtMain.py +++ b/vnpy/trader/vtMain.py @@ -1,22 +1,31 @@ # encoding: UTF-8 + +# 重载sys模块,设置默认字符串编码方式为utf8 +import sys +reload(sys) +sys.setdefaultencoding('utf8') + import sys import os import ctypes import platform +system = platform.system() # 将repostory的目录,作为根目录,添加到系统环境中。 ROOT_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..' , '..')) sys.path.append(ROOT_PATH) from vnpy.trader.vtEngine import MainEngine -from vnpy.trader.uiQt import qApp +from vnpy.trader.uiQt import createQApp from vnpy.trader.uiMainWindow import * # 加载底层接口 from vnpy.trader.gateway import ctpGateway -# 初始化的接口模块,以及其指定的名称,CTP是模块,value,是该模块下的多个连接配置文件,如 CTP_JR_connect.json -init_gateway_names = {'CTP': ['CTP', 'CTP_Prod', 'CTP_Post', 'CTP_EBF', 'CTP_JR', 'CTP_JR2']} +# 初始化的接口模块,以及其指定的名称,CTP是模块,value,是该模块下的多个连接配置文件,如 CTP_JR_connect.json 'CTP_Prod', 'CTP_JR', , 'CTP_JK', 'CTP_02' +init_gateway_names = {'CTP': ['CTP','CTP_YH01', 'CTP_YH02', 'CTP_YHHZQQ','CTP_JR2']} + +from vnpy.trader.app import (ctaStrategy, riskManager, spreadTrading) # 文件路径名 path = os.path.abspath(os.path.dirname(__file__)) @@ -24,43 +33,31 @@ ICON_FILENAME = 'vnpy.ico' ICON_FILENAME = os.path.join(path, ICON_FILENAME) from vnpy.trader.setup_logger import setup_logger -setup_logger(filename='logs/vnpy_{0}.log'.format(datetime.now().strftime('%m%d_%H%M')), debug=False) +setup_logger(filename='logs/vnpy.log', debug=False) # ---------------------------------------------------------------------- def main(): """主程序入口""" - # 重载sys模块,设置默认字符串编码方式为utf8 - reload(sys) - sys.setdefaultencoding('utf8') + # 创建Qt应用对象 + qApp = createQApp() - """ - # 设置Windows底部任务栏图标 - if 'Windows' in platform.uname(): - ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID('vn.trader') + # 创建事件引擎 + ee = EventEngine2() - # 初始化Qt应用对象 - app = QtGui.QApplication(sys.argv) - app.setWindowIcon(QtGui.QIcon(ICON_FILENAME)) - app.setFont(BASIC_FONT) - - # 设置Qt的皮肤 - try: - from vnpy.trader.vtGlobal import globalSetting - if globalSetting['darkStyle']: - import qdarkstyle - app.setStyleSheet(qdarkstyle.load_stylesheet(pyside=False)) - - except: - pass - """ # 初始化主引擎和主窗口对象 - mainEngine = MainEngine() + mainEngine = MainEngine(ee) + # 添加Gatway for gw_name in init_gateway_names['CTP']: print 'add {0}'.format(gw_name) mainEngine.addGateway(ctpGateway, gw_name) - mainWindow = MainWindow(mainEngine, mainEngine.eventEngine) + # 添加应用 + mainEngine.addApp(ctaStrategy) + mainEngine.addApp(riskManager) + mainEngine.addApp(spreadTrading) + + mainWindow = MainWindow(mainEngine, ee) mainWindow.showMaximized() # 在主线程中启动Qt事件循环 diff --git a/vnpy/trader/vtObject.py b/vnpy/trader/vtObject.py index e35c8ea1..89dd0ede 100644 --- a/vnpy/trader/vtObject.py +++ b/vnpy/trader/vtObject.py @@ -241,6 +241,19 @@ class VtLogData(VtBaseData): self.logTime = datetime.now().strftime('%X:%f') self.logContent = EMPTY_UNICODE # 日志信息 +class VtSignalData(VtBaseData): + """信号数据类""" + + # ---------------------------------------------------------------------- + def __init__(self): + super(VtSignalData, self).__init__() + self.time = datetime.now().strftime('%X:%f') + self.source = EMPTY_STRING # 来源 + self.symbol = EMPTY_STRING # 合约信息 + self.direction = EMPTY_STRING #信号方向 + self.price = EMPTY_FLOAT # 信号价格 + self.level = EMPTY_INT # 0 普通信号,1,强信号 + ######################################################################## class VtContractData(VtBaseData):