初步完成价差交易界面
This commit is contained in:
parent
2578e1b419
commit
79a9ac2bfb
Binary file not shown.
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 65 KiB |
@ -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'被动腿全撤')
|
||||
|
@ -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'
|
||||
|
||||
|
||||
|
||||
|
@ -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()
|
||||
|
||||
|
||||
|
||||
|
@ -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()
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user