diff --git a/examples/VnTrader/run.py b/examples/VnTrader/run.py index 22c5a54a..0af7dabe 100644 --- a/examples/VnTrader/run.py +++ b/examples/VnTrader/run.py @@ -17,8 +17,7 @@ from vnpy.trader.gateway import (ctpGateway, femasGateway, xspeedGateway, shzdGateway, huobiGateway, okcoinGateway) # 加载上层应用 -from vnpy.trader.app import (riskManager, dataRecorder, - ctaStrategy, spreadTrading) +from vnpy.trader.app import (riskManager, ctaStrategy, spreadTrading) #---------------------------------------------------------------------- @@ -43,7 +42,6 @@ def main(): # 添加上层应用 me.addApp(riskManager) - me.addApp(dataRecorder) me.addApp(ctaStrategy) me.addApp(spreadTrading) diff --git a/vnpy/data/shcifco/test.py b/vnpy/data/shcifco/test.py new file mode 100644 index 00000000..15d8e192 --- /dev/null +++ b/vnpy/data/shcifco/test.py @@ -0,0 +1,27 @@ +# encoding: UTF-8 + +from vnshcifco import ShcifcoApi, PERIOD_1MIN + + +if __name__ == "__main__": + ip = '101.231.179.199' + port = '10102' + token = 'testd2cda34b2d317779e812eb84ee4224a6_qpweqf1' + symbol = 'cu1709' + + # 创建API对象 + api = ShcifcoApi(ip, port, token) + + # 获取最新tick + print api.getLastTick(symbol) + + # 获取最新价格 + print api.getLastPrice(symbol) + + # 获取最新分钟线 + print api.getLastBar(symbol) + + # 获取历史分钟线 + print api.getHisBar(symbol, 502, period=PERIOD_1MIN) + + \ No newline at end of file diff --git a/vnpy/data/shcifco/vnshcifco.py b/vnpy/data/shcifco/vnshcifco.py index 94927d9c..568cd0d0 100644 --- a/vnpy/data/shcifco/vnshcifco.py +++ b/vnpy/data/shcifco/vnshcifco.py @@ -5,6 +5,12 @@ import requests HTTP_OK = 200 +PERIOD_1MIN = '1m' +PERIOD_5MIN = '5m' +PERIOD_15MIN = '15m' +PERIOD_60MIN = '60m' +PERIOD_1DAY = '1d' + ######################################################################## class ShcifcoApi(object): @@ -38,8 +44,12 @@ class ShcifcoApi(object): """获取最新Tick""" path = 'lasttick' params = {'ids': symbol} - data = self.getData(path, params) + data = self.getData(path, params) + if not data: + return None + + data = data.split(';')[0] l = data.split(',') d = { 'symbol': l[0], @@ -58,8 +68,12 @@ class ShcifcoApi(object): """获取最新成交价""" path = 'lastprice' params = {'ids': symbol} - data = self.getData(path, params) + data = self.getData(path, params) + if not data: + return None + + data = data.split(';')[0] price = float(data) return price @@ -67,9 +81,13 @@ class ShcifcoApi(object): def getLastBar(self, symbol): """获取最新的一分钟K线数据""" path = 'lastbar' - params = {'ids': symbol} - data = self.getData(path, params) + params = {'id': symbol} + data = self.getData(path, params) + if not data: + return None + + data = data.split(';')[0] l = data.split(',') d = { 'symbol': l[0], @@ -78,18 +96,19 @@ class ShcifcoApi(object): 'high': float(l[3]), 'low': float(l[4]), 'close': float(l[5]), - 'volume': int([6]) + 'volume': int(l[6]), + 'openInterest': int(l[7]) } return d #---------------------------------------------------------------------- def getHisBar(self, symbol, num, date='', period=''): """获取历史K线数据""" - path = 'lastbar' + path = 'hisbar' # 默认参数 params = { - 'ids': symbol, + 'id': symbol, 'num': num } # 可选参数 @@ -99,40 +118,31 @@ class ShcifcoApi(object): params[period] = period data = self.getData(path, params) + if not data: + return None barList = [] l = data.split(';') for barStr in l: + # 过滤某些空数据 + if ',' not in barStr: + continue + barData = barStr.split(',') d = { 'symbol': barData[0], - 'time': barData[1], - 'open': float(barData[2]), - 'high': float(barData[3]), - 'low': float(barData[4]), - 'close': float(barData[5]), - 'volume': int([6]) + 'date': barData[1], + 'time': barData[2], + 'open': float(barData[3]), + 'high': float(barData[4]), + 'low': float(barData[5]), + 'close': float(barData[6]), + 'volume': int(barData[7]), + 'openInterest': int(barData[8]) } barList.append(d) return barList -if __name__ == "__main__": - ip = '101.231.179.199' - port = '10102' - token = 'testd2cda34b2d317779e812eb84ee4224a6_123456' - - api = ShcifcoApi(ip, port, token) - api.getData(path, params) - - print api.getLastTick('cu1709') - - print api.getLastPrice('cu1709') - - print api.getLastBar('cu1709') - - print api.getHisBar('cu1709', 50) - - \ No newline at end of file diff --git a/vnpy/trader/app/dataRecorder/drEngine.py b/vnpy/trader/app/dataRecorder/drEngine.py index 31f1b5a3..c9af1522 100644 --- a/vnpy/trader/app/dataRecorder/drEngine.py +++ b/vnpy/trader/app/dataRecorder/drEngine.py @@ -77,7 +77,7 @@ class DrEngine(object): # 读取配置 gatewayName = d['gateway'] symbol = d['symbol'] - exchange = d['symbol'] + exchange = d['exchange'] currency = d['currency'] productClass = d['product'] recordTick = d['tick'] diff --git a/vnpy/trader/app/spreadTrading/ST_setting.json b/vnpy/trader/app/spreadTrading/ST_setting.json index b2edf2c1..ba2c1da2 100644 --- a/vnpy/trader/app/spreadTrading/ST_setting.json +++ b/vnpy/trader/app/spreadTrading/ST_setting.json @@ -1,4 +1,25 @@ [ + { + "name": "m.09-01", + + "activeLeg": + { + "vtSymbol": "m1709", + "ratio": 1, + "multiplier": 1.0, + "payup": 2 + }, + + "passiveLegs": [ + { + "vtSymbol": "m1801", + "ratio": -1, + "multiplier": -1.0, + "payup": 2 + } + ] + }, + { "name": "IF.07-09", diff --git a/vnpy/trader/app/spreadTrading/stAlgo.py b/vnpy/trader/app/spreadTrading/stAlgo.py index afd4f743..8c35698b 100644 --- a/vnpy/trader/app/spreadTrading/stAlgo.py +++ b/vnpy/trader/app/spreadTrading/stAlgo.py @@ -117,7 +117,8 @@ class StAlgoTemplate(object): #---------------------------------------------------------------------- def writeLog(self, content): """输出算法日志""" - content = ':'.join([self.spreadName, content]) + prefix = ' '.join([self.spreadName, self.algoName]) + content = ':'.join([prefix, content]) self.algoEngine.writeLog(content) #---------------------------------------------------------------------- @@ -287,6 +288,8 @@ class SniperAlgo(StAlgoTemplate): self.hedgeCount = 0 self.active = True + self.writeLog(u'算法启动') + return self.active #---------------------------------------------------------------------- @@ -296,7 +299,9 @@ class SniperAlgo(StAlgoTemplate): self.hedgingTaskDict.clear() self.cancelAllOrders() - self.active = False + self.active = False + self.writeLog(u'算法停止') + return self.active #---------------------------------------------------------------------- @@ -448,7 +453,7 @@ class SniperAlgo(StAlgoTemplate): cancelPassive = False for vtSymbol in self.passiveVtSymbols: - if self.legOrderDict[vtSymbol]: + if vtSymbol in self.legOrderDict and self.legOrderDict[vtSymbol]: self.cancelLegOrder(vtSymbol) cancelPassive = True diff --git a/vnpy/trader/app/spreadTrading/stEngine.py b/vnpy/trader/app/spreadTrading/stEngine.py index 6789da12..1ba5e9b8 100644 --- a/vnpy/trader/app/spreadTrading/stEngine.py +++ b/vnpy/trader/app/spreadTrading/stEngine.py @@ -93,10 +93,10 @@ class StDataEngine(object): activeSetting = setting['activeLeg'] activeLeg = StLeg() - activeLeg.vtSymbol = activeSetting['vtSymbol'] - activeLeg.ratio = activeSetting['ratio'] - activeLeg.multiplier = activeSetting['multiplier'] - activeLeg.payup = activeSetting['payup'] + activeLeg.vtSymbol = str(activeSetting['vtSymbol']) + activeLeg.ratio = float(activeSetting['ratio']) + activeLeg.multiplier = float(activeSetting['multiplier']) + activeLeg.payup = int(activeSetting['payup']) spread.addActiveLeg(activeLeg) self.legDict[activeLeg.vtSymbol] = activeLeg @@ -110,10 +110,10 @@ class StDataEngine(object): for d in passiveSettingList: passiveLeg = StLeg() - passiveLeg.vtSymbol = d['vtSymbol'] - passiveLeg.ratio = d['ratio'] - passiveLeg.multiplier = d['multiplier'] - passiveLeg.payup = d['payup'] + passiveLeg.vtSymbol = str(d['vtSymbol']) + passiveLeg.ratio = float(d['ratio']) + passiveLeg.multiplier = float(d['multiplier']) + passiveLeg.payup = int(d['payup']) spread.addPassiveLeg(passiveLeg) self.legDict[passiveLeg.vtSymbol] = passiveLeg @@ -176,7 +176,7 @@ class StDataEngine(object): # 更新腿持仓 leg = self.legDict[trade.vtSymbol] direction = trade.direction - offset = trade.offst + offset = trade.offset if direction == DIRECTION_LONG: if offset == OFFSET_OPEN: @@ -212,7 +212,7 @@ class StDataEngine(object): return # 更新腿持仓 - leg = self.legDict[trade.vtSymbol] + leg = self.legDict[pos.vtSymbol] direction = pos.direction if direction == DIRECTION_LONG: @@ -222,7 +222,7 @@ class StDataEngine(object): leg.netPos = leg.longPos - leg.shortPos # 更新价差持仓 - spread = self.vtSymbolSpreadDict[trade.vtSymbol] + spread = self.vtSymbolSpreadDict[pos.vtSymbol] spread.calculatePos() # 推送价差持仓更新 @@ -327,7 +327,7 @@ class StAlgoEngine(object): """处理成交事件""" trade = event.dict_['data'] - algo = self.algoDict.get(trade.vtSymbol, None) + algo = self.vtSymbolAlgoDict.get(trade.vtSymbol, None) if algo: algo.updateTrade(trade) @@ -335,8 +335,8 @@ class StAlgoEngine(object): def processOrderEvent(self, event): """处理委托事件""" order = event.dict_['data'] + algo = self.vtSymbolAlgoDict.get(order.vtSymbol, None) - algo = self.algoDict.get(order.vtSymbol, None) if algo: algo.updateOrder(order) @@ -358,7 +358,7 @@ class StAlgoEngine(object): req.exchange = contract.exchange req.direction = direction req.offset = offset - req.volume = volume + req.volume = int(volume) req.priceType = PRICETYPE_LIMITPRICE if direction == DIRECTION_LONG: @@ -443,7 +443,12 @@ class StAlgoEngine(object): # 创建算法对象 l = self.dataEngine.getAllSpreads() for spread in l: - self.algoDict[spread.name] = SniperAlgo(self, spread) + algo = SniperAlgo(self, spread) + self.algoDict[spread.name] = algo + + # 保存腿代码和算法对象的映射 + for leg in spread.allLegs: + self.vtSymbolAlgoDict[leg.vtSymbol] = algo # 加载配置 f = shelve.open(self.algoFilePath) diff --git a/vnpy/trader/app/spreadTrading/uiStWidget.py b/vnpy/trader/app/spreadTrading/uiStWidget.py index d2613146..91f9c48b 100644 --- a/vnpy/trader/app/spreadTrading/uiStWidget.py +++ b/vnpy/trader/app/spreadTrading/uiStWidget.py @@ -319,7 +319,7 @@ class StActiveButton(QtWidgets.QPushButton): def buttonClicked(self): """改变运行模式""" if self.active: - self.stop + self.stop() else: self.start() @@ -334,7 +334,6 @@ class StActiveButton(QtWidgets.QPushButton): def start(self): """启动""" algoActive = self.algoEngine.startAlgo(self.spreadName) - if algoActive: self.setStarted() diff --git a/vnpy/trader/uiMainWindow.py b/vnpy/trader/uiMainWindow.py index 27d92ad9..27c3f5e7 100644 --- a/vnpy/trader/uiMainWindow.py +++ b/vnpy/trader/uiMainWindow.py @@ -1,6 +1,7 @@ # encoding: UTF-8 import psutil +import traceback from vnpy.trader.vtFunction import loadIconPath from vnpy.trader.vtGlobal import globalSetting @@ -257,18 +258,25 @@ class MainWindow(QtWidgets.QMainWindow): #---------------------------------------------------------------------- def loadWindowSettings(self, settingName): """载入窗口设置""" - settings = QtCore.QSettings('vn.trader', settingName) - # 这里由于PyQt4的版本不同,settings.value('state')调用返回的结果可能是: - # 1. None(初次调用,注册表里无相应记录,因此为空) - # 2. QByteArray(比较新的PyQt4) - # 3. QVariant(以下代码正确执行所需的返回结果) - # 所以为了兼容考虑,这里加了一个try...except,如果是1、2的情况就pass - # 可能导致主界面的设置无法载入(每次退出时的保存其实是成功了) - try: - self.restoreState(settings.value('state').toByteArray()) - self.restoreGeometry(settings.value('geometry').toByteArray()) - except AttributeError: - pass + settings = QtCore.QSettings('vn.trader', settingName) + state = settings.value('state') + geometry = settings.value('geometry') + + # 尚未初始化 + if state is None: + return + # 老版PyQt + elif isinstance(state, QtCore.QVariant): + self.restoreState(state.toByteArray()) + self.restoreGeometry(geometry.toByteArray()) + # 新版PyQt + elif isinstance(state, QtCore.QByteArray): + self.restoreState(state) + self.restoreGeometry(geometry) + # 异常 + else: + content = u'载入窗口配置异常,请检查' + self.mainEngine.writeLog(content) #---------------------------------------------------------------------- def restoreWindow(self):