[Add]初步完成OptionMaster手动交易模块
This commit is contained in:
parent
b2aa6c5c2b
commit
e096455b44
@ -1 +1 @@
|
|||||||
B7/DvEptJ5IBD1LIj9SEFg==
|
HqLpRXdyn/k8CK6bQvjTlg==
|
@ -43,6 +43,10 @@ DX_TARGET = 0.00001
|
|||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def calculatePrice(f, k, r, t, v, cp):
|
def calculatePrice(f, k, r, t, v, cp):
|
||||||
"""计算期权价格"""
|
"""计算期权价格"""
|
||||||
|
# 如果波动率为0,则直接返回期权空间价值
|
||||||
|
if v <= 0:
|
||||||
|
return max(0, cp * (f - k))
|
||||||
|
|
||||||
d1 = (log(f / k) + (0.5 * pow(v, 2) + r) * t) / (v * sqrt(t))
|
d1 = (log(f / k) + (0.5 * pow(v, 2) + r) * t) / (v * sqrt(t))
|
||||||
d2 = d1 - v * sqrt(t)
|
d2 = d1 - v * sqrt(t)
|
||||||
price = cp * (f * cdf(cp * d1) - k * cdf(cp * d2) * exp(-r * t))
|
price = cp * (f * cdf(cp * d1) - k * cdf(cp * d2) * exp(-r * t))
|
||||||
@ -121,9 +125,13 @@ def calculateImpv(price, f, k, r, t, cp):
|
|||||||
for i in range(50):
|
for i in range(50):
|
||||||
# 计算当前猜测波动率对应的期权价格和vega值
|
# 计算当前猜测波动率对应的期权价格和vega值
|
||||||
p = calculatePrice(f, k, r, t, v, cp)
|
p = calculatePrice(f, k, r, t, v, cp)
|
||||||
#print 'calculating vega', f, k, r, t, v, cp
|
|
||||||
vega = calculateOriginalVega(f, k, r, t, v, cp)
|
vega = calculateOriginalVega(f, k, r, t, v, cp)
|
||||||
|
|
||||||
|
# 如果vega过小接近0,则直接返回
|
||||||
|
if not vega:
|
||||||
|
return v
|
||||||
|
|
||||||
# 计算误差
|
# 计算误差
|
||||||
dx = (price - p) / vega
|
dx = (price - p) / vega
|
||||||
|
|
||||||
|
@ -376,6 +376,7 @@ class OmPortfolio(object):
|
|||||||
self.underlyingDict = OrderedDict()
|
self.underlyingDict = OrderedDict()
|
||||||
self.chainDict = OrderedDict()
|
self.chainDict = OrderedDict()
|
||||||
self.optionDict = {}
|
self.optionDict = {}
|
||||||
|
self.instrumentDict = {}
|
||||||
|
|
||||||
for underlying in underlyingList:
|
for underlying in underlyingList:
|
||||||
self.underlyingDict[underlying.symbol] = underlying
|
self.underlyingDict[underlying.symbol] = underlying
|
||||||
@ -385,6 +386,9 @@ class OmPortfolio(object):
|
|||||||
self.optionDict.update(chain.callDict)
|
self.optionDict.update(chain.callDict)
|
||||||
self.optionDict.update(chain.putDict)
|
self.optionDict.update(chain.putDict)
|
||||||
|
|
||||||
|
self.instrumentDict.update(self.underlyingDict)
|
||||||
|
self.instrumentDict.update(self.optionDict)
|
||||||
|
|
||||||
# 持仓数据
|
# 持仓数据
|
||||||
self.longPos = EMPTY_INT
|
self.longPos = EMPTY_INT
|
||||||
self.shortPos = EMPTY_INT
|
self.shortPos = EMPTY_INT
|
||||||
|
41
vnpy/trader/app/optionMaster/uiOmBase.py
Normal file
41
vnpy/trader/app/optionMaster/uiOmBase.py
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
# encoding: UTF-8
|
||||||
|
|
||||||
|
from vnpy.trader.uiQt import QtGui, QtWidgets, QtCore
|
||||||
|
|
||||||
|
COLOR_BID = QtGui.QColor(255,174,201)
|
||||||
|
COLOR_ASK = QtGui.QColor(160,255,160)
|
||||||
|
COLOR_STRIKE = QtGui.QColor(0,0,160)
|
||||||
|
COLOR_POS = QtGui.QColor(225,255,255)
|
||||||
|
COLOR_SYMBOL = QtGui.QColor('white')
|
||||||
|
COLOR_BLACK = QtGui.QColor('black')
|
||||||
|
|
||||||
|
CALL_SUFFIX = '_call'
|
||||||
|
PUT_SUFFIX = '_put'
|
||||||
|
|
||||||
|
STYLESHEET_START = "background-color: rgb(111,255,244); color: black"
|
||||||
|
STYLESHEET_STOP = "background-color: rgb(255,201,111); color: black"
|
||||||
|
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
class OmCell(QtWidgets.QTableWidgetItem):
|
||||||
|
"""单元格"""
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def __init__(self, text=None, background=None, foreground=None, data=None):
|
||||||
|
"""Constructor"""
|
||||||
|
super(OmCell, self).__init__()
|
||||||
|
|
||||||
|
self.data = data
|
||||||
|
self.background = None
|
||||||
|
|
||||||
|
if text:
|
||||||
|
self.setText(text)
|
||||||
|
|
||||||
|
if foreground:
|
||||||
|
self.setForeground(foreground)
|
||||||
|
|
||||||
|
if background:
|
||||||
|
self.setBackground(background)
|
||||||
|
self.background = background
|
||||||
|
|
||||||
|
self.setTextAlignment(QtCore.Qt.AlignCenter)
|
411
vnpy/trader/app/optionMaster/uiOmManualTrader.py
Normal file
411
vnpy/trader/app/optionMaster/uiOmManualTrader.py
Normal file
@ -0,0 +1,411 @@
|
|||||||
|
# encoding: UTF-8
|
||||||
|
|
||||||
|
from vnpy.event import Event
|
||||||
|
|
||||||
|
from vnpy.trader.vtConstant import DIRECTION_LONG, DIRECTION_SHORT, OFFSET_OPEN, OFFSET_CLOSE, PRICETYPE_LIMITPRICE
|
||||||
|
from vnpy.trader.vtObject import VtOrderReq
|
||||||
|
from vnpy.trader.vtEvent import EVENT_TICK, EVENT_TRADE
|
||||||
|
from vnpy.trader.uiBasicWidget import WorkingOrderMonitor, PositionMonitor
|
||||||
|
|
||||||
|
from uiOmBase import *
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
class ChainMonitor(QtWidgets.QTableWidget):
|
||||||
|
"""期权链监控"""
|
||||||
|
headers = [
|
||||||
|
u'代码',
|
||||||
|
u'买价',
|
||||||
|
u'买量',
|
||||||
|
u'买隐波',
|
||||||
|
u'卖价',
|
||||||
|
u'卖量',
|
||||||
|
u'卖隐波',
|
||||||
|
u'净仓',
|
||||||
|
u'行权价',
|
||||||
|
u'净仓',
|
||||||
|
u'买价',
|
||||||
|
u'买量',
|
||||||
|
u'买隐波',
|
||||||
|
u'卖价',
|
||||||
|
u'卖量',
|
||||||
|
u'卖隐波',
|
||||||
|
u'代码'
|
||||||
|
]
|
||||||
|
|
||||||
|
signalTick = QtCore.pyqtSignal(type(Event()))
|
||||||
|
signalPos = QtCore.pyqtSignal(type(Event()))
|
||||||
|
signalTrade = QtCore.pyqtSignal(type(Event()))
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def __init__(self, omEngine, eventEngine, parent=None):
|
||||||
|
"""Constructor"""
|
||||||
|
super(ChainMonitor, self).__init__(parent)
|
||||||
|
|
||||||
|
self.omEngine = omEngine
|
||||||
|
self.eventEngine = eventEngine
|
||||||
|
|
||||||
|
# 保存代码和持仓的字典
|
||||||
|
self.bidPriceDict = {}
|
||||||
|
self.bidVolumeDict = {}
|
||||||
|
self.bidImpvDict = {}
|
||||||
|
self.askPriceDict = {}
|
||||||
|
self.askVolumeDict = {}
|
||||||
|
self.askImpvDict = {}
|
||||||
|
self.posDict = {}
|
||||||
|
|
||||||
|
# 保存期权对象的字典
|
||||||
|
portfolio = omEngine.portfolio
|
||||||
|
|
||||||
|
self.instrumentDict = {}
|
||||||
|
self.instrumentDict.update(portfolio.optionDict)
|
||||||
|
self.instrumentDict.update(portfolio.underlyingDict)
|
||||||
|
|
||||||
|
# 初始化
|
||||||
|
self.initUi()
|
||||||
|
self.registerEvent()
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def initUi(self):
|
||||||
|
"""初始化界面"""
|
||||||
|
portfolio = self.omEngine.portfolio
|
||||||
|
|
||||||
|
# 初始化表格
|
||||||
|
self.setColumnCount(len(self.headers))
|
||||||
|
self.setHorizontalHeaderLabels(self.headers)
|
||||||
|
|
||||||
|
rowCount = 0
|
||||||
|
rowCount += len(portfolio.underlyingDict)
|
||||||
|
rowCount += len(portfolio.chainDict)
|
||||||
|
for chain in portfolio.chainDict.values():
|
||||||
|
rowCount += len(chain.callDict)
|
||||||
|
self.setRowCount(rowCount)
|
||||||
|
|
||||||
|
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)
|
||||||
|
self.horizontalHeader().setResizeMode(self.columnCount()-1, QtWidgets.QHeaderView.ResizeToContents)
|
||||||
|
|
||||||
|
# 初始化标的单元格
|
||||||
|
row = 0
|
||||||
|
|
||||||
|
for underlying in portfolio.underlyingDict.values():
|
||||||
|
symbol = underlying.symbol
|
||||||
|
|
||||||
|
cellSymbol = OmCell(symbol, COLOR_SYMBOL, COLOR_BLACK, underlying)
|
||||||
|
cellBidPrice = OmCell(str(underlying.bidPrice1), COLOR_BID, COLOR_BLACK, underlying)
|
||||||
|
cellBidVolume = OmCell(str(underlying.bidVolume1), COLOR_BID, COLOR_BLACK, underlying)
|
||||||
|
cellAskPrice = OmCell(str(underlying.askPrice1), COLOR_ASK, COLOR_BLACK, underlying)
|
||||||
|
cellAskVolume = OmCell(str(underlying.askVolume1), COLOR_ASK, COLOR_BLACK, underlying)
|
||||||
|
cellPos = OmCell(str(underlying.netPos), COLOR_POS, COLOR_BLACK, underlying)
|
||||||
|
|
||||||
|
self.setItem(row, 0, cellSymbol)
|
||||||
|
self.setItem(row, 1, cellBidPrice)
|
||||||
|
self.setItem(row, 2, cellBidVolume)
|
||||||
|
self.setItem(row, 4, cellAskPrice)
|
||||||
|
self.setItem(row, 5, cellAskVolume)
|
||||||
|
self.setItem(row, 7, cellPos)
|
||||||
|
|
||||||
|
self.bidPriceDict[symbol] = cellBidPrice
|
||||||
|
self.bidVolumeDict[symbol] = cellBidVolume
|
||||||
|
self.askPriceDict[symbol] = cellAskPrice
|
||||||
|
self.askVolumeDict[symbol] = cellAskVolume
|
||||||
|
self.posDict[symbol] = cellPos
|
||||||
|
|
||||||
|
row += 1
|
||||||
|
|
||||||
|
row += 1
|
||||||
|
|
||||||
|
# 初始化期权单元格
|
||||||
|
for chain in portfolio.chainDict.values():
|
||||||
|
|
||||||
|
# call
|
||||||
|
callRow = row
|
||||||
|
|
||||||
|
for option in chain.callDict.values():
|
||||||
|
cellSymbol = OmCell(option.symbol, COLOR_SYMBOL, COLOR_BLACK, option)
|
||||||
|
cellBidPrice = OmCell(str(option.bidPrice1), COLOR_BID, COLOR_BLACK, option)
|
||||||
|
cellBidVolume = OmCell(str(option.bidVolume1), COLOR_BID, COLOR_BLACK, option)
|
||||||
|
cellBidImpv = OmCell('%.1f' %(option.bidImpv*100), COLOR_BID, COLOR_BLACK, option)
|
||||||
|
cellAskPrice = OmCell(str(option.askPrice1), COLOR_ASK, COLOR_BLACK, option)
|
||||||
|
cellAskVolume = OmCell(str(option.askVolume1), COLOR_ASK, COLOR_BLACK, option)
|
||||||
|
cellAskImpv = OmCell('%.1f' %(option.askImpv*100), COLOR_ASK, COLOR_BLACK, option)
|
||||||
|
cellPos = OmCell(str(option.netPos), COLOR_POS, COLOR_BLACK, option)
|
||||||
|
cellStrike = OmCell(str(option.k), COLOR_STRIKE)
|
||||||
|
|
||||||
|
self.setItem(callRow, 0, cellSymbol)
|
||||||
|
self.setItem(callRow, 1, cellBidPrice)
|
||||||
|
self.setItem(callRow, 2, cellBidVolume)
|
||||||
|
self.setItem(callRow, 3, cellBidImpv)
|
||||||
|
self.setItem(callRow, 4, cellAskPrice)
|
||||||
|
self.setItem(callRow, 5, cellAskVolume)
|
||||||
|
self.setItem(callRow, 6, cellAskImpv)
|
||||||
|
self.setItem(callRow, 7, cellPos)
|
||||||
|
self.setItem(callRow, 8, cellStrike)
|
||||||
|
|
||||||
|
self.bidPriceDict[option.symbol] = cellBidPrice
|
||||||
|
self.bidVolumeDict[option.symbol] = cellBidVolume
|
||||||
|
self.bidImpvDict[option.symbol] = cellBidImpv
|
||||||
|
self.askPriceDict[option.symbol] = cellAskPrice
|
||||||
|
self.askVolumeDict[option.symbol] = cellAskVolume
|
||||||
|
self.askImpvDict[option.symbol] = cellAskImpv
|
||||||
|
self.posDict[option.symbol] = cellPos
|
||||||
|
|
||||||
|
callRow += 1
|
||||||
|
|
||||||
|
# put
|
||||||
|
putRow = row
|
||||||
|
|
||||||
|
for option in chain.putDict.values():
|
||||||
|
cellSymbol = OmCell(option.symbol, COLOR_SYMBOL, COLOR_BLACK, option)
|
||||||
|
cellBidPrice = OmCell(str(option.bidPrice1), COLOR_BID, COLOR_BLACK, option)
|
||||||
|
cellBidVolume = OmCell(str(option.bidVolume1), COLOR_BID, COLOR_BLACK, option)
|
||||||
|
cellBidImpv = OmCell('%.1f' %(option.bidImpv*100), COLOR_BID, COLOR_BLACK, option)
|
||||||
|
cellAskPrice = OmCell(str(option.askPrice1), COLOR_ASK, COLOR_BLACK, option)
|
||||||
|
cellAskVolume = OmCell(str(option.askVolume1), COLOR_ASK, COLOR_BLACK, option)
|
||||||
|
cellAskImpv = OmCell('%.1f' %(option.askImpv*100), COLOR_ASK, COLOR_BLACK, option)
|
||||||
|
cellPos = OmCell(str(option.netPos), COLOR_POS, COLOR_BLACK, option)
|
||||||
|
|
||||||
|
self.setItem(putRow, 9, cellPos)
|
||||||
|
self.setItem(putRow, 10, cellBidPrice)
|
||||||
|
self.setItem(putRow, 11, cellBidVolume)
|
||||||
|
self.setItem(putRow, 12, cellBidImpv)
|
||||||
|
self.setItem(putRow, 13, cellAskPrice)
|
||||||
|
self.setItem(putRow, 14, cellAskVolume)
|
||||||
|
self.setItem(putRow, 15, cellAskImpv)
|
||||||
|
self.setItem(putRow, 16, cellSymbol)
|
||||||
|
|
||||||
|
self.bidPriceDict[option.symbol] = cellBidPrice
|
||||||
|
self.bidVolumeDict[option.symbol] = cellBidVolume
|
||||||
|
self.bidImpvDict[option.symbol] = cellBidImpv
|
||||||
|
self.askPriceDict[option.symbol] = cellAskPrice
|
||||||
|
self.askVolumeDict[option.symbol] = cellAskVolume
|
||||||
|
self.askImpvDict[option.symbol] = cellAskImpv
|
||||||
|
self.posDict[option.symbol] = cellPos
|
||||||
|
|
||||||
|
putRow += 1
|
||||||
|
|
||||||
|
row = putRow + 1
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def registerEvent(self):
|
||||||
|
"""注册事件监听"""
|
||||||
|
self.signalTick.connect(self.processTickEvent)
|
||||||
|
self.signalTrade.connect(self.processTradeEvent)
|
||||||
|
|
||||||
|
portfolio = self.omEngine.portfolio
|
||||||
|
|
||||||
|
for underlying in portfolio.underlyingDict.values():
|
||||||
|
self.eventEngine.register(EVENT_TICK + underlying.vtSymbol, self.signalTick.emit)
|
||||||
|
self.eventEngine.register(EVENT_TRADE + underlying.vtSymbol, self.signalTick.emit)
|
||||||
|
|
||||||
|
for chain in portfolio.chainDict.values():
|
||||||
|
for option in chain.optionDict.values():
|
||||||
|
self.eventEngine.register(EVENT_TICK + option.vtSymbol, self.signalTick.emit)
|
||||||
|
self.eventEngine.register(EVENT_TRADE + option.vtSymbol, self.signalTrade.emit)
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def processTickEvent(self, event):
|
||||||
|
"""行情更新"""
|
||||||
|
tick = event.dict_['data']
|
||||||
|
symbol = tick.symbol
|
||||||
|
|
||||||
|
if symbol in self.bidImpvDict:
|
||||||
|
option = self.instrumentDict[symbol]
|
||||||
|
self.bidImpvDict[symbol].setText('%.1f' %(option.bidImpv*100))
|
||||||
|
self.askImpvDict[symbol].setText('%.1f' %(option.askImpv*100))
|
||||||
|
|
||||||
|
self.bidPriceDict[symbol].setText(str(tick.bidPrice1))
|
||||||
|
self.bidVolumeDict[symbol].setText(str(tick.bidVolume1))
|
||||||
|
self.askPriceDict[symbol].setText(str(tick.askPrice1))
|
||||||
|
self.askVolumeDict[symbol].setText(str(tick.askVolume1))
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def processTradeEvent(self, event):
|
||||||
|
"""成交更新"""
|
||||||
|
trade = event.dict_['data']
|
||||||
|
|
||||||
|
symbol = trade.symbol
|
||||||
|
instrument = self.instrumentDict[symbol]
|
||||||
|
self.posDict[symbol].setText(str(instrument.netPos))
|
||||||
|
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
class TradingWidget(QtWidgets.QWidget):
|
||||||
|
"""交易组件"""
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def __init__(self, omEngine, parent=None):
|
||||||
|
"""Constructor"""
|
||||||
|
super(TradingWidget, self).__init__(parent)
|
||||||
|
|
||||||
|
self.omEngine = omEngine
|
||||||
|
self.mainEngine = omEngine.mainEngine
|
||||||
|
self.portfolio = omEngine.portfolio
|
||||||
|
|
||||||
|
self.initUi()
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def initUi(self):
|
||||||
|
"""初始化界面"""
|
||||||
|
self.setFixedWidth(200)
|
||||||
|
|
||||||
|
labelTradingWidget = QtWidgets.QLabel(u'期权交易')
|
||||||
|
labelSymbol = QtWidgets.QLabel(u'代码')
|
||||||
|
labelDirection = QtWidgets.QLabel(u'方向')
|
||||||
|
labelPrice = QtWidgets.QLabel(u'价格')
|
||||||
|
labelVolume = QtWidgets.QLabel(u'数量')
|
||||||
|
|
||||||
|
self.lineSymbol = QtWidgets.QLineEdit()
|
||||||
|
self.comboDirection = QtWidgets.QComboBox()
|
||||||
|
self.comboDirection.addItems([DIRECTION_LONG, DIRECTION_SHORT])
|
||||||
|
self.linePrice = QtWidgets.QLineEdit()
|
||||||
|
self.lineVolume = QtWidgets.QLineEdit()
|
||||||
|
self.buttonSendOrder = QtWidgets.QPushButton(u'发单')
|
||||||
|
self.buttonSendOrder.clicked.connect(self.sendOrder)
|
||||||
|
|
||||||
|
grid = QtWidgets.QGridLayout()
|
||||||
|
grid.addWidget(labelTradingWidget, 0, 0, 1, 2)
|
||||||
|
grid.addWidget(labelSymbol, 1, 0)
|
||||||
|
grid.addWidget(labelDirection, 2, 0)
|
||||||
|
grid.addWidget(labelPrice, 3, 0)
|
||||||
|
grid.addWidget(labelVolume, 4, 0)
|
||||||
|
grid.addWidget(self.lineSymbol, 1, 1)
|
||||||
|
grid.addWidget(self.comboDirection, 2, 1)
|
||||||
|
grid.addWidget(self.linePrice, 3, 1)
|
||||||
|
grid.addWidget(self.lineVolume, 4, 1)
|
||||||
|
grid.addWidget(self.buttonSendOrder, 5, 0, 1, 2)
|
||||||
|
self.setLayout(grid)
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def sendOrder(self):
|
||||||
|
"""发送委托"""
|
||||||
|
try:
|
||||||
|
symbol = str(self.lineSymbol.text())
|
||||||
|
direction = str(self.comboDirection.currentText())
|
||||||
|
price = float(self.linePrice.text())
|
||||||
|
volume = int(self.lineVolume.text())
|
||||||
|
except:
|
||||||
|
return
|
||||||
|
|
||||||
|
instrument = self.portfolio.instrumentDict.get(symbol, None)
|
||||||
|
if not instrument:
|
||||||
|
return
|
||||||
|
|
||||||
|
# 做多
|
||||||
|
if direction == DIRECTION_LONG:
|
||||||
|
# 如果空头仓位大于等于买入量,则只需平
|
||||||
|
if instrument.shortPos >= volume:
|
||||||
|
self.fastTrade(symbol, DIRECTION_LONG, OFFSET_CLOSE, price, volume)
|
||||||
|
# 否则先平后开
|
||||||
|
else:
|
||||||
|
openVolume = volume - instrument.shortPos
|
||||||
|
if instrument.shortPos:
|
||||||
|
self.fastTrade(symbol, DIRECTION_LONG, OFFSET_CLOSE, price, instrument.shortPos)
|
||||||
|
self.fastTrade(symbol, DIRECTION_LONG, OFFSET_OPEN, price, openVolume)
|
||||||
|
# 做空
|
||||||
|
else:
|
||||||
|
if instrument.longPos >= volume:
|
||||||
|
self.fastTrade(symbol, DIRECTION_SHORT, OFFSET_CLOSE, price, volume)
|
||||||
|
else:
|
||||||
|
openVolume = volume - instrument.longPos
|
||||||
|
if instrument.longPos:
|
||||||
|
self.fastTrade(symbol, DIRECTION_SHORT, OFFSET_CLOSE, price, instrument.longPos)
|
||||||
|
self.fastTrade(symbol ,DIRECTION_SHORT, OFFSET_OPEN, price, openVolume)
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def fastTrade(self, symbol, direction, offset, price, volume):
|
||||||
|
"""封装下单函数"""
|
||||||
|
contract = self.mainEngine.getContract(symbol)
|
||||||
|
if not contract:
|
||||||
|
return
|
||||||
|
|
||||||
|
req = VtOrderReq()
|
||||||
|
req.symbol = symbol
|
||||||
|
req.exchange = contract.exchange
|
||||||
|
req.direction = direction
|
||||||
|
req.offset = offset
|
||||||
|
req.price = price
|
||||||
|
req.volume = volume
|
||||||
|
req.priceType = PRICETYPE_LIMITPRICE
|
||||||
|
self.mainEngine.sendOrder(req, contract.gatewayName)
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def updateWidget(self, item):
|
||||||
|
"""双击监控组件单元格后自动更新组件"""
|
||||||
|
instrument = item.data
|
||||||
|
if not instrument:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.lineSymbol.setText(instrument.symbol)
|
||||||
|
|
||||||
|
# short
|
||||||
|
if item.background is COLOR_BID:
|
||||||
|
self.comboDirection.setCurrentIndex(1)
|
||||||
|
self.linePrice.setText(str(instrument.bidPrice1))
|
||||||
|
self.lineVolume.setText(str(instrument.bidVolume1))
|
||||||
|
# long
|
||||||
|
elif item.background is COLOR_ASK:
|
||||||
|
self.comboDirection.setCurrentIndex(0)
|
||||||
|
self.linePrice.setText(str(instrument.askPrice1))
|
||||||
|
self.lineVolume.setText(str(instrument.askVolume1))
|
||||||
|
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
class ManualTrader(QtWidgets.QWidget):
|
||||||
|
"""手动交易组件"""
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def __init__(self, omEngine, parent=None):
|
||||||
|
"""Constructor"""
|
||||||
|
super(ManualTrader, self).__init__(parent)
|
||||||
|
|
||||||
|
self.omEngine = omEngine
|
||||||
|
self.mainEngine = omEngine.mainEngine
|
||||||
|
self.eventEngine = omEngine.eventEngine
|
||||||
|
|
||||||
|
self.initUi()
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def initUi(self):
|
||||||
|
"""初始化界面"""
|
||||||
|
self.setWindowTitle(u'手动交易')
|
||||||
|
|
||||||
|
posMonitor = PositionMonitor(self.mainEngine, self.eventEngine)
|
||||||
|
for i in range(posMonitor.columnCount()):
|
||||||
|
posMonitor.horizontalHeader().setResizeMode(QtWidgets.QHeaderView.Stretch)
|
||||||
|
posMonitor.setSorting(False)
|
||||||
|
|
||||||
|
orderMonitor = WorkingOrderMonitor(self.mainEngine, self.eventEngine)
|
||||||
|
for i in range(orderMonitor.columnCount()):
|
||||||
|
orderMonitor.horizontalHeader().setResizeMode(QtWidgets.QHeaderView.Stretch)
|
||||||
|
orderMonitor.setSorting(False)
|
||||||
|
|
||||||
|
tradingWidget = TradingWidget(self.omEngine)
|
||||||
|
|
||||||
|
chainMonitor = ChainMonitor(self.omEngine, self.eventEngine)
|
||||||
|
chainMonitor.itemDoubleClicked.connect(tradingWidget.updateWidget)
|
||||||
|
|
||||||
|
vbox1 = QtWidgets.QVBoxLayout()
|
||||||
|
vbox1.addWidget(orderMonitor)
|
||||||
|
vbox1.addWidget(posMonitor)
|
||||||
|
|
||||||
|
vbox2 = QtWidgets.QVBoxLayout()
|
||||||
|
vbox2.addWidget(tradingWidget)
|
||||||
|
vbox2.addStretch()
|
||||||
|
|
||||||
|
hbox = QtWidgets.QHBoxLayout()
|
||||||
|
hbox.addLayout(vbox1)
|
||||||
|
hbox.addLayout(vbox2)
|
||||||
|
|
||||||
|
vbox3 = QtWidgets.QVBoxLayout()
|
||||||
|
vbox3.addWidget(chainMonitor)
|
||||||
|
vbox3.addLayout(hbox)
|
||||||
|
|
||||||
|
self.setLayout(vbox3)
|
||||||
|
|
||||||
|
|
@ -9,6 +9,7 @@ from vnpy.event import Event
|
|||||||
from vnpy.trader.uiQt import QtWidgets, QtCore
|
from vnpy.trader.uiQt import QtWidgets, QtCore
|
||||||
|
|
||||||
from .omBase import EVENT_OM_LOG
|
from .omBase import EVENT_OM_LOG
|
||||||
|
from .uiOmManualTrader import ManualTrader
|
||||||
|
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
@ -51,12 +52,16 @@ class OmManager(QtWidgets.QWidget):
|
|||||||
self.buttonInit = QtWidgets.QPushButton(u'初始化')
|
self.buttonInit = QtWidgets.QPushButton(u'初始化')
|
||||||
self.buttonInit.clicked.connect(self.initOmEngine)
|
self.buttonInit.clicked.connect(self.initOmEngine)
|
||||||
|
|
||||||
|
self.buttonManualTrader = QtWidgets.QPushButton(u'手动交易')
|
||||||
|
self.buttonManualTrader.clicked.connect(self.openManualTrader)
|
||||||
|
|
||||||
self.logMonitor = QtWidgets.QTextEdit()
|
self.logMonitor = QtWidgets.QTextEdit()
|
||||||
self.logMonitor.setReadOnly(True)
|
self.logMonitor.setReadOnly(True)
|
||||||
|
|
||||||
hbox = QtWidgets.QHBoxLayout()
|
hbox = QtWidgets.QHBoxLayout()
|
||||||
hbox.addWidget(self.comboSettingFile)
|
hbox.addWidget(self.comboSettingFile)
|
||||||
hbox.addWidget(self.buttonInit)
|
hbox.addWidget(self.buttonInit)
|
||||||
|
hbox.addWidget(self.buttonManualTrader)
|
||||||
hbox.addStretch()
|
hbox.addStretch()
|
||||||
|
|
||||||
hbox2 = QtWidgets.QHBoxLayout()
|
hbox2 = QtWidgets.QHBoxLayout()
|
||||||
@ -99,7 +104,7 @@ class OmManager(QtWidgets.QWidget):
|
|||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def openManualTrader(self):
|
def openManualTrader(self):
|
||||||
"""打开手动交易"""
|
"""打开手动交易组件"""
|
||||||
try:
|
try:
|
||||||
self.widgetDict['manualTrader'].showMaximized()
|
self.widgetDict['manualTrader'].showMaximized()
|
||||||
except KeyError:
|
except KeyError:
|
||||||
@ -120,4 +125,3 @@ class OmManager(QtWidgets.QWidget):
|
|||||||
self.signal.connect(self.processLogEvent)
|
self.signal.connect(self.processLogEvent)
|
||||||
|
|
||||||
self.eventEngine.register(EVENT_OM_LOG, self.signal.emit)
|
self.eventEngine.register(EVENT_OM_LOG, self.signal.emit)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user