初步完成价差交易界面

This commit is contained in:
vn.py 2017-06-23 16:27:05 +08:00
parent 2578e1b419
commit 79a9ac2bfb
5 changed files with 654 additions and 46 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 65 KiB

View File

@ -12,9 +12,9 @@ from vnpy.trader.vtConstant import (EMPTY_INT, EMPTY_FLOAT,
########################################################################
class StAlgoTemplate(object):
"""价差算法交易模板"""
MODE_LONGSHORT = 1
MODE_LONGONLY = 2
MODE_SHORTONLY = 3
MODE_LONGSHORT = u'双向'
MODE_LONGONLY = u'做多'
MODE_SHORTONLY = u'做空'
SPREAD_LONG = 1
SPREAD_SHORT = 2
@ -65,7 +65,7 @@ class StAlgoTemplate(object):
raise NotImplementedError
#----------------------------------------------------------------------
def start(self, mode=MODE_LONGSHORT):
def start(self):
""""""
raise NotImplementedError
@ -74,7 +74,79 @@ class StAlgoTemplate(object):
""""""
raise NotImplementedError
#----------------------------------------------------------------------
def setBuyPrice(self, buyPrice):
"""设置买开的价格"""
self.buyPrice = buyPrice
#----------------------------------------------------------------------
def setSellPrice(self, sellPrice):
"""设置卖平的价格"""
self.sellPrice = sellPrice
#----------------------------------------------------------------------
def setShortPrice(self, shortPrice):
"""设置卖开的价格"""
self.shortPrice = shortPrice
#----------------------------------------------------------------------
def setCoverPrice(self, coverPrice):
"""设置买平的价格"""
self.coverPrice = coverPrice
#----------------------------------------------------------------------
def setMode(self, mode):
"""设置算法交易方向"""
self.mode = mode
#----------------------------------------------------------------------
def setMaxOrderSize(self, maxOrderSize):
"""设置最大单笔委托数量"""
self.maxOrderSize = maxOrderSize
#----------------------------------------------------------------------
def setMaxPosSize(self, maxPosSize):
"""设置最大持仓数量"""
self.maxPosSize = maxPosSize
#----------------------------------------------------------------------
def putEvent(self):
"""发出算法更新事件"""
self.algoEngine.putAlgoEvent(self)
#----------------------------------------------------------------------
def writeLog(self, content):
"""输出算法日志"""
content = ':'.join([self.spreadName, content])
self.algoEngine.writeLog(content)
#----------------------------------------------------------------------
def getAlgoParams(self):
"""获取算法参数"""
d = {
"spreadName": self.spreadName,
"algoName": self.algoName,
"buyPrice": self.buyPrice,
"sellPrice": self.sellPrice,
"shortPrice": self.shortPrice,
"coverPrice": self.coverPrice,
"maxOrderSize": self.maxOrderSize,
"maxPosSize": self.maxPosSize,
"mode": self.mode
}
return d
#----------------------------------------------------------------------
def setAlgoParams(self, d):
"""设置算法参数"""
self.buyPrice = d.get('buyPrice', EMPTY_FLOAT)
self.sellPrice = d.get('sellPrice', EMPTY_FLOAT)
self.shortPrice = d.get('shortPrice', EMPTY_FLOAT)
self.coverPrice = d.get('coverPrice', EMPTY_FLOAT)
self.maxOrderSize = d.get('maxOrderSize', EMPTY_INT)
self.maxPosSize = d.get('maxPosSize', EMPTY_INT)
self.mode = d.get('mode', self.MODE_LONGSHORT)
########################################################################
class SniperAlgo(StAlgoTemplate):
@ -82,9 +154,9 @@ class SniperAlgo(StAlgoTemplate):
FINISHED_STATUS = [STATUS_ALLTRADED, STATUS_CANCELLED, STATUS_REJECTED]
#----------------------------------------------------------------------
def __init__(self, algoEngine):
def __init__(self, algoEngine, spread):
"""Constructor"""
super(SniperAlgo, self).__init__(algoEngine)
super(SniperAlgo, self).__init__(algoEngine, spread)
self.algoName = u'Sniper'
self.quoteInterval = 2 # 主动腿报价撤单再发前等待的时间
@ -125,11 +197,13 @@ class SniperAlgo(StAlgoTemplate):
spread.netPos < self.maxPosSize and
spread.askPrice <= self.buyPrice):
self.quoteActiveLeg(self.SPREAD_LONG)
self.writeLog(u'买入开仓')
# 卖出
elif (spread.netPos > 0 and
spread.bidPrice >= self.sellPrice):
self.quoteActiveLeg(self.SPREAD_SHORT)
self.writeLog(u'卖出平仓')
# 允许做空
if self.mode == self.MODE_LONGSHORT or self.mode == self.MODE_SHORTONLY:
@ -138,11 +212,13 @@ class SniperAlgo(StAlgoTemplate):
spread.netPos > -self.maxPosSize and
spread.bidPrice >= self.shortPrice):
self.quoteActiveLeg(self.SPREAD_SHORT)
self.writeLog(u'卖出开仓')
# 平空
elif (spread.netPos < 0 and
spread.askPrice <= self.coverPrice):
self.quoteActiveLeg(self.SPREAD_LONG)
self.writeLog(u'买入平仓')
#----------------------------------------------------------------------
def updateSpreadPos(self, spread):
@ -180,10 +256,14 @@ class SniperAlgo(StAlgoTemplate):
# 检查若是被动腿,且已经没有未完成委托,则执行对冲
if not orderList and vtSymbol in self.passiveVtSymbols:
self.hedgePassiveLeg(vtSymbol)
self.writeLog(u'发出新的被动腿%s对冲单' %vtSymbol)
#----------------------------------------------------------------------
def updateTimer(self):
"""计时更新"""
if not self.active:
return
self.quoteCount += 1
self.hedgeCount += 1
@ -200,10 +280,14 @@ class SniperAlgo(StAlgoTemplate):
self.hedgeCount = 0
#----------------------------------------------------------------------
def start(self, mode=MODE_LONGSHORT):
def start(self):
"""启动"""
self.mode = mode
self.active = True
self.quoteCount = 0
self.hedgeCount = 0
return self.active
#----------------------------------------------------------------------
def stop(self):
@ -212,6 +296,8 @@ class SniperAlgo(StAlgoTemplate):
self.hedgingTaskDict.clear()
self.cancelAllOrders()
return self.active
#----------------------------------------------------------------------
def sendLegOrder(self, leg, legVolume):
@ -310,6 +396,9 @@ class SniperAlgo(StAlgoTemplate):
self.hedgingTaskDict[leg.vtSymbol] = newHedgingTask
else:
self.hedgingTaskDict[leg.vtSymbol] += newHedgingTask
# 输出日志
self.writeLog(u'主动腿%s成交,方向%s,数量%s' %(trade.vtSymbol, trade.direction, trade.volume))
#----------------------------------------------------------------------
def newPassiveLegTrade(self, trade):
@ -328,6 +417,9 @@ class SniperAlgo(StAlgoTemplate):
if not self.hedgingTaskDict[trade.vtSymbol]:
del self.hedgingTaskDict[trade.vtSymbol]
# 输出日志
self.writeLog(u'被动腿%s成交,方向%s,数量%s' %(trade.vtSymbol, trade.direction, trade.volume))
#----------------------------------------------------------------------
def cancelLegOrder(self, vtSymbol):
"""撤销某条腿的委托"""
@ -339,15 +431,27 @@ class SniperAlgo(StAlgoTemplate):
for vtOrderID in orderList:
self.algoEngine.cancelOrder(vtOrderID)
self.writeLog(u'撤单%s的所有委托' %vtSymbol)
#----------------------------------------------------------------------
def cancelAllOrders(self):
"""撤销全部委托"""
for orderList in self.legOrderDict.values():
for vtOrderID in orderList:
self.algoEngine.cancelOrder(vtOrderID)
self.writeLog(u'全部撤单')
#----------------------------------------------------------------------
def cancelAllPassiveLegOrders(self):
"""撤销全部被动腿委托"""
cancelPassive = False
for vtSymbol in self.passiveVtSymbols:
self.cancelLegOrder(vtSymbol)
if self.legOrderDict[vtSymbol]:
self.cancelLegOrder(vtSymbol)
cancelPassive = True
# 只有确实发出撤单委托时,才输出信息
if cancelPassive:
self.writeLog(u'被动腿全撤')

View File

@ -13,6 +13,8 @@ from vnpy.trader.vtConstant import (EMPTY_INT, EMPTY_FLOAT,
EVENT_SPREADTRADING_TICK = 'eSpreadTradingTick.'
EVENT_SPREADTRADING_POS = 'eSpreadTradingPos.'
EVENT_SPREADTRADING_LOG = 'eSpreadTradingLog'
EVENT_SPREADTRADING_ALGO = 'eSpreadTradingAlgo.'
EVENT_SPREADTRADING_ALGOLOG = 'eSpreadTradingAlgoLog'

View File

@ -2,10 +2,10 @@
import json
import traceback
from copy import copy
import shelve
from vnpy.event import Event
from vnpy.trader.vtFunction import getJsonPath
from vnpy.trader.vtFunction import getJsonPath, getTempPath
from vnpy.trader.vtEvent import (EVENT_TICK, EVENT_TRADE, EVENT_POSITION,
EVENT_TIMER, EVENT_ORDER)
from vnpy.trader.vtObject import (VtSubscribeReq, VtOrderReq,
@ -14,7 +14,9 @@ from vnpy.trader.vtConstant import (DIRECTION_LONG, DIRECTION_SHORT,
OFFSET_OPEN, OFFSET_CLOSE)
from .stBase import (StLeg, StSpread, EVENT_SPREADTRADING_TICK,
EVENT_SPREADTRADING_POS, EVENT_SPREADTRADING_LOG)
EVENT_SPREADTRADING_POS, EVENT_SPREADTRADING_LOG,
EVENT_SPREADTRADING_ALGO, EVENT_SPREADTRADING_ALGOLOG)
from .stAlgo import SniperAlgo
########################################################################
@ -121,6 +123,9 @@ class StDataEngine(object):
# 初始化价差
spread.initSpread()
self.putSpreadTickEvent(spread)
self.putSpreadPosEvent(spread)
# 返回结果
result = True
msg = u'%s价差创建成功' %spread.name
@ -145,7 +150,12 @@ class StDataEngine(object):
spread = self.vtSymbolSpreadDict[tick.vtSymbol]
spread.calculatePrice()
# 推送价差行情更新
# 发出事件
self.putSpreadTickEvent(spread)
#----------------------------------------------------------------------
def putSpreadTickEvent(self, spread):
"""发出价差行情更新事件"""
event1 = Event(EVENT_SPREADTRADING_TICK+spread.name)
event1.dict_['data'] = spread
self.eventEngine.put(event1)
@ -215,13 +225,19 @@ class StDataEngine(object):
spread.calculatePos()
# 推送价差持仓更新
self.putSpreadPosEvent(spread)
#----------------------------------------------------------------------
def putSpreadPosEvent(self, spread):
"""发出价差持仓事件"""
event1 = Event(EVENT_SPREADTRADING_POS+spread.name)
event1.dict_['data'] = spread
self.eventEngine.put(event1)
event2 = Event(EVENT_SPREADTRADING_POS)
event2.dict_['data'] = spread
self.eventEngine.put(event2)
self.eventEngine.put(event2)
#----------------------------------------------------------------------
def registerEvent(self):
@ -236,6 +252,7 @@ class StDataEngine(object):
contract = self.mainEngine.getContract(vtSymbol)
if not contract:
self.writeLog(u'订阅行情失败,找不到该合约%s' %vtSymbol)
return
req = VtSubscribeReq()
req.symbol = contract.symbol
@ -254,18 +271,21 @@ class StDataEngine(object):
self.eventEngine.put(event)
#----------------------------------------------------------------------
def stop(self):
"""停止"""
pass
def getAllSpreads(self):
"""获取所有的价差"""
return self.spreadDict.values()
########################################################################
class StAlgoEngine(object):
"""价差算法交易引擎"""
algoFileName = 'SpreadTradingAlgo.vt'
algoFilePath = getTempPath(algoFileName)
#----------------------------------------------------------------------
def __init__(self, mainEngine, eventEngine):
def __init__(self, dataEngine, mainEngine, eventEngine):
"""Constructor"""
self.dataEngine = dataEngine
self.mainEngine = mainEngine
self.eventEngine = eventEngine
@ -387,6 +407,122 @@ class StAlgoEngine(object):
vtOrderID = self.sendOrder(vtSymbol, DIRECTION_LONG, OFFSET_CLOSE, price, volume, payup)
return [vtOrderID]
#----------------------------------------------------------------------
def putAlgoEvent(self, algo):
"""发出算法状态更新事件"""
event = Event(EVENT_SPREADTRADING_ALGO+algo.name)
self.eventEngine.put(event)
#----------------------------------------------------------------------
def writeLog(self, content):
"""输出日志"""
log = VtLogData()
log.logContent = content
event = Event(EVENT_SPREADTRADING_ALGOLOG)
event.dict_['data'] = log
self.eventEngine.put(event)
#----------------------------------------------------------------------
def saveSetting(self):
"""保存算法配置"""
setting = {}
for algo in self.algoDict.values():
setting[algo.spreadName] = algo.getAlgoParams()
f = shelve.open(self.algoFilePath)
f['setting'] = setting
f.close()
#----------------------------------------------------------------------
def loadSetting(self):
"""加载算法配置"""
# 创建算法对象
l = self.dataEngine.getAllSpreads()
for spread in l:
self.algoDict[spread.name] = SniperAlgo(self, spread)
# 加载配置
f = shelve.open(self.algoFilePath)
setting = f.get('setting', None)
f.close()
if not setting:
return
for algo in self.algoDict.values():
if algo.spreadName in setting:
d = setting[algo.spreadName]
algo.setAlgoParams(d)
#----------------------------------------------------------------------
def stopAll(self):
"""停止全部算法"""
for algo in self.algoDict.values():
algo.stop()
#----------------------------------------------------------------------
def startAlgo(self, spreadName):
"""启动算法"""
algo = self.algoDict[spreadName]
algoActive = algo.start()
return algoActive
#----------------------------------------------------------------------
def stopAlgo(self, spreadName):
"""停止算法"""
algo = self.algoDict[spreadName]
algoActive = algo.stop()
return algoActive
#----------------------------------------------------------------------
def getAllAlgoParams(self):
"""获取所有算法的参数"""
return [algo.getAlgoParams() for algo in self.algoDict.values()]
#----------------------------------------------------------------------
def setAlgoBuyPrice(self, spreadName, buyPrice):
"""设置算法买开价格"""
algo = self.algoDict[spreadName]
algo.setBuyPrice(buyPrice)
#----------------------------------------------------------------------
def setAlgoSellPrice(self, spreadName, sellPrice):
"""设置算法卖平价格"""
algo = self.algoDict[spreadName]
algo.setSellPrice(sellPrice)
#----------------------------------------------------------------------
def setAlgoShortPrice(self, spreadName, shortPrice):
"""设置算法卖开价格"""
algo = self.algoDict[spreadName]
algo.setShortPrice(shortPrice)
#----------------------------------------------------------------------
def setAlgoCoverPrice(self, spreadName, coverPrice):
"""设置算法买平价格"""
algo = self.algoDict[spreadName]
algo.setCoverPrice(coverPrice)
#----------------------------------------------------------------------
def setAlgoMode(self, spreadName, mode):
"""设置算法工作模式"""
algo = self.algoDict[spreadName]
algo.setMode(mode)
#----------------------------------------------------------------------
def setAlgoMaxOrderSize(self, spreadName, maxOrderSize):
"""设置算法单笔委托限制"""
algo = self.algoDict[spreadName]
algo.setMaxOrderSize(maxOrderSize)
#----------------------------------------------------------------------
def setAlgoMaxPosSize(self, spreadName, maxPosSize):
"""设置算法持仓限制"""
algo = self.algoDict[spreadName]
algo.setMaxPosSize(maxPosSize)
########################################################################
class StEngine(object):
@ -399,12 +535,21 @@ class StEngine(object):
self.eventEngine = eventEngine
self.dataEngine = StDataEngine(mainEngine, eventEngine)
self.algoEngine = StAlgoEngine(mainEngine, eventEngine)
self.algoEngine = StAlgoEngine(self.dataEngine, mainEngine, eventEngine)
#----------------------------------------------------------------------
def loadSetting(self):
""""""
def init(self):
"""初始化"""
self.dataEngine.loadSetting()
self.algoEngine.loadSetting()
#----------------------------------------------------------------------
def stop(self):
"""停止"""
self.dataEngine.saveSetting()
self.algoEngine.stopAll()
self.algoEngine.saveSetting()

View File

@ -2,14 +2,20 @@
from collections import OrderedDict
from vnpy.trader.uiQt import QtWidgets
from vnpy.event import Event
from vnpy.trader.uiQt import QtWidgets, QtCore
from vnpy.trader.uiBasicWidget import (BasicMonitor, BasicCell, PnlCell,
AskCell, BidCell, BASIC_FONT)
from .stBase import (EVENT_SPREADTRADING_TICK, EVENT_SPREADTRADING_POS,
EVENT_SPREADTRADING_LOG)
EVENT_SPREADTRADING_LOG, EVENT_SPREADTRADING_ALGO,
EVENT_SPREADTRADING_ALGOLOG)
from .stAlgo import StAlgoTemplate
STYLESHEET_START = 'background-color: rgb(111,255,244); color: black'
STYLESHEET_STOP = 'background-color: rgb(255,201,111); color: black'
########################################################################
class StTickMonitor(BasicMonitor):
@ -64,25 +70,365 @@ class StPosMonitor(BasicMonitor):
########################################################################
class StLogMonitor(BasicMonitor):
class StLogMonitor(QtWidgets.QTextEdit):
"""价差日志监控"""
signal = QtCore.pyqtSignal(type(Event()))
#----------------------------------------------------------------------
def __init__(self, mainEngine, eventEngine, parent=None):
"""Constructor"""
super(StLogMonitor, self).__init__(parent)
self.eventEngine = eventEngine
self.registerEvent()
#----------------------------------------------------------------------
def processLogEvent(self, event):
"""处理日志事件"""
log = event.dict_['data']
content = '%s:%s' %(log.logTime, log.logContent)
self.append(content)
#----------------------------------------------------------------------
def registerEvent(self):
"""注册事件监听"""
self.signal.connect(self.processLogEvent)
self.eventEngine.register(EVENT_SPREADTRADING_LOG, self.signal.emit)
########################################################################
class StAlgoLogMonitor(BasicMonitor):
"""价差日志监控"""
#----------------------------------------------------------------------
def __init__(self, mainEngine, eventEngine, parent=None):
"""Constructor"""
super(StLogMonitor, self).__init__(mainEngine, eventEngine, parent)
super(StAlgoLogMonitor, self).__init__(mainEngine, eventEngine, parent)
d = OrderedDict()
d['logTime'] = {'chinese':u'时间', 'cellType':BasicCell}
d['logContent'] = {'chinese':u'日志', 'cellType':BasicCell}
d['logContent'] = {'chinese':u'信息', 'cellType':BasicCell}
self.setHeaderDict(d)
self.setEventType(EVENT_SPREADTRADING_LOG)
self.setEventType(EVENT_SPREADTRADING_ALGOLOG)
self.setFont(BASIC_FONT)
self.initTable()
self.registerEvent()
self.registerEvent()
########################################################################
class StBuyPriceSpinBox(QtWidgets.QDoubleSpinBox):
""""""
#----------------------------------------------------------------------
def __init__(self, algoEngine, spreadName, price, parent=None):
"""Constructor"""
super(StBuyPriceSpinBox, self).__init__(parent)
self.algoEngine = algoEngine
self.spreadName = spreadName
self.setDecimals(4)
self.setRange(-10000, 10000)
self.setValue(price)
self.valueChanged.connect(self.setPrice)
#----------------------------------------------------------------------
def setPrice(self, value):
"""设置价格"""
self.algoEngine.setAlgoBuyPrice(self.spreadName, value)
########################################################################
class StSellPriceSpinBox(QtWidgets.QDoubleSpinBox):
""""""
#----------------------------------------------------------------------
def __init__(self, algoEngine, spreadName, price, parent=None):
"""Constructor"""
super(StSellPriceSpinBox, self).__init__(parent)
self.algoEngine = algoEngine
self.spreadName = spreadName
self.setDecimals(4)
self.setRange(-10000, 10000)
self.setValue(price)
self.valueChanged.connect(self.setPrice)
#----------------------------------------------------------------------
def setPrice(self, value):
"""设置价格"""
self.algoEngine.setAlgoSellPrice(self.spreadName, value)
########################################################################
class StShortPriceSpinBox(QtWidgets.QDoubleSpinBox):
""""""
#----------------------------------------------------------------------
def __init__(self, algoEngine, spreadName, price, parent=None):
"""Constructor"""
super(StShortPriceSpinBox, self).__init__(parent)
self.algoEngine = algoEngine
self.spreadName = spreadName
self.setDecimals(4)
self.setRange(-10000, 10000)
self.setValue(price)
self.valueChanged.connect(self.setPrice)
#----------------------------------------------------------------------
def setPrice(self, value):
"""设置价格"""
self.algoEngine.setAlgoShortPrice(self.spreadName, value)
########################################################################
class StCoverPriceSpinBox(QtWidgets.QDoubleSpinBox):
""""""
#----------------------------------------------------------------------
def __init__(self, algoEngine, spreadName, price, parent=None):
"""Constructor"""
super(StCoverPriceSpinBox, self).__init__(parent)
self.algoEngine = algoEngine
self.spreadName = spreadName
self.setDecimals(4)
self.setRange(-10000, 10000)
self.setValue(price)
self.valueChanged.connect(self.setPrice)
#----------------------------------------------------------------------
def setPrice(self, value):
"""设置价格"""
self.algoEngine.setAlgoCoverPrice(self.spreadName, value)
########################################################################
class StMaxPosSizeSpinBox(QtWidgets.QSpinBox):
""""""
#----------------------------------------------------------------------
def __init__(self, algoEngine, spreadName, size, parent=None):
"""Constructor"""
super(StMaxPosSizeSpinBox, self).__init__(parent)
self.algoEngine = algoEngine
self.spreadName = spreadName
self.setRange(-10000, 10000)
self.setValue(size)
self.valueChanged.connect(self.setSize)
#----------------------------------------------------------------------
def setSize(self, size):
"""设置价格"""
self.algoEngine.setAlgoMaxPosSize(self.spreadName, size)
########################################################################
class StMaxOrderSizeSpinBox(QtWidgets.QSpinBox):
""""""
#----------------------------------------------------------------------
def __init__(self, algoEngine, spreadName, size, parent=None):
"""Constructor"""
super(StMaxOrderSizeSpinBox, self).__init__(parent)
self.algoEngine = algoEngine
self.spreadName = spreadName
self.setRange(-10000, 10000)
self.setValue(size)
self.valueChanged.connect(self.setSize)
#----------------------------------------------------------------------
def setSize(self, size):
"""设置价格"""
self.algoEngine.setAlgoMaxOrderSize(self.spreadName, size)
########################################################################
class StModeComboBox(QtWidgets.QComboBox):
""""""
#----------------------------------------------------------------------
def __init__(self, algoEngine, spreadName, mode, parent=None):
"""Constructor"""
super(StModeComboBox, self).__init__(parent)
self.algoEngine = algoEngine
self.spreadName = spreadName
l = [StAlgoTemplate.MODE_LONGSHORT,
StAlgoTemplate.MODE_LONGONLY,
StAlgoTemplate.MODE_SHORTONLY]
self.addItems(l)
self.setCurrentIndex(l.index(mode))
self.currentIndexChanged.connect(self.setMode)
#----------------------------------------------------------------------
def setMode(self):
"""设置模式"""
mode = unicode(self.currentText())
self.algoEngine.setAlgoMode(self.spreadName, mode)
#----------------------------------------------------------------------
def algoActiveChanged(self, active):
"""算法运行状态改变"""
# 只允许算法停止时修改运行模式
if active:
self.setEnabled(False)
else:
self.setEnabled(True)
########################################################################
class StActiveButton(QtWidgets.QPushButton):
""""""
signalActive = QtCore.pyqtSignal(bool)
#----------------------------------------------------------------------
def __init__(self, algoEngine, spreadName, parent=None):
"""Constructor"""
super(StActiveButton, self).__init__(parent)
self.algoEngine = algoEngine
self.spreadName = spreadName
self.active = False
self.setStopped()
self.clicked.connect(self.buttonClicked)
#----------------------------------------------------------------------
def buttonClicked(self):
"""改变运行模式"""
if self.active:
algoActive = self.algoEngine.stopAlgo(self.spreadName)
if not algoActive:
self.setStopped()
else:
algoActive = self.algoEngine.startAlgo(self.spreadName)
if algoActive:
self.setStarted()
#----------------------------------------------------------------------
def setStarted(self):
"""算法启动"""
self.setText(u'运行中')
self.setStyleSheet(STYLESHEET_START)
self.active = True
self.signalActive.emit(self.active)
#----------------------------------------------------------------------
def setStopped(self):
"""算法停止"""
self.setText(u'已停止')
self.setStyleSheet(STYLESHEET_STOP)
self.active = False
self.signalActive.emit(self.active)
########################################################################
class StAlgoManager(QtWidgets.QTableWidget):
""""""
#----------------------------------------------------------------------
def __init__(self, stEngine, parent=None):
"""Constructor"""
super(StAlgoManager, self).__init__(parent)
self.algoEngine = stEngine.algoEngine
self.initUi()
#----------------------------------------------------------------------
def initUi(self):
"""初始化表格"""
headers = [u'价差',
u'算法',
'BuyPrice',
'SellPrice',
'CoverPrice',
'ShortPrice',
u'委托上限',
u'持仓上限',
u'模式',
u'状态']
self.setColumnCount(len(headers))
self.setHorizontalHeaderLabels(headers)
self.horizontalHeader().setResizeMode(QtWidgets.QHeaderView.Stretch)
self.verticalHeader().setVisible(False)
self.setEditTriggers(self.NoEditTriggers)
#----------------------------------------------------------------------
def initCells(self):
"""初始化单元格"""
algoEngine = self.algoEngine
l = self.algoEngine.getAllAlgoParams()
self.setRowCount(len(l))
for row, d in enumerate(l):
cellSpreadName = QtWidgets.QTableWidgetItem(d['spreadName'])
cellAlgoName = QtWidgets.QTableWidgetItem(d['algoName'])
spinBuyPrice = StBuyPriceSpinBox(algoEngine, d['spreadName'], d['buyPrice'])
spinSellPrice = StSellPriceSpinBox(algoEngine, d['spreadName'], d['sellPrice'])
spinShortPrice = StShortPriceSpinBox(algoEngine, d['spreadName'], d['shortPrice'])
spinCoverPrice = StCoverPriceSpinBox(algoEngine, d['spreadName'], d['coverPrice'])
spinMaxOrderSize = StMaxOrderSizeSpinBox(algoEngine, d['spreadName'], d['maxOrderSize'])
spinMaxPosSize = StMaxPosSizeSpinBox(algoEngine, d['spreadName'], d['maxPosSize'])
comboMode = StModeComboBox(algoEngine, d['spreadName'], d['mode'])
buttonActive = StActiveButton(algoEngine, d['spreadName'])
self.setItem(row, 0, cellSpreadName)
self.setItem(row, 1, cellAlgoName)
self.setCellWidget(row, 2, spinBuyPrice)
self.setCellWidget(row, 3, spinSellPrice)
self.setCellWidget(row, 4, spinCoverPrice)
self.setCellWidget(row, 5, spinShortPrice)
self.setCellWidget(row, 6, spinMaxOrderSize)
self.setCellWidget(row, 7, spinMaxPosSize)
self.setCellWidget(row, 8, comboMode)
self.setCellWidget(row, 9, buttonActive)
buttonActive.signalActive.connect(comboMode.algoActiveChanged)
########################################################################
class StGroup(QtWidgets.QGroupBox):
"""集合显示"""
#----------------------------------------------------------------------
def __init__(self, widget, title, parent=None):
"""Constructor"""
super(StGroup, self).__init__(parent)
self.setTitle(title)
vbox = QtWidgets.QVBoxLayout()
vbox.addWidget(widget)
self.setLayout(vbox)
########################################################################
class StManager(QtWidgets.QWidget):
@ -105,37 +451,48 @@ class StManager(QtWidgets.QWidget):
self.setWindowTitle(u'价差交易')
# 创建按钮
buttonLoadSetting = QtWidgets.QPushButton(u'加载配置')
buttonLoadSetting.clicked.connect(self.stEngine.loadSetting)
buttonInit = QtWidgets.QPushButton(u'初始化')
buttonInit.clicked.connect(self.init)
# 创建组件
tickMonitor = StTickMonitor(self.mainEngine, self.eventEngine)
posMonitor = StPosMonitor(self.mainEngine, self.eventEngine)
logMonitor = StLogMonitor(self.mainEngine, self.eventEngine)
self.algoManager = StAlgoManager(self.stEngine)
algoLogMonitor = StAlgoLogMonitor(self.mainEngine, self.eventEngine)
# 创建集合
groupTick = StGroup(tickMonitor, u'价差行情')
groupPos = StGroup(posMonitor, u'价差持仓')
groupLog = StGroup(logMonitor, u'日志信息')
groupAlgo = StGroup(self.algoManager, u'价差算法')
groupAlgoLog = StGroup(algoLogMonitor, u'算法信息')
# 设置布局
hbox1 = QtWidgets.QHBoxLayout()
hbox1.addWidget(buttonLoadSetting)
hbox1.addStretch()
hbox = QtWidgets.QHBoxLayout()
hbox.addWidget(buttonInit)
hbox.addStretch()
hbox2 = QtWidgets.QHBoxLayout()
hbox2.addWidget(tickMonitor)
hbox2.addWidget(posMonitor)
vbox = QtWidgets.QVBoxLayout()
vbox.addLayout(hbox1)
vbox.addLayout(hbox2)
vbox.addWidget(logMonitor)
self.setLayout(vbox)
grid = QtWidgets.QGridLayout()
grid.addLayout(hbox, 0, 0, 1, 2)
grid.addWidget(groupTick, 1, 0)
grid.addWidget(groupPos, 1, 1)
grid.addWidget(groupAlgo, 2, 0, 1, 2)
grid.addWidget(groupLog, 3, 0)
grid.addWidget(groupAlgoLog, 3, 1)
self.setLayout(grid)
#----------------------------------------------------------------------
def show(self):
"""重载显示"""
self.showMaximized()
#----------------------------------------------------------------------
def init(self):
"""初始化"""
self.stEngine.init()
self.algoManager.initCells()