Skip to content

Commit 7eb9f8f

Browse files
committed
Loading data : the user config file now load previous data files
1 parent 7faa0bb commit 7eb9f8f

10 files changed

+266
-122
lines changed

Singleton.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
class Singleton:
2+
__instance = None
3+
4+
def __new__(cls,*args, **kwargs):
5+
if cls.__instance is None :
6+
cls.__instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
7+
return cls.__instance

SkinokBacktraderUI.py

Lines changed: 44 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
from CerebroEnhanced import *
2424

2525
import sys, os
26+
27+
from dataManager import DataManager
2628
sys.path.append(os.path.dirname(os.path.realpath(__file__)) + '/observers')
2729
sys.path.append(os.path.dirname(os.path.realpath(__file__)) + '/strategies')
2830
sys.path.append(os.path.dirname(os.path.realpath(__file__)) + '/../finplot')
@@ -34,6 +36,7 @@
3436

3537
from observers.SkinokObserver import SkinokObserver
3638
from wallet import Wallet
39+
from userConfig import UserConfig
3740

3841
class SkinokBacktraderUI:
3942

@@ -64,6 +67,42 @@ def __init__(self):
6467
# Timeframes
6568
self.timeFrameIndex = {"M1" : 0, "M5" : 10, "M15": 20, "M30": 30, "H1":40, "H4":50, "D":60, "W":70}
6669

70+
self.dataManager = DataManager()
71+
72+
# Restore previous session for faster tests
73+
self.loadConfig()
74+
75+
pass
76+
77+
def loadConfig(self):
78+
79+
userConfig = UserConfig()
80+
userConfig.loadConfigFile()
81+
82+
isEmpty = True
83+
84+
# Load previous data files
85+
for timeframe in self.timeFrameIndex.keys():
86+
87+
if timeframe in userConfig.data.keys():
88+
89+
filePath = userConfig.data[timeframe]['filePath']
90+
timeFormat = userConfig.data[timeframe]['timeFormat']
91+
separator = userConfig.data[timeframe]['separator']
92+
93+
fileName = os.path.basename(filePath)
94+
95+
df, errorMessage = self.dataManager.loadDataFile(filePath,timeFormat, separator)
96+
97+
if df is not None:
98+
self.dataframes[fileName] = df
99+
isEmpty = False
100+
else:
101+
print(f" Error loading user data file : {errorMessage}")
102+
103+
if not isEmpty:
104+
self.importData()
105+
67106
pass
68107

69108
def resetCerebro(self):
@@ -97,53 +136,16 @@ def resetCerebro(self):
97136

98137
pass
99138

100-
# Return True if loading is successfull & the error string if False
101-
def loadData(self, dataPath, datetimeFormat, separator):
102139

103-
# Try importing data file
104-
# We should code a widget that ask for options as : separators, date format, and so on...
105-
try:
106-
fileName = os.path.basename(dataPath)
107-
108-
# Python contains
109-
if not dataPath in self.dataframes:
110-
if pd.__version__<'2.0.0':
111-
self.dataframes[fileName] = pd.read_csv(dataPath,
112-
sep=separator,
113-
parse_dates=[0],
114-
date_parser=lambda x: pd.to_datetime(x, format=datetimeFormat),
115-
skiprows=0,
116-
header=0,
117-
names=["Time", "Open", "High", "Low", "Close", "Volume"],
118-
index_col=0)
119-
else:
120-
self.dataframes[fileName] = pd.read_csv(dataPath,
121-
sep=separator,
122-
parse_dates=[0],
123-
date_format=datetimeFormat,
124-
skiprows=0,
125-
header=0,
126-
names=["Time", "Open", "High", "Low", "Close", "Volume"],
127-
index_col=0)
128-
129-
except ValueError as err:
130-
return False, "ValueError error:" + str(err)
131-
except AttributeError as err:
132-
return False, "AttributeError error:" + str(err)
133-
except IndexError as err:
134-
return False, "IndexError error:" + str(err)
135-
except :
136-
return False, "Unexpected error:" + str(sys.exc_info()[0])
137-
138-
return True, ""
139-
140-
def importData(self, fileNames):
140+
def importData(self):
141141

142142
try:
143+
144+
fileNames = list(self.dataframes.keys())
143145

144146
# Sort data by timeframe
145147
# For cerebro, we need to add lower timeframes first
146-
fileNames.sort( key=lambda x: self.timeFrameIndex[self.findTimeFrame(self.dataframes[x])])
148+
fileNames.sort( key=lambda x: self.timeFrameIndex[self.dataManager.findTimeFrame(self.dataframes[x])] )
147149

148150
# Files should be loaded in the good order
149151
for fileName in fileNames:
@@ -160,7 +162,7 @@ def importData(self, fileNames):
160162
self.cerebro.adddata(self.data) # Add the data feed
161163

162164
# Find timeframe
163-
timeframe = self.findTimeFrame(df)
165+
timeframe = self.dataManager.findTimeFrame(df)
164166

165167
# Create the chart window for the good timeframe (if it does not already exists?)
166168
self.interface.createChartDock(timeframe)
@@ -182,29 +184,7 @@ def importData(self, fileNames):
182184
return False
183185
pass
184186

185-
def findTimeFrame(self, df):
186-
187-
if len(df.index) > 2:
188-
dtDiff = df.index[1] - df.index[0]
189-
190-
if dtDiff.total_seconds() == 60:
191-
return "M1"
192-
elif dtDiff.total_seconds() == 300:
193-
return "M5"
194-
elif dtDiff.total_seconds() == 900:
195-
return "M15"
196-
elif dtDiff.total_seconds() == 1800:
197-
return "M30"
198-
elif dtDiff.total_seconds() == 3600:
199-
return "H1"
200-
elif dtDiff.total_seconds() == 14400:
201-
return "H4"
202-
elif dtDiff.total_seconds() == 86400:
203-
return "D"
204-
elif dtDiff.total_seconds() == 604800:
205-
return "W"
206187

207-
pass
208188

209189
def addStrategy(self, strategyName):
210190

connectors/OandaV20Connector.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
2+
3+
# Après avoir importé les librairies nécessaires
4+
class OandaV20Connector(OandaV20Store):
5+
# Le constructeur de la classe
6+
def __init__(self, token, account, practice=True):
7+
# Appelle le constructeur de la classe parente
8+
super().__init__(token=token, account=account, practice=practice)
9+
# Crée un broker à partir du store
10+
self.broker = self.getbroker()
11+
# Crée un data feed à partir du store
12+
self.data = self.getdata(dataname="EUR_USD", timeframe=bt.TimeFrame.Minutes, compression=1)
13+
14+
# Une méthode pour ajouter le data feed au Cerebro
15+
def add_data(self, cerebro):
16+
cerebro.adddata(self.data)
17+
18+
# Une méthode pour ajouter le broker au Cerebro
19+
def add_broker(self, cerebro):
20+
cerebro.setbroker(self.broker)

dataManager.py

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
2+
import os,sys
3+
import Singleton
4+
import pandas as pd
5+
6+
from Singleton import Singleton
7+
8+
class DataManager(Singleton):
9+
10+
def DatetimeFormat(self, dataFilePath):
11+
fileparts = os.path.split(dataFilePath)
12+
datafile = fileparts[1]
13+
# print(datafile[-4:])
14+
if datafile[-4:]=='.csv':
15+
df = pd.read_csv(dataFilePath, nrows=1)
16+
17+
timestring = df.iloc[0,0]
18+
ncolon = timestring.count(':')
19+
if ncolon==2:
20+
return "%Y-%m-%d %H:%M:%S"
21+
elif ncolon==1:
22+
return "%Y-%m-%d %H:%M"
23+
else:
24+
nspace = timestring.count(' ')
25+
if nspace==1:
26+
return "%Y-%m-%d %H"
27+
else:
28+
return "%Y-%m-%d"
29+
30+
return ""
31+
32+
33+
# Return True if loading is successfull & the error string if False
34+
# dataPath is the full file path
35+
def loadDataFile(self, dataPath, datetimeFormat, separator):
36+
37+
# Try importing data file
38+
# We should code a widget that ask for options as : separators, date format, and so on...
39+
try:
40+
41+
# Python contains
42+
if pd.__version__<'2.0.0':
43+
df = pd.read_csv(dataPath,
44+
sep=separator,
45+
parse_dates=[0],
46+
date_parser=lambda x: pd.to_datetime(x, format=datetimeFormat),
47+
skiprows=0,
48+
header=0,
49+
names=["Time", "Open", "High", "Low", "Close", "Volume"],
50+
index_col=0)
51+
else:
52+
df = pd.read_csv(dataPath,
53+
sep=separator,
54+
parse_dates=[0],
55+
date_format=datetimeFormat,
56+
skiprows=0,
57+
header=0,
58+
names=["Time", "Open", "High", "Low", "Close", "Volume"],
59+
index_col=0)
60+
61+
return df, ""
62+
63+
except ValueError as err:
64+
return None, "ValueError error:" + str(err)
65+
except AttributeError as err:
66+
return None, "AttributeError error:" + str(err)
67+
except IndexError as err:
68+
return None, "IndexError error:" + str(err)
69+
except :
70+
return None, "Unexpected error:" + str(sys.exc_info()[0])
71+
72+
73+
def findTimeFrame(self, df):
74+
75+
if len(df.index) > 2:
76+
dtDiff = df.index[1] - df.index[0]
77+
78+
if dtDiff.total_seconds() == 60:
79+
return "M1"
80+
elif dtDiff.total_seconds() == 300:
81+
return "M5"
82+
elif dtDiff.total_seconds() == 900:
83+
return "M15"
84+
elif dtDiff.total_seconds() == 1800:
85+
return "M30"
86+
elif dtDiff.total_seconds() == 3600:
87+
return "H1"
88+
elif dtDiff.total_seconds() == 14400:
89+
return "H4"
90+
elif dtDiff.total_seconds() == 86400:
91+
return "D"
92+
elif dtDiff.total_seconds() == 604800:
93+
return "W"
94+
95+
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