Skip to content

Commit 32e6c7f

Browse files
committed
Rework on Strategy UI + fix minor bugs
1 parent e3d1d3d commit 32e6c7f

10 files changed

+1043
-298
lines changed

SkinokBacktraderUI.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ def importData(self, fileNames):
169169
self.interface.drawChart(df, timeframe)
170170

171171
# Enable run button
172-
self.interface.strategyTesterUI.runBacktestPB.setEnabled(True)
172+
self.interface.strategyTesterUI.runBacktestBtn.setEnabled(True)
173173

174174
return True
175175

finplotWindow.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def __init__(self, dockArea, dockChart, interface):
4343

4444
self.last_ax_data_xtick = []
4545

46-
46+
4747
pass
4848

4949
#########
@@ -68,6 +68,7 @@ def createPlotWidgets(self, timeframe):
6868
# Ax Profit & Loss
6969
self.interface.strategyResultsUI.ResultsTabWidget.widget(1).layout().addWidget(self.axPnL.ax_widget)
7070

71+
fplt.add_crosshair_info(self.update_crosshair_text, ax=self.ax0)
7172
pass
7273

7374
def drawCandles(self):
@@ -76,7 +77,7 @@ def drawCandles(self):
7677

7778
#self.hover_label = fplt.add_legend('', ax=self.ax0)
7879
#fplt.set_time_inspector(self.update_legend_text, ax=self.ax0, when='hover', data=data)
79-
fplt.add_crosshair_info(self.update_crosshair_text, ax=self.ax0)
80+
8081

8182
# Inside plot widget controls
8283
#self.createControlPanel(self.ax0.ax_widget)
@@ -238,9 +239,9 @@ def update_legend_text(self, x, y, ax, data):
238239
pass
239240

240241
def update_crosshair_text(self,x, y, xtext, ytext):
241-
ytext = '%s \n open: %.4f\n close: %.4f\n high: %.4f\n low: %.4f' \
242-
% (ytext, self.data.iloc[x].Open, self.data.iloc[x].Close, self.data.iloc[x].High, self.data.iloc[x].Low)
243-
return xtext, ytext
242+
ytext = '%s \n Open: %.5f\n Close: %.5f\n High: %.5f\n Low: %.5f' \
243+
% (ytext, self.data.iloc[x].Open, self.data.iloc[x].Close, self.data.iloc[x].High, self.data.iloc[x].Low)
244+
return xtext,ytext
244245

245246
def activateDarkMode(self, activated):
246247

strategyResultsUI.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,18 @@
44

55
class StrategyResultsUI(QtWidgets.QWidget):
66

7-
def __init__(self, controller):
7+
def __init__(self, controller, parent = None):
88
super(StrategyResultsUI, self).__init__()
99

1010
self.controller = controller
1111

12+
self.parent = parent
13+
1214
# It does not finish by a "/"
1315
self.current_dir_path = os.path.dirname(os.path.realpath(__file__))
1416

1517
uic.loadUi( self.current_dir_path + "/ui/strategyResults.ui", self)
1618

17-
self.SummaryGB = self.findChild(QtWidgets.QGroupBox, "SummaryGB")
19+
self.summaryTableWidget= self.findChild(QtWidgets.QTableWidget, "summaryTableWidget")
1820
self.TradesGB = self.findChild(QtWidgets.QGroupBox, "TradesGB")
1921

strategyTesterUI.py

Lines changed: 117 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,58 @@
11
from PyQt6 import QtCore, QtWidgets, uic
22

33
import os
4+
import loadDataFilesUI
45

56
class StrategyTesterUI(QtWidgets.QWidget):
67

7-
def __init__(self, controller):
8+
def __init__(self, controller, parentWindow):
89
super(StrategyTesterUI, self).__init__()
910

1011
self.controller = controller
1112

13+
self.parent = parentWindow
14+
1215
# It does not finish by a "/"
1316
self.current_dir_path = os.path.dirname(os.path.realpath(__file__))
1417

1518
uic.loadUi( self.current_dir_path + "/ui/strategyTester.ui", self)
19+
20+
# Data
21+
self.importDataBtn = self.findChild(QtWidgets.QPushButton, "importDataBtn")
22+
self.importDataBtn.clicked.connect( self.loadData )
23+
24+
# Strategy type PushButtons
25+
self.strategyTypeAITensorFlowBtn = self.findChild(QtWidgets.QPushButton, "strategyTypeAITensorFlowBtn")
26+
self.strategyTypeAiStablebaselinesBtn = self.findChild(QtWidgets.QPushButton, "strategyTypeAiStablebaselinesBtn")
27+
self.strategyTypeAlgoBtn = self.findChild(QtWidgets.QPushButton, "strategyTypeAlgoBtn")
28+
self.strategyTypeAiTorchBtn = self.findChild(QtWidgets.QPushButton, "strategyTypeAiTorchBtn")
1629

17-
self.runBacktestPB = self.findChild(QtWidgets.QPushButton, "runBacktestPB")
18-
self.runBacktestPB.clicked.connect(self.run)
30+
self.strategyTypeDetailsSW = self.findChild(QtWidgets.QStackedWidget, "strategyTypeDetailsSW")
1931

20-
self.runningStratPB = self.findChild(QtWidgets.QProgressBar, "runningStratPB")
32+
# Ai Algo
33+
self.AiModelPathLE = self.findChild(QtWidgets.QLineEdit, "AiModelPathLE")
34+
self.AiModelPathBtn = self.findChild(QtWidgets.QPushButton, "AiModelPathBtn")
2135

36+
# Custom Algo
37+
self.runningStratBtn = self.findChild(QtWidgets.QProgressBar, "runningStratBtn")
2238
self.strategyNameCB = self.findChild(QtWidgets.QComboBox, "strategyNameCB")
39+
40+
# Run button
41+
self.runBacktestBtn = self.findChild(QtWidgets.QPushButton, "runBacktestBtn")
42+
43+
# Connect ui buttons
44+
self.strategyTypeAITensorFlowBtn.clicked.connect(self.strategyTypeAITensorFlowActivated)
45+
self.strategyTypeAiStablebaselinesBtn.clicked.connect(self.strategyTypeAiStablebaselinesActivated)
46+
self.strategyTypeAiTorchBtn.clicked.connect(self.strategyTypeAiTorchActivated)
47+
self.strategyTypeAlgoBtn.clicked.connect(self.strategyTypeAlgoActivated)
48+
49+
self.AiModelPathBtn.clicked.connect(self.openAiFileDialog)
50+
2351
self.strategyNameCB.currentIndexChanged.connect(self.strategyNameActivated)
52+
self.runBacktestBtn.clicked.connect(self.run)
2453

25-
self.runBacktestPB.setEnabled(False)
54+
# Init Run button to false waiting for user inputs
55+
self.runBacktestBtn.setEnabled(False)
2656

2757
def initialize(self):
2858

@@ -33,16 +63,96 @@ def initialize(self):
3363
self.strategyBaseName = []
3464
for stratName in self.strategyNames:
3565
# here remove file extension
36-
self.strategyBaseName.append(QtCore.QFileInfo(stratName).baseName())
66+
if not stratName.startswith('Ai'):
67+
self.strategyBaseName.append(QtCore.QFileInfo(stratName).baseName())
3768

3869
self.strategyNameCB.addItems(self.strategyBaseName)
3970
self.strategyNameCB.setCurrentIndex(self.strategyNameCB.count()-1)
71+
72+
#
73+
self.loadDataFileUI = loadDataFilesUI.LoadDataFilesUI(self.controller, self.parent)
74+
self.loadDataFileUI.hide()
75+
pass
76+
77+
def loadData(self):
78+
self.loadDataFileUI.show()
4079
pass
4180

4281
def run(self):
4382
self.controller.run()
83+
pass
4484

4585
def strategyNameActivated(self):
4686
stratBaseName = self.strategyNameCB.currentText()
4787
self.controller.addStrategy(stratBaseName)
48-
88+
pass
89+
90+
def strategyTypeAITensorFlowActivated(self):
91+
if self.strategyTypeAITensorFlowBtn.isChecked():
92+
self.strategyTypeDetailsSW.setCurrentIndex(1)
93+
self.AiModelChecked = "AiTensorFlowModel"
94+
pass
95+
96+
def strategyTypeAiStablebaselinesActivated(self):
97+
if self.strategyTypeAiStablebaselinesBtn.isChecked():
98+
self.strategyTypeDetailsSW.setCurrentIndex(1)
99+
self.AiModelChecked = "AiStableBaselinesModel"
100+
pass
101+
102+
def strategyTypeAiTorchActivated(self):
103+
if self.strategyTypeAiTorchBtn.isChecked():
104+
self.strategyTypeDetailsSW.setCurrentIndex(1)
105+
self.AiModelChecked = "AiTorchModel"
106+
pass
107+
108+
def strategyTypeAlgoActivated(self):
109+
if self.strategyTypeAlgoBtn.isChecked():
110+
self.strategyTypeDetailsSW.setCurrentIndex(0)
111+
pass
112+
113+
def openAiFileDialog(self):
114+
115+
if self.AiModelChecked == "AiTensorFlowModel":
116+
self.loadTFModel()
117+
elif self.AiModelChecked == "AiStableBaselinesModel":
118+
self.loadStableBaselinesModel()
119+
elif self.AiModelChecked == "AiTorchModel":
120+
self.loadTorchModel()
121+
122+
pass
123+
124+
# Load an AI Model from Tensor Flow framework
125+
def loadTFModel(self):
126+
127+
ai_model_dir = QtWidgets.QFileDialog.getExistingDirectory(self.parent,"Open Tensorflow Model", self.current_dir_path)
128+
129+
self.controller.addStrategy(self.AiModelChecked)
130+
131+
self.AiModelPathLE.setText(ai_model_dir)
132+
self.controller.strategyParametersSave("model", ai_model_dir)
133+
134+
pass
135+
136+
# Load an AI Model from Stable Baselines framework
137+
def loadStableBaselinesModel(self):
138+
139+
ai_model_zip_file = QtWidgets.QFileDialog.getOpenFileName(self.parent,"Open Torch Model", self.current_dir_path, "*.zip")[0]
140+
141+
self.controller.addStrategy(self.AiModelChecked)
142+
143+
self.AiModelPathLE.setText(ai_model_zip_file)
144+
self.controller.strategyParametersSave("model", ai_model_zip_file)
145+
146+
pass
147+
148+
# Load an AI Model from Py Torch framework
149+
def loadTorchModel(self):
150+
151+
ai_model_zip_file = QtWidgets.QFileDialog.getOpenFileName(self.parent,"Open Torch Model", self.current_dir_path, "*.zip")[0]
152+
153+
self.controller.addStrategy(self.AiModelChecked)
154+
155+
self.AiModelPathLE.setText(ai_model_zip_file)
156+
self.controller.strategyParametersSave("model", ai_model_zip_file)
157+
158+
pass

ui/loadDataFiles_ui.py

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
# Form implementation generated from reading ui file 'c:\perso\trading\anaconda3\backtrader-ichimoku\ui\loadDataFiles.ui'
2+
#
3+
# Created by: PyQt6 UI code generator 6.5.0
4+
#
5+
# WARNING: Any manual changes made to this file will be lost when pyuic6 is
6+
# run again. Do not edit this file unless you know what you are doing.
7+
8+
9+
from PyQt6 import QtCore, QtGui, QtWidgets
10+
11+
12+
class Ui_Form(object):
13+
def setupUi(self, Form):
14+
Form.setObjectName("Form")
15+
Form.resize(488, 458)
16+
self.gridLayout_2 = QtWidgets.QGridLayout(Form)
17+
self.gridLayout_2.setObjectName("gridLayout_2")
18+
self.dataFilesListWidget = QtWidgets.QListWidget(parent=Form)
19+
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Preferred)
20+
sizePolicy.setHorizontalStretch(0)
21+
sizePolicy.setVerticalStretch(0)
22+
sizePolicy.setHeightForWidth(self.dataFilesListWidget.sizePolicy().hasHeightForWidth())
23+
self.dataFilesListWidget.setSizePolicy(sizePolicy)
24+
self.dataFilesListWidget.setObjectName("dataFilesListWidget")
25+
self.gridLayout_2.addWidget(self.dataFilesListWidget, 3, 0, 1, 1)
26+
self.label_4 = QtWidgets.QLabel(parent=Form)
27+
self.label_4.setObjectName("label_4")
28+
self.gridLayout_2.addWidget(self.label_4, 2, 0, 1, 1)
29+
self.importPB = QtWidgets.QPushButton(parent=Form)
30+
self.importPB.setMinimumSize(QtCore.QSize(0, 40))
31+
self.importPB.setObjectName("importPB")
32+
self.gridLayout_2.addWidget(self.importPB, 5, 0, 1, 2)
33+
self.verticalLayout = QtWidgets.QVBoxLayout()
34+
self.verticalLayout.setObjectName("verticalLayout")
35+
self.gridLayout_2.addLayout(self.verticalLayout, 3, 1, 1, 1)
36+
self.groupBox = QtWidgets.QGroupBox(parent=Form)
37+
self.groupBox.setObjectName("groupBox")
38+
self.gridLayout = QtWidgets.QGridLayout(self.groupBox)
39+
self.gridLayout.setObjectName("gridLayout")
40+
self.semicolonRB = QtWidgets.QRadioButton(parent=self.groupBox)
41+
self.semicolonRB.setObjectName("semicolonRB")
42+
self.gridLayout.addWidget(self.semicolonRB, 3, 3, 1, 1)
43+
self.label = QtWidgets.QLabel(parent=self.groupBox)
44+
self.label.setObjectName("label")
45+
self.gridLayout.addWidget(self.label, 0, 0, 1, 1)
46+
self.label_3 = QtWidgets.QLabel(parent=self.groupBox)
47+
self.label_3.setObjectName("label_3")
48+
self.gridLayout.addWidget(self.label_3, 1, 0, 1, 1)
49+
self.label_2 = QtWidgets.QLabel(parent=self.groupBox)
50+
self.label_2.setObjectName("label_2")
51+
self.gridLayout.addWidget(self.label_2, 3, 0, 1, 1)
52+
self.tabRB = QtWidgets.QRadioButton(parent=self.groupBox)
53+
self.tabRB.setChecked(True)
54+
self.tabRB.setObjectName("tabRB")
55+
self.gridLayout.addWidget(self.tabRB, 3, 1, 1, 1)
56+
self.commaRB = QtWidgets.QRadioButton(parent=self.groupBox)
57+
self.commaRB.setObjectName("commaRB")
58+
self.gridLayout.addWidget(self.commaRB, 3, 2, 1, 1)
59+
self.filePathLE = QtWidgets.QLineEdit(parent=self.groupBox)
60+
self.filePathLE.setObjectName("filePathLE")
61+
self.gridLayout.addWidget(self.filePathLE, 0, 1, 1, 3)
62+
self.openFilePB = QtWidgets.QToolButton(parent=self.groupBox)
63+
self.openFilePB.setObjectName("openFilePB")
64+
self.gridLayout.addWidget(self.openFilePB, 0, 4, 1, 1)
65+
self.datetimeFormatLE = QtWidgets.QComboBox(parent=self.groupBox)
66+
self.datetimeFormatLE.setObjectName("datetimeFormatLE")
67+
self.gridLayout.addWidget(self.datetimeFormatLE, 1, 1, 1, 4)
68+
self.loadFilePB = QtWidgets.QPushButton(parent=self.groupBox)
69+
self.loadFilePB.setMinimumSize(QtCore.QSize(0, 40))
70+
self.loadFilePB.setObjectName("loadFilePB")
71+
self.gridLayout.addWidget(self.loadFilePB, 4, 1, 1, 4)
72+
self.errorLabel = QtWidgets.QLabel(parent=self.groupBox)
73+
self.errorLabel.setStyleSheet("color: red")
74+
self.errorLabel.setText("")
75+
self.errorLabel.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
76+
self.errorLabel.setObjectName("errorLabel")
77+
self.gridLayout.addWidget(self.errorLabel, 5, 0, 1, 5)
78+
self.gridLayout_2.addWidget(self.groupBox, 0, 0, 1, 2)
79+
self.label_5 = QtWidgets.QLabel(parent=Form)
80+
self.label_5.setStyleSheet("font-style: italic")
81+
self.label_5.setScaledContents(False)
82+
self.label_5.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
83+
self.label_5.setWordWrap(True)
84+
self.label_5.setObjectName("label_5")
85+
self.gridLayout_2.addWidget(self.label_5, 4, 0, 1, 1)
86+
87+
self.retranslateUi(Form)
88+
QtCore.QMetaObject.connectSlotsByName(Form)
89+
90+
def retranslateUi(self, Form):
91+
_translate = QtCore.QCoreApplication.translate
92+
Form.setWindowTitle(_translate("Form", "Import one or multiple data files"))
93+
self.label_4.setText(_translate("Form", "List of all files to import in cerebro"))
94+
self.importPB.setText(_translate("Form", "Import all data files"))
95+
self.groupBox.setTitle(_translate("Form", "Loading a new data file"))
96+
self.semicolonRB.setText(_translate("Form", "semicolon"))
97+
self.label.setText(_translate("Form", "Import a new data file"))
98+
self.label_3.setText(_translate("Form", "Date time format"))
99+
self.label_2.setText(_translate("Form", "Separator"))
100+
self.tabRB.setText(_translate("Form", "tab"))
101+
self.commaRB.setText(_translate("Form", "comma"))
102+
self.openFilePB.setText(_translate("Form", "..."))
103+
self.loadFilePB.setText(_translate("Form", "Load .CSV file"))
104+
self.label_5.setText(_translate("Form", "Files should be ordered from lower (on top) to higher timeframe (at bottom)."))

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy