def __init__(self, PARTS=10): self.dLocation = '/home' loc = '' if os.path.exists(os.getcwd() + '/Locale/desF'): f = open(os.getcwd() + '/Locale/desF', 'r') loc = f.read() f.close() if len(loc) > 0: if os.path.exists(loc): self.dLocation = loc self.PARTS = PARTS self.fileName = '____' self.obj = DownloadWindow(self.PARTS) self.clear()
def __init__(self,PARTS=10) : self.dLocation = '/home' loc='' if os.path.exists(os.getcwd()+'/Locale/desF') : f=open(os.getcwd()+'/Locale/desF','r') loc=f.read() f.close() if len(loc) > 0: if os.path.exists(loc) : self.dLocation=loc self.PARTS=PARTS self.fileName='____' self.obj = DownloadWindow(self.PARTS) self.clear()
class Interface : ''' Store Download information start 'em ''' def __init__(self,PARTS=10) : self.dLocation = '/home' loc='' if os.path.exists(os.getcwd()+'/Locale/desF') : f=open(os.getcwd()+'/Locale/desF','r') loc=f.read() f.close() if len(loc) > 0: if os.path.exists(loc) : self.dLocation=loc self.PARTS=PARTS self.fileName='____' self.obj = DownloadWindow(self.PARTS) self.clear() def clear(self) : ''' reinitialize interface for another download ''' self.dt='' self.tm='' self.url='' self.flag = 0 # Terminate,Fatal Error,Downloading,Show,Started,Inform Completion,Terminated,Hide self.free=0 self.length = 0 self.downloaded = 0 self.timeLeft = '' self.obj.Clear() def getInfo(self) : ''' builds an Info() object out of download informations ''' obj=Info() obj.url=self.url obj.fileName=self.fileName obj.date=self.dt obj.time=self.tm obj.length=self.length return obj def start_from_Part(self,wMutex,bit) : ''' When a download is resumed it is started from partial downloads ''' self.obj.PARTS=self.PARTS try : x=self.obj.getPartDownload(self.getInfo(),self,wMutex,bit) if x==0 : self.flag = self.flag | 0x0040 return except : self.flag = self.flag | 0x0040 return self.obj.resize(700,225) self.free=0 if x==2: self.flag=self.flag | 0x0008 return self.flag=self.flag | 0x0100 def start_Download(self,url,wMutex,bit=0) : ''' If a fresh download is started it starts from here ''' self.obj.PARTS=self.PARTS self.url=url self.dt = time.strftime("%a %d %b %Y",time.localtime()) self.tm = time.strftime("%H:%M:%S",time.localtime()) try : self.fileName,self.length=self.obj.getDownload(str(url),self,wMutex,bit) except urllib2.URLError as e : self.flag = self.flag | 0x0040 except Exception : self.flag = self.flag | 0x0040 return self.obj.resize(700,225) self.free=0 self.flag = self.flag | 0x0008
class Interface: ''' Store Download information start 'em ''' def __init__(self, PARTS=10): self.dLocation = '/home' loc = '' if os.path.exists(os.getcwd() + '/Locale/desF'): f = open(os.getcwd() + '/Locale/desF', 'r') loc = f.read() f.close() if len(loc) > 0: if os.path.exists(loc): self.dLocation = loc self.PARTS = PARTS self.fileName = '____' self.obj = DownloadWindow(self.PARTS) self.clear() def clear(self): ''' reinitialize interface for another download ''' self.dt = '' self.tm = '' self.url = '' self.flag = 0 # Terminate,Fatal Error,Downloading,Show,Started,Inform Completion,Terminated,Hide self.free = 0 self.length = 0 self.downloaded = 0 self.timeLeft = '' self.obj.Clear() def getInfo(self): ''' builds an Info() object out of download informations ''' obj = Info() obj.url = self.url obj.fileName = self.fileName obj.date = self.dt obj.time = self.tm obj.length = self.length return obj def start_from_Part(self, wMutex, bit): ''' When a download is resumed it is started from partial downloads ''' self.obj.PARTS = self.PARTS try: x = self.obj.getPartDownload(self.getInfo(), self, wMutex, bit) if x == 0: self.flag = self.flag | 0x0040 return except: self.flag = self.flag | 0x0040 return self.obj.resize(700, 225) self.free = 0 if x == 2: self.flag = self.flag | 0x0008 return self.flag = self.flag | 0x0100 def start_Download(self, url, wMutex, bit=0): ''' If a fresh download is started it starts from here ''' self.obj.PARTS = self.PARTS self.url = url self.dt = time.strftime("%a %d %b %Y", time.localtime()) self.tm = time.strftime("%H:%M:%S", time.localtime()) try: self.fileName, self.length = self.obj.getDownload( str(url), self, wMutex, bit) except urllib2.URLError as e: self.flag = self.flag | 0x0040 except Exception: self.flag = self.flag | 0x0040 return self.obj.resize(700, 225) self.free = 0 self.flag = self.flag | 0x0008
class MainWindow(QMainWindow): def __init__(self): super().__init__() #MainWindow初始化 self.newWindows = [] self.setWindowTitle("股票回测") self.setGeometry(400, 100, 1150, 850) self.setMinimumSize(1150, 850) #设置MainWindow的CentralWidget的UI self.ui = Ui_MainCentralWidget() central = QWidget() self.ui.setupUi(central) self.setCentralWidget(central) #菜单栏设置 menubar = QMenuBar() self.setMenuBar(menubar) # 各菜单功能设置 menu1 = menubar.addMenu("文件(&F)") self.close_action = menu1.addAction("退出(&Q)") menu2 = menubar.addMenu("下载(&D)") self.download_action = menu2.addAction("数据下载(&D)") self.download_action.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_D)) self.update_action = menu2.addAction("数据更新(&U)") self.update_action.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_U)) menu3 = QMenu('帮助(&H)') menubar.addMenu(menu3) self.instruction_action = QAction('使用说明(&H)') self.instruction_action.setShortcut( QKeySequence(Qt.CTRL + Qt.Key_Question)) menu3.addAction(self.instruction_action) menu3.addSeparator() self.strategydescription_action = menu3.addAction("策略说明") #回测线程 self.backtraderThread = backtraderThread() self.backtraderThread.backtrader_end.connect(self.showResult) self.backtraderThread.showError.connect(self.showError) #更新数据线程 self.updateCsvThread = updateCsvThread() self.updateCsvThread.update_end.connect(self.updateEnd) #连接Signal与Slot self.ui.button.clicked.connect(self.handleCalc) self.instruction_action.triggered.connect(self.openInstructionWindow) self.download_action.triggered.connect(self.openDownloadWindow) self.update_action.triggered.connect(self.updateCsv) self.close_action.triggered.connect(self.close) self.strategydescription_action.triggered.connect( self.openStrategyDescriptionWindow) #Tab设置 QWidget.setTabOrder(self.ui.dataline, self.ui.strategyline) QWidget.setTabOrder(self.ui.strategyline, self.ui.cashline) QWidget.setTabOrder(self.ui.cashline, self.ui.commline) def handleCalc(self): #策略名 strategyname = self.ui.strategyline.text() #初始资金 cash = self.ui.cashline.text() if cash: cash = float(cash) else: cash = 100 #手续费 commission = self.ui.commline.text() if commission: commission = float(commission) else: commission = 0.003 # 数据csv文件 fromdate = self.ui.datebegin.ui.line.text() todate = self.ui.dateend.ui.line.text() code = self.ui.dataline.text()[0:6] datapath = './MyStrategy/datas/' + code + '.csv' # 判断是否存在该股票数据 if os.path.exists(datapath): # 回测线程参数设置 self.backtraderThread.setup(code, fromdate, todate, strategyname, cash, commission) # 回测过程中禁止再次回测 if not self.backtraderThread.isRunning(): # 状态栏显示 self.statusBar().showMessage('正在回测...') self.statusBar().show() # 线程开始 self.backtraderThread.start() else: QMessageBox.critical(self, '错误', '本地不存在此股票数据!') # 展示回测结果 def showResult(self, params, strategyresult, cerebro, Strategyname, code): # 关闭状态栏 self.statusBar().close() # 回测时,策略使用多组参数 if strategyresult.__len__() > 1: self.openResultWindow(params, strategyresult, cerebro, Strategyname, code) # 回测时,策略使用一组参数 elif strategyresult.__len__() == 1: # 回测过后的,策略实体 strategy = strategyresult[0][1] # 生成回测结果图 fig = cerebro.plotone(strategy, style='bar') fig[0].suptitle(Strategyname + code) # 回测日志 log = strategy.buysellLog \ + "总收益率:%.2f%%\n"%(strategy.analyzers.returns.get_analysis()['rtot']*100)\ + "日平均收益率:%.4f%%\n"%(strategy.analyzers.returns.get_analysis()['ravg']*100)\ + "年平均收益率:%.2f%%"%(strategy.analyzers.returns.get_analysis()['rnorm']*100) # 结果详情窗口实例化 detailsWindow = DetailsWindow(fig[0], log) self.newWindows.append(detailsWindow) self.newWindows[-1].show() # 回测线程的异常处理函数 def showError(self, Error): self.statusBar().close() if Error == "KeyError": QMessageBox.critical(self, '错误', '本地不存在此策略!') elif Error == "ValueError": QMessageBox.critical(self, '错误', '输入正确的日期格式!') elif Error == "IndexError": QMessageBox.critical(self, '错误', '回测日期过短!') # 打开使用多组参数回测的结果窗口 def openResultWindow(self, params, strategyresult, cerebro, Strategyname, code): resultWindow = ResultWindow() resultWindow.setFigure(params, strategyresult, cerebro, Strategyname, code) self.newWindows.append(resultWindow) self.newWindows[-1].show() # 打开说明窗口 def openInstructionWindow(self): self.instructuonWindow = InstructionWindow() self.instructuonWindow.show() # 打开下载窗口 def openDownloadWindow(self): self.downloadWindow = DownloadWindow() self.downloadWindow.show() self.downloadWindow.ui.pushButton.clicked.connect(self.download) # 打开策略说明窗口 def openStrategyDescriptionWindow(self): strategyList = list(BackTesting._STRATS.keys()) self.strategyDescriptionWindow = StrategyDescriptionWindow( strategyList) self.strategyDescriptionWindow.show() # 更新已有股票数据 def updateCsv(self): self.statusBar().showMessage('正在更新...') self.statusBar().show() if not self.updateCsvThread.isRunning(): self.updateCsvThread.start() # 股票数据更新结束,调用 def updateEnd(self): QMessageBox.information(self, '数据更新', '更新成功!') self.statusBar().close() self.updateCsvThread.terminate() # 下载股票数据 def download(self): code = self.downloadWindow.ui.inputLine.text() filename = './MyStrategy/datas/' + code + '.csv' if os.path.exists(filename): QMessageBox.information(self.downloadWindow, '股票已存在', '该股票代码已存在,无需下载!') else: result = FormatCsv.downloadcsv(code) if not result: QMessageBox.critical(self.downloadWindow, '错误', '该股票代码输入错误或不存在!') else: QMessageBox.information(self.downloadWindow, '下载成功', '下载成功!') # 刷新主窗口中的股票代码列表 dataList = [] with open('./MyStrategy/datas/codelist.csv', "r", encoding="gbk") as f: text = f.readlines() for data in text: code = data.rstrip() dataList.append(code) self.ui.datamodel.setStringList(dataList)
def openDownloadWindow(self): self.downloadWindow = DownloadWindow() self.downloadWindow.show() self.downloadWindow.ui.pushButton.clicked.connect(self.download)