diff --git a/examples/CryptoTrader/algoBasket.csv b/examples/CryptoTrader/algoBasket.csv new file mode 100644 index 00000000..dfecd5b2 --- /dev/null +++ b/examples/CryptoTrader/algoBasket.csv @@ -0,0 +1,3 @@ +templateName,settingName,vtSymbol,direction,targetPrice,totalVolume,time,interval,priceLevel,minVolume +TWAP,BUY_BTC_TWAP,BTCUSD.BITFINEX,多,4000,10,200,10,3,1 +TWAP,SELL_BTC_TWAP,BTCUSD.BITFINEX,空,9000,10,200,10,3,1 diff --git a/vnpy/trader/app/algoTrading/twapAlgo.py b/vnpy/trader/app/algoTrading/twapAlgo.py index b4bc9f7d..d3727136 100644 --- a/vnpy/trader/app/algoTrading/twapAlgo.py +++ b/vnpy/trader/app/algoTrading/twapAlgo.py @@ -21,15 +21,15 @@ class TwapAlgo(AlgoTemplate): """Constructor""" super(TwapAlgo, self).__init__(engine, setting, algoName) - # 参数 - self.vtSymbol = setting['vtSymbol'] # 合约代码 - self.direction = setting['direction'] # 买卖 - self.targetPrice = setting['targetPrice'] # 目标价格 - self.totalVolume = setting['totalVolume'] # 总数量 - self.time = setting['time'] # 执行时间 - self.interval = setting['interval'] # 执行间隔 - self.minVolume = setting['minVolume'] # 最小委托数量 - self.priceLevel = setting['priceLevel'] # 使用第几档价格委托 + # 参数,强制类型转换,保证从CSV加载的配置正确 + self.vtSymbol = str(setting['vtSymbol']) # 合约代码 + self.direction = unicode(setting['direction']) # 买卖 + self.targetPrice = float(setting['targetPrice']) # 目标价格 + self.totalVolume = float(setting['totalVolume']) # 总数量 + self.time = int(setting['time']) # 执行时间 + self.interval = int(setting['interval']) # 执行间隔 + self.minVolume = float(setting['minVolume']) # 最小委托数量 + self.priceLevel = int(setting['priceLevel']) # 使用第几档价格委托 # 变量 self.orderSize = self.totalVolume / (self.time / self.interval) diff --git a/vnpy/trader/app/algoTrading/uiAlgoManager.py b/vnpy/trader/app/algoTrading/uiAlgoManager.py index fa92fae3..811d1b08 100644 --- a/vnpy/trader/app/algoTrading/uiAlgoManager.py +++ b/vnpy/trader/app/algoTrading/uiAlgoManager.py @@ -1,5 +1,9 @@ # encoding: UTF-8 +import csv +import traceback +from collections import OrderedDict + from vnpy.event import Event from vnpy.trader.uiQt import QtCore, QtWidgets @@ -26,7 +30,7 @@ class StopButton(QtWidgets.QPushButton): self.setText(u'停止') self.clicked.connect(self.stopAlgo) else: - self.setText(u'全部停止') + self.setText(u'停止全部算法') self.clicked.connect(self.stopAll) #---------------------------------------------------------------------- @@ -388,17 +392,32 @@ class AlgoManager(QtWidgets.QWidget): """""" self.setWindowTitle(u'算法交易') - self.tab = QtWidgets.QTabWidget() - self.buttonStop = StopButton(self.algoEngine) + buttonWidth = 400 + buttonHeight = 60 - self.tab.setMaximumWidth(400) - self.buttonStop.setMaximumWidth(400) - self.buttonStop.setFixedHeight(100) + self.tab = QtWidgets.QTabWidget() + self.tab.setMaximumWidth(buttonWidth) + + self.buttonStop = StopButton(self.algoEngine) + self.buttonStop.setMaximumWidth(buttonWidth) + self.buttonStop.setFixedHeight(buttonHeight) + + self.buttonAddAlgo = QtWidgets.QPushButton(u'启动篮子算法') + self.buttonAddAlgo.setStyleSheet("color:white;background-color:green") + self.buttonAddAlgo.clicked.connect(self.addAlgoFromCsv) + self.buttonAddAlgo.setFixedHeight(buttonHeight) + + self.buttonSaveSetting = QtWidgets.QPushButton(u'加载算法配置') + self.buttonSaveSetting.setStyleSheet("color:white;background-color:blue") + self.buttonSaveSetting.clicked.connect(self.saveSettingFromCsv) + self.buttonSaveSetting.setFixedHeight(buttonHeight) vbox1 = QtWidgets.QVBoxLayout() vbox1.addWidget(self.tab) vbox1.addStretch() vbox1.addWidget(self.buttonStop) + vbox1.addWidget(self.buttonAddAlgo) + vbox1.addWidget(self.buttonSaveSetting) workingMonitor = AlgoStatusMonitor(self.algoEngine, AlgoStatusMonitor.MODE_WORKING) historyMonitor = AlgoStatusMonitor(self.algoEngine, AlgoStatusMonitor.MODE_HISTORY) @@ -431,6 +450,45 @@ class AlgoManager(QtWidgets.QWidget): #---------------------------------------------------------------------- def addAlgoWidget(self, widgetClass): - """""" + """添加算法控制组件 """ w = widgetClass(self.algoEngine) - self.tab.addTab(w, w.templateName) \ No newline at end of file + self.tab.addTab(w, w.templateName) + + #---------------------------------------------------------------------- + def loadCsv(self, path): + """读取CSV配置文件""" + try: + with open(unicode(path)) as f: + buf = [line.encode('UTF-8') for line in f] + + reader = csv.DictReader(buf) + l = [] + + for d in reader: + setting = OrderedDict() + for name in reader.fieldnames: + setting[str(name)] = d[name] + l.append(setting) + + return l + + except: + msg = traceback.format_exc() + self.algoEngine.writeLog(u'读取CSV文件失败:\n' + msg) + return [] + + #---------------------------------------------------------------------- + def saveSettingFromCsv(self): + """从CSV加载配置到数据库""" + path, fileType = QtWidgets.QFileDialog.getOpenFileName(self, u'加载算法配置', '', 'CSV(*.csv)') + l = self.loadCsv(path) + for setting in l: + self.algoEngine.saveAlgoSetting(setting) + + #---------------------------------------------------------------------- + def addAlgoFromCsv(self): + """从CSV启动一篮子算法""" + path, fileType = QtWidgets.QFileDialog.getOpenFileName(self, u'启动篮子算法', '', 'CSV(*.csv) ') + l = self.loadCsv(path) + for setting in l: + self.algoEngine.addAlgo(setting) \ No newline at end of file diff --git a/vnpy/trader/uiBasicWidget.py b/vnpy/trader/uiBasicWidget.py index 6ef2dcee..4cde79f1 100644 --- a/vnpy/trader/uiBasicWidget.py +++ b/vnpy/trader/uiBasicWidget.py @@ -375,7 +375,7 @@ class BasicMonitor(QtWidgets.QTableWidget): self.menu.close() # 获取想要保存的文件名 - path = QtWidgets.QFileDialog.getSaveFileName(self, vtText.SAVE_DATA, '', 'CSV(*.csv)') + path, fileType = QtWidgets.QFileDialog.getSaveFileName(self, vtText.SAVE_DATA, '', 'CSV(*.csv)') try: #if not path.isEmpty():