From 644d14881c3e339d5c0248da0791ed38a5f625b7 Mon Sep 17 00:00:00 2001 From: "vn.py" Date: Sun, 2 Dec 2018 13:24:04 +0800 Subject: [PATCH] =?UTF-8?q?[Add]=E6=96=B0=E5=A2=9E=E4=BA=A4=E6=98=93?= =?UTF-8?q?=E5=A4=8D=E5=88=B6=E6=A8=A1=E5=9D=97TradeCopy?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/VnTrader/run.py | 4 +- vnpy/__init__.py | 2 +- vnpy/trader/app/tradeCopy/__init__.py | 10 + vnpy/trader/app/tradeCopy/tc.ico | Bin 0 -> 20510 bytes vnpy/trader/app/tradeCopy/tcEngine.py | 319 ++++++++++++++++++++++++ vnpy/trader/app/tradeCopy/uiTcWidget.py | 199 +++++++++++++++ 6 files changed, 532 insertions(+), 2 deletions(-) create mode 100644 vnpy/trader/app/tradeCopy/__init__.py create mode 100644 vnpy/trader/app/tradeCopy/tc.ico create mode 100644 vnpy/trader/app/tradeCopy/tcEngine.py create mode 100644 vnpy/trader/app/tradeCopy/uiTcWidget.py diff --git a/examples/VnTrader/run.py b/examples/VnTrader/run.py index b2975c27..53872f1f 100644 --- a/examples/VnTrader/run.py +++ b/examples/VnTrader/run.py @@ -35,7 +35,8 @@ elif system == 'Windows': # 加载上层应用 from vnpy.trader.app import (riskManager, ctaStrategy, - spreadTrading, algoTrading) + spreadTrading, algoTrading, + tradeCopy) #---------------------------------------------------------------------- @@ -67,6 +68,7 @@ def main(): me.addApp(ctaStrategy) me.addApp(spreadTrading) me.addApp(algoTrading) + me.addApp(tradeCopy) # 创建主窗口 mw = MainWindow(me, ee) diff --git a/vnpy/__init__.py b/vnpy/__init__.py index 708620bf..4d027381 100644 --- a/vnpy/__init__.py +++ b/vnpy/__init__.py @@ -1,4 +1,4 @@ # encoding: UTF-8 -__version__ = '1.9.0' +__version__ = '1.9.2' __author__ = 'Xiaoyou Chen' \ No newline at end of file diff --git a/vnpy/trader/app/tradeCopy/__init__.py b/vnpy/trader/app/tradeCopy/__init__.py new file mode 100644 index 00000000..6f445281 --- /dev/null +++ b/vnpy/trader/app/tradeCopy/__init__.py @@ -0,0 +1,10 @@ +# encoding: UTF-8 + +from .tcEngine import TcEngine +from .uiTcWidget import TcManager + +appName = 'TradeCopy' +appDisplayName = u'交易复制' +appEngine = TcEngine +appWidget = TcManager +appIco = 'tc.ico' \ No newline at end of file diff --git a/vnpy/trader/app/tradeCopy/tc.ico b/vnpy/trader/app/tradeCopy/tc.ico new file mode 100644 index 0000000000000000000000000000000000000000..e7ee47a923dfcb1aa7484622a870f32890db441e GIT binary patch literal 20510 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 S&b^lBGo5?k7Z7i;+ pos: + req.offset = OFFSET_OPEN + + if DIRECTION_LONG in vtPositionName: + req.direction = DIRECTION_LONG + if tick.upperLimit: + req.price = tick.upperLimit + else: + req.price = tick.askPrice1 + elif DIRECTION_SHROT in vtPositionName: + req.direction = DIRECTION_SHROT + if tick.lowerLimit: + req.price = tick.lowerLimit + else: + req.price = tick.bidPrice1 + + self.mainEngine.sendOrder(req, contract.gatewayName) + + # Close position + elif target < pos: + req.offset = OFFSET_CLOSE + + if DIRECTION_LONG in vtPositionName: + req.direction = DIRECTION_SHROT + if tick.upperLimit: + req.price = tick.upperLimit + else: + req.price = tick.askPrice1 + + elif DIRECTION_SHROT in vtPositionName: + req.direction = DIRECTION_LONG + if tick.lowerLimit: + req.price = tick.lowerLimit + else: + req.price = tick.bidPrice1 + + # Use auto-convert for solving today/yesterday position problem + reqList = self.mainEngine.convertOrderReq(req) + for convertedReq in reqList: + self.mainEngine.sendOrder(convertedReq, contract.gatewayName) + + # Write log + msg = u'发出%s委托 %s%s %s@%s' %(vtSymbol, req.direction, req.offset, + req.price, req.volume) + self.writeLog(msg) + + #---------------------------------------------------------------------- + def cancelOrder(self, vtSymbol): + """ + Cancel all orders of a certain vtSymbol + """ + l = self.mainEngine.getAllWorkingOrders() + for order in l: + if order.vtSymbol == vtSymbol: + req = VtCancelOrderReq() + req.orderID = order.orderID + req.frontID = order.frontID + req.sessionID = order.sessionID + req.symbol = order.symbol + req.exchange = order.exchange + self.mainEngine.cancelOrder(req, order.gatewayName) + + self.writeLog(u'撤销%s全部活动中委托' %vtSymbol) + + #---------------------------------------------------------------------- + def checkNoWorkingOrder(self, vtSymbol): + """ + Check if there is still any working orders of a certain vtSymbol + """ + l = self.mainEngine.getAllWorkingOrders() + for order in l: + if order.vtSymbol == vtSymbol: + return False + + return True + + #---------------------------------------------------------------------- + def writeLog(self, msg): + """""" + log = VtLogData() + log.logContent = msg + + event = Event(EVENT_TC_LOG) + event.dict_['data'] = log + self.eventEngine.put(event) + + #---------------------------------------------------------------------- + def getPos(self): + """ + Get currenct position data of provider + """ + return dict(self.posDict) + + #---------------------------------------------------------------------- + def initTarget(self): + """ + Init target data of subscriber based on position data from provider + """ + d = self.client.getPos() + for vtPositionName, pos in d.items(): + l = vtPositionName.split('.') + direction = l[-1] + vtSymbol = vtPositionName.replace('.' + direction, '') + + data = { + 'vtPositionName': vtPositionName, + 'vtSymbol': vtSymbol, + 'pos': pos + } + self.updatePos(data) + + self.writeLog(u'目标仓位初始化完成') + + +######################################################################## +class TcClient(RpcClient): + """""" + + #---------------------------------------------------------------------- + def __init__(self, engine, reqAddress, subAddress): + """Constructor""" + super(TcClient, self).__init__(reqAddress, subAddress) + + self.engine = engine + + #---------------------------------------------------------------------- + def callback(self, topic, data): + """""" + self.engine.updatePos(data) + + \ No newline at end of file diff --git a/vnpy/trader/app/tradeCopy/uiTcWidget.py b/vnpy/trader/app/tradeCopy/uiTcWidget.py new file mode 100644 index 00000000..5cdfc9d4 --- /dev/null +++ b/vnpy/trader/app/tradeCopy/uiTcWidget.py @@ -0,0 +1,199 @@ +# encoding: UTF-8 + +import shelve + +from vnpy.event import Event +from vnpy.trader.uiQt import QtCore, QtGui, QtWidgets +from vnpy.trader.vtFunction import getTempPath + +from .tcEngine import EVENT_TC_LOG + + +######################################################################## +class TcManager(QtWidgets.QWidget): + """""" + REQ_ADDRESS = 'tcp://localhost:2015' + SUB_ADDRESS = 'tcp://localhost:2018' + REP_ADDRESS = 'tcp://*:2015' + PUB_ADDRESS = 'tcp://*:2018' + COPY_RATIO = '1' + INTERVAL = '1' + + settingFileName = 'TradeCopy.vt' + settingFilePath = getTempPath(settingFileName) + + signal = QtCore.Signal(type(Event())) + + #---------------------------------------------------------------------- + def __init__(self, tcEngine, eventEngine, parent=None): + """Constructor""" + super(TcManager, self).__init__(parent) + + self.tcEngine = tcEngine + self.eventEngine = eventEngine + + self.initUi() + self.loadSetting() + self.registerEvent() + + self.tcEngine.writeLog(u'欢迎使用TradeCopy交易复制模块') + + #---------------------------------------------------------------------- + def initUi(self): + """""" + self.setWindowTitle(u'交易复制') + self.setMinimumWidth(700) + self.setMinimumHeight(700) + + # 创建组件 + self.lineReqAddress = QtWidgets.QLineEdit(self.REQ_ADDRESS) + self.lineSubAddress= QtWidgets.QLineEdit(self.SUB_ADDRESS) + self.lineRepAddress = QtWidgets.QLineEdit(self.REP_ADDRESS) + self.linePubAddress = QtWidgets.QLineEdit(self.PUB_ADDRESS) + + validator = QtGui.QDoubleValidator() + validator.setBottom(0) + self.lineCopyRatio = QtWidgets.QLineEdit() + self.lineCopyRatio.setValidator(validator) + self.lineCopyRatio.setText(self.COPY_RATIO) + + validator2 = QtGui.QIntValidator() + validator2.setBottom(1) + self.lineInterval = QtWidgets.QLineEdit() + self.lineInterval.setValidator(validator2) + self.lineInterval.setText(self.INTERVAL) + + self.buttonProvider = QtWidgets.QPushButton(u'启动发布者') + self.buttonProvider.clicked.connect(self.startProvider) + + self.buttonSubscriber = QtWidgets.QPushButton(u'启动订阅者') + self.buttonSubscriber.clicked.connect(self.startSubscriber) + + self.buttonStopEngine = QtWidgets.QPushButton(u'停止') + self.buttonStopEngine.clicked.connect(self.stopEngine) + self.buttonStopEngine.setEnabled(False) + + self.buttonResetAddress = QtWidgets.QPushButton(u'重置地址') + self.buttonResetAddress.clicked.connect(self.resetAddress) + + self.logMonitor = QtWidgets.QTextEdit() + self.logMonitor.setReadOnly(True) + + self.widgetList = [ + self.lineCopyRatio, + self.lineInterval, + self.linePubAddress, + self.lineSubAddress, + self.lineRepAddress, + self.lineReqAddress, + self.buttonProvider, + self.buttonSubscriber, + self.buttonResetAddress + ] + + # 布局 + QLabel = QtWidgets.QLabel + grid = QtWidgets.QGridLayout() + + grid.addWidget(QLabel(u'响应地址'), 0, 0) + grid.addWidget(self.lineRepAddress, 0, 1) + grid.addWidget(QLabel(u'请求地址'), 0, 2) + grid.addWidget(self.lineReqAddress, 0, 3) + + grid.addWidget(QLabel(u'发布地址'), 1, 0) + grid.addWidget(self.linePubAddress, 1, 1) + grid.addWidget(QLabel(u'订阅地址'), 1, 2) + grid.addWidget(self.lineSubAddress, 1, 3) + + grid.addWidget(QLabel(u'发布间隔(秒)'), 2, 0) + grid.addWidget(self.lineInterval, 2, 1) + grid.addWidget(QLabel(u'复制比例(倍)'), 2, 2) + grid.addWidget(self.lineCopyRatio, 2, 3) + + grid.addWidget(self.buttonProvider, 3, 0, 1, 2) + grid.addWidget(self.buttonSubscriber, 3, 2, 1, 2) + grid.addWidget(self.buttonStopEngine, 4, 0, 1, 2) + grid.addWidget(self.buttonResetAddress, 4, 2, 1, 2) + + grid.addWidget(self.logMonitor, 5, 0, 1, 4) + + self.setLayout(grid) + + #---------------------------------------------------------------------- + def saveSetting(self): + """""" + f = shelve.open(self.settingFilePath) + f['repAddress'] = self.lineRepAddress.text() + f['reqAddress'] = self.lineReqAddress.text() + f['pubAddress'] = self.linePubAddress.text() + f['subAddress'] = self.lineSubAddress.text() + f['copyRatio'] = self.lineCopyRatio.text() + f['interval'] = self.lineInterval.text() + f.close() + + #---------------------------------------------------------------------- + def loadSetting(self): + """""" + f = shelve.open(self.settingFilePath) + if f: + self.lineRepAddress.setText(f['repAddress']) + self.lineReqAddress.setText(f['reqAddress']) + self.linePubAddress.setText(f['pubAddress']) + self.lineSubAddress.setText(f['subAddress']) + self.lineCopyRatio.setText(f['copyRatio']) + self.lineInterval.setText(f['interval']) + f.close() + + #---------------------------------------------------------------------- + def resetAddress(self): + """""" + self.lineReqAddress.setText(self.REQ_ADDRESS) + self.lineRepAddress.setText(self.REP_ADDRESS) + self.linePubAddress.setText(self.PUB_ADDRESS) + self.lineSubAddress.setText(self.SUB_ADDRESS) + + #---------------------------------------------------------------------- + def stopEngine(self): + """""" + self.tcEngine.stop() + + for widget in self.widgetList: + widget.setEnabled(True) + self.buttonStopEngine.setEnabled(False) + + #---------------------------------------------------------------------- + def registerEvent(self): + """""" + self.signal.connect(self.processLogEvent) + self.eventEngine.register(EVENT_TC_LOG, self.signal.emit) + + #---------------------------------------------------------------------- + def processLogEvent(self, event): + """""" + log = event.dict_['data'] + txt = '%s: %s' %(log.logTime, log.logContent) + self.logMonitor.append(txt) + + #---------------------------------------------------------------------- + def startProvider(self): + """""" + repAddress = str(self.lineRepAddress.text()) + pubAddress = str(self.linePubAddress.text()) + interval = int(self.lineInterval.text()) + self.tcEngine.startProvider(repAddress, pubAddress, interval) + + for widget in self.widgetList: + widget.setEnabled(False) + self.buttonStopEngine.setEnabled(True) + + #---------------------------------------------------------------------- + def startSubscriber(self): + """""" + reqAddress = str(self.lineReqAddress.text()) + subAddress = str(self.lineSubAddress.text()) + copyRatio = float(self.lineCopyRatio.text()) + self.tcEngine.startSubscriber(reqAddress, subAddress, copyRatio) + + for widget in self.widgetList: + widget.setEnabled(False) + self.buttonStopEngine.setEnabled(True) \ No newline at end of file