From dfb23ab2f486991061df1331e0015e663bbc789b Mon Sep 17 00:00:00 2001 From: "vn.py" Date: Fri, 1 Dec 2017 13:09:21 +0800 Subject: [PATCH] =?UTF-8?q?[Add]=E6=96=B0=E5=A2=9E=E6=B3=A2=E5=8A=A8?= =?UTF-8?q?=E7=8E=87=E7=AE=A1=E7=90=86=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../data/TRADE_MARKET_110100001088sop.dat | 2 +- vnpy/trader/app/optionMaster/omBase.py | 2 - .../app/optionMaster/uiOmVolatilityManager.py | 233 +++++++++++++++++- vnpy/trader/app/optionMaster/uiOmWidget.py | 33 ++- vnpy/trader/uiBasicWidget.py | 4 +- 5 files changed, 266 insertions(+), 8 deletions(-) diff --git a/examples/OptionMaster/data/TRADE_MARKET_110100001088sop.dat b/examples/OptionMaster/data/TRADE_MARKET_110100001088sop.dat index f85b1e8e..db1d5d87 100644 --- a/examples/OptionMaster/data/TRADE_MARKET_110100001088sop.dat +++ b/examples/OptionMaster/data/TRADE_MARKET_110100001088sop.dat @@ -1 +1 @@ -4kpJoMUXCPNmN66luTh0Lg== \ No newline at end of file +1akdYJY+uYtFOYGtWEJkKg== \ No newline at end of file diff --git a/vnpy/trader/app/optionMaster/omBase.py b/vnpy/trader/app/optionMaster/omBase.py index 94887789..b3c03863 100644 --- a/vnpy/trader/app/optionMaster/omBase.py +++ b/vnpy/trader/app/optionMaster/omBase.py @@ -210,8 +210,6 @@ class OmOption(OmInstrument): self.bidImpv = self.calculateImpv(self.bidPrice1, underlyingPrice, self.k, self.r, self.t, self.cp) self.midImpv = (self.askImpv + self.bidImpv) / 2 - - self.pricingImpv = self.midImpv #---------------------------------------------------------------------- def calculateTheoGreeks(self): diff --git a/vnpy/trader/app/optionMaster/uiOmVolatilityManager.py b/vnpy/trader/app/optionMaster/uiOmVolatilityManager.py index db48a611..bcfced59 100644 --- a/vnpy/trader/app/optionMaster/uiOmVolatilityManager.py +++ b/vnpy/trader/app/optionMaster/uiOmVolatilityManager.py @@ -123,4 +123,235 @@ class VolatilityChart(pg.GraphicsWindow): def closeEvent(self, event): """关闭""" self.eventEngine.unregister(EVENT_TIMER, self.signal.emit) - \ No newline at end of file + + +######################################################################## +class ChainVolatilityMonitor(QtWidgets.QTableWidget): + """期权链波动率监控""" + headers = [ + u'代码', + u'买隐波', + u'定价', + u'卖隐波', + u'行权价', + u'买隐波', + u'定价', + u'卖隐波', + u'代码' + ] + + #---------------------------------------------------------------------- + def __init__(self, chain, parent=None): + """Constructor""" + super(ChainVolatilityMonitor, self).__init__(parent) + + self.chain = chain + self.cellDict = {} # key: symbol, value: dict of cells + + self.initUi() + self.itemChanged.connect(self.pricingImpvChanged) + + #---------------------------------------------------------------------- + def initUi(self): + """初始化界面""" + chain = self.chain + + # 初始化表格 + self.setColumnCount(len(self.headers)) + self.setHorizontalHeaderLabels(self.headers) + self.setRowCount(len(chain.callDict)) + self.verticalHeader().setVisible(False) + + for i in range(self.columnCount()): + self.horizontalHeader().setResizeMode(i, QtWidgets.QHeaderView.Stretch) + + # 初始化单元格 + for row, option in enumerate(chain.callDict.values()): + cellSymbol = OmCell(option.symbol, COLOR_SYMBOL, COLOR_BLACK) + cellBid = OmCell('%.1f' %(option.bidImpv*100), COLOR_BID, COLOR_BLACK) + cellPricing = OmCell('%.1f' %(option.pricingImpv*100), COLOR_POS, COLOR_BLACK) + cellAsk = OmCell('%.1f' %(option.askImpv*100), COLOR_ASK, COLOR_BLACK) + cellStrike = OmCell(str(option.k), COLOR_STRIKE) + + cellPricing.data = option.symbol + + self.setItem(row, 0, cellSymbol) + self.setItem(row, 1, cellBid) + self.setItem(row, 2, cellPricing) + self.setItem(row, 3, cellAsk) + self.setItem(row, 4, cellStrike) + + d = {} + d['bid'] = cellBid + d['ask'] = cellAsk + d['pricing'] = cellPricing + self.cellDict[option.symbol] = d + + for row, option in enumerate(chain.putDict.values()): + cellSymbol = OmCell(option.symbol, COLOR_SYMBOL, COLOR_BLACK) + cellBid = OmCell('%.1f' %(option.bidImpv*100), COLOR_BID, COLOR_BLACK) + cellPricing = OmCell('%.1f' %(option.pricingImpv*100), COLOR_POS, COLOR_BLACK) + cellAsk = OmCell('%.1f' %(option.askImpv*100), COLOR_ASK, COLOR_BLACK) + + cellPricing.data = option.symbol + + self.setItem(row, 5, cellBid) + self.setItem(row, 6, cellPricing) + self.setItem(row, 7, cellAsk) + self.setItem(row, 8, cellSymbol) + + d = {} + d['bid'] = cellBid + d['ask'] = cellAsk + d['pricing'] = cellPricing + self.cellDict[option.symbol] = d + + #---------------------------------------------------------------------- + def refresh(self): + """刷新数据""" + for option in self.chain.optionDict.values(): + d = self.cellDict[option.symbol] + d['bid'].setText('%.1f' %(option.bidImpv*100)) + d['ask'].setText('%.1f' %(option.askImpv*100)) + d['pricing'].setText('%.1f' %(option.pricingImpv*100)) + + #---------------------------------------------------------------------- + def pricingImpvChanged(self, item): + """更细定价波动率""" + if not item.data: + return + + option = self.chain.optionDict[item.data] + newImpv = float(item.text())/100 + + if option.pricingImpv != newImpv: + option.pricingImpv = newImpv + + +######################################################################## +class ChainVolatilityManager(QtWidgets.QWidget): + """期权链波动率管理""" + IMPV_CHANGE_STEP = 0.001 + + #---------------------------------------------------------------------- + def __init__(self, chain, parent=None): + """Constructor""" + super(ChainVolatilityManager, self).__init__(parent) + + self.chain = chain + + self.initUi() + + #---------------------------------------------------------------------- + def initUi(self): + """初始化界面""" + self.monitor = ChainVolatilityMonitor(self.chain) + + buttonCallIncrease = QtWidgets.QPushButton(u'看涨+' + ('%.1f%%' %(self.IMPV_CHANGE_STEP*100))) + buttonCallDecrease = QtWidgets.QPushButton(u'看涨-' + ('%.1f%%' %(self.IMPV_CHANGE_STEP*100))) + buttonPutIncrease = QtWidgets.QPushButton(u'看跌+' + ('%.1f%%' %(self.IMPV_CHANGE_STEP*100))) + buttonPutDecrease = QtWidgets.QPushButton(u'看跌-' + ('%.1f%%' %(self.IMPV_CHANGE_STEP*100))) + buttonCallReset = QtWidgets.QPushButton(u'看涨重置') + buttonPutReset = QtWidgets.QPushButton(u'看跌重置') + buttonRefresh = QtWidgets.QPushButton(u'刷新') + + buttonCallIncrease.clicked.connect(self.callIncrease) + buttonCallDecrease.clicked.connect(self.callDecrease) + buttonPutIncrease.clicked.connect(self.putIncrease) + buttonPutDecrease.clicked.connect(self.putDecrease) + buttonCallReset.clicked.connect(self.callReset) + buttonPutReset.clicked.connect(self.putReset) + buttonRefresh.clicked.connect(self.monitor.refresh) + + hbox = QtWidgets.QHBoxLayout() + hbox.addStretch() + hbox.addWidget(buttonCallIncrease) + hbox.addWidget(buttonCallReset) + hbox.addWidget(buttonCallDecrease) + hbox.addStretch() + hbox.addWidget(buttonRefresh) + hbox.addStretch() + hbox.addWidget(buttonPutIncrease) + hbox.addWidget(buttonPutReset) + hbox.addWidget(buttonPutDecrease) + hbox.addStretch() + + vbox = QtWidgets.QVBoxLayout() + vbox.addLayout(hbox) + vbox.addWidget(self.monitor) + + self.setLayout(vbox) + + #---------------------------------------------------------------------- + def callIncrease(self): + """看涨增加""" + for option in self.chain.callDict.values(): + option.pricingImpv += self.IMPV_CHANGE_STEP + self.monitor.refresh() + + #---------------------------------------------------------------------- + def callDecrease(self): + """看涨减少""" + for option in self.chain.callDict.values(): + option.pricingImpv -= self.IMPV_CHANGE_STEP + self.monitor.refresh() + + #---------------------------------------------------------------------- + def callReset(self): + """看涨重置为中值""" + for option in self.chain.callDict.values(): + option.pricingImpv = option.midImpv + self.monitor.refresh() + + #---------------------------------------------------------------------- + def putIncrease(self): + """看跌增加""" + for option in self.chain.putDict.values(): + option.pricingImpv += self.IMPV_CHANGE_STEP + self.monitor.refresh() + + #---------------------------------------------------------------------- + def putDecrease(self): + """看跌减少""" + for option in self.chain.putDict.values(): + option.pricingImpv -= self.IMPV_CHANGE_STEP + self.monitor.refresh() + + #---------------------------------------------------------------------- + def putReset(self): + """看跌重置为中值""" + for option in self.chain.putDict.values(): + option.pricingImpv = option.midImpv + self.monitor.refresh() + + + +######################################################################## +class VolatilityManager(QtWidgets.QWidget): + """波动率管理""" + + #---------------------------------------------------------------------- + def __init__(self, omEngine, parent=None): + """Constructor""" + super(VolatilityManager, self).__init__(parent) + + self.omEngine = omEngine + self.portfolio = omEngine.portfolio + self.eventEngine = omEngine.eventEngine + + self.initUi() + + #---------------------------------------------------------------------- + def initUi(self): + """初始化界面""" + self.setWindowTitle(u'波动率管理') + + tab = QtWidgets.QTabWidget() + for chain in self.portfolio.chainDict.values(): + chainManager = ChainVolatilityManager(chain) + tab.addTab(chainManager, chain.symbol) + + vbox = QtWidgets.QVBoxLayout() + vbox.addWidget(tab) + + self.setLayout(vbox) \ No newline at end of file diff --git a/vnpy/trader/app/optionMaster/uiOmWidget.py b/vnpy/trader/app/optionMaster/uiOmWidget.py index 93b75f80..f60f7e97 100644 --- a/vnpy/trader/app/optionMaster/uiOmWidget.py +++ b/vnpy/trader/app/optionMaster/uiOmWidget.py @@ -11,7 +11,7 @@ from .omBase import EVENT_OM_LOG from .uiOmBase import QtWidgets, QtCore from .uiOmManualTrader import ManualTrader from .uiOmGreeksMonitor import GreeksMonitor -from .uiOmVolatilityManager import VolatilityChart +from .uiOmVolatilityManager import VolatilityChart, VolatilityManager ######################################################################## @@ -56,12 +56,19 @@ class OmManager(QtWidgets.QWidget): self.buttonManualTrader = QtWidgets.QPushButton(u'手动交易') self.buttonManualTrader.clicked.connect(self.openManualTrader) + self.buttonManualTrader.setDisabled(True) self.buttonGreeksMonitor = QtWidgets.QPushButton(u'希腊值监控') self.buttonGreeksMonitor.clicked.connect(self.openGreeksMonitor) + self.buttonGreeksMonitor.setDisabled(True) self.buttonVolatilityChart = QtWidgets.QPushButton(u'波动率图表') self.buttonVolatilityChart.clicked.connect(self.openVolatilityChart) + self.buttonVolatilityChart.setDisabled(True) + + self.buttonVolatilityManager = QtWidgets.QPushButton(u'波动率管理') + self.buttonVolatilityManager.clicked.connect(self.openVolatilityManager) + self.buttonVolatilityManager.setDisabled(True) self.logMonitor = QtWidgets.QTextEdit() self.logMonitor.setReadOnly(True) @@ -72,6 +79,7 @@ class OmManager(QtWidgets.QWidget): hbox.addWidget(self.buttonManualTrader) hbox.addWidget(self.buttonGreeksMonitor) hbox.addWidget(self.buttonVolatilityChart) + hbox.addWidget(self.buttonVolatilityManager) hbox.addStretch() hbox2 = QtWidgets.QHBoxLayout() @@ -94,8 +102,20 @@ class OmManager(QtWidgets.QWidget): if result: self.writeLog(u'引擎初始化成功') + self.enableButtons() else: self.writeLog(u'请勿重复初始化引擎') + + #---------------------------------------------------------------------- + def enableButtons(self): + """启用按钮""" + self.comboSettingFile.setDisabled(True) + self.buttonInit.setDisabled(True) + + self.buttonManualTrader.setEnabled(True) + self.buttonGreeksMonitor.setEnabled(True) + self.buttonVolatilityChart.setEnabled(True) + self.buttonVolatilityManager.setEnabled(True) #---------------------------------------------------------------------- def writeLog(self, content, time=''): @@ -137,7 +157,16 @@ class OmManager(QtWidgets.QWidget): self.widgetDict['volatilityChart'].showMaximized() except KeyError: self.widgetDict['volatilityChart'] = VolatilityChart(self.omEngine) - self.widgetDict['volatilityChart'].showMaximized() + self.widgetDict['volatilityChart'].showMaximized() + + #---------------------------------------------------------------------- + def openVolatilityManager(self): + """打开波动率管理组件""" + try: + self.widgetDict['volatilityManager'].show() + except KeyError: + self.widgetDict['volatilityManager'] = VolatilityManager(self.omEngine) + self.widgetDict['volatilityManager'].show() #---------------------------------------------------------------------- def close(self): diff --git a/vnpy/trader/uiBasicWidget.py b/vnpy/trader/uiBasicWidget.py index 29376662..e1db5059 100644 --- a/vnpy/trader/uiBasicWidget.py +++ b/vnpy/trader/uiBasicWidget.py @@ -454,8 +454,8 @@ class MarketMonitor(BasicMonitor): # 设置字体 self.setFont(BASIC_FONT) - # 设置允许排序 - self.setSorting(True) + # 设置排序 + self.setSorting(False) # 初始化表格 self.initTable()