代码拉取完成,页面将自动刷新
同步操作将从 张洋/backtrader 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
###############################################################################
#
# Copyright (C) 2021 - Skinok
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
from PyQt6 import QtWidgets
from PyQt6 import QtGui
from PyQt6 import QtCore
from pyqtgraph.dockarea import DockArea, Dock
import os
import time
import backtrader as bt
# Ui made with Qt Designer
import strategyTesterUI
import strategyResultsUI
import indicatorParametersUI
import strategyManualUI
import strategyChartsUI
import strategyOrderUI
import strategyIndicatorUI
# Import Chart lib
import finplotWindow
import qdarkstyle
import functools
from logger_module import logger
from cerebroConfig import CerebroConfig
import finplot as fplt
import createCerebroUI
import openCerebroUI
class UserInterface:
#########
#
#########
def __init__(self, controller):
self.controller = controller # SkinokBacktraderUI
# It does not finish by a "/"
self.current_dir_path = os.path.dirname(os.path.realpath(__file__))
# Qt
self.app = QtWidgets.QApplication([])
self.win = QtWidgets.QMainWindow()
# All dock area of each time frame
self.dock_charts= {}
self.tab_charts = {}
self.tab_orders = {}
self.timeFramePB = {}
# Resize windows properties
self.win.resize(100, 50)
self.win.setWindowTitle("Skinok Backtrader UI v0.3")
# Set width/height of QSplitter
self.app.setStyleSheet(qdarkstyle.load_stylesheet())
pass
def initialize(self):
# 创建主Docks
self.createMainDocks()
# 创建所有UI
self.createUIs()
# Enable run button
self.strategyTesterUI.runBacktestBtn.setEnabled(False)
self.strategyTesterUI.initialize()
pass
#########
# Create all main window docks
#########
def createMainDocks(self):
self.dockArea = DockArea()
self.win.setCentralWidget(self.dockArea)
self.dock_stackedCharts = Dock("Strategy Charts", size = (1500, 600), closable = False, hideTitle=True)
self.dockArea.addDock(self.dock_stackedCharts, position='above')
self.dock_strategyIndicator = Dock("Strategy Indicator", size = (1500, 200), closable = False, hideTitle=True)
self.dockArea.addDock(self.dock_strategyIndicator, position='bottom')
self.dock_strategyResultsUI = Dock("Strategy Tester", size = (1500, 200), closable = False, hideTitle=True)
self.dockArea.addDock(self.dock_strategyResultsUI, position='bottom')
self.dock_strategyManual = Dock("Strategy Manual",size = (300, 1000), closable = False, hideTitle=True)
self.dockArea.addDock(self.dock_strategyManual, position='right')
self.dock_strategyManual.hide()
# Create Strategy Tester Tab
self.dock_strategyTester = Dock("Strategy Tester",size = (300, 1000), closable = False, hideTitle=True)
self.dockArea.addDock(self.dock_strategyTester, position='left')
self.dock_strategyTester.hide()
pass
#########
# Create all dock contents
#########
def createUIs(self):
#创建一些按钮在菜单栏下方
#self.createControlPanel()
#创建整个主界面的四个dock UI,左侧工具、蜡烛图、指标、交易窗
self.createStrategyTesterUI()
#创建 测试结果表
self.createTradesUI()
self.createSummaryUI()
#创建菜单栏和菜单项
self.createMenuBar()
self.createActions()
pass
#########
# UI : main window menu bar
#########
def createMenuBar(self):
#self.menubar = self.win.menuBar()
#self.indicatorsMenu = self.menubar.addMenu("Indicators")
#self.indicatorsMenu.addActions(self.indicatorsActionGroup.actions())
#self.backtestDataMenu = self.menubar.addMenu("Backtest Data")
#self.backtestDataMenu.addActions(self.backtestDataActionGroup.actions())
#self.aiMenu = self.menubar.addMenu("Artificial Intelligence")
#self.aiMenu.addActions(self.aiActionGroup.actions())
#self.optionsMenu = self.menubar.addMenu("Options")
#self.optionsMenu.addActions(self.optionsActionGroup.actions())
self.menubar = QtWidgets.QMenuBar(self.win)
self.win.setMenuBar(self.menubar)
pass
#########
# Quick menu actions
#########
def createActions(self):
# Data sources
#self.backtestDataActionGroup = QtGui.QActionGroup(self.win)
#self.openCSVAction = QtGui.QAction(QtGui.QIcon(""),"Open CSV File", self.backtestDataActionGroup)
# AI
#self.aiActionGroup = QtGui.QActionGroup(self.win)
#self.loadTFModelAction = QtGui.QAction(QtGui.QIcon(""),"Load Tensorflow Model", self.aiActionGroup)
#self.loadTFModelAction.triggered.connect( self.loadTFModel )
#self.loadTorchModelAction = QtWidgets.QAction(QtGui.QIcon(""),"Load Torch Model", self.aiActionGroup)
#self.loadTorchModelAction.triggered.connect( self.loadTorchModel )
#self.loadStableBaselines3Action = QtGui.QAction(QtGui.QIcon(""),"Load Stable Baselines 3 Model", self.aiActionGroup)
#self.loadStableBaselines3Action.triggered.connect( self.loadStableBaselinesModel )
# Options
#self.optionsActionGroup = QtGui.QActionGroup(self.win)
# 创建一个菜单
self.file_menu = self.menubar.addMenu(' 文件 ')
self.new_action = QtGui.QAction('新建一个回测', self.file_menu)
self.open_action = QtGui.QAction('打开已有回测', self.file_menu)
self.del_action = QtGui.QAction('删除一个回测', self.file_menu)
self.file_menu.addAction(self.new_action)
self.file_menu.addAction(self.open_action)
self.file_menu.addAction(self.del_action)
self.new_action.triggered.connect(self.showCreateCerebroUI)
self.open_action.triggered.connect(self.showOpenCerebro)
self.del_action.triggered.connect(self.showRemoveCerebro)
self.help_menu = self.menubar.addMenu(' 帮助 ')
#创建回测界面
self.createCerebroUI = createCerebroUI.CreateCerebroUI(self.controller, self.win)
self.createCerebroUI.hide()
self.openCerebroUI = openCerebroUI.OpenCerebroUI(self.controller, self.win)
self.openCerebroUI.hide()
pass
def showCreateCerebroUI(self):
self.createCerebroUI.show()
pass
def showOpenCerebro(self):
self.openCerebroUI.listCerebro()
self.openCerebroUI.show()
pass
def showRemoveCerebro(self):
logger.info("")
pass
#########
# UI parameters for testing stategies
#########
def createStrategyTesterUI(self):
self.strategyTesterUI = strategyTesterUI.StrategyTesterUI(self.controller, self.win)
self.dock_strategyTester.addWidget(self.strategyTesterUI)
self.strategyChartsUI = strategyChartsUI.StrategyChatrsUI(self.controller, self.win)
self.dock_stackedCharts.addWidget(self.strategyChartsUI, 0, 0)
self.ochlLay = self.strategyChartsUI.verticalLayout_1
self.button_group1 = QtWidgets.QButtonGroup(self.strategyChartsUI)
self.button_group1.addButton(self.strategyChartsUI.radioButton15T, id=0)
self.button_group1.addButton(self.strategyChartsUI.radioButton1H, id=1)
self.button_group1.addButton(self.strategyChartsUI.radioButton2H, id=2)
self.button_group1.addButton(self.strategyChartsUI.radioButton4H, id=3)
self.button_group1.addButton(self.strategyChartsUI.radioButton1D, id=4)
self.button_group1.buttonClicked.connect(self.on_timeframe_radio_button_clicked)
self.strategyChartsUI.checkBoxMA.stateChanged.connect(self.on_ma_checkbox_clicked)
self.strategyChartsUI.checkBoxBOLL.stateChanged.connect(self.on_boll_checkbox_clicked)
self.strategyChartsUI.checkBoxRSI.stateChanged.connect(self.on_rsi_checkbox_clicked)
self.strategyChartsUI.checkBoxKDJ.stateChanged.connect(self.on_kdj_checkbox_clicked)
self.strategyChartsUI.checkBoxMACD.stateChanged.connect(self.on_macd_checkbox_clicked)
self.strategyChartsUI.checkBoxKDJ.hide()
self.strategyIndicatorUI = strategyIndicatorUI.StrategyIndicatorUI(self.controller, self.win)
self.dock_strategyIndicator.addWidget(self.strategyIndicatorUI)
self.indicatorLay1 = self.strategyIndicatorUI.verticalLayout_1
self.strategyManualUI = strategyManualUI.StrategyManualUI(self.controller, self.win)
self.dock_strategyManual.addWidget(self.strategyManualUI)
self.strategyResultsUI = strategyResultsUI.StrategyResultsUI(self.controller, self.win)
self.dock_strategyResultsUI.addWidget(self.strategyResultsUI)
self.strategyTesterUI.startingCashLE.setText(str(self.controller.cerebro.broker.cash))
validator = QtGui.QDoubleValidator(-9999999, 9999999, 6, self.strategyTesterUI.startingCashLE)
validator.setLocale(QtCore.QLocale("en"))
self.strategyTesterUI.startingCashLE.setValidator( validator )
self.strategyTesterUI.startingCashLE.textChanged.connect( self.controller.cashChanged )
pass
def on_timeframe_radio_button_clicked(self, button):
button_id = self.button_group1.id(button)
if self.controller.timeFrame != self.controller.sysTimeFrames[button_id]:
self.controller.timeFrame = self.controller.sysTimeFrames[button_id]
self.controller.df = self.controller.dataFile.dataFrame.head(self.controller.dataFile.index)
if button_id != 0:
self.controller.df = self.controller.df.resample(self.controller.timeFrame).agg({'Open': 'first', 'High': 'max', 'Low': 'min', 'Close': 'last', 'Volume': 'sum'})
self.controller.df = self.controller.df[self.controller.df['Volume'] != 0]
data = self.controller.dataFile.dataFrame.resample(self.controller.timeFrame).agg({'Open': 'first', 'High': 'max', 'Low': 'min', 'Close': 'last', 'Volume': 'sum'})
data = data[data['Volume'] != 0]
else:
data = self.controller.dataFile.dataFrame
self.controller.indIndex = len(self.controller.df)
self.fpltWindow.resetAXS()
self.fpltWindow.setChartData(self.controller.df)
self.fpltWindow.drawCandles()
self.updateIndicatorData(data)
self.updateIndicatorIndex(self.controller.indIndex)
if self.strategyChartsUI.checkBoxMA.isChecked():
self.fpltWindow.drawEma(isUpdate=False)
if self.strategyChartsUI.checkBoxBOLL.isChecked():
self.fpltWindow.drawBoll(isUpdate=False)
if self.strategyChartsUI.checkBoxRSI.isChecked():
self.fpltWindow.drawRsi(isUpdate=False)
if self.strategyChartsUI.checkBoxKDJ.isChecked():
self.fpltWindow.drawKdj(isUpdate=False)
if self.strategyChartsUI.checkBoxMACD.isChecked():
self.fpltWindow.drawMacd(isUpdate=False)
self.setOrders(self.controller.myOrders)
fplt.refresh()
def on_ma_checkbox_clicked(self, state):
if state == QtCore.Qt.CheckState.Checked.value:
self.controller.userConfig.saveParameter("MA", True)
self.fpltWindow.drawEma()
self.fpltWindow.showEma()
pass
elif state == QtCore.Qt.CheckState.Unchecked.value:
self.controller.userConfig.saveParameter("MA", False)
self.fpltWindow.hideEma()
pass
def on_boll_checkbox_clicked(self, state):
if state == QtCore.Qt.CheckState.Checked.value:
self.controller.userConfig.saveParameter("BOLL", True)
self.fpltWindow.drawBoll()
self.fpltWindow.showBoll()
pass
elif state == QtCore.Qt.CheckState.Unchecked.value:
self.controller.userConfig.saveParameter("BOLL", False)
self.fpltWindow.hideBoll()
pass
def on_rsi_checkbox_clicked(self, state):
if state == QtCore.Qt.CheckState.Checked.value:
self.controller.userConfig.saveParameter("RSI", True)
self.fpltWindow.drawRsi()
self.fpltWindow.showRsi()
pass
elif state == QtCore.Qt.CheckState.Unchecked.value:
self.controller.userConfig.saveParameter("RSI", False)
self.fpltWindow.hideRsi()
pass
def on_kdj_checkbox_clicked(self, state):
if state == QtCore.Qt.CheckState.Checked.value:
self.controller.userConfig.saveParameter("KDJ", True)
self.fpltWindow.drawKdj()
self.fpltWindow.showKdj()
pass
elif state == QtCore.Qt.CheckState.Unchecked.value:
self.controller.userConfig.saveParameter("KDJ", False)
self.fpltWindow.hideKdj()
pass
def on_macd_checkbox_clicked(self, state):
if state == QtCore.Qt.CheckState.Checked.value:
self.controller.userConfig.saveParameter("MACD", True)
self.fpltWindow.drawMacd()
self.fpltWindow.showMacd()
pass
elif state == QtCore.Qt.CheckState.Unchecked.value:
self.controller.userConfig.saveParameter("MACD", False)
self.fpltWindow.hideMacd()
pass
def updateCsvData(self, data):
self.fpltWindow.setChartData(data)
def updateIndicatorData(self, data):
self.fpltWindow.updateIndicatorData(data)
def updateIndicatorIndex(self, index):
self.fpltWindow.updateIndicatorIndex(index)
def updateCsvUI(self):
self.fpltWindow.updateCandles()
if self.strategyChartsUI.checkBoxMA.isChecked():
self.fpltWindow.drawEma()
if self.strategyChartsUI.checkBoxBOLL.isChecked():
self.fpltWindow.drawBoll()
if self.strategyChartsUI.checkBoxRSI.isChecked():
self.fpltWindow.drawRsi()
if self.strategyChartsUI.checkBoxKDJ.isChecked():
self.fpltWindow.drawKdj()
if self.strategyChartsUI.checkBoxMACD.isChecked():
self.fpltWindow.drawMacd()
self.strategyManualUI.runningStratPB.setValue(self.controller.dataFile.index)
row = self.controller.df.loc[self.controller.df.index[-1]]
close = row['Close']
open = row['Open']
rise = (close - open)/open * 100
rise = "%.2f" % rise
srt_text = f'{close}\n{rise}%'
if open > close:
self.strategyManualUI.label_4.setStyleSheet('color: green')
else:
self.strategyManualUI.label_4.setStyleSheet('color: red')
self.strategyManualUI.label_4.setText(srt_text)
fplt.refresh()
#########
# Strategy results : trades tab
#########
def createTradesUI(self):
self.tradeTableWidget = QtWidgets.QTableWidget(self.strategyResultsUI.TradesGB)
self.tradeTableWidget.setColumnCount(7)
labels = [ "Trade id","Direction", "Date Open", "Date Close", "Price", "Commission", "Profit Net" ]
self.tradeTableWidget.setHorizontalHeaderLabels( labels )
self.tradeTableWidget.verticalHeader().setVisible(False)
self.tradeTableWidget.horizontalHeader().setStretchLastSection(True)
self.tradeTableWidget.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.ResizeMode.Stretch)
#self.tradeTableWidget.setStyleSheet("alternate-background-color: #AAAAAA;background-color: #CCCCCC;")
self.tradeTableWidget.setAlternatingRowColors(True)
self.tradeTableWidget.setSortingEnabled(True)
self.tradeTableWidget.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectionBehavior.SelectRows)
self.tradeTableWidget.setEditTriggers(QtWidgets.QAbstractItemView.EditTrigger.NoEditTriggers)
self.strategyResultsUI.ResultsTabWidget.widget(0).layout().addWidget(self.tradeTableWidget)
pass
#########
# Create all chart dock for ONE timeframe
#########
def createChartDock(self):
self.fpltWindow = finplotWindow.FinplotWindow(self)
self.fpltWindow.createPlotWidgets()
self.fpltWindow.show()
self.dark_mode_toggle()
pass
def deleteChartDock(self, timeframe):
del self.dockAreaTimeframes[timeframe]
del self.dock_charts[timeframe]
del self.dock_rsi[timeframe]
self.fpltWindow.resetPlots()
del self.fpltWindow
self.controlPanelLayout.removeWidget(self.timeFramePB[timeframe])
del self.timeFramePB[timeframe]
pass
def fillTradesUI(self, trades):
# Delete all previous results by settings row count to 0
self.tradeTableWidget.setRowCount(0)
for key, values in trades:
self.tradeTableWidget.setRowCount(len(values[0]))
row = 0
for trade in values[0]:
if not trade.isopen:
# Trade id
item = QtWidgets.QTableWidgetItem( str(trade.ref) )
item.setTextAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
self.tradeTableWidget.setItem(row,0,item)
item = QtWidgets.QTableWidgetItem( "Buy" if trade.long else "Sell" )
item.setTextAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
self.tradeTableWidget.setItem(row,1,item)
item = QtWidgets.QTableWidgetItem( str(bt.num2date(trade.dtopen)) )
item.setTextAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
self.tradeTableWidget.setItem(row,2,item)
item = QtWidgets.QTableWidgetItem( str(bt.num2date(trade.dtclose)) )
item.setTextAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
self.tradeTableWidget.setItem(row,3,item)
item = QtWidgets.QTableWidgetItem( str(trade.price) )
item.setTextAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
self.tradeTableWidget.setItem(row,4,item)
item = QtWidgets.QTableWidgetItem( str(trade.commission) )
item.setTextAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
self.tradeTableWidget.setItem(row,5,item)
item = QtWidgets.QTableWidgetItem( str(trade.pnlcomm) )
item.setTextAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
self.tradeTableWidget.setItem(row,6,item)
row += 1
# Click on a trade line will move the chart to the corresponding trade
self.tradeTableWidget.cellClicked.connect( self.tradeClicked );
pass
# Slot when a trade has been clicked
def tradeClicked(self, row, column):
selectedItems = self.tradeTableWidget.selectedItems() # QList<QTableWidgetItem *>
if len(selectedItems) > 4:
dateTradeOpen = selectedItems[2].text()
dateTradeClose = selectedItems[3].text()
self.fpltWindow.zoomTo(dateTradeOpen,dateTradeClose)
pass
#########
# Strategy results : Order tab
#########
def createOrdersUI(self):
self.orderTableWidget = QtWidgets.QTableWidget(self.dock_orders)
self.orderTableWidget.setColumnCount(8)
labels = [ "Order ref" , "Direction", "Date Open", "Date Close", "Execution Type", "Size", "Price", "Profit" ]
self.orderTableWidget.setHorizontalHeaderLabels( labels )
self.orderTableWidget.horizontalHeader().setStretchLastSection(True)
self.orderTableWidget.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.ResizeMode.Stretch)
self.orderTableWidget.setStyleSheet("alternate-background-color: #AAAAAA;background-color: #CCCCCC;")
self.orderTableWidget.setAlternatingRowColors(True)
self.orderTableWidget.setSortingEnabled(True)
self.orderTableWidget.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectionBehavior.SelectRows)
self.orderTableWidget.setEditTriggers(QtWidgets.QAbstractItemView.EditTrigger.NoEditTriggers)
self.dock_orders.addWidget(self.orderTableWidget)
pass
def fillOrdersUI(self, orders):
self.orderTableWidget.setRowCount(len(orders))
for i in range(len(orders)):
order = orders[i]
self.orderTableWidget.setItem(i,0,QtWidgets.QTableWidgetItem( str(order.ref ) ))
self.orderTableWidget.setItem(i,1,QtWidgets.QTableWidgetItem( "Buy" if order.isbuy() else "Sell"))
self.orderTableWidget.setItem(i,2,QtWidgets.QTableWidgetItem( str(bt.num2date(order.created.dt)) ))
self.orderTableWidget.setItem(i,3,QtWidgets.QTableWidgetItem( str(bt.num2date(order.executed.dt)) ))
self.orderTableWidget.setItem(i,4,QtWidgets.QTableWidgetItem( str(order.exectype) ))
self.orderTableWidget.setItem(i,5,QtWidgets.QTableWidgetItem( str(order.size ) ))
self.orderTableWidget.setItem(i,6,QtWidgets.QTableWidgetItem( str(order.price ) ))
self.orderTableWidget.setItem(i,7,QtWidgets.QTableWidgetItem( str(order.executed.pnl) ))
pass
#########
# Strategy results : Summary UI
#########
def createSummaryUI(self):
self.summaryTableWidget = self.strategyTesterUI.summaryTableWidget
self.summaryTableWidget.setColumnCount(2)
self.summaryTableWidget.verticalHeader().hide()
self.summaryTableWidget.horizontalHeader().hide()
self.summaryTableWidget.setShowGrid(False)
self.summaryTableWidget.setStyleSheet("QTableWidget { border: 0; }")
pass
def fillSummaryUI(self, brokerCash, brokerValue, tradeAnalysis):
# Delete all previous rows
self.summaryTableWidget.setRowCount(0)
self.summaryTableWidget.setRowCount(8)
self.summaryTableWidget.setItem(0,0,QtWidgets.QTableWidgetItem("Cash"))
item = QtWidgets.QTableWidgetItem(str(round(brokerCash,2)))
item.setTextAlignment(QtCore.Qt.AlignmentFlag.AlignHCenter)
self.summaryTableWidget.setItem(0,1,item)
self.summaryTableWidget.setItem(1,0,QtWidgets.QTableWidgetItem("Value"))
item = QtWidgets.QTableWidgetItem(str(round(brokerValue,2)))
item.setTextAlignment(QtCore.Qt.AlignmentFlag.AlignHCenter)
self.summaryTableWidget.setItem(1,1,item)
# if there are some trades
if len(tradeAnalysis) > 1:
self.summaryTableWidget.setItem(2,0,QtWidgets.QTableWidgetItem("Profit total"))
item = QtWidgets.QTableWidgetItem(str(round(tradeAnalysis["pnl"]["net"]["total"],2)))
item.setTextAlignment(QtCore.Qt.AlignmentFlag.AlignHCenter)
self.summaryTableWidget.setItem(2,1, item )
self.summaryTableWidget.setItem(3,0,QtWidgets.QTableWidgetItem("Number of trades"))
item = QtWidgets.QTableWidgetItem(str(round(tradeAnalysis["total"]["total"],2)))
item.setTextAlignment(QtCore.Qt.AlignmentFlag.AlignHCenter)
self.summaryTableWidget.setItem(3,1,item)
self.summaryTableWidget.setItem(4,0,QtWidgets.QTableWidgetItem("Won"))
item = QtWidgets.QTableWidgetItem(str(round(tradeAnalysis["won"]['total'],2)))
item.setTextAlignment(QtCore.Qt.AlignmentFlag.AlignHCenter)
self.summaryTableWidget.setItem(4,1,item)
self.summaryTableWidget.setItem(5,0,QtWidgets.QTableWidgetItem("Lost"))
item = QtWidgets.QTableWidgetItem(str(round(tradeAnalysis["lost"]['total'],2)))
item.setTextAlignment(QtCore.Qt.AlignmentFlag.AlignHCenter)
self.summaryTableWidget.setItem(5,1,item)
self.summaryTableWidget.setItem(6,0,QtWidgets.QTableWidgetItem("Long"))
item = QtWidgets.QTableWidgetItem(str(round(tradeAnalysis["long"]["total"],2)))
item.setTextAlignment(QtCore.Qt.AlignmentFlag.AlignHCenter)
self.summaryTableWidget.setItem(6,1,item)
self.summaryTableWidget.setItem(7,0,QtWidgets.QTableWidgetItem("Short"))
item = QtWidgets.QTableWidgetItem(str(round(tradeAnalysis["short"]["total"],2)))
item.setTextAlignment(QtCore.Qt.AlignmentFlag.AlignHCenter)
self.summaryTableWidget.setItem(7,1,item)
self.summaryTableWidget.horizontalHeader().setStretchLastSection(True)
self.summaryTableWidget.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.ResizeMode.Stretch)
self.summaryTableWidget.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectionBehavior.SelectRows)
pass
#########
# Show all
#########
def show(self):
#self.fpltWindow[timeframe].show() # prepares plots when they're all setup
self.win.show()
self.app.exec_()
pass
#########
# Get strategy running progress bar
#########
def getProgressBar(self):
return self.strategyTesterUI.runningStratPB
#########
# Draw chart
#########
def initChart(self, data, index=0):
self.fpltWindow.setChartData(data)
self.fpltWindow.initChart(index)
def updateChart(self):
self.fpltWindow.updateCandles()
if self.strategyChartsUI.checkBoxMA.isChecked():
self.fpltWindow.updateEma()
if self.strategyChartsUI.checkBoxBOLL.isChecked():
pass
def setOneOrder(self, order):
self.fpltWindow.drawOneOrder(order)
#########
# Draw orders on chart
#########
def setOrders(self, orders):
self.fpltWindow.drawOrders(orders)
pass
#########
# Draw PnL chart
# A python expert could do waaaaay better optimized on this function
# But anyway... it works...
#########
def displayPnL(self, pnl_dataframe):
# draw charts
self.fpltWindow.drawPnL(pnl_dataframe)
self.togglePnLWidget()
pass
#########
# Control panel overlay on top/above of the finplot window
#########
def createControlPanel(self):
self.controlPanel = QtWidgets.QWidget(self.dock_stackedCharts)
self.dock_stackedCharts.addWidget(self.controlPanel,0,0)
self.controlPanelLayout = QtWidgets.QHBoxLayout(self.controlPanel)
# SMA
self.SmaPB = QtWidgets.QPushButton(self.controlPanel)
self.SmaPB.setText("SMA")
self.SmaPB.setCheckable(True)
self.SmaPB.setMaximumWidth(100)
self.SmaPB.toggled[bool].connect(self.addSma)
self.controlPanelLayout.addWidget(self.SmaPB)
# EMA
self.EmaPB = QtWidgets.QPushButton(self.controlPanel)
self.EmaPB.setText("EMA")
self.EmaPB.setCheckable(True)
self.EmaPB.setMaximumWidth(100)
self.EmaPB.toggled[bool].connect(self.addEma)
self.controlPanelLayout.addWidget(self.EmaPB)
# Spacer
spacer = QtWidgets.QSpacerItem(50,20,QtWidgets.QSizePolicy.Policy.Minimum)
self.controlPanelLayout.addSpacerItem(spacer)
# Spacer
self.controlPanelLayout.insertSpacerItem(0, QtWidgets.QSpacerItem( 0,0, hPolicy=QtWidgets.QSizePolicy.Policy.Expanding, vPolicy=QtWidgets.QSizePolicy.Policy.Preferred) )
return self.controlPanel
#########
# Toggle anther UI Theme
#########
def dark_mode_toggle(self):
self.fpltWindow.activateDarkMode(True)
pass
##########
# INDICATORS
##########
def toogleTimeframe(self, timeframe):
if self.timeFramePB[timeframe].isChecked():
logger.info("Display " + timeframe)
self.current_timeframe = timeframe
index = self.stackedCharts.indexOf( self.dockAreaTimeframes[timeframe])
self.stackedCharts.setCurrentIndex( index )
self.togglePnLWidget()
pass
def togglePnLWidget(self):
self.fpltWindow.showPnL()
def resetChart(self):
self.fpltWindow.resetChart()
self.fpltWindow.updateChart()
pass
# On chart indicators
def addSma(self):
# Show indicator parameter dialog
paramDialog = indicatorParametersUI.IndicatorParametersUI()
paramDialog.setWindowFlags(QtCore.Qt.CustomizeWindowHint)
paramDialog.setTitle("SMA Indicator parameters")
paramDialog.addParameter("SMA Period", 14)
paramDialog.addParameter("Plot width", 1)
paramDialog.addParameterColor("Plot color", "#FFFF00")
paramDialog.adjustSize()
if paramDialog.exec() == QtWidgets.QDialog.DialogCode.Accepted:
period = paramDialog.getValue("SMA Period")
width = paramDialog.getValue("Plot width")
qColor = paramDialog.getColorValue("Plot color")
self.fpltWindow.drawSma( period, qColor, width)
pass
# On chart indicators
def addEma(self):
# Show indicator parameter dialog
paramDialog = indicatorParametersUI.IndicatorParametersUI()
paramDialog.setWindowFlags(QtCore.Qt.CustomizeWindowHint)
paramDialog.setTitle("EMA Indicator parameters")
paramDialog.addParameter("EMA Period", 9)
paramDialog.addParameter("Plot width", 1)
paramDialog.addParameterColor("Plot color", "#FFFF00")
paramDialog.adjustSize()
if paramDialog.exec() == QtWidgets.QDialog.DialogCode.Accepted:
period = paramDialog.getValue("EMA Period")
width = paramDialog.getValue("Plot width")
qColor = paramDialog.getColorValue("Plot color")
self.fpltWindow.drawEma( period, qColor, width )
pass
def toogleOrder(self):
logger.info("in toogleOrder")
pass
# indicators in external windows
def toogleRsi(self):
if self.RsiPB.isChecked():
# Show indicator parameter dialog
paramDialog = indicatorParametersUI.IndicatorParametersUI()
paramDialog.setWindowFlags(QtCore.Qt.WindowType.CustomizeWindowHint)
paramDialog.setTitle("RSI Indicator parameters")
paramDialog.addParameter("RSI Period", 14)
paramDialog.addParameterColor("Plot color", "#FFFF00")
paramDialog.adjustSize()
if paramDialog.exec() == QtWidgets.QDialog.DialogCode.Accepted:
period = paramDialog.getValue("RSI Period")
qColor = paramDialog.getColorValue("Plot color")
self.fpltWindow.drawRsi( period, qColor )
self.dock_rsi[self.current_timeframe].show()
else:
# Cancel
self.RsiPB.setChecked(False)
self.dock_rsi[self.current_timeframe].hide()
else:
self.dock_rsi[self.current_timeframe].hide()
pass
def toogleStochastic(self):
if self.StochasticPB.isChecked():
# Show indicator parameter dialog
paramDialog = indicatorParametersUI.IndicatorParametersUI()
paramDialog.setWindowFlags(QtCore.Qt.WindowType.CustomizeWindowHint)
paramDialog.setTitle("Stochastic Indicator parameters")
paramDialog.addParameter("Stochastic Period K", 14)
paramDialog.addParameter("Stochastic Smooth K", 3)
paramDialog.addParameter("Stochastic Smooth D", 3)
paramDialog.adjustSize()
if paramDialog.exec() == QtWidgets.QDialog.DialogCode.Accepted:
period = paramDialog.getValue("Stochastic Period K")
smooth_k = paramDialog.getValue("Stochastic Smooth K")
smooth_d = paramDialog.getValue("Stochastic Smooth D")
self.fpltWindow.drawStochastic( period, smooth_k, smooth_d )
self.dock_stochastic[self.current_timeframe].show()
else:
# Cancel
self.RsiPB.setChecked(False)
self.dock_stochastic[self.current_timeframe].hide()
else:
self.dock_stochastic[self.current_timeframe].hide()
pass
def toogleStochasticRsi(self):
if self.StochasticRsiPB.isChecked():
# Show indicator parameter dialog
paramDialog = indicatorParametersUI.IndicatorParametersUI()
paramDialog.setWindowFlags(QtCore.Qt.WindowType.CustomizeWindowHint)
paramDialog.setTitle("Stochastic Indicator parameters")
paramDialog.addParameter("Stochastic Rsi Period K", 14)
paramDialog.addParameter("Stochastic Rsi Smooth K", 3)
paramDialog.addParameter("Stochastic Rsi Smooth D", 3)
paramDialog.adjustSize()
if (paramDialog.exec() == QtWidgets.QDialog.DialogCode.Accepted ):
period = paramDialog.getValue("Stochastic Rsi Period K")
smooth_k = paramDialog.getValue("Stochastic Rsi Smooth K")
smooth_d = paramDialog.getValue("Stochastic Rsi Smooth D")
self.fpltWindow.drawStochasticRsi( period, smooth_k, smooth_d)
self.dock_stochasticRsi[self.current_timeframe].show()
else:
# Cancel
self.RsiPB.setChecked(False)
self.dock_stochasticRsi[self.current_timeframe].hide()
else:
self.dock_stochasticRsi[self.current_timeframe].hide()
pass
# On chart indicators
def toogleIchimoku(self):
self.fpltWindow.setIndicator("Ichimoku", self.IchimokuPB.isChecked() )
pass
def volumes_toggle(self):
self.fpltWindow.setIndicator("Volumes", self.volumesCB.isChecked())
pass
#########
# Obsolete (Strategy results : transcations tab)
#########
def createTransactionsUI(self, trades):
self.transactionTableWidget = QtWidgets.QTableWidget(self.dock_trades)
self.transactionTableWidget.setRowCount(len(trades))
self.transactionTableWidget.setColumnCount(4)
labels = [ "Date","Size", "Price", "Value" ]
self.transactionTableWidget.setHorizontalHeaderLabels( labels )
row = 0
for date,values in trades:
#for trade in trades:
self.transactionTableWidget.setItem(row, 0, QtWidgets.QTableWidgetItem(date.strftime("%Y/%m/%d %H:%M:%S")))
self.transactionTableWidget.setItem(row, 1, QtWidgets.QTableWidgetItem(str(values[0][0])))
self.transactionTableWidget.setItem(row, 2, QtWidgets.QTableWidgetItem(str(values[0][1])))
self.transactionTableWidget.setItem(row, 3, QtWidgets.QTableWidgetItem(str(values[0][2])))
row += 1
self.transactionTableWidget.horizontalHeader().setStretchLastSection(True)
self.transactionTableWidget.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.ResizeMode.Stretch)
self.transactionTableWidget.setStyleSheet("alternate-background-color: #AAAAAA;background-color: #CCCCCC;")
self.transactionTableWidget.setAlternatingRowColors(True)
self.transactionTableWidget.setSortingEnabled(True)
self.transactionTableWidget.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectionBehavior.SelectRows)
self.transactionTableWidget.setEditTriggers(QtWidgets.QAbstractItemView.EditTrigger.NoEditTriggers)
self.dock_transactions.addWidget(self.transactionTableWidget)
pass
def fillStrategyParameters(self, strategy):
# Rest widget rows
for indexRow in range(self.strategyTesterUI.parametersLayout.rowCount()):
self.strategyTesterUI.parametersLayout.removeRow(0)
# Insert parameters
row = 0
for parameterName, parameterValue in strategy.params._getitems():
if parameterName is not 'model':
label = QtWidgets.QLabel(parameterName)
if type(parameterValue) == bool:
checkBox = QtWidgets.QCheckBox(str())
checkBox.setObjectName(parameterName)
checkBox.setChecked(parameterValue)
checkBox.stateChanged.connect(functools.partial(self.controller.strategyParametersChanged, checkBox, parameterName, parameterValue))
self.strategyTesterUI.parametersLayout.addRow(label, checkBox )
else:
lineEdit = QtWidgets.QLineEdit(str(parameterValue))
lineEdit.setObjectName(parameterName)
# Connect the parameter changed slot
lineEdit.textChanged.connect(functools.partial(self.controller.strategyParametersChanged, lineEdit, parameterName, parameterValue))
self.strategyTesterUI.parametersLayout.addRow(label, lineEdit )
# Save the parameter to inject it in the addStrategy method
self.controller.strategyParametersSave(parameterName, parameterValue)
row = row + 1
pass
# Parameter box size
self.strategyTesterUI.parametersLayout.update()
self.strategyTesterUI.parametersScrollArea.adjustSize()
pass
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。