[Add]添加希腊值监控组件
This commit is contained in:
parent
d3d1afd7c7
commit
796adc7673
@ -1 +1 @@
|
|||||||
HqLpRXdyn/k8CK6bQvjTlg==
|
4kpJoMUXCPNmN66luTh0Lg==
|
@ -79,7 +79,7 @@ def calculateTheta(f, k, r, t, v, cp):
|
|||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def calculateVega(f, k, r, t, v, cp):
|
def calculateVega(f, k, r, t, v, cp):
|
||||||
"""计算Vega值"""
|
"""计算Vega值"""
|
||||||
vega = calculateVega(f, k, r, t, v, cp) / 100
|
vega = calculateOriginalVega(f, k, r, t, v, cp) / 100
|
||||||
return vega
|
return vega
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
|
@ -145,7 +145,7 @@ class OmUnderlying(OmInstrument):
|
|||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def calculatePosGreeks(self):
|
def calculatePosGreeks(self):
|
||||||
"""计算持仓希腊值"""
|
"""计算持仓希腊值"""
|
||||||
self.posDelta = self.theoDelta * self.netPos
|
self.posDelta = self.theoDelta * self.netPos * self.size
|
||||||
|
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
@ -210,6 +210,8 @@ class OmOption(OmInstrument):
|
|||||||
self.bidImpv = self.calculateImpv(self.bidPrice1, underlyingPrice, self.k,
|
self.bidImpv = self.calculateImpv(self.bidPrice1, underlyingPrice, self.k,
|
||||||
self.r, self.t, self.cp)
|
self.r, self.t, self.cp)
|
||||||
self.midImpv = (self.askImpv + self.bidImpv) / 2
|
self.midImpv = (self.askImpv + self.bidImpv) / 2
|
||||||
|
|
||||||
|
self.pricingImpv = self.midImpv
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def calculateTheoGreeks(self):
|
def calculateTheoGreeks(self):
|
||||||
@ -228,11 +230,11 @@ class OmOption(OmInstrument):
|
|||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def calculatePosGreeks(self):
|
def calculatePosGreeks(self):
|
||||||
"""计算持仓希腊值"""
|
"""计算持仓希腊值"""
|
||||||
self.posValue = self.theoPrice * self.netPos
|
self.posValue = self.theoPrice * self.netPos * self.size
|
||||||
self.posDelta = self.theoDelta * self.netPos
|
self.posDelta = self.theoDelta * self.netPos * self.size
|
||||||
self.posGamma = self.theoGamma * self.netPos
|
self.posGamma = self.theoGamma * self.netPos * self.size
|
||||||
self.posTheta = self.theoTheta * self.netPos
|
self.posTheta = self.theoTheta * self.netPos * self.size
|
||||||
self.posVega = self.theoVega * self.netPos
|
self.posVega = self.theoVega * self.netPos * self.size
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def newTick(self, tick):
|
def newTick(self, tick):
|
||||||
|
294
vnpy/trader/app/optionMaster/uiOmGreeksMonitor.py
Normal file
294
vnpy/trader/app/optionMaster/uiOmGreeksMonitor.py
Normal file
@ -0,0 +1,294 @@
|
|||||||
|
# encoding: UTF-8
|
||||||
|
|
||||||
|
from vnpy.event import Event
|
||||||
|
from vnpy.trader.vtEvent import EVENT_TIMER
|
||||||
|
|
||||||
|
from .uiOmBase import *
|
||||||
|
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
class GreeksMonitor(QtWidgets.QTableWidget):
|
||||||
|
"""希腊值监控"""
|
||||||
|
headers = [
|
||||||
|
u'代码',
|
||||||
|
u'多仓',
|
||||||
|
u'空仓',
|
||||||
|
u'净仓',
|
||||||
|
u'Delta',
|
||||||
|
u'Gamma',
|
||||||
|
u'Theta',
|
||||||
|
u'Vega',
|
||||||
|
u'持仓Delta',
|
||||||
|
u'持仓Gamma',
|
||||||
|
u'持仓Theta',
|
||||||
|
u'持仓Vega'
|
||||||
|
]
|
||||||
|
|
||||||
|
signal = QtCore.pyqtSignal(type(Event()))
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def __init__(self, omEngine, parent=None):
|
||||||
|
"""Constructor"""
|
||||||
|
super(GreeksMonitor, self).__init__()
|
||||||
|
|
||||||
|
self.portfolio = omEngine.portfolio
|
||||||
|
self.eventEngine = omEngine.eventEngine
|
||||||
|
|
||||||
|
self.cellDict = {} # key:symbol, value:cell dict
|
||||||
|
self.updateTrigger = 2
|
||||||
|
self.updateCount = 0
|
||||||
|
|
||||||
|
self.initUi()
|
||||||
|
self.initCells()
|
||||||
|
self.registerEvent()
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def initUi(self):
|
||||||
|
"""初始化界面"""
|
||||||
|
portfolio = self.portfolio
|
||||||
|
|
||||||
|
self.setWindowTitle(u'希腊值监控')
|
||||||
|
|
||||||
|
# 计算所需行数
|
||||||
|
totalRow = 1
|
||||||
|
totalRow += len(portfolio.underlyingDict) + 1
|
||||||
|
totalRow += len(portfolio.chainDict) + 1
|
||||||
|
|
||||||
|
for chain in portfolio.chainDict.values():
|
||||||
|
totalRow += len(chain.optionDict) + 1
|
||||||
|
|
||||||
|
# 初始化表格
|
||||||
|
self.setColumnCount(len(self.headers))
|
||||||
|
self.setHorizontalHeaderLabels(self.headers)
|
||||||
|
self.setRowCount(totalRow)
|
||||||
|
self.verticalHeader().setVisible(False)
|
||||||
|
self.setEditTriggers(self.NoEditTriggers)
|
||||||
|
|
||||||
|
for i in range(self.columnCount()):
|
||||||
|
self.horizontalHeader().setResizeMode(i, QtWidgets.QHeaderView.Stretch)
|
||||||
|
self.horizontalHeader().setResizeMode(0, QtWidgets.QHeaderView.ResizeToContents)
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def initCells(self):
|
||||||
|
"""初始化单元格"""
|
||||||
|
portfolio = self.portfolio
|
||||||
|
row = 0
|
||||||
|
|
||||||
|
# 组合
|
||||||
|
cellSymbol = OmCell(portfolio.name, COLOR_SYMBOL, COLOR_BLACK)
|
||||||
|
cellLongPos = OmCell(0, COLOR_POS, COLOR_BLACK)
|
||||||
|
cellShortPos = OmCell(0, COLOR_POS, COLOR_BLACK)
|
||||||
|
cellNetPos = OmCell(0, COLOR_POS, COLOR_BLACK)
|
||||||
|
cellPosDelta = OmCell(0, COLOR_STRIKE)
|
||||||
|
cellPosGamma = OmCell(0, COLOR_STRIKE)
|
||||||
|
cellPosTheta = OmCell(0, COLOR_STRIKE)
|
||||||
|
cellPosVega = OmCell(0, COLOR_STRIKE)
|
||||||
|
|
||||||
|
self.setItem(row, 0, cellSymbol)
|
||||||
|
self.setItem(row, 1, cellLongPos)
|
||||||
|
self.setItem(row, 2, cellShortPos)
|
||||||
|
self.setItem(row, 3, cellNetPos)
|
||||||
|
self.setItem(row, 8, cellPosDelta)
|
||||||
|
self.setItem(row, 9, cellPosGamma)
|
||||||
|
self.setItem(row, 10, cellPosTheta)
|
||||||
|
self.setItem(row, 11, cellPosVega)
|
||||||
|
|
||||||
|
d = {}
|
||||||
|
d['longPos'] = cellLongPos
|
||||||
|
d['shortPos'] = cellShortPos
|
||||||
|
d['netPos'] = cellNetPos
|
||||||
|
d['posDelta'] = cellPosDelta
|
||||||
|
d['posGamma'] = cellPosGamma
|
||||||
|
d['posTheta'] = cellPosTheta
|
||||||
|
d['posVega'] = cellPosVega
|
||||||
|
self.cellDict[portfolio.name] = d
|
||||||
|
|
||||||
|
row += 1
|
||||||
|
|
||||||
|
# 标的
|
||||||
|
row += 1 # 空行
|
||||||
|
|
||||||
|
for underlying in portfolio.underlyingDict.values():
|
||||||
|
cellSymbol = OmCell(underlying.symbol, COLOR_SYMBOL, COLOR_BLACK)
|
||||||
|
cellLongPos = OmCell(0, COLOR_POS, COLOR_BLACK)
|
||||||
|
cellShortPos = OmCell(0, COLOR_POS, COLOR_BLACK)
|
||||||
|
cellNetPos = OmCell(0, COLOR_POS, COLOR_BLACK)
|
||||||
|
cellTheoDelta = OmCell('%.3f' %underlying.theoDelta)
|
||||||
|
cellPosDelta = OmCell(0, COLOR_STRIKE)
|
||||||
|
|
||||||
|
self.setItem(row, 0, cellSymbol)
|
||||||
|
self.setItem(row, 1, cellLongPos)
|
||||||
|
self.setItem(row, 2, cellShortPos)
|
||||||
|
self.setItem(row, 3, cellNetPos)
|
||||||
|
self.setItem(row, 4, cellTheoDelta)
|
||||||
|
self.setItem(row, 8, cellPosDelta)
|
||||||
|
|
||||||
|
d = {}
|
||||||
|
d['longPos'] = cellLongPos
|
||||||
|
d['shortPos'] = cellShortPos
|
||||||
|
d['netPos'] = cellNetPos
|
||||||
|
d['theoDelta'] = cellTheoDelta
|
||||||
|
d['posDelta'] = cellPosDelta
|
||||||
|
self.cellDict[underlying.symbol] = d
|
||||||
|
|
||||||
|
row += 1
|
||||||
|
|
||||||
|
# 期权链
|
||||||
|
row += 1
|
||||||
|
|
||||||
|
for chain in portfolio.chainDict.values():
|
||||||
|
cellSymbol = OmCell(chain.symbol, COLOR_SYMBOL, COLOR_BLACK)
|
||||||
|
cellLongPos = OmCell(0, COLOR_POS, COLOR_BLACK)
|
||||||
|
cellShortPos = OmCell(0, COLOR_POS, COLOR_BLACK)
|
||||||
|
cellNetPos = OmCell(0, COLOR_POS, COLOR_BLACK)
|
||||||
|
cellTheoDelta = OmCell(0)
|
||||||
|
cellTheoGamma = OmCell(0)
|
||||||
|
cellTheoTheta = OmCell(0)
|
||||||
|
cellTheoVega = OmCell(0)
|
||||||
|
cellPosDelta = OmCell(0, COLOR_STRIKE)
|
||||||
|
cellPosGamma = OmCell(0, COLOR_STRIKE)
|
||||||
|
cellPosTheta = OmCell(0, COLOR_STRIKE)
|
||||||
|
cellPosVega = OmCell(0, COLOR_STRIKE)
|
||||||
|
|
||||||
|
self.setItem(row, 0, cellSymbol)
|
||||||
|
self.setItem(row, 1, cellLongPos)
|
||||||
|
self.setItem(row, 2, cellShortPos)
|
||||||
|
self.setItem(row, 3, cellNetPos)
|
||||||
|
self.setItem(row, 4, cellTheoDelta)
|
||||||
|
self.setItem(row, 5, cellTheoGamma)
|
||||||
|
self.setItem(row, 6, cellTheoTheta)
|
||||||
|
self.setItem(row, 7, cellTheoVega)
|
||||||
|
self.setItem(row, 8, cellPosDelta)
|
||||||
|
self.setItem(row, 9, cellPosGamma)
|
||||||
|
self.setItem(row, 10, cellPosTheta)
|
||||||
|
self.setItem(row, 11, cellPosVega)
|
||||||
|
|
||||||
|
d = {}
|
||||||
|
d['longPos'] = cellLongPos
|
||||||
|
d['shortPos'] = cellShortPos
|
||||||
|
d['netPos'] = cellNetPos
|
||||||
|
d['theoDelta'] = cellTheoDelta
|
||||||
|
d['theoGamma'] = cellTheoGamma
|
||||||
|
d['theoTheta'] = cellTheoTheta
|
||||||
|
d['theoVega'] = cellTheoVega
|
||||||
|
d['posDelta'] = cellPosDelta
|
||||||
|
d['posGamma'] = cellPosGamma
|
||||||
|
d['posTheta'] = cellPosTheta
|
||||||
|
d['posVega'] = cellPosVega
|
||||||
|
self.cellDict[chain.symbol + '_chain'] = d
|
||||||
|
|
||||||
|
row += 1
|
||||||
|
|
||||||
|
# 期权
|
||||||
|
for chain in portfolio.chainDict.values():
|
||||||
|
row += 1
|
||||||
|
|
||||||
|
for option in chain.optionDict.values():
|
||||||
|
cellSymbol = OmCell(option.symbol, COLOR_SYMBOL, COLOR_BLACK)
|
||||||
|
cellLongPos = OmCell(0, COLOR_POS, COLOR_BLACK)
|
||||||
|
cellShortPos = OmCell(0, COLOR_POS, COLOR_BLACK)
|
||||||
|
cellNetPos = OmCell(0, COLOR_POS, COLOR_BLACK)
|
||||||
|
cellTheoDelta = OmCell(0)
|
||||||
|
cellTheoGamma = OmCell(0)
|
||||||
|
cellTheoTheta = OmCell(0)
|
||||||
|
cellTheoVega = OmCell(0)
|
||||||
|
cellPosDelta = OmCell(0, COLOR_STRIKE)
|
||||||
|
cellPosGamma = OmCell(0, COLOR_STRIKE)
|
||||||
|
cellPosTheta = OmCell(0, COLOR_STRIKE)
|
||||||
|
cellPosVega = OmCell(0, COLOR_STRIKE)
|
||||||
|
|
||||||
|
self.setItem(row, 0, cellSymbol)
|
||||||
|
self.setItem(row, 1, cellLongPos)
|
||||||
|
self.setItem(row, 2, cellShortPos)
|
||||||
|
self.setItem(row, 3, cellNetPos)
|
||||||
|
self.setItem(row, 4, cellTheoDelta)
|
||||||
|
self.setItem(row, 5, cellTheoGamma)
|
||||||
|
self.setItem(row, 6, cellTheoTheta)
|
||||||
|
self.setItem(row, 7, cellTheoVega)
|
||||||
|
self.setItem(row, 8, cellPosDelta)
|
||||||
|
self.setItem(row, 9, cellPosGamma)
|
||||||
|
self.setItem(row, 10, cellPosTheta)
|
||||||
|
self.setItem(row, 11, cellPosVega)
|
||||||
|
|
||||||
|
d = {}
|
||||||
|
d['longPos'] = cellLongPos
|
||||||
|
d['shortPos'] = cellShortPos
|
||||||
|
d['netPos'] = cellNetPos
|
||||||
|
d['theoDelta'] = cellTheoDelta
|
||||||
|
d['theoGamma'] = cellTheoGamma
|
||||||
|
d['theoTheta'] = cellTheoTheta
|
||||||
|
d['theoVega'] = cellTheoVega
|
||||||
|
d['posDelta'] = cellPosDelta
|
||||||
|
d['posGamma'] = cellPosGamma
|
||||||
|
d['posTheta'] = cellPosTheta
|
||||||
|
d['posVega'] = cellPosVega
|
||||||
|
self.cellDict[option.symbol] = d
|
||||||
|
|
||||||
|
row += 1
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def registerEvent(self):
|
||||||
|
"""注册事件监听"""
|
||||||
|
self.signal.connect(self.updateTable)
|
||||||
|
self.eventEngine.register(EVENT_TIMER, self.signal.emit)
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def processTimerEvent(self, event):
|
||||||
|
"""处理定时事件"""
|
||||||
|
self.updateCount += 1
|
||||||
|
|
||||||
|
if self.updateCount >= self.updateTrigger:
|
||||||
|
self.updateCount = 0
|
||||||
|
self.updateTable()
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def updateTable(self):
|
||||||
|
"""更新表格"""
|
||||||
|
# 更新组合
|
||||||
|
portfolio = self.portfolio
|
||||||
|
|
||||||
|
d = self.cellDict[portfolio.name]
|
||||||
|
d['longPos'].setText(str(portfolio.longPos))
|
||||||
|
d['shortPos'].setText(str(portfolio.shortPos))
|
||||||
|
d['netPos'].setText(str(portfolio.netPos))
|
||||||
|
d['posDelta'].setText('%.1f' %portfolio.posDelta)
|
||||||
|
d['posGamma'].setText('%.1f' %portfolio.posGamma)
|
||||||
|
d['posTheta'].setText('%.1f' %portfolio.posTheta)
|
||||||
|
d['posVega'].setText('%.1f' %portfolio.posVega)
|
||||||
|
|
||||||
|
# 更新标的
|
||||||
|
for underlying in portfolio.underlyingDict.values():
|
||||||
|
d = self.cellDict[underlying.symbol]
|
||||||
|
d['longPos'].setText(str(underlying.longPos))
|
||||||
|
d['shortPos'].setText(str(underlying.shortPos))
|
||||||
|
d['netPos'].setText(str(underlying.netPos))
|
||||||
|
d['posDelta'].setText('%.1f' %underlying.posDelta)
|
||||||
|
|
||||||
|
# 更新期权链
|
||||||
|
for chain in portfolio.chainDict.values():
|
||||||
|
d = self.cellDict[chain.symbol + '_chain']
|
||||||
|
d['longPos'].setText(str(chain.longPos))
|
||||||
|
d['shortPos'].setText(str(chain.shortPos))
|
||||||
|
d['netPos'].setText(str(chain.netPos))
|
||||||
|
d['posDelta'].setText('%.1f' %chain.posDelta)
|
||||||
|
d['posGamma'].setText('%.1f' %chain.posGamma)
|
||||||
|
d['posTheta'].setText('%.1f' %chain.posTheta)
|
||||||
|
d['posVega'].setText('%.1f' %chain.posVega)
|
||||||
|
|
||||||
|
# 更新期权
|
||||||
|
for chain in portfolio.chainDict.values():
|
||||||
|
for option in chain.optionDict.values():
|
||||||
|
d = self.cellDict[option.symbol]
|
||||||
|
d['longPos'].setText(str(option.longPos))
|
||||||
|
d['shortPos'].setText(str(option.shortPos))
|
||||||
|
d['netPos'].setText(str(option.netPos))
|
||||||
|
d['theoDelta'].setText('%.3f' %option.theoDelta)
|
||||||
|
d['theoGamma'].setText('%.3f' %option.theoGamma)
|
||||||
|
d['theoTheta'].setText('%.3f' %option.theoTheta)
|
||||||
|
d['theoVega'].setText('%.3f' %option.theoVega)
|
||||||
|
d['posDelta'].setText('%.1f' %option.posDelta)
|
||||||
|
d['posGamma'].setText('%.1f' %option.posGamma)
|
||||||
|
d['posTheta'].setText('%.1f' %option.posTheta)
|
||||||
|
d['posVega'].setText('%.1f' %option.posVega)
|
||||||
|
|
||||||
|
|
@ -6,10 +6,11 @@ import os
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from vnpy.event import Event
|
from vnpy.event import Event
|
||||||
from vnpy.trader.uiQt import QtWidgets, QtCore
|
|
||||||
|
|
||||||
from .omBase import EVENT_OM_LOG
|
from .omBase import EVENT_OM_LOG
|
||||||
|
from .uiOmBase import QtWidgets, QtCore
|
||||||
from .uiOmManualTrader import ManualTrader
|
from .uiOmManualTrader import ManualTrader
|
||||||
|
from .uiOmGreeksMonitor import GreeksMonitor
|
||||||
|
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
@ -55,6 +56,9 @@ class OmManager(QtWidgets.QWidget):
|
|||||||
self.buttonManualTrader = QtWidgets.QPushButton(u'手动交易')
|
self.buttonManualTrader = QtWidgets.QPushButton(u'手动交易')
|
||||||
self.buttonManualTrader.clicked.connect(self.openManualTrader)
|
self.buttonManualTrader.clicked.connect(self.openManualTrader)
|
||||||
|
|
||||||
|
self.buttonGreeksMonitor = QtWidgets.QPushButton(u'希腊值监控')
|
||||||
|
self.buttonGreeksMonitor.clicked.connect(self.openGreeksMonitor)
|
||||||
|
|
||||||
self.logMonitor = QtWidgets.QTextEdit()
|
self.logMonitor = QtWidgets.QTextEdit()
|
||||||
self.logMonitor.setReadOnly(True)
|
self.logMonitor.setReadOnly(True)
|
||||||
|
|
||||||
@ -62,6 +66,7 @@ class OmManager(QtWidgets.QWidget):
|
|||||||
hbox.addWidget(self.comboSettingFile)
|
hbox.addWidget(self.comboSettingFile)
|
||||||
hbox.addWidget(self.buttonInit)
|
hbox.addWidget(self.buttonInit)
|
||||||
hbox.addWidget(self.buttonManualTrader)
|
hbox.addWidget(self.buttonManualTrader)
|
||||||
|
hbox.addWidget(self.buttonGreeksMonitor)
|
||||||
hbox.addStretch()
|
hbox.addStretch()
|
||||||
|
|
||||||
hbox2 = QtWidgets.QHBoxLayout()
|
hbox2 = QtWidgets.QHBoxLayout()
|
||||||
@ -110,6 +115,15 @@ class OmManager(QtWidgets.QWidget):
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
self.widgetDict['manualTrader'] = ManualTrader(self.omEngine)
|
self.widgetDict['manualTrader'] = ManualTrader(self.omEngine)
|
||||||
self.widgetDict['manualTrader'].showMaximized()
|
self.widgetDict['manualTrader'].showMaximized()
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def openGreeksMonitor(self):
|
||||||
|
"""打开希腊值监控组件"""
|
||||||
|
try:
|
||||||
|
self.widgetDict['greeksMonitor'].showMaximized()
|
||||||
|
except KeyError:
|
||||||
|
self.widgetDict['greeksMonitor'] = GreeksMonitor(self.omEngine)
|
||||||
|
self.widgetDict['greeksMonitor'].showMaximized()
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def close(self):
|
def close(self):
|
||||||
|
Loading…
Reference in New Issue
Block a user