Skip to content

Commit 71630a3

Browse files
committed
save code changes
1 parent 543ebb2 commit 71630a3

File tree

9 files changed

+603
-65
lines changed

9 files changed

+603
-65
lines changed

.qt_for_python/uic/loadDataFiles.py

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
class Ui_Form(object):
1515
def setupUi(self, Form):
1616
Form.setObjectName("Form")
17-
Form.resize(390, 458)
17+
Form.resize(488, 458)
1818
self.gridLayout_2 = QtWidgets.QGridLayout(Form)
1919
self.gridLayout_2.setObjectName("gridLayout_2")
2020
self.dataFilesListWidget = QtWidgets.QListWidget(Form)
@@ -29,6 +29,7 @@ def setupUi(self, Form):
2929
self.label_4.setObjectName("label_4")
3030
self.gridLayout_2.addWidget(self.label_4, 2, 0, 1, 1)
3131
self.importPB = QtWidgets.QPushButton(Form)
32+
self.importPB.setMinimumSize(QtCore.QSize(0, 40))
3233
self.importPB.setObjectName("importPB")
3334
self.gridLayout_2.addWidget(self.importPB, 5, 0, 1, 2)
3435
self.verticalLayout = QtWidgets.QVBoxLayout()
@@ -38,40 +39,44 @@ def setupUi(self, Form):
3839
self.groupBox.setObjectName("groupBox")
3940
self.gridLayout = QtWidgets.QGridLayout(self.groupBox)
4041
self.gridLayout.setObjectName("gridLayout")
42+
self.semicolonRB = QtWidgets.QRadioButton(self.groupBox)
43+
self.semicolonRB.setObjectName("semicolonRB")
44+
self.gridLayout.addWidget(self.semicolonRB, 3, 3, 1, 1)
4145
self.label = QtWidgets.QLabel(self.groupBox)
4246
self.label.setObjectName("label")
4347
self.gridLayout.addWidget(self.label, 0, 0, 1, 1)
44-
self.filePathLE = QtWidgets.QLineEdit(self.groupBox)
45-
self.filePathLE.setObjectName("filePathLE")
46-
self.gridLayout.addWidget(self.filePathLE, 0, 1, 1, 2)
47-
self.openFilePB = QtWidgets.QToolButton(self.groupBox)
48-
self.openFilePB.setObjectName("openFilePB")
49-
self.gridLayout.addWidget(self.openFilePB, 0, 3, 1, 1)
5048
self.label_3 = QtWidgets.QLabel(self.groupBox)
5149
self.label_3.setObjectName("label_3")
5250
self.gridLayout.addWidget(self.label_3, 1, 0, 1, 1)
53-
self.datetimeFormatLE = QtWidgets.QLineEdit(self.groupBox)
54-
self.datetimeFormatLE.setObjectName("datetimeFormatLE")
55-
self.gridLayout.addWidget(self.datetimeFormatLE, 1, 1, 1, 2)
5651
self.label_2 = QtWidgets.QLabel(self.groupBox)
5752
self.label_2.setObjectName("label_2")
58-
self.gridLayout.addWidget(self.label_2, 2, 0, 1, 1)
53+
self.gridLayout.addWidget(self.label_2, 3, 0, 1, 1)
5954
self.tabRB = QtWidgets.QRadioButton(self.groupBox)
6055
self.tabRB.setChecked(True)
6156
self.tabRB.setObjectName("tabRB")
62-
self.gridLayout.addWidget(self.tabRB, 2, 1, 1, 1)
57+
self.gridLayout.addWidget(self.tabRB, 3, 1, 1, 1)
6358
self.commaRB = QtWidgets.QRadioButton(self.groupBox)
6459
self.commaRB.setObjectName("commaRB")
65-
self.gridLayout.addWidget(self.commaRB, 2, 2, 1, 1)
60+
self.gridLayout.addWidget(self.commaRB, 3, 2, 1, 1)
61+
self.filePathLE = QtWidgets.QLineEdit(self.groupBox)
62+
self.filePathLE.setObjectName("filePathLE")
63+
self.gridLayout.addWidget(self.filePathLE, 0, 1, 1, 3)
64+
self.openFilePB = QtWidgets.QToolButton(self.groupBox)
65+
self.openFilePB.setObjectName("openFilePB")
66+
self.gridLayout.addWidget(self.openFilePB, 0, 4, 1, 1)
67+
self.datetimeFormatLE = QtWidgets.QLineEdit(self.groupBox)
68+
self.datetimeFormatLE.setObjectName("datetimeFormatLE")
69+
self.gridLayout.addWidget(self.datetimeFormatLE, 1, 1, 1, 4)
70+
self.loadFilePB = QtWidgets.QPushButton(self.groupBox)
71+
self.loadFilePB.setMinimumSize(QtCore.QSize(0, 40))
72+
self.loadFilePB.setObjectName("loadFilePB")
73+
self.gridLayout.addWidget(self.loadFilePB, 4, 1, 1, 4)
6674
self.errorLabel = QtWidgets.QLabel(self.groupBox)
6775
self.errorLabel.setStyleSheet("color: red")
6876
self.errorLabel.setText("")
6977
self.errorLabel.setAlignment(QtCore.Qt.AlignCenter)
7078
self.errorLabel.setObjectName("errorLabel")
71-
self.gridLayout.addWidget(self.errorLabel, 4, 0, 1, 3)
72-
self.loadFilePB = QtWidgets.QPushButton(self.groupBox)
73-
self.loadFilePB.setObjectName("loadFilePB")
74-
self.gridLayout.addWidget(self.loadFilePB, 3, 1, 1, 2)
79+
self.gridLayout.addWidget(self.errorLabel, 5, 0, 1, 5)
7580
self.gridLayout_2.addWidget(self.groupBox, 0, 0, 1, 2)
7681
self.label_5 = QtWidgets.QLabel(Form)
7782
self.label_5.setStyleSheet("font-style: italic")
@@ -90,11 +95,12 @@ def retranslateUi(self, Form):
9095
self.label_4.setText(_translate("Form", "List of all files to import in cerebro"))
9196
self.importPB.setText(_translate("Form", "Import all data files"))
9297
self.groupBox.setTitle(_translate("Form", "Loading a new data file"))
98+
self.semicolonRB.setText(_translate("Form", "semicolon"))
9399
self.label.setText(_translate("Form", "Import a new data file"))
94-
self.openFilePB.setText(_translate("Form", "..."))
95100
self.label_3.setText(_translate("Form", "Date time format"))
96101
self.label_2.setText(_translate("Form", "Separator"))
97102
self.tabRB.setText(_translate("Form", "tab"))
98103
self.commaRB.setText(_translate("Form", "comma"))
104+
self.openFilePB.setText(_translate("Form", "..."))
99105
self.loadFilePB.setText(_translate("Form", "Load .CSV file"))
100106
self.label_5.setText(_translate("Form", "Files should be ordered from lower (on top) to higher timeframe (at bottom)."))

SkinokBacktraderUI.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@ def loadData(self, dataPath, datetimeFormat, separator):
125125
return False, "ValueError error:" + str(err)
126126
except AttributeError as err:
127127
return False, "AttributeError error:" + str(err)
128+
except IndexError as err:
129+
return False, "IndexError error:" + str(err)
128130
except :
129131
return False, "Unexpected error:" + str(sys.exc_info()[0])
130132

@@ -225,7 +227,7 @@ def strategyParametersChanged(self, lineEdit, parameterName, parameterOldValue):
225227
if isinstance(param, int):
226228
self.strategyParameters[parameterName] = int(lineEdit.text())
227229
elif isinstance(param, float):
228-
self.strategyParameters[parameterName] = int(lineEdit.text())
230+
self.strategyParameters[parameterName] = float(lineEdit.text())
229231
else:
230232
self.strategyParameters[parameterName] = lineEdit.text()
231233

@@ -246,8 +248,8 @@ def run(self):
246248
self.interface.resetChart()
247249

248250
# Add strategy here to get modified parameters
249-
test = self.strategyParameters
250-
self.strategyIndex = self.cerebro.addstrategy(self.strategyClass, test)
251+
params = self.strategyParameters
252+
self.strategyIndex = self.cerebro.addstrategy(self.strategyClass, params)
251253

252254
# Wallet Management : reset between each run
253255
self.cerebro.broker.setcash(self.startingcash)

indicators/ichimoku.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@
1414

1515
class Ichimoku():
1616

17+
'''
18+
THIS CLASS TAKE A PANDA DATAFRAME AS INPUT, AND NOT A BACKTRADER DATA FEED (Use bt.Ind.Ichimoku instead)
19+
'''
20+
21+
1722
'''
1823
Developed and published in his book in 1969 by journalist Goichi Hosoda
1924
@@ -37,6 +42,10 @@ class Ichimoku():
3742
3843
'''
3944

45+
46+
'''
47+
THIS METHOD TAKE A PANDA DATAFRAME AS INPUT, AND NOT A BACKTRADER DATA FEED (Use bt.Ind.Ichimoku instead)
48+
'''
4049
def __init__(self, dataFrames, tenkan = 9, kijun = 26, senkou = 52, senkou_lead = 26, chikou = 26):
4150

4251
# Tenkan-sen (Conversion Line): (9-period high + 9-period low)/2))

loadDataFilesUI.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ def __init__(self, controller, parent = None):
2323

2424
self.tabRB = self.findChild(QtWidgets.QRadioButton, "tabRB")
2525
self.commaRB = self.findChild(QtWidgets.QRadioButton, "commaRB")
26+
self.semicolonRB = self.findChild(QtWidgets.QRadioButton, "semicolonRB")
2627

2728
self.openFilePB = self.findChild(QtWidgets.QToolButton, "openFilePB")
2829
self.loadFilePB = self.findChild(QtWidgets.QPushButton, "loadFilePB")
@@ -51,7 +52,7 @@ def openFile(self):
5152
def loadFile(self):
5253

5354
# try loading file by controller
54-
separator = '\t' if self.tabRB.isChecked() else ','
55+
separator = '\t' if self.tabRB.isChecked() else ',' if self.commaRB.isChecked() else ';'
5556
success, errorMessage = self.controller.loadData(self.dataFileName, self.datetimeFormatLE.text(), separator)
5657

5758
if success:

strategies/AiStableBaselinesModel.py

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
###############################################################################
2+
#
3+
# Copyright (C) 2021 - Skinok
4+
#
5+
# This program is free software: you can redistribute it and/or modify
6+
# it under the terms of the GNU General Public License as published by
7+
# the Free Software Foundation, either version 3 of the License, or
8+
# (at your option) any later version.
9+
#
10+
# This program is distributed in the hope that it will be useful,
11+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
# GNU General Public License for more details.
14+
#
15+
# You should have received a copy of the GNU General Public License
16+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
#
18+
###############################################################################
19+
import backtrader as bt
20+
21+
import metaStrategy as mt
22+
23+
from stable_baselines3 import PPO
24+
25+
import numpy as np
26+
from enum import Enum
27+
28+
# action list
29+
class Action(Enum):
30+
HOLD=0
31+
BUY=1
32+
SELL=2
33+
34+
# Create a subclass of Strategy to define the indicators and logic
35+
class AiStableBaselinesModel(mt.MetaStrategy):
36+
37+
params = (
38+
('model', ""), # Model name
39+
('tradeSize', 5000),
40+
('atrperiod', 14), # ATR Period (standard)
41+
('atrdist_SL', 3), # ATR distance for stop price
42+
('atrdist_TP', 5), # ATR distance for take profit price
43+
)
44+
45+
def notify_order(self, order):
46+
if order.status == order.Completed:
47+
#print("Order completed")
48+
pass
49+
50+
if not order.alive():
51+
self.order = None # indicate no order is pending
52+
53+
def __init__(self, *argv):
54+
55+
# used to modify parameters
56+
super().__init__(argv[0])
57+
58+
# Ichi indicator
59+
self.ichimoku = bt.ind.Ichimoku()
60+
61+
# To set the stop price
62+
self.atr = bt.indicators.ATR(self.data, period=self.p.atrperiod)
63+
64+
self.stochastic = bt.ind.stochastic.Stochastic(self.data)
65+
66+
pass
67+
68+
def start(self):
69+
self.order = None # sentinel to avoid operrations on pending order
70+
71+
# Load the model
72+
self.model = PPO.load(self.p.model)
73+
pass
74+
75+
def next(self):
76+
77+
self.obseravation = self.next_observation()
78+
79+
# Prepare data for Model
80+
action, _states = self.model.predict(self.obseravation) # deterministic=True
81+
82+
if not self.position: # not in the market
83+
84+
if action == Action.SELL.value:
85+
self.order = self.sell(size=self.p.tradeSize)
86+
ldist = self.atr[0] * self.p.atrdist_SL
87+
self.lstop = self.data.close[0] + ldist
88+
pdist = self.atr[0] * self.p.atrdist_TP
89+
self.take_profit = self.data.close[0] - pdist
90+
91+
elif action == Action.BUY.value:
92+
self.order = self.buy(size=self.p.tradeSize)
93+
ldist = self.atr[0] * self.p.atrdist_SL
94+
self.lstop = self.data.close[0] - ldist
95+
pdist = self.atr[0] * self.p.atrdist_TP
96+
self.take_profit = self.data.close[0] + pdist
97+
98+
else: # in the market
99+
pclose = self.data.close[0]
100+
pstop = self.lstop # seems to be the bug
101+
102+
if (not ((pstop<pclose<self.take_profit)|(pstop>pclose>self.take_profit))):
103+
self.close() # Close position
104+
105+
pass
106+
107+
# Here you have to transform self object price and indicators into a np.array input for AI Model
108+
# How you do it depend on your AI Model inputs
109+
# Strategy is in the data preparation for AI :D
110+
def next_observation(self):
111+
112+
# https://stackoverflow.com/questions/53979199/tensorflow-keras-returning-multiple-predictions-while-expecting-one
113+
114+
# Ichimoku
115+
inputs = [ self.ichimoku.tenkan[0], self.ichimoku.kijun[0], self.ichimoku.senkou[0], self.ichimoku.senkou_lead[0], self.ichimoku.chikou[0] ]
116+
117+
# Stochastic
118+
inputs = inputs + [self.stochastic.percK[0] / 100.0, self.stochastic.percD[0] / 100.0]
119+
120+
return np.array(inputs)
121+
122+
pass

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