def parent(self, index): if not index.isValid(): return QtCore.QModelIndex() childItem = index.internalPointer() parentItem = childItem.parent() if parentItem == self.rootItem: return QtCore.QModelIndex() return self.createIndex(parentItem.row(), 0, parentItem)
def index(self, row, column, parent): if not self.hasIndex(row, column, parent): return QtCore.QModelIndex() if parent is None or not parent.isValid(): parentItem = self.rootItem else: parentItem = parent.internalPointer() childItem = parentItem.child(row) if childItem: return self.createIndex(row, column, childItem) else: return QtCore.QModelIndex()
def generatePicture(self): ## pre-computing a QPicture object allows paint() to run much more quickly, ## rather than re-drawing the shapes every time. self.picture = QtGui.QPicture() p = QtGui.QPainter(self.picture) p.setPen(pg.mkPen(color='w', width=0.4)) # 0.4 means w*2 # w = (self.data[1][0] - self.data[0][0]) / 3. w = 0.2 for (t, open, close, min, max) in self.data: p.drawLine(QtCore.QPointF(t, min), QtCore.QPointF(t, max)) if open > close: p.setBrush(pg.mkBrush('g')) else: p.setBrush(pg.mkBrush('r')) p.drawRect(QtCore.QRectF(t-w, open, w*2, close-open)) p.end()
def generatePicture(self): ## pre-computing a QPicture object allows paint() to run much more quickly, ## rather than re-drawing the shapes every time. self.picture = QtGui.QPicture() p = QtGui.QPainter(self.picture) p.setPen(pg.mkPen(color='w')) # 0.4 means w*2, width=0.4 w = 0.2 # w*2是 阴线阳线宽度 # 用来记录上一个k线值 和打印更新的k线状态值 global pre if len(self.data) == 0: pass elif len(self.data) < 2: pre = self.data[0] cur = self.data[0] else: cur = self.data[-1] if pre == cur: pass else: print cur pre = cur for (t, open_price, close_price, min_price, max_price) in self.data: ''' 这里对画最高最低值的竖直线的一种意外情况的判断, 如果max和min一样,则画出来的直线实际上成了一个方块 ''' if abs(min_price - max_price) < 0.00000001: pass # 如果最高价和最低价相同,则不绘制这直线 else: p.drawLine(QtCore.QPointF(t, min_price), QtCore.QPointF(t, max_price)) if open_price > close_price: p.setBrush(pg.mkBrush('g')) else: p.setBrush(pg.mkBrush('r')) # 绘制open和close的柱状图 p.drawRect( QtCore.QRectF(t - w, open_price, w * 2, close_price - open_price)) p.end()
class CtaStrategyManager(QtGui.QGroupBox): """策略管理组件""" signal = QtCore.pyqtSignal(type(Event())) # ---------------------------------------------------------------------- def __init__(self, ctaEngine, eventEngine, name, parent=None): """Constructor""" super(CtaStrategyManager, self).__init__(parent) self.ctaEngine = ctaEngine self.eventEngine = eventEngine self.name = name self.initUi() self.updateMonitor() self.registerEvent() # ---------------------------------------------------------------------- def initUi(self): """初始化界面""" self.setTitle(self.name) self.paramMonitor = CtaValueMonitor(self) self.varMonitor = CtaValueMonitor(self) hbox2 = QtGui.QHBoxLayout() hbox2.addWidget(self.paramMonitor) hbox3 = QtGui.QHBoxLayout() hbox3.addWidget(self.varMonitor) vbox = QtGui.QVBoxLayout() vbox.addLayout(hbox2) vbox.addLayout(hbox3) self.setLayout(vbox) # ---------------------------------------------------------------------- def updateMonitor(self, event=None): """显示策略最新状态""" paramDict = self.ctaEngine.getStrategyParam(self.name) if paramDict: self.paramMonitor.updateData(paramDict) varDict = self.ctaEngine.getStrategyVar(self.name) if varDict: self.varMonitor.updateData(varDict) # ---------------------------------------------------------------------- def registerEvent(self): """注册事件监听""" self.signal.connect(self.updateMonitor) self.eventEngine.register(EVENT_CTA_STRATEGY + self.name, self.signal.emit)
def edit(self): self.textBrowser = QtGui.QTextBrowser() self.textBrowser.setGeometry(QtCore.QRect(0, 0, 1000, 1000)) self.textBrowser.setReadOnly(False) self.textBrowser.setObjectName(QtCore.QString.fromUtf8("textBrowser")) f = open(self.setting['base']['strategy_file']) my_data = f.read() f.close() self.textBrowser.append(my_data.decode('utf-8')) self.textBrowser.showMaximized()
class ValueMonitor(QtGui.QTableWidget): """数值监控""" signal = QtCore.pyqtSignal() #---------------------------------------------------------------------- def __init__(self, parent=None): """Constructor""" super(ValueMonitor, self).__init__(parent) self.keyCellDict = {} self.row = 0 self.data = None self.initUi() self.signal.connect(self.updateTable) #---------------------------------------------------------------------- def initUi(self): """初始化界面""" self.setColumnCount(2) self.verticalHeader().setVisible(False) self.horizontalHeader().setVisible(False) self.setEditTriggers(self.NoEditTriggers) self.setAlternatingRowColors(True) #---------------------------------------------------------------------- def updateData(self, data): """更新数据""" self.data = data self.signal.emit() #---------------------------------------------------------------------- def updateTable(self): """更新表格""" for key, value in self.data.items(): if key in self.keyCellDict: cell = self.keyCellDict[key] cell.setText(unicode(value)) else: # 创建并保存单元格 keyCell = BasicCell(unicode(key)) cell = BasicCell(unicode(value)) self.keyCellDict[key] = cell # 移动到下一行 self.insertRow(self.row) self.setItem(self.row, 0, keyCell) self.setItem(self.row, 1, cell) self.row += 1
class TaskManager(QWidget): """任务管理主界面""" signal = QtCore.Signal(type(Event())) #---------------------------------------------------------------------- def __init__(self, ctaEngine, eventEngine, parent=None): """Constructor""" super(TaskManager, self).__init__(parent) self.taskTab = TaskTable() self.eventEngine = eventEngine self.initUi() self.signal.connect(self.init) self.eventEngine.register(EVENT_TIMER, self.signal.emit) #---------------------------------------------------------------------- def initUi(self): """初始化界面""" self.setWindowTitle(u'任务管理') buttonStopAll = QPushButton(u'全部停止') buttonStopAll.setObjectName(_fromUtf8('redButton')) buttonStopAll.clicked.connect(self.taskTab.stopAll) buttonClearAll = QPushButton(u'清空所有') buttonClearAll.setObjectName(_fromUtf8('blueButton')) buttonClearAll.clicked.connect(self.taskTab.clearAll) buttonShowAll = QPushButton(u'连续显示') buttonShowAll.setObjectName(_fromUtf8('greenButton')) buttonShowAll.clicked.connect(self.taskTab.showAll) hbox11 = QHBoxLayout() hbox11.addWidget(buttonStopAll) hbox11.addWidget(buttonClearAll) hbox11.addWidget(buttonShowAll) hbox11.addStretch() grid = QVBoxLayout() grid.addLayout(hbox11) grid.addWidget(self.taskTab) self.setLayout(grid) #---------------------------------------------------------------------- def show(self): """重载显示""" self.showMaximized() #---------------------------------------------------------------------- def init(self): """初始化""" self.taskTab.initCells()
class CtaStrategyManager(QtGui.QGroupBox): """策略管理组件""" signal = QtCore.pyqtSignal(type(Event())) #---------------------------------------------------------------------- def __init__(self, ctaEngine, eventEngine, name, parent=None): """Constructor""" super(CtaStrategyManager, self).__init__(parent) self.ctaEngine = ctaEngine self.eventEngine = eventEngine self.name = name self.initUi() self.updateMonitor() self.registerEvent() #---------------------------------------------------------------------- def initUi(self): """初始化界面""" self.setTitle(self.name) self.paramMonitor = CtaValueMonitor(self) self.varMonitor = CtaValueMonitor(self) maxHeight = 60 self.paramMonitor.setMaximumHeight(maxHeight) self.varMonitor.setMaximumHeight(maxHeight) buttonInit = QtGui.QPushButton(u'初始化') buttonStart = QtGui.QPushButton(u'启动') buttonStop = QtGui.QPushButton(u'停止') buttonInit.clicked.connect(self.init) buttonStart.clicked.connect(self.start) buttonStop.clicked.connect(self.stop) hbox1 = QtGui.QHBoxLayout() hbox1.addWidget(buttonInit) hbox1.addWidget(buttonStart) hbox1.addWidget(buttonStop) hbox1.addStretch() hbox2 = QtGui.QHBoxLayout() hbox2.addWidget(self.paramMonitor) hbox3 = QtGui.QHBoxLayout() hbox3.addWidget(self.varMonitor) vbox = QtGui.QVBoxLayout() vbox.addLayout(hbox1) vbox.addLayout(hbox2) vbox.addLayout(hbox3) self.setLayout(vbox) #---------------------------------------------------------------------- def updateMonitor(self, event=None): """显示策略最新状态""" paramDict = self.ctaEngine.getStrategyParam(self.name) if paramDict: self.paramMonitor.updateData(paramDict) varDict = self.ctaEngine.getStrategyVar(self.name) if varDict: self.varMonitor.updateData(varDict) #---------------------------------------------------------------------- def registerEvent(self): """注册事件监听""" self.signal.connect(self.updateMonitor) self.eventEngine.register(EVENT_CTA_STRATEGY + self.name, self.signal.emit) #---------------------------------------------------------------------- def init(self): """初始化策略""" self.ctaEngine.initStrategy(self.name) #---------------------------------------------------------------------- def start(self): """启动策略""" self.ctaEngine.startStrategy(self.name) #---------------------------------------------------------------------- def stop(self): """停止策略""" self.ctaEngine.stopStrategy(self.name)
class StockValueMonitor(QtGui.QTableWidget): """参数监控""" signal = QtCore.pyqtSignal(type(Event())) #---------------------------------------------------------------------- def __init__(self, stockBacktestEngine, eventEngine, name, parent=None): """Constructor""" super(StockValueMonitor, self).__init__(parent) self.stockBacktestEngine = stockBacktestEngine self.eventEngine = eventEngine self.name = name self.data = {} self.keyCellDict = {} self.lables = [ 'run_id', 'strategy_file', 'start_date', 'end_date', 'stock_starting_cash', 'frequency', 'matching_type', 'benchmark', 'slippage', 'commission_multiplier', 'margin_multiplier' ] self.typeMap = [ int, str, str, str, int, str, str, str, float, float, float ] self.inited = False self.initUi() #---------------------------------------------------------------------- def initUi(self): """初始化界面""" self.setRowCount(1) self.verticalHeader().setVisible(False) self.setMaximumHeight(self.sizeHint().height()) #---------------------------------------------------------------------- def updateData(self, data): """更新数据""" self.data = data if not self.inited: if 'run_id' in data.keys(): self.setEditTriggers(self.DoubleClicked) self.setColumnCount(len(self.lables)) self.setFixedHeight(85) self.setHorizontalHeaderLabels(self.lables) self.resizeColumnsToContents() self.resizeRowsToContents() col = 0 cell = QtGui.QTableWidgetItem(unicode(data['run_id'])) self.resizeColumnsToContents() self.keyCellDict['run_id'] = cell self.setItem(0, col, cell) col += 1 cell = QtGui.QTableWidgetItem(unicode(data['strategy_file'])) self.resizeColumnsToContents() self.keyCellDict['strategy_file'] = cell self.setItem(0, col, cell) col += 1 cell = QtGui.QTableWidgetItem(unicode(data['start_date'])) self.resizeColumnsToContents() self.keyCellDict['start_date'] = cell self.setItem(0, col, cell) col += 1 cell = QtGui.QTableWidgetItem(unicode(data['end_date'])) self.resizeColumnsToContents() self.keyCellDict['end_date'] = cell self.setItem(0, col, cell) col += 1 """ cell = QtGui.QCalendarWidget() self.resizeColumnsToContents() self.resizeRowsToContents() self.keyCellDict['start_date'] = cell self.setCellWidget(0, col, cell) col += 1 cell = QtGui.QCalendarWidget() self.resizeColumnsToContents() self.resizeRowsToContents() self.keyCellDict['end_date'] = cell self.setCellWidget(0, col, cell) col += 1 """ cell = QtGui.QTableWidgetItem( unicode(data['stock_starting_cash'])) self.resizeColumnsToContents() self.keyCellDict['stock_starting_cash'] = cell self.setItem(0, col, cell) col += 1 cell = QtGui.QComboBox() cell.addItem("1d") cell.addItem("1m") cell.addItem("tick") self.resizeColumnsToContents() self.keyCellDict['frequency'] = cell self.setCellWidget(0, col, cell) cell.currentIndexChanged.connect(self.sendChangeSignal2) col += 1 cell = QtGui.QComboBox() cell.addItem("current_bar") cell.addItem("next_bar") self.resizeColumnsToContents() self.keyCellDict['matching_type'] = cell self.setCellWidget(0, col, cell) cell.currentIndexChanged.connect(self.sendChangeSignal3) col += 1 cell = QtGui.QTableWidgetItem(unicode(data['benchmark'])) self.resizeColumnsToContents() self.keyCellDict['benchmark'] = cell self.setItem(0, col, cell) col += 1 cell = QtGui.QTableWidgetItem(unicode(data['slippage'])) self.resizeColumnsToContents() self.keyCellDict['slippage'] = cell self.setItem(0, col, cell) col += 1 cell = QtGui.QTableWidgetItem( unicode(data['commission_multiplier'])) self.resizeColumnsToContents() self.keyCellDict['commission_multiplier'] = cell self.setItem(0, col, cell) col += 1 cell = QtGui.QTableWidgetItem( unicode(data['margin_multiplier'])) self.resizeColumnsToContents() self.keyCellDict['margin_multiplier'] = cell self.setItem(0, col, cell) col += 1 else: self.setEditTriggers(self.NoEditTriggers) self.setColumnCount(len(data)) self.setFixedHeight(85) self.setHorizontalHeaderLabels(data.keys()) self.resizeColumnsToContents() col = 0 for k, v in data.items(): cell = QtGui.QTableWidgetItem(unicode(v)) self.keyCellDict[k] = cell self.setItem(0, col, cell) col += 1 self.inited = True else: for k, v in data.items(): cell = self.keyCellDict[k] cell.setText(unicode(v)) self.cellChanged.connect(self.sendChangeSignal) # ---------------------------------------------------------------------- def sendChangeSignal(self): sentData = self.data col = self.currentColumn() sentData[self.lables[col]] = self.typeMap[col]( self.keyCellDict[self.lables[col]].text()) event = Event(type_=EVENT_SET_CHANGED + self.name) event.dict_ = sentData event.dict_['name'] = self.name self.eventEngine.put(event) self.data = sentData # ---------------------------------------------------------------------- def sendChangeSignal2(self): sentData = self.data col = 5 sentData[self.lables[col]] = self.typeMap[col]( self.keyCellDict[self.lables[col]].currentText()) event = Event(type_=EVENT_SET_CHANGED + self.name) event.dict_ = sentData event.dict_['name'] = self.name self.eventEngine.put(event) self.data = sentData # ---------------------------------------------------------------------- def sendChangeSignal3(self): sentData = self.data col = 6 sentData[self.lables[col]] = self.typeMap[col]( self.keyCellDict[self.lables[col]].currentText()) event = Event(type_=EVENT_SET_CHANGED + self.name) event.dict_ = sentData event.dict_['name'] = self.name self.eventEngine.put(event) self.data = sentData
class DrEngineManager(QtWidgets.QWidget): """行情数据记录引擎管理组件""" signal = QtCore.pyqtSignal(type(Event())) #---------------------------------------------------------------------- def __init__(self, drEngine, eventEngine, parent=None): """Constructor""" super(DrEngineManager, self).__init__(parent) self.drEngine = drEngine self.eventEngine = eventEngine self.initUi() self.updateSetting() self.registerEvent() #---------------------------------------------------------------------- def initUi(self): """初始化界面""" self.setWindowTitle(text.DATA_RECORDER) # 记录合约配置监控 tickLabel = QtWidgets.QLabel(text.TICK_RECORD) self.tickTable = QtWidgets.QTableWidget() self.tickTable.setColumnCount(2) self.tickTable.verticalHeader().setVisible(False) self.tickTable.setEditTriggers(QtWidgets.QTableWidget.NoEditTriggers) self.tickTable.horizontalHeader().setResizeMode( QtWidgets.QHeaderView.Stretch) self.tickTable.setAlternatingRowColors(True) self.tickTable.setHorizontalHeaderLabels( [text.CONTRACT_SYMBOL, text.GATEWAY]) barLabel = QtWidgets.QLabel(text.BAR_RECORD) self.barTable = QtWidgets.QTableWidget() self.barTable.setColumnCount(2) self.barTable.verticalHeader().setVisible(False) self.barTable.setEditTriggers(QtWidgets.QTableWidget.NoEditTriggers) self.barTable.horizontalHeader().setResizeMode( QtWidgets.QHeaderView.Stretch) self.barTable.setAlternatingRowColors(True) self.barTable.setHorizontalHeaderLabels( [text.CONTRACT_SYMBOL, text.GATEWAY]) activeLabel = QtWidgets.QLabel(text.DOMINANT_CONTRACT) self.activeTable = QtWidgets.QTableWidget() self.activeTable.setColumnCount(2) self.activeTable.verticalHeader().setVisible(False) self.activeTable.setEditTriggers(QtWidgets.QTableWidget.NoEditTriggers) self.activeTable.horizontalHeader().setResizeMode( QtWidgets.QHeaderView.Stretch) self.activeTable.setAlternatingRowColors(True) self.activeTable.setHorizontalHeaderLabels( [text.DOMINANT_SYMBOL, text.CONTRACT_SYMBOL]) # 日志监控 self.logMonitor = QtWidgets.QTextEdit() self.logMonitor.setReadOnly(True) self.logMonitor.setMinimumHeight(600) # 设置布局 grid = QtWidgets.QGridLayout() grid.addWidget(tickLabel, 0, 0) grid.addWidget(barLabel, 0, 1) grid.addWidget(activeLabel, 0, 2) grid.addWidget(self.tickTable, 1, 0) grid.addWidget(self.barTable, 1, 1) grid.addWidget(self.activeTable, 1, 2) vbox = QtWidgets.QVBoxLayout() vbox.addLayout(grid) vbox.addWidget(self.logMonitor) self.setLayout(vbox) #---------------------------------------------------------------------- def updateLog(self, event): """更新日志""" log = event.dict_['data'] content = '\t'.join([log.logTime, log.logContent]) self.logMonitor.append(content) #---------------------------------------------------------------------- def registerEvent(self): """注册事件监听""" self.signal.connect(self.updateLog) self.eventEngine.register(EVENT_DATARECORDER_LOG, self.signal.emit) #---------------------------------------------------------------------- def updateSetting(self): """显示引擎行情记录配置""" with open(self.drEngine.settingFileName) as f: drSetting = json.load(f) if 'tick' in drSetting: l = drSetting['tick'] for setting in l: self.tickTable.insertRow(0) self.tickTable.setItem(0, 0, TableCell(setting[0])) self.tickTable.setItem(0, 1, TableCell(setting[1])) if 'bar' in drSetting: l = drSetting['bar'] for setting in l: self.barTable.insertRow(0) self.barTable.setItem(0, 0, TableCell(setting[0])) self.barTable.setItem(0, 1, TableCell(setting[1])) if 'active' in drSetting: d = drSetting['active'] for activeSymbol, symbol in d.items(): self.activeTable.insertRow(0) self.activeTable.setItem(0, 0, TableCell(activeSymbol)) self.activeTable.setItem(0, 1, TableCell(symbol))
class CtaEngineManager(QtGui.QWidget): """CTA引擎管理组件""" signal = QtCore.pyqtSignal(type(Event())) #---------------------------------------------------------------------- def __init__(self, ctaEngine, eventEngine, parent=None): """Constructor""" super(CtaEngineManager, self).__init__(parent) self.ctaEngine = ctaEngine self.eventEngine = eventEngine self.strategyLoaded = False self.initUi() self.registerEvent() # 记录日志 self.ctaEngine.writeCtaLog(u'CTA引擎启动成功') #---------------------------------------------------------------------- def initUi(self): """初始化界面""" self.setWindowTitle(u'CTA策略') # 按钮 testButton = QtGui.QPushButton('test') loadButton = QtGui.QPushButton(u'加载策略') initAllButton = QtGui.QPushButton(u'全部初始化') startAllButton = QtGui.QPushButton(u'全部启动') stopAllButton = QtGui.QPushButton(u'全部停止') loadButton.clicked.connect(self.load) initAllButton.clicked.connect(self.initAll) startAllButton.clicked.connect(self.startAll) stopAllButton.clicked.connect(self.stopAll) # 滚动区域,放置所有的CtaStrategyManager self.scrollArea = QtGui.QScrollArea() self.scrollArea.setWidgetResizable(True) # CTA组件的日志监控 self.ctaLogMonitor = QtGui.QTextEdit() self.ctaLogMonitor.setReadOnly(True) self.ctaLogMonitor.setMaximumHeight(200) # 设置布局 hbox2 = QtGui.QHBoxLayout() hbox2.addWidget(testButton) hbox2.addWidget(loadButton) hbox2.addWidget(initAllButton) hbox2.addWidget(startAllButton) hbox2.addWidget(stopAllButton) hbox2.addStretch() vbox = QtGui.QVBoxLayout() vbox.addLayout(hbox2) vbox.addWidget(self.scrollArea) vbox.addWidget(self.ctaLogMonitor) self.setLayout(vbox) #---------------------------------------------------------------------- def initStrategyManager(self): """初始化策略管理组件界面""" w = QtGui.QWidget() vbox = QtGui.QVBoxLayout() for name in self.ctaEngine.strategyDict.keys(): strategyManager = CtaStrategyManager(self.ctaEngine, self.eventEngine, name) vbox.addWidget(strategyManager) vbox.addStretch() w.setLayout(vbox) self.scrollArea.setWidget(w) #---------------------------------------------------------------------- def initAll(self): """全部初始化""" for name in self.ctaEngine.strategyDict.keys(): self.ctaEngine.initStrategy(name) #---------------------------------------------------------------------- def startAll(self): """全部启动""" for name in self.ctaEngine.strategyDict.keys(): self.ctaEngine.startStrategy(name) #---------------------------------------------------------------------- def stopAll(self): """全部停止""" for name in self.ctaEngine.strategyDict.keys(): self.ctaEngine.stopStrategy(name) #---------------------------------------------------------------------- def load(self): """加载策略""" if not self.strategyLoaded: self.ctaEngine.loadSetting() self.initStrategyManager() self.strategyLoaded = True self.ctaEngine.writeCtaLog(u'策略加载成功') #---------------------------------------------------------------------- def updateCtaLog(self, event): """更新CTA相关日志""" log = event.dict_['data'] print type(log) content = '\t'.join([log.logTime, log.logContent]) self.ctaLogMonitor.append(content) #---------------------------------------------------------------------- def registerEvent(self): """注册事件监听""" self.signal.connect(self.updateCtaLog) self.eventEngine.register(EVENT_CTA_LOG, self.signal.emit)
class CtaStrategyManager(QtGui.QGroupBox): """策略管理组件""" signal = QtCore.pyqtSignal(type(Event())) #---------------------------------------------------------------------- def __init__(self, ctaEngine, eventEngine, name, className=None, direction=None, vtSymbol=None, longsymbol=None, shortsymbol=None, parent=None): """Constructor""" super(CtaStrategyManager, self).__init__(parent) self.ctaEngine = ctaEngine self.eventEngine = eventEngine self.name = name self.initUi() self.updateMonitor() self.registerEvent() if className == 'tradeTest': self.paramWindow = ParamWindow(self.name, longsymbol, shortsymbol) elif className == "CtpAndIB": self.paramWindow = ParamWindow3(self.name, longsymbol, shortsymbol) else: self.paramWindow = ParamWindow2(self.name, direction, vtSymbol) #---------------------------------------------------------------------- def initUi(self): """初始化界面""" self.setTitle(self.name) self.paramMonitor = CtaValueMonitor(self) self.varMonitor = CtaValueMonitor(self) maxHeight = 60 self.paramMonitor.setMaximumHeight(maxHeight) self.varMonitor.setMaximumHeight(maxHeight) buttonInit = QtGui.QPushButton(u'初始化') buttonStart = QtGui.QPushButton(u'启动') buttonStop = QtGui.QPushButton(u'停止') buttonParam = QtGui.QPushButton(u'参数') buttonDelete = QtGui.QPushButton(u'删除') buttonDelete.clicked.connect(self.delete) buttonInit.clicked.connect(self.init) buttonStart.clicked.connect(self.start) buttonStop.clicked.connect(self.stop) buttonParam.clicked.connect(self.param) hbox1 = QtGui.QHBoxLayout() hbox1.addWidget(buttonInit) hbox1.addWidget(buttonStart) hbox1.addWidget(buttonStop) hbox1.addWidget(buttonParam) hbox1.addWidget(buttonDelete) hbox1.addStretch() hbox2 = QtGui.QHBoxLayout() hbox2.addWidget(self.paramMonitor) hbox3 = QtGui.QHBoxLayout() hbox3.addWidget(self.varMonitor) vbox = QtGui.QVBoxLayout() vbox.addLayout(hbox1) vbox.addLayout(hbox2) vbox.addLayout(hbox3) self.setLayout(vbox) #---------------------------------------------------------------------- def updateMonitor(self, event=None): """显示策略最新状态""" paramDict = self.ctaEngine.getStrategyParam(self.name) if paramDict: self.paramMonitor.updateData(paramDict) self.paramMonitor.setColumnWidth(3, 300) varDict = self.ctaEngine.getStrategyVar(self.name) if varDict: self.varMonitor.updateData(varDict) self.varMonitor.setColumnWidth(3, 300) #---------------------------------------------------------------------- def registerEvent(self): """注册事件监听""" self.signal.connect(self.updateMonitor) self.eventEngine.register(EVENT_CTA_STRATEGY + self.name, self.signal.emit) #---------------------------------------------------------------------- def init(self): """初始化策略""" self.ctaEngine.initStrategy(self.name) #---------------------------------------------------------------------- def start(self): """启动策略""" self.ctaEngine.startStrategy(self.name) #---------------------------------------------------------------------- def stop(self): """停止策略""" self.ctaEngine.stopStrategy(self.name) #========================================================================================== def param(self): self.paramWindow.paramters = self.paramWindow.loadParameter() self.paramWindow.showParam() self.paramWindow.show() #def position(self): #self.ctaEngine.excPos(self.name) #def updateInfo(self): #self.ctaEngine.loadPosInfo() def delete(self): settingFileName = 'ctaAlgo/CTA_setting.json' reply = QtGui.QMessageBox.question( self, u'删除', u'是否删除配置文件?', QtGui.QMessageBox.Yes | QtGui.QMessageBox.No, QtGui.QMessageBox.No) with open(settingFileName, 'r') as f: l = json.load(f) f.close() #flag = True for x in l: if x['name'] == self.name: l.remove(x) #flag = False with open(settingFileName, 'w') as f: json.dump(l, f) f.close() if reply == QtGui.QMessageBox.Yes: fileName = "parameter_" + self.name + ".json" os.remove(fileName) else: pass0
class DrEditWidget(QtGui.QWidget): """行情数据记录引擎管理组件""" signal = QtCore.pyqtSignal(type(Event())) def __init__(self, drWidget, mainEngine, eventEngine, parent=None): """Constructor""" super(DrEditWidget, self).__init__(parent) self.drWidget = drWidget self.mainEngine = mainEngine self.eventEngine = eventEngine self.hasChanged = False # 保存合约详细信息的字典 self.contractDict = {} self.initUi() self.updateSetting() self.loadData() self.registerEvent() def closeEvent(self, QCloseEvent): if self.hasChanged: self.drWidget.restart() def initUi(self): vbox = QtGui.QVBoxLayout() vline = QtGui.QHBoxLayout() vline.setSpacing(2) btnTickAll = QtGui.QPushButton(u"全部记录Tick", self) btnBarAll = QtGui.QPushButton(u'全部记录Bar', self) btnSaveAll = QtGui.QPushButton(u'保存设置(重启后生效)', self) btnTickAll.clicked.connect(self.selectAllTick) btnBarAll.clicked.connect(self.selectAllBar) btnSaveAll.clicked.connect(self.saveSetting) vline.addWidget(btnTickAll) vline.addWidget(btnBarAll) vline.addWidget(btnSaveAll) vbox.addLayout(vline) self.qTreeView = QTreeView() self.model = TreeModel() self.qTreeView.setModel(self.model) self.qTreeView.setSelectionMode(QtGui.QAbstractItemView.NoSelection) self.qTreeView.setItemDelegateForColumn(1, CheckBoxDelegate(self)) self.qTreeView.setItemDelegateForColumn(2, CheckBoxDelegate(self)) self.qTreeView.setItemDelegateForColumn(3, CheckBoxDelegate(self)) self.qTreeView.setItemDelegateForColumn(5, ComboDelegate(self, ["CTP", "LTS", "XTP", "FEMAS", "XSPEED", "QDP", "KSOTP", "KSGOLD", "SGIT"])) vbox.addWidget(self.qTreeView) self.setLayout(vbox) def getContractChineseName(self, str): line = str.strip().decode('utf-8', 'ignore') # 处理前进行相关的处理,包括转换成Unicode等 p2 = re.compile(ur'[^\u4e00-\u9fa5]') # 中文的编码范围是:\u4e00到\u9fa5 zh = " ".join(p2.split(line)).strip() zh = ",".join(zh.split()) outStr = zh # 经过相关处理后得到中文的文本 return outStr def loadData(self): child = [] tick = {} bar = {} active = [] with open(self.mainEngine.drEngine.settingFileName) as f: drSetting = json.load(f) if 'tick' in drSetting: l = drSetting['tick'] for setting in l: tick[setting[0]] = setting[1] if 'bar' in drSetting: l = drSetting['bar'] for setting in l: bar[setting[0]] = setting[1] if 'active' in drSetting: d = drSetting['active'] for activeSymbol, symbol in d.items(): active.append(symbol) contractDict = {} contracts = self.mainEngine.getAllContracts() for contract in contracts: contractName = self.getContractChineseName(contract.name) gateWayName = u"CTP" hasTick = tick.has_key(contract.symbol) hasBar = bar.has_key(contract.symbol) hasActive = contract.symbol in active if hasTick: gateWayName = tick[contract.symbol] elif hasBar: gateWayName = bar[contract.symbol] if contractDict.has_key(contractName): parentItem = contractDict[contractName] item = TreeItem([contract.symbol, hasTick, hasBar, hasActive, contract.exchange, gateWayName], parentItem) parentItem.appendChild(item) else: item = TreeItem([contractName, False, False, False, contract.exchange, gateWayName], self.model.rootItem) contractDict[contractName] = item child.append(item) subItem = TreeItem([contract.symbol, hasTick, hasBar, hasActive, contract.exchange, gateWayName], item) item.appendChild(subItem) # yumi = TreeItem([u"玉米", False, False, False, "SH", "CTP"], self.model.rootItem) # yumi.appendChild(TreeItem([u"c1705", False, False, False, "SH", "CTP"], yumi)) # yumi.appendChild(TreeItem([u"c1703", False, False, False, "SH", "CTP"], yumi)) # yumi.appendChild(TreeItem([u"c1707", False, False, False, "SH", "CTP"], yumi)) # yumi.appendChild(TreeItem([u"c1709", False, False, False, "SH", "CTP"], yumi)) # dianfen = TreeItem([u"淀粉", False, False, False, "SH", "CTP"], self.model.rootItem) # dianfen.appendChild(TreeItem([u"d1705", False, False, False, "SH", "CTP"], dianfen)) # dianfen.appendChild(TreeItem([u"d1703", False, False, False, "SH", "CTP"], dianfen)) # dianfen.appendChild(TreeItem([u"d1707", False, False, False, "SH", "CTP"], dianfen)) # dianfen.appendChild(TreeItem([u"d1709", False, False, False, "SH", "CTP"], dianfen)) # # child.append(yumi) # child.append(dianfen) self.model.setDataSource(child) self.qTreeView.expandAll() def saveSetting(self): setting = {} setting["tick"] = [] setting["bar"] = [] setting["active"] = {} queue = Queue() queue.put(self.model.rootItem) while queue.qsize() > 0: item = queue.get() for child in item.childItems: queue.put(child) if item.parentItem is not None and item.parentItem != self.model.rootItem: name = item.data(0) interface = item.data(5) if item.data(1): setting["tick"].append([name, interface]) if item.data(2): setting["bar"].append([name, interface]) if item.data(3): setting["active"][item.parentItem.data(0)] = name if self.mainEngine.drEngine.saveSetting(setting): self.hasChanged = True self.close() def selectAllTick(self): self.selectAll(True, False, True) def selectAllBar(self): self.selectAll(False, True, True) def selectAll(self, tick=False, bar=False, select=False): column = None if tick: column = 1 if bar: column = 2 for row in range(self.model.rootItem.childCount()): childIndex = self.model.index(row, column, None) self.model.setData(childIndex, QtCore.Qt.Unchecked if select == False else QtCore.Qt.Checked, QtCore.Qt.CheckStateRole) def updateSetting(self): pass def updateContract(self, event): """更新合约数据""" contract = event.dict_['data'] self.contractDict[contract.vtSymbol] = contract self.contractDict[contract.symbol] = contract # 使用常规代码(不包括交易所)可能导致重复 # ---------------------------------------------------------------------- def registerEvent(self): """注册事件监听""" self.signal.connect(self.updateContract) self.eventEngine.register(EVENT_CONTRACT, self.signal.emit)
class CtaEngineManager(QtGui.QWidget): """CTA引擎管理组件""" signal = QtCore.pyqtSignal(type(Event())) # ---------------------------------------------------------------------- def __init__(self, ctaEngine, eventEngine, parent=None): """Constructor""" super(CtaEngineManager, self).__init__(parent) self.ctaEngine = ctaEngine self.eventEngine = eventEngine self.strategyLoaded = False self.initUi() self.registerEvent() # 记录日志 self.ctaEngine.writeCtaLog(text.CTA_ENGINE_STARTED) # ---------------------------------------------------------------------- def initUi(self): """初始化界面""" self.setWindowTitle(text.CTA_STRATEGY) # 按钮 loadButton = QtGui.QPushButton(text.LOAD_STRATEGY) initAllButton = QtGui.QPushButton(text.INIT_ALL) startAllButton = QtGui.QPushButton(text.START_ALL) stopAllButton = QtGui.QPushButton(text.STOP_ALL) savePositionButton = QtGui.QPushButton(text.SAVE_POSITION_DATA) loadButton.clicked.connect(self.load) initAllButton.clicked.connect(self.initAll) startAllButton.clicked.connect(self.startAll) stopAllButton.clicked.connect(self.stopAll) savePositionButton.clicked.connect(self.ctaEngine.savePosition) # 滚动区域,放置所有的CtaStrategyManager self.scrollArea = QtGui.QScrollArea() self.scrollArea.setWidgetResizable(True) # CTA组件的日志监控 self.ctaLogMonitor = QtGui.QTextEdit() self.ctaLogMonitor.setReadOnly(True) self.ctaLogMonitor.setMaximumHeight(200) # 设置布局 hbox2 = QtGui.QHBoxLayout() hbox2.addWidget(loadButton) hbox2.addWidget(initAllButton) hbox2.addWidget(startAllButton) hbox2.addWidget(stopAllButton) hbox2.addWidget(savePositionButton) hbox2.addStretch() vbox = QtGui.QVBoxLayout() vbox.addLayout(hbox2) vbox.addWidget(self.scrollArea) vbox.addWidget(self.ctaLogMonitor) self.setLayout(vbox) # ---------------------------------------------------------------------- def initStrategyManager(self): """初始化策略管理组件界面""" w = QtGui.QWidget() vbox = QtGui.QVBoxLayout() for name in self.ctaEngine.strategyDict.keys(): strategyManager = CtaStrategyManager(self.ctaEngine, self.eventEngine, name) vbox.addWidget(strategyManager) vbox.addStretch() w.setLayout(vbox) self.scrollArea.setWidget(w) # ---------------------------------------------------------------------- def initAll(self): """全部初始化""" for name in self.ctaEngine.strategyDict.keys(): self.ctaEngine.initStrategy(name) # ---------------------------------------------------------------------- def startAll(self): """全部启动""" for name in self.ctaEngine.strategyDict.keys(): self.ctaEngine.startStrategy(name) # ---------------------------------------------------------------------- def stopAll(self): """全部停止""" for name in self.ctaEngine.strategyDict.keys(): self.ctaEngine.stopStrategy(name) # ---------------------------------------------------------------------- def load(self): """加载策略""" if not self.strategyLoaded: self.ctaEngine.loadSetting() self.initStrategyManager() self.strategyLoaded = True self.ctaEngine.writeCtaLog(text.STRATEGY_LOADED) # ---------------------------------------------------------------------- def updateCtaLog(self, event): """更新CTA相关日志""" log = event.dict_['data'] content = '\t'.join([log.logTime, log.logContent]) self.ctaLogMonitor.append(content) # ---------------------------------------------------------------------- def registerEvent(self): """注册事件监听""" self.signal.connect(self.updateCtaLog) self.eventEngine.register(EVENT_CTA_LOG, self.signal.emit) # ---------------------------------------------------------------------- def closeEvent(self, event): """关闭窗口时的事件""" reply = QtGui.QMessageBox.question(self, text.SAVE_POSITION_DATA, text.SAVE_POSITION_QUESTION, QtGui.QMessageBox.Yes | QtGui.QMessageBox.No, QtGui.QMessageBox.No) if reply == QtGui.QMessageBox.Yes: self.ctaEngine.savePosition() event.accept()
class CtaEngineManager(QtGui.QWidget): """CTA引擎管理组件""" signal = QtCore.pyqtSignal(type(Event())) # ---------------------------------------------------------------------- def __init__(self, ctaEngine, eventEngine, parent=None): """Constructor""" super(CtaEngineManager, self).__init__(parent) self.gatewayName = 'CTP' # gateway对象名称 self.gateway = VtGateway(eventEngine, self.gatewayName) # gateway对象 self.ctaEngine = ctaEngine self.eventEngine = eventEngine self.strategyLoaded = False # 初始化界面 self.initUi() # 注册事件监听 self.registerEvent() # 记录日志 self.ctaEngine.writeCtaLog(CTA_ENGINE_STARTED) # 初始化策略 # 预留几秒时间缓冲 t.sleep(5) while self.strategyLoaded is False: self.load() else: init = self.initAll() if init is True: self.startAll() # ---------------------------------------------------------------------- def initUi(self): """初始化界面""" self.setWindowTitle(CTA_STRATEGY) # 按钮 startAllButton = QtGui.QPushButton(START_ALL) stopAllButton = QtGui.QPushButton(STOP_ALL) savePositionButton = QtGui.QPushButton(SAVE_POSITION_DATA) startAllButton.clicked.connect(self.startAll) stopAllButton.clicked.connect(self.stopAll) # savePositionButton.clicked.connect(self.ctaEngine.savePosition) # 滚动区域,放置所有的CtaStrategyManager self.scrollArea = QtGui.QScrollArea() self.scrollArea.setWidgetResizable(True) # CTA组件的日志监控 self.ctaLogMonitor = QtGui.QTextEdit() self.ctaLogMonitor.setReadOnly(True) self.ctaLogMonitor.setMaximumHeight(200) # 设置布局 hbox2 = QtGui.QHBoxLayout() hbox2.addWidget(startAllButton) hbox2.addWidget(stopAllButton) # hbox2.addWidget(savePositionButton) hbox2.addStretch() vbox = QtGui.QVBoxLayout() vbox.addLayout(hbox2) vbox.addWidget(self.scrollArea) vbox.addWidget(self.ctaLogMonitor) self.setLayout(vbox) # ---------------------------------------------------------------------- def initStrategyManager(self): """初始化策略管理组件界面""" w = QtGui.QWidget() vbox = QtGui.QVBoxLayout() for name in list(self.ctaEngine.strategyDict.keys()): strategyManager = CtaStrategyManager(self.ctaEngine, self.eventEngine, name) vbox.addWidget(strategyManager) vbox.addStretch() w.setLayout(vbox) self.scrollArea.setWidget(w) # ---------------------------------------------------------------------- def initAll(self): """全部初始化""" for name in list(self.ctaEngine.strategyDict.keys()): self.ctaEngine.initStrategy(name) log = VtLogData() log.gatewayName = self.gatewayName log.logContent = u'策略全部初始化' self.gateway.onLog(log) return True # ---------------------------------------------------------------------- def startAll(self): """全部启动""" for name in list(self.ctaEngine.strategyDict.keys()): self.ctaEngine.startStrategy(name) log = VtLogData() log.gatewayName = self.gatewayName log.logContent = u'策略全部启动' self.gateway.onLog(log) # ---------------------------------------------------------------------- def stopAll(self): """全部停止""" for name in list(self.ctaEngine.strategyDict.keys()): self.ctaEngine.stopStrategy(name) log = VtLogData() log.gatewayName = self.gatewayName log.logContent = u'策略全部停止' self.gateway.onLog(log) # ---------------------------------------------------------------------- def load(self): """加载策略""" if not self.strategyLoaded: self.ctaEngine.loadSetting() self.initStrategyManager() self.strategyLoaded = True self.ctaEngine.writeCtaLog(STRATEGY_LOADED) log = VtLogData() log.gatewayName = self.gatewayName log.logContent = u'全部策略加载完成' self.gateway.onLog(log) # ---------------------------------------------------------------------- def updateCtaLog(self, event): """更新CTA相关日志""" log = event.dict_['data'] content = '\t'.join([log.logTime, log.logContent]) self.ctaLogMonitor.append(content) # ---------------------------------------------------------------------- def registerEvent(self): """注册事件监听""" self.signal.connect(self.updateCtaLog) self.eventEngine.register(EVENT_CTA_LOG, self.signal.emit)
class PriceWidget(QtGui.QWidget): """用于显示价格走势图""" signal = QtCore.pyqtSignal(type(Event())) # tick图的相关参数、变量 listlastPrice = np.empty(1000) fastMA = 0 midMA = 0 slowMA = 0 listfastMA = np.empty(1000) listmidMA = np.empty(1000) listslowMA = np.empty(1000) tickFastAlpha = 0.0333 # 快速均线的参数,30 tickMidAlpha = 0.0167 # 中速均线的参数,60 tickSlowAlpha = 0.0083 # 慢速均线的参数,120 ptr = 0 ticktime = None # tick数据时间 # K线图EMA均线的参数、变量 EMAFastAlpha = 0.0167 # 快速EMA的参数,60 EMASlowAlpha = 0.0083 # 慢速EMA的参数,120 fastEMA = 0 # 快速EMA的数值 slowEMA = 0 # 慢速EMA的数值 listfastEMA = [] listslowEMA = [] # K线缓存对象 barOpen = 0 barHigh = 0 barLow = 0 barClose = 0 barTime = None barOpenInterest = 0 num = 0 # 保存K线数据的列表对象 listBar = [] listClose = [] listHigh = [] listLow = [] listOpen = [] listOpenInterest = [] # 是否完成了历史数据的读取 initCompleted = False # 初始化时读取的历史数据的起始日期(可以选择外部设置) startDate = None symbol = 'SR701' # 用来记录前一个记录,方便打印更新的状态K线值到控制台 pre = None class CandlestickItem(pg.GraphicsObject): def __init__(self, data): pg.GraphicsObject.__init__(self) self.data = data ## data must have fields: time, open, close, min, max self.generatePicture() def generatePicture(self): ## pre-computing a QPicture object allows paint() to run much more quickly, ## rather than re-drawing the shapes every time. self.picture = QtGui.QPicture() p = QtGui.QPainter(self.picture) p.setPen(pg.mkPen(color='w')) # 0.4 means w*2, width=0.4 w = 0.2 # w*2是 阴线阳线宽度 # 用来记录上一个k线值 和打印更新的k线状态值 global pre if len(self.data) == 0: pass elif len(self.data) < 2: pre = self.data[0] cur = self.data[0] else: cur = self.data[-1] if pre == cur: pass else: print cur pre = cur for (t, open_price, close_price, min_price, max_price) in self.data: ''' 这里对画最高最低值的竖直线的一种意外情况的判断, 如果max和min一样,则画出来的直线实际上成了一个方块 ''' if abs(min_price - max_price) < 0.00000001: pass # 如果最高价和最低价相同,则不绘制这直线 else: p.drawLine(QtCore.QPointF(t, min_price), QtCore.QPointF(t, max_price)) if open_price > close_price: p.setBrush(pg.mkBrush('g')) else: p.setBrush(pg.mkBrush('r')) # 绘制open和close的柱状图 p.drawRect( QtCore.QRectF(t - w, open_price, w * 2, close_price - open_price)) p.end() def paint(self, p, *args): p.drawPicture(0, 0, self.picture) def boundingRect(self): ## boundingRect _must_ indicate the entire area that will be drawn on ## or else we will get artifacts and possibly crashing. ## (in this case, QPicture does all the work of computing the bouning rect for us) return QtCore.QRectF(self.picture.boundingRect()) # ---------------------------------------------------------------------- def __init__(self, eventEngine, mainEngine, parent=None): """Constructor""" super(PriceWidget, self).__init__(parent) self.__eventEngine = eventEngine self.__mainEngine = mainEngine # MongoDB数据库相关 self.__mongoConnected = False self.__mongoConnection = None self.__mongoTickDB = None # 调用函数 self.__connectMongo() self.initUi(startDate=None) self.registerTickEvent() # self.registerBarEvent() # ---------------------------------------------------------------------- def initUi(self, startDate=None): """初始化界面""" self.setWindowTitle(u'Price') self.vbl_1 = QtGui.QVBoxLayout() self.initplotTick() # plotTick初始化 self.vbl_2 = QtGui.QVBoxLayout() self.initplotKline() # plotKline初始化 self.initplotTendency() # plot分时图的初始化 # 整体布局 self.hbl = QtGui.QHBoxLayout() self.hbl.addLayout(self.vbl_1) self.hbl.addLayout(self.vbl_2) self.setLayout(self.hbl) self.initHistoricalData() # 下载历史数据 # ---------------------------------------------------------------------- def initplotTick(self): """""" self.pw1 = pg.PlotWidget(name='Plot1') self.vbl_1.addWidget(self.pw1) self.pw1.setRange(xRange=[-360, 0]) self.pw1.setLimits(xMax=5) self.pw1.setDownsampling(mode='peak') self.pw1.setClipToView(True) self.curve1 = self.pw1.plot() self.curve2 = self.pw1.plot() self.curve3 = self.pw1.plot() self.curve4 = self.pw1.plot() # ---------------------------------------------------------------------- def initplotKline(self): """Kline""" self.pw2 = pg.PlotWidget(name='Plot2') # K线图 self.vbl_2.addWidget(self.pw2) self.pw2.setDownsampling(mode='peak') self.pw2.setClipToView(True) self.curve5 = self.pw2.plot() self.curve6 = self.pw2.plot() self.candle = self.CandlestickItem(self.listBar) self.pw2.addItem(self.candle) ## Draw an arrowhead next to the text box # self.arrow = pg.ArrowItem() # self.pw2.addItem(self.arrow) # ---------------------------------------------------------------------- def initplotTendency(self): """""" self.pw3 = pg.PlotWidget(name='Plot3') self.vbl_2.addWidget(self.pw3) self.pw3.setDownsampling(mode='peak') self.pw3.setClipToView(True) self.pw3.setMaximumHeight(200) self.pw3.setXLink('Plot2') # X linked with Plot2 self.curve7 = self.pw3.plot() # ---------------------------------------------------------------------- def initHistoricalData(self, startDate=None): """初始历史数据""" td = timedelta(days=1) # 读取3天的历史TICK数据 if startDate: cx = self.loadTick(self.symbol, startDate - td) else: today = datetime.today().replace(hour=0, minute=0, second=0, microsecond=0) cx = self.loadTick(self.symbol, today - td) if cx: for data in cx: tick = Tick(data['InstrumentID']) tick.openPrice = data['OpenPrice'] tick.highPrice = data['HighestPrice'] tick.lowPrice = data['LowestPrice'] tick.lastPrice = data['LastPrice'] tick.volume = data['Volume'] tick.openInterest = data['OpenInterest'] tick.upperLimit = data['UpperLimitPrice'] tick.lowerLimit = data['LowerLimitPrice'] tick.time = data['UpdateTime'] tick.ms = data['UpdateMillisec'] tick.bidPrice1 = data['BidPrice1'] tick.bidPrice2 = data['BidPrice2'] tick.bidPrice3 = data['BidPrice3'] tick.bidPrice4 = data['BidPrice4'] tick.bidPrice5 = data['BidPrice5'] tick.askPrice1 = data['AskPrice1'] tick.askPrice2 = data['AskPrice2'] tick.askPrice3 = data['AskPrice3'] tick.askPrice4 = data['AskPrice4'] tick.askPrice5 = data['AskPrice5'] tick.bidVolume1 = data['BidVolume1'] tick.bidVolume2 = data['BidVolume2'] tick.bidVolume3 = data['BidVolume3'] tick.bidVolume4 = data['BidVolume4'] tick.bidVolume5 = data['BidVolume5'] tick.askVolume1 = data['AskVolume1'] tick.askVolume2 = data['AskVolume2'] tick.askVolume3 = data['AskVolume3'] tick.askVolume4 = data['AskVolume4'] tick.askVolume5 = data['AskVolume5'] self.onTick(tick) self.initCompleted = True # 读取历史数据完成 # pprint('load historic data completed') # ---------------------------------------------------------------------- def plotTick(self): """画tick图""" if self.initCompleted: self.curve1.setData(self.listlastPrice[:self.ptr]) self.curve2.setData(self.listfastMA[:self.ptr], pen=(255, 0, 0), name="Red curve") self.curve3.setData(self.listmidMA[:self.ptr], pen=(0, 255, 0), name="Green curve") self.curve4.setData(self.listslowMA[:self.ptr], pen=(0, 0, 255), name="Blue curve") self.curve1.setPos(-self.ptr, 0) self.curve2.setPos(-self.ptr, 0) self.curve3.setPos(-self.ptr, 0) self.curve4.setPos(-self.ptr, 0) # ---------------------------------------------------------------------- def plotKline(self): """K线图""" if self.initCompleted: # 均线 self.curve5.setData(self.listfastEMA, pen=(255, 0, 0), name="Red curve") self.curve6.setData(self.listslowEMA, pen=(0, 255, 0), name="Green curve") # 画K线 self.pw2.removeItem(self.candle) self.candle = self.CandlestickItem(self.listBar) self.pw2.addItem(self.candle) # self.plotText() # 显示开仓信号位置 # ---------------------------------------------------------------------- def plotTendency(self): """""" if self.initCompleted: self.curve7.setData(self.listOpenInterest, pen=(255, 255, 255), name="White curve") # ---------------------------------------------------------------------- def plotText(self): lenClose = len(self.listClose) if lenClose >= 5: # Fractal Signal if self.listClose[-1] > self.listClose[-2] and self.listClose[ -3] > self.listClose[-2] and self.listClose[ -4] > self.listClose[-2] and self.listClose[ -5] > self.listClose[-2] and self.listfastEMA[ -1] > self.listslowEMA[-1]: ## Draw an arrowhead next to the text box # self.pw2.removeItem(self.arrow) self.arrow = pg.ArrowItem(pos=(lenClose - 1, self.listLow[-1]), angle=90, brush=(255, 0, 0)) self.pw2.addItem(self.arrow) elif self.listClose[-1] < self.listClose[-2] and self.listClose[ -3] < self.listClose[-2] and self.listClose[ -4] < self.listClose[-2] and self.listClose[ -5] < self.listClose[-2] and self.listfastEMA[ -1] < self.listslowEMA[-1]: ## Draw an arrowhead next to the text box # self.pw2.removeItem(self.arrow) self.arrow = pg.ArrowItem(pos=(lenClose - 1, self.listHigh[-1]), angle=-90, brush=(0, 255, 0)) self.pw2.addItem(self.arrow) # ---------------------------------------------------------------------- def updateMarketData(self, event): """更新行情""" # 切换到DrTickData # old code tick = event.dict_['data'] # tick.openPrice = data['OpenPrice'] # tick.highPrice = data['HighestPrice'] # tick.lowPrice = data['LowestPrice'] # tick.lastPrice = data['LastPrice'] # # tick.volume = data['Volume'] # tick.openInterest = data['OpenInterest'] # # tick.upperLimit = data['UpperLimitPrice'] # tick.lowerLimit = data['LowerLimitPrice'] # # tick.time = data['UpdateTime'] # tick.ms = data['UpdateMillisec'] # # tick.bidPrice1 = data['BidPrice1'] # tick.bidPrice2 = data['BidPrice2'] # tick.bidPrice3 = data['BidPrice3'] # tick.bidPrice4 = data['BidPrice4'] # tick.bidPrice5 = data['BidPrice5'] # # tick.askPrice1 = data['AskPrice1'] # tick.askPrice2 = data['AskPrice2'] # tick.askPrice3 = data['AskPrice3'] # tick.askPrice4 = data['AskPrice4'] # tick.askPrice5 = data['AskPrice5'] # # tick.bidVolume1 = data['BidVolume1'] # tick.bidVolume2 = data['BidVolume2'] # tick.bidVolume3 = data['BidVolume3'] # tick.bidVolume4 = data['BidVolume4'] # tick.bidVolume5 = data['BidVolume5'] # # tick.askVolume1 = data['AskVolume1'] # tick.askVolume2 = data['AskVolume2'] # tick.askVolume3 = data['AskVolume3'] # tick.askVolume4 = data['AskVolume4'] # tick.askVolume5 = data['AskVolume5'] self.onTick(tick) # tick数据更新 # # 将数据插入MongoDB数据库,实盘建议另开程序记录TICK数据 # self.__recordTick(data) # ---------------------------------------------------------------------- def updateBar(self, event): """更新Bar列表,绘制新图""" data = event.dict_['data'] print 'updateBar', datetime.utcnow() # ---------------------------------------------------------------------- def onTick(self, tick): """tick数据更新""" from datetime import time # 首先生成datetime.time格式的时间(便于比较),从字符串时间转化为time格式的时间 hh, mm, ss = tick.time.split(':') self.ticktime = time(int(float(hh)), int(float(mm)), int(float(ss))) # 计算tick图的相关参数 if self.ptr == 0: self.fastMA = tick.lastPrice self.midMA = tick.lastPrice self.slowMA = tick.lastPrice else: self.fastMA = ( 1 - self.tickFastAlpha ) * self.fastMA + self.tickFastAlpha * tick.lastPrice self.midMA = (1 - self.tickMidAlpha ) * self.midMA + self.tickMidAlpha * tick.lastPrice self.slowMA = ( 1 - self.tickSlowAlpha ) * self.slowMA + self.tickSlowAlpha * tick.lastPrice self.listlastPrice[self.ptr] = tick.lastPrice self.listfastMA[self.ptr] = self.fastMA self.listmidMA[self.ptr] = self.midMA self.listslowMA[self.ptr] = self.slowMA self.ptr += 1 # pprint("----------") # pprint(self.ptr) if self.ptr >= self.listlastPrice.shape[0]: tmp = self.listlastPrice self.listlastPrice = np.empty(self.listlastPrice.shape[0] * 2) self.listlastPrice[:tmp.shape[0]] = tmp tmp = self.listfastMA self.listfastMA = np.empty(self.listfastMA.shape[0] * 2) self.listfastMA[:tmp.shape[0]] = tmp tmp = self.listmidMA self.listmidMA = np.empty(self.listmidMA.shape[0] * 2) self.listmidMA[:tmp.shape[0]] = tmp tmp = self.listslowMA self.listslowMA = np.empty(self.listslowMA.shape[0] * 2) self.listslowMA[:tmp.shape[0]] = tmp # K线数据 # 假设是收到的第一个TICK if self.barOpen == 0: # 初始化新的K线数据 self.barOpen = tick.lastPrice self.barHigh = tick.lastPrice self.barLow = tick.lastPrice self.barClose = tick.lastPrice self.barTime = self.ticktime self.barOpenInterest = tick.openInterest self.onBar(self.num, self.barOpen, self.barClose, self.barLow, self.barHigh, self.barOpenInterest) else: # 如果是当前一分钟内的数据 if self.ticktime.minute == self.barTime.minute: if self.ticktime.second >= 30 and self.barTime.second < 30: # 判断30秒周期K线 # 先保存K线收盘价 self.num += 1 self.onBar(self.num, self.barOpen, self.barClose, self.barLow, self.barHigh, self.barOpenInterest) # 初始化新的K线数据 self.barOpen = tick.lastPrice self.barHigh = tick.lastPrice self.barLow = tick.lastPrice self.barClose = tick.lastPrice self.barTime = self.ticktime self.barOpenInterest = tick.openInterest # 汇总TICK生成K线 self.barHigh = max(self.barHigh, tick.lastPrice) self.barLow = min(self.barLow, tick.lastPrice) self.barClose = tick.lastPrice self.barTime = self.ticktime self.listBar.pop() self.listfastEMA.pop() self.listslowEMA.pop() self.listOpen.pop() self.listClose.pop() self.listHigh.pop() self.listLow.pop() self.listOpenInterest.pop() self.onBar(self.num, self.barOpen, self.barClose, self.barLow, self.barHigh, self.barOpenInterest) # 如果是新一分钟的数据 else: # 先保存K线收盘价 self.num += 1 self.onBar(self.num, self.barOpen, self.barClose, self.barLow, self.barHigh, self.barOpenInterest) # 初始化新的K线数据 self.barOpen = tick.lastPrice self.barHigh = tick.lastPrice self.barLow = tick.lastPrice self.barClose = tick.lastPrice self.barTime = self.ticktime self.barOpenInterest = tick.openInterest # ---------------------------------------------------------------------- def onBar(self, n, o, c, l, h, oi): self.listBar.append((n, o, c, l, h)) self.listOpen.append(o) self.listClose.append(c) self.listHigh.append(h) self.listLow.append(l) self.listOpenInterest.append(oi) #计算K线图EMA均线 if self.fastEMA: self.fastEMA = c * self.EMAFastAlpha + self.fastEMA * ( 1 - self.EMAFastAlpha) self.slowEMA = c * self.EMASlowAlpha + self.slowEMA * ( 1 - self.EMASlowAlpha) else: self.fastEMA = c self.slowEMA = c self.listfastEMA.append(self.fastEMA) self.listslowEMA.append(self.slowEMA) # 调用画图函数 self.plotTick() # tick图 self.plotKline() # K线图 self.plotTendency() # K线副图,持仓量 # ---------------------------------------------------------------------- def __connectMongo(self): """连接MongoDB数据库""" try: self.__mongoConnection = MongoClient() self.__mongoConnected = True self.__mongoTickDB = self.__mongoConnection['TickDB'] except ConnectionFailure: pass # ---------------------------------------------------------------------- def __recordTick(self, data): """将Tick数据插入到MongoDB中""" if self.__mongoConnected: symbol = data['InstrumentID'] data['date'] = self.today self.__mongoTickDB[symbol].insert(data) # ---------------------------------------------------------------------- def loadTick(self, symbol, startDate, endDate=None): """从MongoDB中读取Tick数据""" if self.__mongoConnected: collection = self.__mongoTickDB[symbol] # 如果输入了读取TICK的最后日期 if endDate: cx = collection.find( {'date': { '$gte': startDate, '$lte': endDate }}) else: cx = collection.find({'date': {'$gte': startDate}}) return cx else: return None # ---------------------------------------------------------------------- def registerTickEvent(self): """注册Tick数据监听""" self.signal.connect(self.updateMarketData) self.__eventEngine.register(EVENT_DATARECORDER_TICK, self.signal.emit) # ---------------------------------------------------------------------- def registerBarEvent(self): """注册Bar数据监听""" self.signal.connect(self.updateBar) self.__eventEngine.register(EVENT_DATARECORDER_BAR, self.signal.emit)
class DrEngineManager(QtGui.QWidget): """行情数据记录引擎管理组件""" signal = QtCore.pyqtSignal(type(Event())) signal2 = QtCore.pyqtSignal(type(Event())) #---------------------------------------------------------------------- def __init__(self, drEngine, mainEngine, eventEngine, parent=None): """Constructor""" super(DrEngineManager, self).__init__(parent) self.drEngine = drEngine self.mainEngine = mainEngine self.eventEngine = eventEngine self.initUi() self.updateSetting() self.registerEvent() #---------------------------------------------------------------------- def initUi(self): """初始化界面""" self.setWindowTitle(u'行情数据记录工具') # 菜单 lineSelect = QtGui.QLabel(u'需要收集的合约:') buttonSelect = QtGui.QPushButton(u'选择') lineType = QtGui.QLabel(u'合成Bar类型:') barType = ['1m', '5m', '15m', '30m', '60m'] comboType = QtGui.QComboBox() comboType.addItems(barType) lineStart = QtGui.QLabel(u'开始收集:') buttonStart = QtGui.QPushButton(u'收集') buttonSelect.clicked.connect(self.select) buttonStart.clicked.connect(self.start) # 记录合约配置监控 tickLabel = QtGui.QLabel(u'Tick记录') self.tickTable = QtGui.QTableWidget() self.tickTable.setColumnCount(2) self.tickTable.verticalHeader().setVisible(False) self.tickTable.setEditTriggers(QtGui.QTableWidget.NoEditTriggers) self.tickTable.horizontalHeader().setResizeMode( QtGui.QHeaderView.Stretch) self.tickTable.setAlternatingRowColors(True) self.tickTable.setHorizontalHeaderLabels([u'合约代码', u'接口']) barLabel = QtGui.QLabel(u'Bar记录') self.barTable = QtGui.QTableWidget() self.barTable.setColumnCount(2) self.barTable.verticalHeader().setVisible(False) self.barTable.setEditTriggers(QtGui.QTableWidget.NoEditTriggers) self.barTable.horizontalHeader().setResizeMode( QtGui.QHeaderView.Stretch) self.barTable.setAlternatingRowColors(True) self.barTable.setHorizontalHeaderLabels([u'合约代码', u'接口']) activeLabel = QtGui.QLabel(u'主力合约') self.activeTable = QtGui.QTableWidget() self.activeTable.setColumnCount(2) self.activeTable.verticalHeader().setVisible(False) self.activeTable.setEditTriggers(QtGui.QTableWidget.NoEditTriggers) self.activeTable.horizontalHeader().setResizeMode( QtGui.QHeaderView.Stretch) self.activeTable.setAlternatingRowColors(True) self.activeTable.setHorizontalHeaderLabels([u'主力代码', u'合约代码']) # 日志监控 self.logMonitor = QtGui.QTextEdit() self.logMonitor.setReadOnly(True) self.logMonitor.setMinimumHeight(600) self.logMonitor2 = QtGui.QTextEdit() self.logMonitor2.setReadOnly(True) self.logMonitor2.setMinimumHeight(600) self.logMonitor3 = QtGui.QTextEdit() self.logMonitor3.setReadOnly(True) self.logMonitor3.setMinimumHeight(600) # 设置布局 hbox = QtGui.QHBoxLayout() hbox.addWidget(lineSelect) hbox.addWidget(buttonSelect) hbox.addWidget(lineType) hbox.addWidget(comboType) hbox.addWidget(lineStart) hbox.addWidget(buttonStart) grid = QtGui.QGridLayout() grid.addWidget(tickLabel, 0, 0) grid.addWidget(barLabel, 0, 1) grid.addWidget(activeLabel, 0, 2) grid.addWidget(self.tickTable, 1, 0) grid.addWidget(self.barTable, 1, 1) grid.addWidget(self.activeTable, 1, 2) grid2 = QtGui.QGridLayout() grid2.addWidget(self.logMonitor, 0, 0) grid2.addWidget(self.logMonitor2, 0, 1) grid2.addWidget(self.logMonitor3, 0, 2) vbox = QtGui.QVBoxLayout() vbox.addLayout(hbox) vbox.addLayout(grid) vbox.addLayout(grid2) self.setLayout(vbox) #---------------------------------------------------------------------- def updateLog(self, event): """更新日志""" log = event.dict_['data'] content = '\t'.join([log.logTime, log.logContent]) self.logMonitor.append(content) # ---------------------------------------------------------------------- def updateLog2(self, event): """更新日志""" log = event.dict_['data'] content = '\t'.join([log.logTime, log.logContent]) self.logMonitor2.append(content) #---------------------------------------------------------------------- def registerEvent(self): """注册事件监听""" self.signal.connect(self.updateLog) self.eventEngine.register(EVENT_DATARECORDER_LOG, self.signal.emit) self.signal2.connect(self.updateLog2) self.eventEngine.register(EVENT_DATARECORDER_LOG2, self.signal2.emit) #---------------------------------------------------------------------- def updateSetting(self): """显示引擎行情记录配置""" with open(self.drEngine.settingFileName) as f: drSetting = json.load(f) if 'tick' in drSetting: l = drSetting['tick'] for setting in l: self.tickTable.insertRow(0) self.tickTable.setItem(0, 0, TableCell(setting[0])) self.tickTable.setItem(0, 1, TableCell(setting[1])) if 'bar' in drSetting: l = drSetting['bar'] for setting in l: self.barTable.insertRow(0) self.barTable.setItem(0, 0, TableCell(setting[0])) self.barTable.setItem(0, 1, TableCell(setting[1])) if 'active' in drSetting: d = drSetting['active'] for activeSymbol, symbol in d.items(): self.activeTable.insertRow(0) self.activeTable.setItem(0, 0, TableCell(activeSymbol)) self.activeTable.setItem(0, 1, TableCell(symbol)) #---------------------------------------------------------------------- def select(self): pass #---------------------------------------------------------------------- def start(self): l = self.mainEngine.getAllContracts() data = {} tick = [[contract.symbol, 'CTP'] for contract in l] bar = [[contract.symbol, 'CTP'] for contract in l] active = {} for contract in l: acticeSymbol = filter(str.isalpha, contract.symbol) active[acticeSymbol + '88'] = contract.symbol data['working'] = True data['tick'] = tick data['bar'] = bar data['active'] = active fileName = os.path.abspath( os.path.dirname(__file__)) + '.\\DR_setting.json' with open(fileName, 'w') as json_file: json_file.write(json.dumps(data)) self.drEngine.loadSetting()
class StockBacktestEngineManager(QtGui.QWidget): """CTA引擎管理组件""" signal = QtCore.pyqtSignal(type(Event())) signal2 = QtCore.pyqtSignal(type(Event())) #---------------------------------------------------------------------- def __init__(self, stockBacktestEngine, eventEngine, parent=None): """Constructor""" super(StockBacktestEngineManager, self).__init__(parent) self.stockBacktestEngine = stockBacktestEngine self.eventEngine = eventEngine self.strategyLoaded = False self.initUi() self.registerEvent() # 记录日志 self.stockBacktestEngine.writeBktLog(u'股票回测引擎启动成功') #---------------------------------------------------------------------- def initUi(self): """初始化界面""" self.setWindowTitle(u'股票策略回测') # 按钮 newButton = QtGui.QPushButton(u'新建策略') loadButton = QtGui.QPushButton(u'加载策略') newButton.clicked.connect(self.new) loadButton.clicked.connect(self.load) # 滚动区域,放置所有的CtaStrategyManager self.scrollArea = QtGui.QScrollArea() self.scrollArea.setWidgetResizable(True) # 回测结果区域,Tab显示各项报告 self.tabWidget = QtGui.QTabWidget(self) self.model = QtGui.QStandardItemModel(self) self.summaryView = QtGui.QTableView(self) self.summaryView.setModel(self.model) self.summaryView.horizontalHeader().setStretchLastSection(True) self.summaryView.setEditTriggers(self.summaryView.NoEditTriggers) self.summaryView.setMaximumHeight(400) self.summaryView.resizeColumnsToContents() self.model2 = QtGui.QStandardItemModel(self) self.total_portfoliosView = QtGui.QTableView(self) self.total_portfoliosView.setModel(self.model2) self.total_portfoliosView.horizontalHeader().setStretchLastSection( True) self.total_portfoliosView.setEditTriggers( self.total_portfoliosView.NoEditTriggers) self.total_portfoliosView.setMaximumHeight(400) self.total_portfoliosView.resizeColumnsToContents() self.model3 = QtGui.QStandardItemModel(self) self.future_portfoliosView = QtGui.QTableView(self) self.future_portfoliosView.setModel(self.model3) self.future_portfoliosView.horizontalHeader().setStretchLastSection( True) self.future_portfoliosView.setEditTriggers( self.future_portfoliosView.NoEditTriggers) self.future_portfoliosView.setMaximumHeight(400) self.future_portfoliosView.resizeColumnsToContents() self.model4 = QtGui.QStandardItemModel(self) self.future_positionsView = QtGui.QTableView(self) self.future_positionsView.setModel(self.model4) self.future_positionsView.horizontalHeader().setStretchLastSection( True) self.future_positionsView.setEditTriggers( self.future_positionsView.NoEditTriggers) self.future_positionsView.setMaximumHeight(400) self.future_positionsView.resizeColumnsToContents() self.model5 = QtGui.QStandardItemModel(self) self.tradesView = QtGui.QTableView(self) self.tradesView.setModel(self.model5) self.tradesView.horizontalHeader().setStretchLastSection(True) self.tradesView.horizontalHeader().setVisible(False) self.tradesView.setEditTriggers(self.tradesView.NoEditTriggers) self.tradesView.setMaximumHeight(400) self.tradesView.resizeColumnsToContents() self.tabWidget.addTab(self.summaryView, "summary") self.tabWidget.addTab(self.total_portfoliosView, "total_portfolios") self.tabWidget.addTab(self.future_portfoliosView, "stock_portfolios") self.tabWidget.addTab(self.future_positionsView, "stock_positions") self.tabWidget.addTab(self.tradesView, "trades") # 回测图表 Button1 = QtGui.QPushButton(u'交易资料') Button2 = QtGui.QPushButton(u'周期分析') Button3 = QtGui.QPushButton(u'策略分析') Button4 = QtGui.QPushButton(u'交易分析') # Button1.clicked.connect(self.show1) # Button2.clicked.connect(self.show2) # Button3.clicked.connect(self.show3) # Button4.clicked.connect(self.show4) # 回测组件的日志监控 self.bktLogMonitor = QtGui.QTextEdit() self.bktLogMonitor.setReadOnly(True) self.bktLogMonitor.setMaximumHeight(100) # 设置布局 hbox2 = QtGui.QHBoxLayout() hbox2.addWidget(newButton) hbox2.addWidget(loadButton) hbox2.addStretch() vbox2 = QtGui.QVBoxLayout() vbox2.addWidget(Button1) vbox2.addWidget(Button2) vbox2.addWidget(Button3) vbox2.addWidget(Button4) vbox2.addStretch() hbox3 = QtGui.QHBoxLayout() hbox3.addLayout(vbox2) hbox3.addWidget(self.tabWidget) vbox = QtGui.QVBoxLayout() vbox.addLayout(hbox2) vbox.addWidget(self.scrollArea) vbox.setSpacing(20) vbox.addLayout(hbox3) # vbox.addWidget(self.tabWidget) vbox.setSpacing(20) vbox.addWidget(self.bktLogMonitor) self.setLayout(vbox) #---------------------------------------------------------------------- def initStrategyManager(self): """初始化策略管理组件界面""" w = QtGui.QWidget() vbox = QtGui.QVBoxLayout() self.runID = 9999 for name in self.stockBacktestEngine.strategyDict.keys(): strategyManager = StockStrategyManager(self.stockBacktestEngine, self.eventEngine, name, self.runID) vbox.addWidget(strategyManager) self.runID -= 1 self.signal2.connect(self.updateBktResult) self.eventEngine.register(EVENT_BKT_STRATEGY + name, self.signal2.emit) vbox.addStretch() w.setLayout(vbox) self.scrollArea.setWidget(w) #---------------------------------------------------------------------- def load(self): """加载策略""" if not self.strategyLoaded: self.stockBacktestEngine.loadStrategy() self.initStrategyManager() self.strategyLoaded = True self.stockBacktestEngine.writeBktLog(u'策略加载成功') #---------------------------------------------------------------------- def new(self): self.stockBacktestEngine.writeBktLog(u'策略新建成功') #---------------------------------------------------------------------- def updateBktResult(self, event): name = event.dict_['name'] fileName = os.path.abspath( os.path.dirname(__file__)) + '\\result\\' + name + '\\summary.csv' fileName2 = os.path.abspath(os.path.dirname( __file__)) + '\\result\\' + name + '\\total_portfolios.csv' fileName3 = os.path.abspath(os.path.dirname( __file__)) + '\\result\\' + name + '\\stock_portfolios.csv' fileName4 = os.path.abspath(os.path.dirname( __file__)) + '\\result\\' + name + '\\stock_positions.csv' fileName5 = os.path.abspath( os.path.dirname(__file__)) + '\\result\\' + name + '\\trades.csv' self.model.clear() self.model2.clear() self.model3.clear() self.model4.clear() self.model5.clear() with open(fileName, "rb") as fileInput: isLable = True for row in csv.reader(fileInput): if isLable: items = [field for field in row] self.model.setHorizontalHeaderLabels(items) isLable = False else: items = [ QtGui.QStandardItem(field.decode('utf-8')) for field in row ] self.model.appendRow(items) self.summaryView.resizeColumnsToContents() fileInput.close() with open(fileName2, "rb") as fileInput: isLable = True for row in csv.reader(fileInput): if isLable: items = [field for field in row] self.model2.setHorizontalHeaderLabels(items) isLable = False else: items = [ QtGui.QStandardItem(field.decode('utf-8')) for field in row ] self.model2.appendRow(items) self.total_portfoliosView.resizeColumnsToContents() fileInput.close() with open(fileName3, "rb") as fileInput: isLable = True for row in csv.reader(fileInput): if isLable: items = [field for field in row] self.model3.setHorizontalHeaderLabels(items) isLable = False else: items = [ QtGui.QStandardItem(field.decode('utf-8')) for field in row ] self.model3.appendRow(items) self.future_portfoliosView.resizeColumnsToContents() fileInput.close() with open(fileName4, "rb") as fileInput: isLable = True for row in csv.reader(fileInput): if isLable: items = [field for field in row] self.model4.setHorizontalHeaderLabels(items) isLable = False else: items = [ QtGui.QStandardItem(field.decode('utf-8')) for field in row ] self.model4.appendRow(items) self.future_positionsView.resizeColumnsToContents() fileInput.close() with open(fileName5, "rb") as fileInput: isLable = True for row in csv.reader(fileInput): if isLable: items = [field for field in row] self.model5.setHorizontalHeaderLabels(items) isLable = False else: items = [ QtGui.QStandardItem(field.decode('utf-8')) for field in row ] self.model5.appendRow(items) self.tradesView.resizeColumnsToContents() fileInput.close() self.stockBacktestEngine.writeBktLog(name + u'绩效报告创建成功') #---------------------------------------------------------------------- def updateBktLog(self, event): """更新回测相关日志""" log = event.dict_['data'] content = '\t'.join([log.logTime, log.logContent]) self.bktLogMonitor.append(content) #---------------------------------------------------------------------- def registerEvent(self): """注册事件监听""" self.signal.connect(self.updateBktLog) self.eventEngine.register(EVENT_BKT_LOG, self.signal.emit)
class StockStrategyManager(QtGui.QGroupBox): """策略管理组件""" signal = QtCore.pyqtSignal(type(Event())) #---------------------------------------------------------------------- def __init__(self, stockBacktestEngine, eventEngine, name, runID, parent=None): """Constructor""" super(StockStrategyManager, self).__init__(parent) self.stockBacktestEngine = stockBacktestEngine self.eventEngine = eventEngine self.name = name self.runID = runID path = os.path.abspath( os.path.dirname(__file__)) + '\\result\\' + self.name + '\\' if not os.path.exists(path): os.makedirs(path) # 创建路径 with open( os.path.abspath(os.path.dirname(__file__)) + '\\config_template.json', 'r') as f: self.setting = json.load(f) self.setting['base']['run_id'] = self.runID self.setting['base']['strategy_file'] = os.path.abspath( os.path.dirname(__file__)) + '\\strategy\\' + self.name + '.py' self.setting['mod']['analyser']['output_file'] = os.path.abspath( os.path.dirname( __file__)) + '\\result\\' + self.name + '\\result.pkl' self.setting['mod']['analyser']['plot'] = os.path.expanduser("~") self.setting['mod']['analyser'][ 'plot_save_file'] = os.path.abspath(os.path.dirname( __file__)) + '\\result\\' + self.name + '\\result.png' self.setting['mod'][ 'analyser']['report_save_path'] = os.path.abspath( os.path.dirname(__file__)) + '\\result\\' self.base = self.setting['base'] self.extra = self.setting['extra'] self.config = {} self.initUi() self.updateMonitor() self.register() #---------------------------------------------------------------------- def initUi(self): """初始化界面""" self.setTitle(self.name) self.baseMonitor = StockValueMonitor(self.stockBacktestEngine, self.eventEngine, self.name) self.extraMonitor = StockValueMonitor(self.stockBacktestEngine, self.eventEngine, self.name) height = 60 self.baseMonitor.setFixedHeight(height) self.extraMonitor.setFixedHeight(height) buttonEdit = QtGui.QPushButton(u'编辑策略') buttonStart = QtGui.QPushButton(u'启动回测') buttonShow = QtGui.QPushButton(u'绩效报告') buttonEdit.clicked.connect(self.edit) buttonStart.clicked.connect(self.start) buttonShow.clicked.connect(self.show) hbox1 = QtGui.QHBoxLayout() hbox1.addWidget(buttonEdit) hbox1.addWidget(buttonStart) hbox1.addWidget(buttonShow) hbox1.addStretch() hbox2 = QtGui.QHBoxLayout() hbox2.addWidget(self.baseMonitor) hbox3 = QtGui.QHBoxLayout() hbox3.addWidget(self.extraMonitor) vbox = QtGui.QVBoxLayout() vbox.addLayout(hbox1) vbox.addLayout(hbox2) vbox.addLayout(hbox3) self.setLayout(vbox) #---------------------------------------------------------------------- def edit(self): self.textBrowser = QtGui.QTextBrowser() self.textBrowser.setGeometry(QtCore.QRect(0, 0, 1000, 1000)) self.textBrowser.setReadOnly(False) self.textBrowser.setObjectName(QtCore.QString.fromUtf8("textBrowser")) f = open(self.setting['base']['strategy_file']) my_data = f.read() f.close() self.textBrowser.append(my_data.decode('utf-8')) self.textBrowser.showMaximized() #---------------------------------------------------------------------- def start(self): """启动回测""" self.config = self.setting self.stockBacktestEngine.writeBktLog(self.name + u'策略回测中') self.stockBacktestEngine.run(self.config) self.stockBacktestEngine.writeBktLog(self.name + u'策略回测成功') #---------------------------------------------------------------------- def show(self): """触发显示绩效报告事件(通常用于通知GUI更新)""" self.stockBacktestEngine.writeBktLog(self.name + u'绩效报告创建中') event = Event(type_=EVENT_BKT_STRATEGY + self.name) event.dict_['name'] = self.name self.eventEngine.put(event) # ---------------------------------------------------------------------- def updateMonitor(self): """显示回测参数最新状态""" self.baseMonitor.updateData(self.base) self.extraMonitor.updateData(self.extra) # ---------------------------------------------------------------------- def updateSetting(self, event): self.setting['base'] = event.dict_ # ---------------------------------------------------------------------- def register(self): """注册事件监听""" self.signal.connect(self.updateSetting) self.eventEngine.register(EVENT_SET_CHANGED + self.name, self.signal.emit)
def boundingRect(self): ## boundingRect _must_ indicate the entire area that will be drawn on ## or else we will get artifacts and possibly crashing. ## (in this case, QPicture does all the work of computing the bouning rect for us) return QtCore.QRectF(self.picture.boundingRect())
class ChanlunEngineManager(QtGui.QWidget): """chanlun引擎管理组件""" signal = QtCore.pyqtSignal(type(Event())) # ---------------------------------------------------------------------- def __init__(self, chanlunEngine, eventEngine, mainEngine, parent=None): """Constructor""" super(ChanlunEngineManager, self).__init__(parent) self.chanlunEngine = chanlunEngine self.eventEngine = eventEngine self.mainEngine = mainEngine self.penLoaded = False self.instrumentid = '' self.initUi() self.registerEvent() # 记录日志 self.chanlunEngine.writeChanlunLog(u'缠论引擎启动成功') # ---------------------------------------------------------------------- def initUi(self): """初始化界面""" self.setWindowTitle(u'缠论策略') # 金融图 self.PriceW = PriceWidget(self.eventEngine, self.chanlunEngine, self) # 期货代码输入框 self.codeEdit = QtGui.QLineEdit() self.codeEdit.setPlaceholderText(u'在此输入期货代码') self.codeEdit.setMaximumWidth(200) # 按钮 penButton = QtGui.QPushButton(u'分笔') segmentButton = QtGui.QPushButton(u'分段') shopButton = QtGui.QPushButton(u'买卖点') restoreButton = QtGui.QPushButton(u'还原') penButton.clicked.connect(self.pen) segmentButton.clicked.connect(self.segment) shopButton.clicked.connect(self.shop) restoreButton.clicked.connect(self.restore) # Chanlun组件的日志监控 self.chanlunLogMonitor = QtGui.QTextEdit() self.chanlunLogMonitor.setReadOnly(True) self.chanlunLogMonitor.setMaximumHeight(200) # 设置布局 self.hbox2 = QtGui.QHBoxLayout() self.hbox2.addWidget(self.codeEdit) self.hbox2.addWidget(penButton) self.hbox2.addWidget(segmentButton) self.hbox2.addWidget(shopButton) self.hbox2.addWidget(restoreButton) self.hbox2.addStretch() tickButton = QtGui.QPushButton(u'Tick') oneMButton = QtGui.QPushButton(u"1分") fiveMButton = QtGui.QPushButton(u'5分') fifteenMButton = QtGui.QPushButton(u'15分') thirtyMButton = QtGui.QPushButton(u'30分') dayButton = QtGui.QPushButton(u'日') weekButton = QtGui.QPushButton(u'周') monthButton = QtGui.QPushButton(u'月') tickButton.clicked.connect(self.openTick) self.vbox1 = QtGui.QVBoxLayout() self.vbox2 = QtGui.QVBoxLayout() self.vbox1.addWidget(self.PriceW) self.vbox2.addWidget(tickButton) self.vbox2.addWidget(oneMButton) self.vbox2.addWidget(fiveMButton) self.vbox2.addWidget(fifteenMButton) self.vbox2.addWidget(thirtyMButton) self.vbox2.addWidget(dayButton) self.vbox2.addWidget(weekButton) self.vbox2.addWidget(monthButton) self.vbox2.addStretch() self.hbox3 = QtGui.QHBoxLayout() self.hbox3.addStretch() self.hbox3.addLayout(self.vbox1) self.hbox3.addLayout(self.vbox2) self.vbox = QtGui.QVBoxLayout() self.vbox.addLayout(self.hbox2) self.vbox.addLayout(self.hbox3) #vbox.addWidget(self.scrollArea) self.vbox.addWidget(self.chanlunLogMonitor) self.setLayout(self.vbox) self.codeEdit.returnPressed.connect(self.updateSymbol) def updateSymbol(self): """合约变化""" # 读取组件数据 instrumentid = str(self.codeEdit.text()) # 获取合约 # instrument = self.__chanlunEngine.selectInstrument(instrumentid) # 重新注册事件监听 self.eventEngine.unregister(EVENT_TICK + self.instrumentid, self.signal.emit) self.eventEngine.register(EVENT_TICK + instrumentid, self.signal.emit) # 订阅合约 # self.__mainEngine.subscribe(instrumentid, instrument['ExchangeID']) # 订阅合约[仿照ctaEngine.py写的] contract = self.mainEngine.getContract(instrumentid) if contract: req = VtSubscribeReq() req.symbol = contract.symbol self.mainEngine.subscribe(req, contract.gatewayName) else: self.writeChanlunLog(u'交易合约%s无法找到' % (instrumentid)) # 更新目前的合约 self.instrumentid = instrumentid # ---------------------------------------------------------------------- def openTick(self): """切换成tick图""" self.chanlunEngine.writeChanlunLog(u'打开tick图') self.vbox1.removeWidget(self.PriceW) # ---------------------------------------------------------------------- def segment(self): """加载分段""" self.chanlunEngine.writeChanlunLog(u'分段') # ---------------------------------------------------------------------- def shop(self): """加载买卖点""" self.chanlunEngine.writeChanlunLog(u'买卖点') # ---------------------------------------------------------------------- def restore(self): """还原初始k线状态""" self.chanlunEngine.writeChanlunLog(u'还原') # ---------------------------------------------------------------------- def pen(self): """加载分笔""" if not self.pen: self.chanlunEngine.loadSetting() # self.initStrategyManager() 此处应该修改成分笔的函数 self.pen = True self.chanlunEngine.writeChanlunLog(u'分笔加载成功') # ---------------------------------------------------------------------- def updateChanlunLog(self, event): """更新缠论相关日志""" self.eventEngine.register(EVENT_CHANLUN_LOG, self.signal.emit) log = event.dict_['data'] print 'chanlun:' print type(log) content = '\t'.join([log.logTime, log.logContent]) self.chanlunLogMonitor.append(content) # ---------------------------------------------------------------------- def registerEvent(self): """注册事件监听""" self.signal.connect(self.registerEvent) self.eventEngine.register(EVENT_CHANLUN_LOG, self.signal.emit)
class PriceWidget(QtGui.QWidget): """用于显示价格走势图""" signal = QtCore.pyqtSignal(type(Event())) # tick图的相关参数、变量 listlastPrice = np.empty(1000) fastMA = 0 midMA = 0 slowMA = 0 listfastMA = np.empty(1000) listmidMA = np.empty(1000) listslowMA = np.empty(1000) tickFastAlpha = 0.0333 # 快速均线的参数,30 tickMidAlpha = 0.0167 # 中速均线的参数,60 tickSlowAlpha = 0.0083 # 慢速均线的参数,120 ptr = 0 ticktime = None # tick数据时间 # K线图EMA均线的参数、变量 EMAFastAlpha = 0.0167 # 快速EMA的参数,60 EMASlowAlpha = 0.0083 # 慢速EMA的参数,120 fastEMA = 0 # 快速EMA的数值 slowEMA = 0 # 慢速EMA的数值 listfastEMA = [] listslowEMA = [] # K线缓存对象 barOpen = 0 barHigh = 0 barLow = 0 barClose = 0 barTime = None barOpenInterest = 0 num = 0 # 保存K线数据的列表对象 listBar = [] listClose = [] listHigh = [] listLow = [] listOpen = [] listOpenInterest = [] # 是否完成了历史数据的读取 initCompleted = True # 初始化时读取的历史数据的起始日期(可以选择外部设置) startDate = None symbol = 'ag1706' class CandlestickItem(pg.GraphicsObject): def __init__(self, data): pg.GraphicsObject.__init__(self) self.data = data ## data must have fields: time, open, close, min, max self.generatePicture() def generatePicture(self): ## pre-computing a QPicture object allows paint() to run much more quickly, ## rather than re-drawing the shapes every time. self.picture = QtGui.QPicture() p = QtGui.QPainter(self.picture) p.setPen(pg.mkPen(color='w', width=0.4)) # 0.4 means w*2 # w = (self.data[1][0] - self.data[0][0]) / 3. w = 0.2 for (t, open, close, min, max) in self.data: p.drawLine(QtCore.QPointF(t, min), QtCore.QPointF(t, max)) if open > close: p.setBrush(pg.mkBrush('g')) else: p.setBrush(pg.mkBrush('r')) p.drawRect(QtCore.QRectF(t-w, open, w*2, close-open)) p.end() def paint(self, p, *args): p.drawPicture(0, 0, self.picture) def boundingRect(self): ## boundingRect _must_ indicate the entire area that will be drawn on ## or else we will get artifacts and possibly crashing. ## (in this case, QPicture does all the work of computing the bouning rect for us) return QtCore.QRectF(self.picture.boundingRect()) #---------------------------------------------------------------------- def __init__(self, eventEngine, chanlunEngine, parent=None): """Constructor""" super(PriceWidget, self).__init__(parent) self.__eventEngine = eventEngine self.__mainEngine = chanlunEngine # MongoDB数据库相关 self.__mongoConnected = False self.__mongoConnection = None self.__mongoTickDB = None # 调用函数 self.__connectMongo() self.initUi(startDate=None) self.registerEvent() #---------------------------------------------------------------------- def initUi(self, startDate=None): """初始化界面""" self.setWindowTitle(u'Price') self.vbl_1 = QtGui.QHBoxLayout() # self.vbl_1.setColumnStretch(1,1) # self.vbl_1.setRowStretch(1,1) # self.initplotTick() # plotTick初始化 # self.vbl_2 = QtGui.QVBoxLayout() self.initplotKline() # plotKline初始化 # self.initplotTendency() # plot分时图的初始化 # 整体布局 # self.hbl = QtGui.QHBoxLayout() self.setLayout(self.vbl_1) # self.hbl.addLayout(self.vbl_2) # self.setLayout(self.hbl) self.initHistoricalData() # 下载历史Tick数据并画图 # self.plotMin() #使用数据库中的分钟数据画K线 #---------------------------------------------------------------------- def initplotTick(self): """""" self.pw1 = pg.PlotWidget(name='Plot1') self.vbl_1.addWidget(self.pw1) self.pw1.setRange(xRange=[-360, 0]) self.pw1.setLimits(xMax=5) self.pw1.setDownsampling(mode='peak') self.pw1.setClipToView(True) self.curve1 = self.pw1.plot() self.curve2 = self.pw1.plot() self.curve3 = self.pw1.plot() self.curve4 = self.pw1.plot() #---------------------------------------------------------------------- def initplotKline(self): """Kline""" self.pw2 = pg.PlotWidget(name='Plot2') # K线图 self.vbl_1.addWidget(self.pw2) self.pw2.setMinimumWidth(1500) # self.vbl_1.setStretchFactor(self.pw2,-1) self.pw2.setDownsampling(mode='peak') self.pw2.setClipToView(True) self.curve5 = self.pw2.plot() self.curve6 = self.pw2.plot() self.candle = self.CandlestickItem(self.listBar) self.pw2.addItem(self.candle) ## Draw an arrowhead next to the text box # self.arrow = pg.ArrowItem() # self.pw2.addItem(self.arrow) #---------------------------------------------------------------------- def initplotTendency(self): """""" self.pw3 = pg.PlotWidget(name='Plot3') self.vbl_2.addWidget(self.pw3) self.pw3.setDownsampling(mode='peak') self.pw3.setClipToView(True) self.pw3.setMaximumHeight(200) self.pw3.setXLink('Plot2') # X linked with Plot2 self.curve7 = self.pw3.plot() def plotMin(self): print "plotMinK start" self.initCompleted = True cx = self.__mongoMinDB[self.symbol].find() print cx.count() if cx: for data in cx: self.barOpen = data['open'] self.barClose = data['close'] self.barLow = data['low'] self.barHigh = data['high'] self.barOpenInterest = data['openInterest'] # print self.num, self.barOpen, self.barClose, self.barLow, self.barHigh, self.barOpenInterest self.onBar(self.num, self.barOpen, self.barClose, self.barLow, self.barHigh, self.barOpenInterest) self.num += 1 print "plotMinK success" #---------------------------------------------------------------------- def initHistoricalData(self,startDate=None): """初始历史数据""" print "download histrical data" self.initCompleted = True # 读取历史数据完成 td = timedelta(days=1) # 读取3天的历史TICK数据 if startDate: cx = self.loadTick(self.symbol, startDate-td) else: today = datetime.today().replace(hour=0, minute=0, second=0, microsecond=0) cx = self.loadTick(self.symbol, today-td) print cx.count() if cx: for data in cx: tick = Tick(data['symbol']) tick.openPrice = data['lastPrice'] tick.highPrice = data['upperLimit'] tick.lowPrice = data['lowerLimit'] tick.lastPrice = data['lastPrice'] tick.volume = data['volume'] tick.openInterest = data['openInterest'] tick.upperLimit = data['upperLimit'] tick.lowerLimit = data['lowerLimit'] tick.time = data['time'] # tick.ms = data['UpdateMillisec'] tick.bidPrice1 = data['bidPrice1'] tick.bidPrice2 = data['bidPrice2'] tick.bidPrice3 = data['bidPrice3'] tick.bidPrice4 = data['bidPrice4'] tick.bidPrice5 = data['bidPrice5'] tick.askPrice1 = data['askPrice1'] tick.askPrice2 = data['askPrice2'] tick.askPrice3 = data['askPrice3'] tick.askPrice4 = data['askPrice4'] tick.askPrice5 = data['askPrice5'] tick.bidVolume1 = data['bidVolume1'] tick.bidVolume2 = data['bidVolume2'] tick.bidVolume3 = data['bidVolume3'] tick.bidVolume4 = data['bidVolume4'] tick.bidVolume5 = data['bidVolume5'] tick.askVolume1 = data['askVolume1'] tick.askVolume2 = data['askVolume2'] tick.askVolume3 = data['askVolume3'] tick.askVolume4 = data['askVolume4'] tick.askVolume5 = data['askVolume5'] self.onTick(tick) print('load historic data completed') #---------------------------------------------------------------------- # def plotTick(self): # """画tick图""" # if self.initCompleted: # self.curve1.setData(self.listlastPrice[:self.ptr]) # self.curve2.setData(self.listfastMA[:self.ptr], pen=(255, 0, 0), name="Red curve") # self.curve3.setData(self.listmidMA[:self.ptr], pen=(0, 255, 0), name="Green curve") # self.curve4.setData(self.listslowMA[:self.ptr], pen=(0, 0, 255), name="Blue curve") # self.curve1.setPos(-self.ptr, 0) # self.curve2.setPos(-self.ptr, 0) # self.curve3.setPos(-self.ptr, 0) # self.curve4.setPos(-self.ptr, 0) #---------------------------------------------------------------------- def plotKline(self): """K线图""" if self.initCompleted: # 均线 self.curve5.setData(self.listfastEMA, pen=(255, 0, 0), name="Red curve") self.curve6.setData(self.listslowEMA, pen=(0, 255, 0), name="Green curve") # 画K线 self.pw2.removeItem(self.candle) self.candle = self.CandlestickItem(self.listBar) self.pw2.addItem(self.candle) self.plotText() # 显示开仓信号位置 #---------------------------------------------------------------------- def plotTendency(self): """持仓""" if self.initCompleted: self.curve7.setData(self.listOpenInterest, pen=(255, 255, 255), name="White curve") #---------------------------------------------------------------------- def plotText(self): lenClose = len(self.listClose) if lenClose >= 5: # Fractal Signal if self.listClose[-1] > self.listClose[-2] and self.listClose[-3] > self.listClose[-2] and self.listClose[-4] > self.listClose[-2] and self.listClose[-5] > self.listClose[-2] and self.listfastEMA[-1] > self.listslowEMA[-1]: ## Draw an arrowhead next to the text box # self.pw2.removeItem(self.arrow) self.arrow = pg.ArrowItem(pos=(lenClose-1, self.listLow[-1]), angle=90, brush=(255, 0, 0))#红色 self.pw2.addItem(self.arrow) elif self.listClose[-1] < self.listClose[-2] and self.listClose[-3] < self.listClose[-2] and self.listClose[-4] < self.listClose[-2] and self.listClose[-5] < self.listClose[-2] and self.listfastEMA[-1] < self.listslowEMA[-1]: ## Draw an arrowhead next to the text box # self.pw2.removeItem(self.arrow) self.arrow = pg.ArrowItem(pos=(lenClose-1, self.listHigh[-1]), angle=-90, brush=(0, 255, 0))#绿色 self.pw2.addItem(self.arrow) #---------------------------------------------------------------------- def updateMarketData(self, event): """更新行情""" print "update" data = event.dict_['data'] print data symbol = data['InstrumentID'] tick = Tick(symbol) tick.openPrice = data['OpenPrice'] tick.highPrice = data['HighestPrice'] tick.lowPrice = data['LowestPrice'] tick.lastPrice = data['LastPrice'] tick.volume = data['Volume'] tick.openInterest = data['OpenInterest'] tick.upperLimit = data['UpperLimitPrice'] tick.lowerLimit = data['LowerLimitPrice'] tick.time = data['UpdateTime'] tick.ms = data['UpdateMillisec'] tick.bidPrice1 = data['BidPrice1'] tick.bidPrice2 = data['BidPrice2'] tick.bidPrice3 = data['BidPrice3'] tick.bidPrice4 = data['BidPrice4'] tick.bidPrice5 = data['BidPrice5'] tick.askPrice1 = data['AskPrice1'] tick.askPrice2 = data['AskPrice2'] tick.askPrice3 = data['AskPrice3'] tick.askPrice4 = data['AskPrice4'] tick.askPrice5 = data['AskPrice5'] tick.bidVolume1 = data['BidVolume1'] tick.bidVolume2 = data['BidVolume2'] tick.bidVolume3 = data['BidVolume3'] tick.bidVolume4 = data['BidVolume4'] tick.bidVolume5 = data['BidVolume5'] tick.askVolume1 = data['AskVolume1'] tick.askVolume2 = data['AskVolume2'] tick.askVolume3 = data['AskVolume3'] tick.askVolume4 = data['AskVolume4'] tick.askVolume5 = data['AskVolume5'] self.onTick(tick) # tick数据更新 # # 将数据插入MongoDB数据库,实盘建议另开程序记录TICK数据 # self.__recordTick(data) #---------------------------------------------------------------------- def onTick(self, tick): """tick数据更新""" from datetime import time # 首先生成datetime.time格式的时间(便于比较),从字符串时间转化为time格式的时间 hh, mm, ss = tick.time.split(':') if(len(ss) > 2): ss1, ss2 = ss.split('.') self.ticktime = time(int(hh), int(mm), int(ss1), microsecond=int(ss2)*100) else: self.ticktime = time(int(hh), int(mm), int(ss), microsecond=tick.ms) # 计算tick图的相关参数 if self.ptr == 0: self.fastMA = tick.lastPrice self.midMA = tick.lastPrice self.slowMA = tick.lastPrice else: self.fastMA = (1-self.tickFastAlpha) * self.fastMA + self.tickFastAlpha * tick.lastPrice self.midMA = (1-self.tickMidAlpha) * self.midMA + self.tickMidAlpha * tick.lastPrice self.slowMA = (1-self.tickSlowAlpha) * self.slowMA + self.tickSlowAlpha * tick.lastPrice self.listlastPrice[self.ptr] = tick.lastPrice self.listfastMA[self.ptr] = self.fastMA self.listmidMA[self.ptr] = self.midMA self.listslowMA[self.ptr] = self.slowMA self.ptr += 1 print("----------") print(self.ptr) if self.ptr >= self.listlastPrice.shape[0]: tmp = self.listlastPrice self.listlastPrice = np.empty(self.listlastPrice.shape[0] * 2) self.listlastPrice[:tmp.shape[0]] = tmp tmp = self.listfastMA self.listfastMA = np.empty(self.listfastMA.shape[0] * 2) self.listfastMA[:tmp.shape[0]] = tmp tmp = self.listmidMA self.listmidMA = np.empty(self.listmidMA.shape[0] * 2) self.listmidMA[:tmp.shape[0]] = tmp tmp = self.listslowMA self.listslowMA = np.empty(self.listslowMA.shape[0] * 2) self.listslowMA[:tmp.shape[0]] = tmp # K线数据 # 假设是收到的第一个TICK if self.barOpen == 0: # 初始化新的K线数据 self.barOpen = tick.lastPrice self.barHigh = tick.lastPrice self.barLow = tick.lastPrice self.barClose = tick.lastPrice self.barTime = self.ticktime self.barOpenInterest = tick.openInterest self.onBar(self.num, self.barOpen, self.barClose, self.barLow, self.barHigh, self.barOpenInterest) else: # 如果是当前一分钟内的数据 if self.ticktime.minute == self.barTime.minute: if self.ticktime.second >= 30 and self.barTime.second < 30: # 判断30秒周期K线 # 先保存K线收盘价 self.num += 1 self.onBar(self.num, self.barOpen, self.barClose, self.barLow, self.barHigh, self.barOpenInterest) # 初始化新的K线数据 self.barOpen = tick.lastPrice self.barHigh = tick.lastPrice self.barLow = tick.lastPrice self.barClose = tick.lastPrice self.barTime = self.ticktime self.barOpenInterest = tick.openInterest # 汇总TICK生成K线 self.barHigh = max(self.barHigh, tick.lastPrice) self.barLow = min(self.barLow, tick.lastPrice) self.barClose = tick.lastPrice self.barTime = self.ticktime self.listBar.pop() self.listfastEMA.pop() self.listslowEMA.pop() self.listOpen.pop() self.listClose.pop() self.listHigh.pop() self.listLow.pop() self.listOpenInterest.pop() self.onBar(self.num, self.barOpen, self.barClose, self.barLow, self.barHigh, self.barOpenInterest) # 如果是新一分钟的数据 else: # 先保存K线收盘价 self.num += 1 self.onBar(self.num, self.barOpen, self.barClose, self.barLow, self.barHigh, self.barOpenInterest) # 初始化新的K线数据 self.barOpen = tick.lastPrice self.barHigh = tick.lastPrice self.barLow = tick.lastPrice self.barClose = tick.lastPrice self.barTime = self.ticktime self.barOpenInterest = tick.openInterest #---------------------------------------------------------------------- def onBar(self, n, o, c, l, h, oi): self.listBar.append((n, o, c, l, h)) self.listOpen.append(o) self.listClose.append(c) self.listHigh.append(h) self.listLow.append(l) self.listOpenInterest.append(oi) #计算K线图EMA均线 if self.fastEMA: self.fastEMA = c*self.EMAFastAlpha + self.fastEMA*(1-self.EMAFastAlpha) self.slowEMA = c*self.EMASlowAlpha + self.slowEMA*(1-self.EMASlowAlpha) else: self.fastEMA = c self.slowEMA = c self.listfastEMA.append(self.fastEMA) self.listslowEMA.append(self.slowEMA) # 调用画图函数 # self.plotTick() # tick图 self.plotKline() # K线图 # self.plotTendency() # K线副图,持仓量 #---------------------------------------------------------------------- def __connectMongo(self): """连接MongoDB数据库""" try: self.__mongoConnection = pymongo.MongoClient("localhost", 27017) self.__mongoConnected = True self.__mongoTickDB = self.__mongoConnection['VnTrader_Tick_Db'] self.__mongoMinDB = self.__mongoConnection['VnTrader_1Min_Db'] except ConnectionFailure: pass #---------------------------------------------------------------------- def __recordTick(self, data): """将Tick数据插入到MongoDB中""" if self.__mongoConnected: symbol = data['InstrumentID'] data['date'] = self.today self.__mongoTickDB[symbol].insert(data) #---------------------------------------------------------------------- def loadTick(self, symbol, startDate, endDate=None): """从MongoDB中读取Tick数据""" cx = self.__mongoTickDB[symbol].find() print cx.count() return cx # if self.__mongoConnected: # collection = self.__mongoTickDB[symbol] # # # 如果输入了读取TICK的最后日期 # if endDate: # cx = collection.find({'date': {'$gte': startDate, '$lte': endDate}}) # else: # cx = collection.find({'date': {'$gte': startDate}}) # return cx # else: # return None #---------------------------------------------------------------------- def registerEvent(self): """注册事件监听""" print "connect" # self.__mainEngine.putMarketEvent() self.signal.connect(self.updateMarketData) self.__eventEngine.register(EVENT_MARKETDATA, self.signal.emit)
class CtaStrategyManager(QtWidgets.QGroupBox): """策略管理组件""" signal = QtCore.pyqtSignal(type(Event())) signalBuy = QtCore.pyqtSignal(type(Event())) #开仓信号,需人工确认 signalShort = QtCore.pyqtSignal(type(Event())) #开仓信号,需人工确认 #---------------------------------------------------------------------- def __init__(self, ctaEngine, eventEngine, name, parent=None): """Constructor""" super(CtaStrategyManager, self).__init__(parent) self.ctaEngine = ctaEngine self.eventEngine = eventEngine self.name = name self.initUi() self.updateMonitor() self.registerEvent() #---------------------------------------------------------------------- def initUi(self): """初始化界面""" self.setTitle(self.name) self.paramMonitor = CtaValueMonitor(self) self.varMonitor = CtaValueMonitor(self) height = 60 self.paramMonitor.setFixedHeight(height) self.varMonitor.setFixedHeight(height) buttonInit = QtWidgets.QPushButton(u'初始化') buttonStart = QtWidgets.QPushButton(u'启动') buttonStop = QtWidgets.QPushButton(u'停止') buttonBuy = QtWidgets.QPushButton(u'开多') buttonSell = QtWidgets.QPushButton(u'平多') buttonShort = QtWidgets.QPushButton(u'开空') buttonCover = QtWidgets.QPushButton(u'平空') buttonParam = QtWidgets.QPushButton(u'参数') buttonInit.clicked.connect(self.init) buttonStart.clicked.connect(self.start) buttonStop.clicked.connect(self.stop) buttonBuy.clicked.connect(self.buy) buttonSell.clicked.connect(self.sell) buttonShort.clicked.connect(self.short) buttonCover.clicked.connect(self.cover) buttonParam.clicked.connect(self.paramSetting) hbox1 = QtWidgets.QHBoxLayout() hbox1.addWidget(buttonInit) hbox1.addWidget(buttonStart) hbox1.addWidget(buttonStop) hbox1.addWidget(buttonBuy) hbox1.addWidget(buttonSell) hbox1.addWidget(buttonShort) hbox1.addWidget(buttonCover) hbox1.addWidget(buttonParam) hbox1.addStretch() hbox2 = QtWidgets.QHBoxLayout() hbox2.addWidget(self.paramMonitor) hbox3 = QtWidgets.QHBoxLayout() hbox3.addWidget(self.varMonitor) vbox = QtWidgets.QVBoxLayout() vbox.addLayout(hbox1) vbox.addLayout(hbox2) vbox.addLayout(hbox3) self.setLayout(vbox) #---------------------------------------------------------------------- def updateMonitor(self, event=None): """显示策略最新状态""" paramDict = self.ctaEngine.getStrategyParam(self.name) if paramDict: self.paramMonitor.updateData(paramDict) varDict = self.ctaEngine.getStrategyVar(self.name) if varDict: self.varMonitor.updateData(varDict) #---------------------------------------------------------------------- def registerEvent(self): """注册事件监听""" self.signal.connect(self.updateMonitor) self.eventEngine.register(EVENT_CTA_STRATEGY + self.name, self.signal.emit) self.signalBuy.connect(self.buy) self.signalShort.connect(self.short) self.eventEngine.register(EVENT_CTA_STRATEGY + self.name + ".BUY", self.signalBuy.emit) self.eventEngine.register(EVENT_CTA_STRATEGY + self.name + ".SHORT", self.signalShort.emit) #---------------------------------------------------------------------- def init(self): """初始化策略""" self.ctaEngine.initStrategy(self.name) #---------------------------------------------------------------------- def start(self): """启动策略""" self.ctaEngine.startStrategy(self.name) #---------------------------------------------------------------------- def stop(self): """停止策略""" self.ctaEngine.stopStrategy(self.name) #---------------------------------------------------------------------- def buy(self): """手动开多""" self.ctaEngine.tradeStrategy(self.name, CTAORDER_BUY) self.ctaEngine.writeCtaLog(u'手动开多' + self.name) #---------------------------------------------------------------------- def sell(self): """手动平多""" self.ctaEngine.tradeStrategy(self.name, CTAORDER_SELL) self.ctaEngine.writeCtaLog(u'手动平多' + self.name) #---------------------------------------------------------------------- def short(self): """手动开空""" self.ctaEngine.tradeStrategy(self.name, CTAORDER_SHORT) self.ctaEngine.writeCtaLog(u'手动开空' + self.name) def cover(self): """手动平空""" self.ctaEngine.tradeStrategy(self.name, CTAORDER_COVER) self.ctaEngine.writeCtaLog(u'手动平空' + self.name) def paramSetting(self): """设置参数窗口""" self.paramWindow = ParamWindow2(self.name) self.paramWindow.paramters = self.paramWindow.loadParameter() self.paramWindow.showParam() self.paramWindow.show()
def initLabel(self): if self.name == "": strategyname_label = QtGui.QLabel(u"策略名", self) strategyname_label.setGeometry(QtCore.QRect(25, 25, 70, 22)) self.strategyname_label = QtGui.QLineEdit(self) self.strategyname_label.setGeometry(QtCore.QRect(120, 25, 70, 22)) self.closeFirst = QtGui.QCheckBox(u'平仓优先', self) self.closeFirst.setGeometry(QtCore.QRect(210, 25, 90, 22)) label_symbol = QtGui.QLabel(u"合约", self) label_symbol.setGeometry(QtCore.QRect(25, 50, 70, 22)) self.lineEdit_label_symbol = QtGui.QLineEdit(self) self.lineEdit_label_symbol.setGeometry(QtCore.QRect(120, 50, 70, 22)) symbolDirection = QtGui.QLabel(u"方向", self) symbolDirection.setGeometry(QtCore.QRect(210, 50, 70, 22)) self.directionCombo = QtGui.QComboBox(self) self.directionCombo.addItem("") self.directionCombo.addItem("long") self.directionCombo.addItem('short') self.directionCombo.setGeometry(QtCore.QRect(245, 50, 50, 22)) label_longBuyUnit = QtGui.QLabel(u"每笔数量", self) label_longBuyUnit.setGeometry(QtCore.QRect(25, 75, 50, 22)) self.lineEdit_label_longBuyUnit = QtGui.QLineEdit(self) self.lineEdit_label_longBuyUnit.setGeometry( QtCore.QRect(120, 75, 70, 22)) maxStpLos = QtGui.QLabel(u'止损', self) maxStpLos.setGeometry(QtCore.QRect(210, 75, 70, 22)) self.lineEdit_label_maxStpLos = QtGui.QLineEdit(self) self.lineEdit_label_maxStpLos.setGeometry(QtCore.QRect( 245, 75, 60, 22)) label_longPriceCoe = QtGui.QLabel(u"价格系数", self) label_longPriceCoe.setGeometry(QtCore.QRect(25, 100, 50, 22)) self.lineEdit_label_longPriceCoe = QtGui.QLineEdit(self) self.lineEdit_label_longPriceCoe.setGeometry( QtCore.QRect(120, 100, 70, 22)) label_longPosition = QtGui.QLabel(u"当前持仓量", self) label_longPosition.setGeometry(QtCore.QRect(25, 125, 50, 22)) self.lineEdit_label_longPosition = QtGui.QLineEdit(self) self.lineEdit_label_longPosition.setGeometry( QtCore.QRect(120, 125, 70, 22)) label_stpProfit = QtGui.QLabel(u"止赢", self) label_stpProfit.setGeometry(QtCore.QRect(25, 150, 50, 22)) self.lineEdit_label_stpProfit = QtGui.QLineEdit(self) self.lineEdit_label_stpProfit.setGeometry( QtCore.QRect(120, 150, 70, 22)) label_slippage = QtGui.QLabel(u"滑点", self) label_slippage.setGeometry(QtCore.QRect(25, 175, 50, 22)) self.lineEdit_label_slippage = QtGui.QLineEdit(self) self.lineEdit_label_slippage.setGeometry(QtCore.QRect( 120, 175, 70, 22)) label_mail = QtGui.QLabel(u"邮箱", self) label_mail.setGeometry(QtCore.QRect(25, 200, 50, 22)) self.lineEdit_label_mail = QtGui.QLineEdit(self) self.lineEdit_label_mail.setGeometry(QtCore.QRect(120, 200, 200, 22)) label_buyPrice = QtGui.QLabel(u"开仓价差", self) label_buyPrice.setGeometry(QtCore.QRect(25, 225, 50, 22)) self.lineEdit_label_buyPrice = QtGui.QLineEdit(self) self.lineEdit_label_buyPrice.setGeometry( QtCore.QRect(120, 225, 200, 22)) label_stoptime = QtGui.QLabel(u"停止时间", self) label_stoptime.setGeometry(QtCore.QRect(25, 250, 50, 22)) self.lineEdit_label_stoptime = QtGui.QLineEdit(self) self.lineEdit_label_stoptime.setGeometry( QtCore.QRect(120, 250, 200, 22)) self.isFilter = QtGui.QCheckBox(u'当波动大于', self) self.isFilter.setGeometry(QtCore.QRect(25, 275, 150, 22)) self.lineEdit_label_var = QtGui.QLineEdit(self) self.lineEdit_label_var.setGeometry(QtCore.QRect(120, 275, 20, 22)) label_pct = QtGui.QLabel(u'% 时忽略', self) label_pct.setGeometry(QtCore.QRect(141, 275, 80, 22))
class DrEngineManager(QtGui.QWidget): """行情数据记录引擎管理组件""" signal = QtCore.pyqtSignal(type(Event())) #---------------------------------------------------------------------- def __init__(self, mainEngine, eventEngine, parent=None): """Constructor""" super(DrEngineManager, self).__init__(parent) self.mainEngine = mainEngine self.drEngine = mainEngine.drEngine self.eventEngine = eventEngine self.initUi() self.updateSetting() self.registerEvent() #---------------------------------------------------------------------- def initUi(self): """初始化界面""" self.setWindowTitle(u'行情数据记录工具') # 记录合约配置监控 tickLabel = QtGui.QLabel(u'Tick记录') self.tickTable = QtGui.QTableWidget() self.tickTable.setColumnCount(2) self.tickTable.verticalHeader().setVisible(False) self.tickTable.setEditTriggers(QtGui.QTableWidget.NoEditTriggers) self.tickTable.horizontalHeader().setResizeMode( QtGui.QHeaderView.Stretch) self.tickTable.setAlternatingRowColors(True) self.tickTable.setHorizontalHeaderLabels([u'合约代码', u'接口']) barLabel = QtGui.QLabel(u'Bar记录') self.barTable = QtGui.QTableWidget() self.barTable.setColumnCount(2) self.barTable.verticalHeader().setVisible(False) self.barTable.setEditTriggers(QtGui.QTableWidget.NoEditTriggers) self.barTable.horizontalHeader().setResizeMode( QtGui.QHeaderView.Stretch) self.barTable.setAlternatingRowColors(True) self.barTable.setHorizontalHeaderLabels([u'合约代码', u'接口']) activeLabel = QtGui.QLabel(u'主力合约') self.activeTable = QtGui.QTableWidget() self.activeTable.setColumnCount(2) self.activeTable.verticalHeader().setVisible(False) self.activeTable.setEditTriggers(QtGui.QTableWidget.NoEditTriggers) self.activeTable.horizontalHeader().setResizeMode( QtGui.QHeaderView.Stretch) self.activeTable.setAlternatingRowColors(True) self.activeTable.setHorizontalHeaderLabels([u'主力代码', u'合约代码']) # 日志监控 self.logMonitor = QtGui.QTextEdit() self.logMonitor.setReadOnly(True) self.logMonitor.setMinimumHeight(600) # 设置布局 grid = QtGui.QGridLayout() grid.addWidget(tickLabel, 0, 0) grid.addWidget(barLabel, 0, 1) grid.addWidget(activeLabel, 0, 2) grid.addWidget(self.tickTable, 1, 0) grid.addWidget(self.barTable, 1, 1) grid.addWidget(self.activeTable, 1, 2) btnEdit = QtGui.QPushButton(u'编辑', self) vbox = QtGui.QVBoxLayout() vbox.addLayout(grid) vline = QtGui.QHBoxLayout() vline.addWidget(btnEdit) vbox.addLayout(vline) vbox.addWidget(self.logMonitor) self.setLayout(vbox) btnEdit.clicked.connect(self.openDr) #---------------------------------------------------------------------- def updateLog(self, event): """更新日志""" log = event.dict_['data'] content = '\t'.join([log.logTime, log.logContent]) self.logMonitor.append(content) #---------------------------------------------------------------------- def registerEvent(self): """注册事件监听""" self.signal.connect(self.updateLog) self.eventEngine.register(EVENT_DATARECORDER_LOG, self.signal.emit) #---------------------------------------------------------------------- def updateSetting(self): """显示引擎行情记录配置""" self.tickTable.clearContents() self.tickTable.setRowCount(0) self.barTable.clearContents() self.barTable.setRowCount(0) self.activeTable.clearContents() self.activeTable.setRowCount(0) with open(self.drEngine.settingFileName) as f: drSetting = json.load(f) if 'tick' in drSetting: l = drSetting['tick'] for setting in l: self.tickTable.insertRow(0) self.tickTable.setItem(0, 0, TableCell(setting[0])) self.tickTable.setItem(0, 1, TableCell(setting[1])) if 'bar' in drSetting: l = drSetting['bar'] for setting in l: self.barTable.insertRow(0) self.barTable.setItem(0, 0, TableCell(setting[0])) self.barTable.setItem(0, 1, TableCell(setting[1])) if 'active' in drSetting: d = drSetting['active'] for activeSymbol, symbol in d.items(): self.activeTable.insertRow(0) self.activeTable.setItem(0, 0, TableCell(activeSymbol)) self.activeTable.setItem(0, 1, TableCell(symbol)) # ---------------------------------------------------------------------- def openDr(self): """打开行情数据记录组件""" self.mDrEditWidget = DrEditWidget(self, self.mainEngine, self.eventEngine) self.mDrEditWidget.setWindowTitle(u"编辑订阅") self.mDrEditWidget.setFixedSize(800, 800) self.mDrEditWidget.show() def restart(self): pass
class CtaEngineManager(QtGui.QWidget): """CTA引擎管理组件""" signal = QtCore.pyqtSignal(type(Event())) #---------------------------------------------------------------------- def __init__(self, ctaEngine, eventEngine, parent=None): """Constructor""" super(CtaEngineManager, self).__init__(parent) self.ctaEngine = ctaEngine self.eventEngine = eventEngine self.strategyLoaded = False self.pw = ParamWindow("", "", "", self) self.gt = ParamWindow2("", "", "", self) self.cai = ParamWindow3("", "", "", self) self.abt = ParamWindow4("", "", "", self) #self.sw = strategyWindow(self.pw, self.gt,self.cai) self.initUi() self.registerEvent() # 记录日志 self.ctaEngine.writeCtaLog(u'CTA引擎启动成功') #---------------------------------------------------------------------- def initUi(self): """初始化界面""" self.setWindowTitle(u'CTA策略') # 按钮 loadButton = QtGui.QPushButton(u'加载策略') initAllButton = QtGui.QPushButton(u'全部初始化') startAllButton = QtGui.QPushButton(u'全部启动') stopAllButton = QtGui.QPushButton(u'全部停止') addStrategy = QtGui.QPushButton(u'添加策略') thumbnail = QtGui.QPushButton(u'策略持仓') loadButton.clicked.connect(self.load) initAllButton.clicked.connect(self.initAll) startAllButton.clicked.connect(self.startAll) stopAllButton.clicked.connect(self.stopAll) addStrategy.clicked.connect(self.addStrategy) thumbnail.clicked.connect(self.thumbnail) # 滚动区域,放置所有的CtaStrategyManager self.scrollArea = QtGui.QScrollArea() self.scrollArea.setWidgetResizable(True) # CTA组件的日志监控 self.ctaLogMonitor = QtGui.QTextEdit() self.ctaLogMonitor.setReadOnly(True) self.ctaLogMonitor.setMaximumHeight(200) # 设置布局 hbox2 = QtGui.QHBoxLayout() hbox2.addWidget(loadButton) hbox2.addWidget(initAllButton) hbox2.addWidget(startAllButton) hbox2.addWidget(stopAllButton) hbox2.addWidget(addStrategy) hbox2.addWidget(thumbnail) hbox2.addStretch() vbox = QtGui.QVBoxLayout() vbox.addLayout(hbox2) vbox.addWidget(self.scrollArea) vbox.addWidget(self.ctaLogMonitor) self.setLayout(vbox) #---------------------------------------------------------------------- def initStrategyManager(self): """初始化策略管理组件界面""" w = QtGui.QWidget() vbox = QtGui.QVBoxLayout() for name in self.ctaEngine.strategyDict.keys(): p = self.ctaEngine.strategyDict[name] if p.className == 'tradeTest': strategyManager = CtaStrategyManager(self.ctaEngine, self.eventEngine, name, p.className, '', '', p.longsymbol, p.shortsymbol) elif p.className == 'CtpAndIB': strategyManager = CtaStrategyManager(self.ctaEngine, self.eventEngine, name, p.className, '', '', p.longsymbol, p.shortsymbol) elif p.className == 'Arbitrage': strategyManager = CtaStrategyManager(self.ctaEngine, self.eventEngine, name, p.className, '', '', p.longsymbol, p.shortsymbol) else: strategyManager = CtaStrategyManager(self.ctaEngine, self.eventEngine, name, p.className, p.direction, p.vtSymbol, '', '') vbox.addWidget(strategyManager) vbox.addStretch() w.setLayout(vbox) self.scrollArea.setWidget(w) #---------------------------------------------------------------------- def initAll(self): """全部初始化""" for name in self.ctaEngine.strategyDict.keys(): self.ctaEngine.initStrategy(name) #---------------------------------------------------------------------- def startAll(self): """全部启动""" for name in self.ctaEngine.strategyDict.keys(): self.ctaEngine.startStrategy(name) #---------------------------------------------------------------------- def stopAll(self): """全部停止""" for name in self.ctaEngine.strategyDict.keys(): self.ctaEngine.stopStrategy(name) #---------------------------------------------------------------------- def thumbnail(self): settingFileName = 'CTA_setting.json' path = os.path.abspath(os.path.dirname(__file__)) settingFileName = os.path.join(path, settingFileName) l = [] with open(settingFileName, 'r') as f: l = json.load(f) f.close() self.tw = thumbnailWindow(l) self.tw.show() def addStrategy(self): self.pw = ParamWindow("", "", "", self.ctaEngine) self.gt = ParamWindow2("", "", "", self.ctaEngine) self.cai = ParamWindow3("", "", "", self.ctaEngine) self.abt = ParamWindow4("", "", "", self.ctaEngine) self.sw = strategyWindow(self.pw, self.gt, self.cai, self.abt) self.sw.show() #---------------------------------------------------------------------- def load(self): """加载策略""" if not self.strategyLoaded: self.ctaEngine.loadSetting() self.initStrategyManager() self.strategyLoaded = True self.ctaEngine.writeCtaLog(u'策略加载成功') #---------------------------------------------------------------------- def updateCtaLog(self, event): """更新CTA相关日志""" log = event.dict_['data'] content = '\t'.join([log.logTime, log.logContent]) self.ctaLogMonitor.append(content) #---------------------------------------------------------------------- def registerEvent(self): """注册事件监听""" self.signal.connect(self.updateCtaLog) self.eventEngine.register(EVENT_CTA_LOG, self.signal.emit)