diff --git a/vnpy/trader/app/ctaStrategy/uiCtaWidget.py b/vnpy/trader/app/ctaStrategy/uiCtaWidget.py index d9e8531b..62366a89 100644 --- a/vnpy/trader/app/ctaStrategy/uiCtaWidget.py +++ b/vnpy/trader/app/ctaStrategy/uiCtaWidget.py @@ -268,13 +268,14 @@ class CtaEngineManager(QtWidgets.QWidget): #---------------------------------------------------------------------- def closeEvent(self, event): """关闭窗口时的事件""" - reply = QtWidgets.QMessageBox.question(self, text.SAVE_POSITION_DATA, - text.SAVE_POSITION_QUESTION, QtWidgets.QMessageBox.Yes | - QtWidgets.QMessageBox.No, QtWidgets.QMessageBox.No) - - if reply == QtWidgets.QMessageBox.Yes: - self.ctaEngine.savePosition() - + if self.isVisible(): + reply = QtWidgets.QMessageBox.question(self, text.SAVE_POSITION_DATA, + text.SAVE_POSITION_QUESTION, QtWidgets.QMessageBox.Yes | + QtWidgets.QMessageBox.No, QtWidgets.QMessageBox.No) + + if reply == QtWidgets.QMessageBox.Yes: + self.ctaEngine.savePosition() + event.accept() diff --git a/vnpy/trader/app/spreadTrading/stBase.py b/vnpy/trader/app/spreadTrading/stBase.py index 9297b764..64f0f00f 100644 --- a/vnpy/trader/app/spreadTrading/stBase.py +++ b/vnpy/trader/app/spreadTrading/stBase.py @@ -11,6 +11,8 @@ from vnpy.trader.vtConstant import (EMPTY_INT, EMPTY_FLOAT, EVENT_SPREADTRADING_TICK = 'eSpreadTradingTick.' +EVENT_SPREADTRADING_POS = 'eSpreadTradingPos.' +EVENT_SPREADTRADING_LOG = 'eSpreadTradingLog' diff --git a/vnpy/trader/app/spreadTrading/stEngine.py b/vnpy/trader/app/spreadTrading/stEngine.py index d5f38a9b..4ce43a52 100644 --- a/vnpy/trader/app/spreadTrading/stEngine.py +++ b/vnpy/trader/app/spreadTrading/stEngine.py @@ -1,14 +1,18 @@ # encoding: UTF-8 import json +import traceback from copy import copy from vnpy.event import Event from vnpy.trader.vtFunction import getJsonPath from vnpy.trader.vtEvent import EVENT_TICK, EVENT_TRADE, EVENT_POSITION -from vnpy.trader.vtObject import VtSubscribeReq +from vnpy.trader.vtObject import VtSubscribeReq, VtLogData +from vnpy.trader.vtConstant import (DIRECTION_LONG, DIRECTION_SHORT, + OFFSET_OPEN, OFFSET_CLOSE) -from .stBase import StLeg, StSpread, EVENT_SPREADTRADING_TICK +from .stBase import (StLeg, StSpread, EVENT_SPREADTRADING_TICK, + EVENT_SPREADTRADING_POS, EVENT_SPREADTRADING_LOG) ######################################################################## @@ -33,11 +37,18 @@ class StEngine(object): #---------------------------------------------------------------------- def loadSetting(self): """加载配置""" - with open(self.settingFilePath) as f: - l = json.load(f) - - for setting in l: - self.createSpread(setting) + try: + with open(self.settingFilePath) as f: + l = json.load(f) + + for setting in l: + result, msg = self.createSpread(setting) + self.writeLog(msg) + + self.writeLog(u'价差配置加载完成') + except: + content = u'价差配置加载出错,原因:' + traceback.format_exc() + self.writeLog(content) #---------------------------------------------------------------------- def saveSetting(self): @@ -53,7 +64,7 @@ class StEngine(object): # 检查价差重名 if setting['name'] in self.spreadDict: - msg = u'%s价差重名' %setting['name'] + msg = u'%s价差存在重名' %setting['name'] return result, msg # 检查腿是否已使用 @@ -132,21 +143,89 @@ class StEngine(object): spread = self.vtSymbolSpreadDict[tick.vtSymbol] spread.calculatePrice() - # 推送价差更新 + # 推送价差行情更新 newSpread = copy(spread) - event = Event(EVENT_SPREADTRADING_TICK) - event.dict_['data'] = newSpread - self.eventEngine.put(event) + + event1 = Event(EVENT_SPREADTRADING_TICK+spread.name) + event1.dict_['data'] = newSpread + self.eventEngine.put(event1) + + event2 = Event(EVENT_SPREADTRADING_TICK) + event2.dict_['data'] = newSpread + self.eventEngine.put(event2) #---------------------------------------------------------------------- def processTradeEvent(self, event): - """""" - pass + """处理成交推送""" + # 检查成交是否需要处理 + trade = event.dict_['data'] + if trade.vtSymbol not in self.legDict: + return + + # 更新腿持仓 + leg = self.legDict[trade.vtSymbol] + direction = trade.direction + offset = trade.offst + + if direction == DIRECTION_LONG: + if offset == OFFSET_OPEN: + leg.longPos += trade.volume + else: + leg.shortPos -= trade.volume + else: + if offset == OFFSET_OPEN: + leg.shortPos += trade.volume + else: + leg.longPos -= trade.volume + leg.netPos = leg.longPos - leg.shortPos + + # 更新价差持仓 + spread = self.vtSymbolSpreadDict[trade.vtSymbol] + spread.calculatePos() + + # 推送价差持仓更新 + newSpread = copy(spread) + + event1 = Event(EVENT_SPREADTRADING_POS+spread.name) + event1.dict_['data'] = newSpread + self.eventEngine.put(event1) + + event2 = Event(EVENT_SPREADTRADING_POS) + event2.dict_['data'] = newSpread + self.eventEngine.put(event2) #---------------------------------------------------------------------- def processPositionEvent(self, event): - """""" - pass + """处理持仓推送""" + # 检查持仓是否需要处理 + pos = event.dict_['data'] + if pos.vtSymbol not in self.legDict: + return + + # 更新腿持仓 + leg = self.legDict[trade.vtSymbol] + direction = pos.direction + + if direction == DIRECTION_LONG: + leg.longPos = pos.position + else: + leg.shortPos = pos.position + leg.netPos = leg.longPos - leg.shortPos + + # 更新价差持仓 + spread = self.vtSymbolSpreadDict[trade.vtSymbol] + spread.calculatePos() + + # 推送价差持仓更新 + newSpread = copy(spread) + + event1 = Event(EVENT_SPREADTRADING_POS+spread.name) + event1.dict_['data'] = newSpread + self.eventEngine.put(event1) + + event2 = Event(EVENT_SPREADTRADING_POS) + event2.dict_['data'] = newSpread + self.eventEngine.put(event2) #---------------------------------------------------------------------- def registerEvent(self): @@ -160,7 +239,7 @@ class StEngine(object): """订阅行情""" contract = self.mainEngine.getContract(vtSymbol) if not contract: - return + self.writeLog(u'订阅行情失败,找不到该合约%s' %vtSymbol) req = VtSubscribeReq() req.symbol = contract.symbol @@ -168,6 +247,16 @@ class StEngine(object): self.mainEngine.subscribe(req, contract.gatewayName) + #---------------------------------------------------------------------- + def writeLog(self, content): + """发出日志""" + log = VtLogData() + log.logContent = content + + event = Event(EVENT_SPREADTRADING_LOG) + event.dict_['data'] = log + self.eventEngine.put(event) + #---------------------------------------------------------------------- def stop(self): """停止""" diff --git a/vnpy/trader/app/spreadTrading/uiStWidget.py b/vnpy/trader/app/spreadTrading/uiStWidget.py index c0cd5b21..9244fc4d 100644 --- a/vnpy/trader/app/spreadTrading/uiStWidget.py +++ b/vnpy/trader/app/spreadTrading/uiStWidget.py @@ -3,23 +3,23 @@ from collections import OrderedDict from vnpy.trader.uiQt import QtWidgets -from vnpy.trader.uiBasicWidget import (BasicMonitor, BasicCell, +from vnpy.trader.uiBasicWidget import (BasicMonitor, BasicCell, PnlCell, AskCell, BidCell, BASIC_FONT) -from .stBase import EVENT_SPREADTRADING_TICK +from .stBase import (EVENT_SPREADTRADING_TICK, EVENT_SPREADTRADING_POS, + EVENT_SPREADTRADING_LOG) ######################################################################## class StTickMonitor(BasicMonitor): - """""" + """价差行情监控""" #---------------------------------------------------------------------- def __init__(self, mainEngine, eventEngine, parent=None): """Constructor""" super(StTickMonitor, self).__init__(mainEngine, eventEngine, parent) - # 设置表头有序字典 d = OrderedDict() d['name'] = {'chinese':u'价差名称', 'cellType':BasicCell} d['bidPrice'] = {'chinese':u'买价', 'cellType':BidCell} @@ -30,22 +30,60 @@ class StTickMonitor(BasicMonitor): d['symbol'] = {'chinese':u'代码', 'cellType':BasicCell} self.setHeaderDict(d) - # 设置数据键 self.setDataKey('name') - - # 设置监控事件类型 self.setEventType(EVENT_SPREADTRADING_TICK) - - # 设置字体 self.setFont(BASIC_FONT) - # 初始化表格 self.initTable() - - # 注册事件监听 self.registerEvent() +######################################################################## +class StPosMonitor(BasicMonitor): + """价差持仓监控""" + + #---------------------------------------------------------------------- + def __init__(self, mainEngine, eventEngine, parent=None): + """Constructor""" + super(StPosMonitor, self).__init__(mainEngine, eventEngine, parent) + + d = OrderedDict() + d['name'] = {'chinese':u'价差名称', 'cellType':BasicCell} + d['netPos'] = {'chinese':u'净仓', 'cellType':PnlCell} + d['longPos'] = {'chinese':u'多仓', 'cellType':BasicCell} + d['shortPos'] = {'chinese':u'空仓', 'cellType':BasicCell} + d['symbol'] = {'chinese':u'代码', 'cellType':BasicCell} + self.setHeaderDict(d) + + self.setDataKey('name') + self.setEventType(EVENT_SPREADTRADING_POS) + self.setFont(BASIC_FONT) + + self.initTable() + self.registerEvent() + + +######################################################################## +class StLogMonitor(BasicMonitor): + """价差日志监控""" + + #---------------------------------------------------------------------- + def __init__(self, mainEngine, eventEngine, parent=None): + """Constructor""" + super(StLogMonitor, self).__init__(mainEngine, eventEngine, parent) + + d = OrderedDict() + d['logTime'] = {'chinese':u'时间', 'cellType':BasicCell} + d['logContent'] = {'chinese':u'日志', 'cellType':BasicCell} + self.setHeaderDict(d) + + self.setEventType(EVENT_SPREADTRADING_LOG) + self.setFont(BASIC_FONT) + + self.initTable() + self.registerEvent() + + ######################################################################## class StManager(QtWidgets.QWidget): """""" @@ -73,15 +111,22 @@ class StManager(QtWidgets.QWidget): # 创建组件 tickMonitor = StTickMonitor(self.mainEngine, self.eventEngine) + posMonitor = StPosMonitor(self.mainEngine, self.eventEngine) + logMonitor = StLogMonitor(self.mainEngine, self.eventEngine) # 设置布局 - hbox = QtWidgets.QHBoxLayout() - hbox.addWidget(buttonLoadSetting) - hbox.addStretch() + hbox1 = QtWidgets.QHBoxLayout() + hbox1.addWidget(buttonLoadSetting) + hbox1.addStretch() + + hbox2 = QtWidgets.QHBoxLayout() + hbox2.addWidget(tickMonitor) + hbox2.addWidget(posMonitor) vbox = QtWidgets.QVBoxLayout() - vbox.addLayout(hbox) - vbox.addWidget(tickMonitor) + vbox.addLayout(hbox1) + vbox.addLayout(hbox2) + vbox.addWidget(logMonitor) self.setLayout(vbox)