初步完成价差交易界面

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): class StAlgoTemplate(object):
"""价差算法交易模板""" """价差算法交易模板"""
MODE_LONGSHORT = 1 MODE_LONGSHORT = u'双向'
MODE_LONGONLY = 2 MODE_LONGONLY = u'做多'
MODE_SHORTONLY = 3 MODE_SHORTONLY = u'做空'
SPREAD_LONG = 1 SPREAD_LONG = 1
SPREAD_SHORT = 2 SPREAD_SHORT = 2
@ -65,7 +65,7 @@ class StAlgoTemplate(object):
raise NotImplementedError raise NotImplementedError
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def start(self, mode=MODE_LONGSHORT): def start(self):
"""""" """"""
raise NotImplementedError raise NotImplementedError
@ -74,6 +74,78 @@ class StAlgoTemplate(object):
"""""" """"""
raise NotImplementedError 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)
######################################################################## ########################################################################
@ -82,9 +154,9 @@ class SniperAlgo(StAlgoTemplate):
FINISHED_STATUS = [STATUS_ALLTRADED, STATUS_CANCELLED, STATUS_REJECTED] FINISHED_STATUS = [STATUS_ALLTRADED, STATUS_CANCELLED, STATUS_REJECTED]
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def __init__(self, algoEngine): def __init__(self, algoEngine, spread):
"""Constructor""" """Constructor"""
super(SniperAlgo, self).__init__(algoEngine) super(SniperAlgo, self).__init__(algoEngine, spread)
self.algoName = u'Sniper' self.algoName = u'Sniper'
self.quoteInterval = 2 # 主动腿报价撤单再发前等待的时间 self.quoteInterval = 2 # 主动腿报价撤单再发前等待的时间
@ -125,11 +197,13 @@ class SniperAlgo(StAlgoTemplate):
spread.netPos < self.maxPosSize and spread.netPos < self.maxPosSize and
spread.askPrice <= self.buyPrice): spread.askPrice <= self.buyPrice):
self.quoteActiveLeg(self.SPREAD_LONG) self.quoteActiveLeg(self.SPREAD_LONG)
self.writeLog(u'买入开仓')
# 卖出 # 卖出
elif (spread.netPos > 0 and elif (spread.netPos > 0 and
spread.bidPrice >= self.sellPrice): spread.bidPrice >= self.sellPrice):
self.quoteActiveLeg(self.SPREAD_SHORT) self.quoteActiveLeg(self.SPREAD_SHORT)
self.writeLog(u'卖出平仓')
# 允许做空 # 允许做空
if self.mode == self.MODE_LONGSHORT or self.mode == self.MODE_SHORTONLY: 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.netPos > -self.maxPosSize and
spread.bidPrice >= self.shortPrice): spread.bidPrice >= self.shortPrice):
self.quoteActiveLeg(self.SPREAD_SHORT) self.quoteActiveLeg(self.SPREAD_SHORT)
self.writeLog(u'卖出开仓')
# 平空 # 平空
elif (spread.netPos < 0 and elif (spread.netPos < 0 and
spread.askPrice <= self.coverPrice): spread.askPrice <= self.coverPrice):
self.quoteActiveLeg(self.SPREAD_LONG) self.quoteActiveLeg(self.SPREAD_LONG)
self.writeLog(u'买入平仓')
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def updateSpreadPos(self, spread): def updateSpreadPos(self, spread):
@ -180,10 +256,14 @@ class SniperAlgo(StAlgoTemplate):
# 检查若是被动腿,且已经没有未完成委托,则执行对冲 # 检查若是被动腿,且已经没有未完成委托,则执行对冲
if not orderList and vtSymbol in self.passiveVtSymbols: if not orderList and vtSymbol in self.passiveVtSymbols:
self.hedgePassiveLeg(vtSymbol) self.hedgePassiveLeg(vtSymbol)
self.writeLog(u'发出新的被动腿%s对冲单' %vtSymbol)
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def updateTimer(self): def updateTimer(self):
"""计时更新""" """计时更新"""
if not self.active:
return
self.quoteCount += 1 self.quoteCount += 1
self.hedgeCount += 1 self.hedgeCount += 1
@ -200,11 +280,15 @@ class SniperAlgo(StAlgoTemplate):
self.hedgeCount = 0 self.hedgeCount = 0
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def start(self, mode=MODE_LONGSHORT): def start(self):
"""启动""" """启动"""
self.mode = mode
self.active = True self.active = True
self.quoteCount = 0
self.hedgeCount = 0
return self.active
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def stop(self): def stop(self):
"""停止""" """停止"""
@ -213,6 +297,8 @@ class SniperAlgo(StAlgoTemplate):
self.hedgingTaskDict.clear() self.hedgingTaskDict.clear()
self.cancelAllOrders() self.cancelAllOrders()
return self.active
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def sendLegOrder(self, leg, legVolume): def sendLegOrder(self, leg, legVolume):
"""发送每条腿的委托""" """发送每条腿的委托"""
@ -311,6 +397,9 @@ class SniperAlgo(StAlgoTemplate):
else: else:
self.hedgingTaskDict[leg.vtSymbol] += newHedgingTask self.hedgingTaskDict[leg.vtSymbol] += newHedgingTask
# 输出日志
self.writeLog(u'主动腿%s成交,方向%s,数量%s' %(trade.vtSymbol, trade.direction, trade.volume))
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def newPassiveLegTrade(self, trade): def newPassiveLegTrade(self, trade):
"""新的被动腿成交""" """新的被动腿成交"""
@ -328,6 +417,9 @@ class SniperAlgo(StAlgoTemplate):
if not self.hedgingTaskDict[trade.vtSymbol]: if not self.hedgingTaskDict[trade.vtSymbol]:
del 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): def cancelLegOrder(self, vtSymbol):
"""撤销某条腿的委托""" """撤销某条腿的委托"""
@ -339,6 +431,8 @@ class SniperAlgo(StAlgoTemplate):
for vtOrderID in orderList: for vtOrderID in orderList:
self.algoEngine.cancelOrder(vtOrderID) self.algoEngine.cancelOrder(vtOrderID)
self.writeLog(u'撤单%s的所有委托' %vtSymbol)
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def cancelAllOrders(self): def cancelAllOrders(self):
"""撤销全部委托""" """撤销全部委托"""
@ -346,8 +440,18 @@ class SniperAlgo(StAlgoTemplate):
for vtOrderID in orderList: for vtOrderID in orderList:
self.algoEngine.cancelOrder(vtOrderID) self.algoEngine.cancelOrder(vtOrderID)
self.writeLog(u'全部撤单')
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def cancelAllPassiveLegOrders(self): def cancelAllPassiveLegOrders(self):
"""撤销全部被动腿委托""" """撤销全部被动腿委托"""
cancelPassive = False
for vtSymbol in self.passiveVtSymbols: for vtSymbol in self.passiveVtSymbols:
if self.legOrderDict[vtSymbol]:
self.cancelLegOrder(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_TICK = 'eSpreadTradingTick.'
EVENT_SPREADTRADING_POS = 'eSpreadTradingPos.' EVENT_SPREADTRADING_POS = 'eSpreadTradingPos.'
EVENT_SPREADTRADING_LOG = 'eSpreadTradingLog' EVENT_SPREADTRADING_LOG = 'eSpreadTradingLog'
EVENT_SPREADTRADING_ALGO = 'eSpreadTradingAlgo.'
EVENT_SPREADTRADING_ALGOLOG = 'eSpreadTradingAlgoLog'

View File

@ -2,10 +2,10 @@
import json import json
import traceback import traceback
from copy import copy import shelve
from vnpy.event import Event 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, from vnpy.trader.vtEvent import (EVENT_TICK, EVENT_TRADE, EVENT_POSITION,
EVENT_TIMER, EVENT_ORDER) EVENT_TIMER, EVENT_ORDER)
from vnpy.trader.vtObject import (VtSubscribeReq, VtOrderReq, from vnpy.trader.vtObject import (VtSubscribeReq, VtOrderReq,
@ -14,7 +14,9 @@ from vnpy.trader.vtConstant import (DIRECTION_LONG, DIRECTION_SHORT,
OFFSET_OPEN, OFFSET_CLOSE) 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) 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() spread.initSpread()
self.putSpreadTickEvent(spread)
self.putSpreadPosEvent(spread)
# 返回结果 # 返回结果
result = True result = True
msg = u'%s价差创建成功' %spread.name msg = u'%s价差创建成功' %spread.name
@ -145,7 +150,12 @@ class StDataEngine(object):
spread = self.vtSymbolSpreadDict[tick.vtSymbol] spread = self.vtSymbolSpreadDict[tick.vtSymbol]
spread.calculatePrice() spread.calculatePrice()
# 推送价差行情更新 # 发出事件
self.putSpreadTickEvent(spread)
#----------------------------------------------------------------------
def putSpreadTickEvent(self, spread):
"""发出价差行情更新事件"""
event1 = Event(EVENT_SPREADTRADING_TICK+spread.name) event1 = Event(EVENT_SPREADTRADING_TICK+spread.name)
event1.dict_['data'] = spread event1.dict_['data'] = spread
self.eventEngine.put(event1) self.eventEngine.put(event1)
@ -215,6 +225,11 @@ class StDataEngine(object):
spread.calculatePos() spread.calculatePos()
# 推送价差持仓更新 # 推送价差持仓更新
self.putSpreadPosEvent(spread)
#----------------------------------------------------------------------
def putSpreadPosEvent(self, spread):
"""发出价差持仓事件"""
event1 = Event(EVENT_SPREADTRADING_POS+spread.name) event1 = Event(EVENT_SPREADTRADING_POS+spread.name)
event1.dict_['data'] = spread event1.dict_['data'] = spread
self.eventEngine.put(event1) self.eventEngine.put(event1)
@ -223,6 +238,7 @@ class StDataEngine(object):
event2.dict_['data'] = spread event2.dict_['data'] = spread
self.eventEngine.put(event2) self.eventEngine.put(event2)
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def registerEvent(self): def registerEvent(self):
"""""" """"""
@ -236,6 +252,7 @@ class StDataEngine(object):
contract = self.mainEngine.getContract(vtSymbol) contract = self.mainEngine.getContract(vtSymbol)
if not contract: if not contract:
self.writeLog(u'订阅行情失败,找不到该合约%s' %vtSymbol) self.writeLog(u'订阅行情失败,找不到该合约%s' %vtSymbol)
return
req = VtSubscribeReq() req = VtSubscribeReq()
req.symbol = contract.symbol req.symbol = contract.symbol
@ -254,18 +271,21 @@ class StDataEngine(object):
self.eventEngine.put(event) self.eventEngine.put(event)
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def stop(self): def getAllSpreads(self):
"""停止""" """获取所有的价差"""
pass return self.spreadDict.values()
######################################################################## ########################################################################
class StAlgoEngine(object): class StAlgoEngine(object):
"""价差算法交易引擎""" """价差算法交易引擎"""
algoFileName = 'SpreadTradingAlgo.vt'
algoFilePath = getTempPath(algoFileName)
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def __init__(self, mainEngine, eventEngine): def __init__(self, dataEngine, mainEngine, eventEngine):
"""Constructor""" """Constructor"""
self.dataEngine = dataEngine
self.mainEngine = mainEngine self.mainEngine = mainEngine
self.eventEngine = eventEngine self.eventEngine = eventEngine
@ -387,6 +407,122 @@ class StAlgoEngine(object):
vtOrderID = self.sendOrder(vtSymbol, DIRECTION_LONG, OFFSET_CLOSE, price, volume, payup) vtOrderID = self.sendOrder(vtSymbol, DIRECTION_LONG, OFFSET_CLOSE, price, volume, payup)
return [vtOrderID] 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): class StEngine(object):
@ -399,12 +535,21 @@ class StEngine(object):
self.eventEngine = eventEngine self.eventEngine = eventEngine
self.dataEngine = StDataEngine(mainEngine, 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.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 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, from vnpy.trader.uiBasicWidget import (BasicMonitor, BasicCell, PnlCell,
AskCell, BidCell, BASIC_FONT) AskCell, BidCell, BASIC_FONT)
from .stBase import (EVENT_SPREADTRADING_TICK, EVENT_SPREADTRADING_POS, 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): class StTickMonitor(BasicMonitor):
@ -64,26 +70,366 @@ 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): def __init__(self, mainEngine, eventEngine, parent=None):
"""Constructor""" """Constructor"""
super(StLogMonitor, self).__init__(mainEngine, eventEngine, parent) super(StAlgoLogMonitor, self).__init__(mainEngine, eventEngine, parent)
d = OrderedDict() d = OrderedDict()
d['logTime'] = {'chinese':u'时间', 'cellType':BasicCell} d['logTime'] = {'chinese':u'时间', 'cellType':BasicCell}
d['logContent'] = {'chinese':u'日志', 'cellType':BasicCell} d['logContent'] = {'chinese':u'信息', 'cellType':BasicCell}
self.setHeaderDict(d) self.setHeaderDict(d)
self.setEventType(EVENT_SPREADTRADING_LOG) self.setEventType(EVENT_SPREADTRADING_ALGOLOG)
self.setFont(BASIC_FONT) self.setFont(BASIC_FONT)
self.initTable() 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): class StManager(QtWidgets.QWidget):
"""""" """"""
@ -105,37 +451,48 @@ class StManager(QtWidgets.QWidget):
self.setWindowTitle(u'价差交易') self.setWindowTitle(u'价差交易')
# 创建按钮 # 创建按钮
buttonLoadSetting = QtWidgets.QPushButton(u'加载配置') buttonInit = QtWidgets.QPushButton(u'初始化')
buttonInit.clicked.connect(self.init)
buttonLoadSetting.clicked.connect(self.stEngine.loadSetting)
# 创建组件 # 创建组件
tickMonitor = StTickMonitor(self.mainEngine, self.eventEngine) tickMonitor = StTickMonitor(self.mainEngine, self.eventEngine)
posMonitor = StPosMonitor(self.mainEngine, self.eventEngine) posMonitor = StPosMonitor(self.mainEngine, self.eventEngine)
logMonitor = StLogMonitor(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() hbox = QtWidgets.QHBoxLayout()
hbox1.addWidget(buttonLoadSetting) hbox.addWidget(buttonInit)
hbox1.addStretch() hbox.addStretch()
hbox2 = QtWidgets.QHBoxLayout() grid = QtWidgets.QGridLayout()
hbox2.addWidget(tickMonitor) grid.addLayout(hbox, 0, 0, 1, 2)
hbox2.addWidget(posMonitor) 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)
vbox = QtWidgets.QVBoxLayout() self.setLayout(grid)
vbox.addLayout(hbox1)
vbox.addLayout(hbox2)
vbox.addWidget(logMonitor)
self.setLayout(vbox)
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def show(self): def show(self):
"""重载显示""" """重载显示"""
self.showMaximized() self.showMaximized()
#----------------------------------------------------------------------
def init(self):
"""初始化"""
self.stEngine.init()
self.algoManager.initCells()