shareddata 2.1.4__tar.gz → 2.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {shareddata-2.1.4 → shareddata-2.2.0}/PKG-INFO +1 -1
- {shareddata-2.1.4 → shareddata-2.2.0}/setup.cfg +1 -1
- shareddata-2.1.4/src/SharedData/SharedDataFrame.py → shareddata-2.2.0/src/SharedData/DataFrame.py +2 -2
- {shareddata-2.1.4 → shareddata-2.2.0}/src/SharedData/Defaults.py +1 -1
- shareddata-2.1.4/src/SharedData/SharedDataFeeder.py → shareddata-2.2.0/src/SharedData/Feeder.py +5 -15
- {shareddata-2.1.4 → shareddata-2.2.0}/src/SharedData/Logger.py +18 -27
- {shareddata-2.1.4 → shareddata-2.2.0}/src/SharedData/LoggerConsumerProcess.py +1 -1
- {shareddata-2.1.4 → shareddata-2.2.0}/src/SharedData/Metadata.py +1 -1
- shareddata-2.1.4/src/SharedData/SharedDataPeriod.py → shareddata-2.2.0/src/SharedData/Period.py +44 -45
- shareddata-2.1.4/src/SharedData/SharedDataRealTime.py → shareddata-2.2.0/src/SharedData/RealTime.py +1 -1
- shareddata-2.1.4/src/SharedData/SharedDataRealTimeProcess.py → shareddata-2.2.0/src/SharedData/RealTimeProcess.py +1 -1
- shareddata-2.2.0/src/SharedData/SharedData.py +197 -0
- shareddata-2.1.4/src/SharedData/SharedDataTable.py → shareddata-2.2.0/src/SharedData/Table.py +62 -59
- shareddata-2.1.4/src/SharedData/SharedDataTableIndex.py → shareddata-2.2.0/src/SharedData/TableIndex.py +23 -23
- shareddata-2.1.4/src/SharedData/SharedDataTimeSeries.py → shareddata-2.2.0/src/SharedData/TimeSeries.py +45 -232
- shareddata-2.2.0/src/SharedData/TimeseriesContainer.py +390 -0
- {shareddata-2.1.4 → shareddata-2.2.0}/src/shareddata.egg-info/PKG-INFO +1 -1
- shareddata-2.2.0/src/shareddata.egg-info/SOURCES.txt +30 -0
- shareddata-2.1.4/src/SharedData/SeriesLib.py +0 -122
- shareddata-2.1.4/src/SharedData/SharedData.py +0 -172
- shareddata-2.1.4/src/shareddata.egg-info/SOURCES.txt +0 -30
- {shareddata-2.1.4 → shareddata-2.2.0}/LICENSE +0 -0
- {shareddata-2.1.4 → shareddata-2.2.0}/README.md +0 -0
- {shareddata-2.1.4 → shareddata-2.2.0}/pyproject.toml +0 -0
- /shareddata-2.1.4/src/SharedData/SharedDataAWSKinesis.py → /shareddata-2.2.0/src/SharedData/AWSKinesis.py +0 -0
- /shareddata-2.1.4/src/SharedData/SharedDataAWSS3.py → /shareddata-2.2.0/src/SharedData/AWSS3.py +0 -0
- {shareddata-2.1.4 → shareddata-2.2.0}/src/SharedData/MultiProc.py +0 -0
- {shareddata-2.1.4 → shareddata-2.2.0}/src/SharedData/SharedNumpy.py +0 -0
- /shareddata-2.1.4/src/SharedData/SharedDataTableIndexJit.py → /shareddata-2.2.0/src/SharedData/TableIndexJit.py +0 -0
- {shareddata-2.1.4 → shareddata-2.2.0}/src/SharedData/Utils.py +0 -0
- {shareddata-2.1.4 → shareddata-2.2.0}/src/SharedData/__init__.py +0 -0
- {shareddata-2.1.4 → shareddata-2.2.0}/src/shareddata.egg-info/dependency_links.txt +0 -0
- {shareddata-2.1.4 → shareddata-2.2.0}/src/shareddata.egg-info/requires.txt +0 -0
- {shareddata-2.1.4 → shareddata-2.2.0}/src/shareddata.egg-info/top_level.txt +0 -0
shareddata-2.1.4/src/SharedData/SharedDataFrame.py → shareddata-2.2.0/src/SharedData/DataFrame.py
RENAMED
|
@@ -14,8 +14,8 @@ from datetime import datetime, timedelta
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
from SharedData.Logger import Logger
|
|
17
|
-
from SharedData.
|
|
18
|
-
from SharedData.
|
|
17
|
+
from SharedData.AWSS3 import S3Download,S3Upload,UpdateModTime
|
|
18
|
+
from SharedData.RealTime import SharedDataRealTime
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
class SharedDataFrame:
|
|
@@ -15,7 +15,7 @@ else:
|
|
|
15
15
|
raise Exception('PYTHONHASHSEED must be set to 0 in the environment!')
|
|
16
16
|
|
|
17
17
|
if not 'DATABASE_FOLDER' in os.environ:
|
|
18
|
-
os.environ['DATABASE_FOLDER'] = os.path.expanduser("~")+'
|
|
18
|
+
os.environ['DATABASE_FOLDER'] = os.path.expanduser("~")+'/db'
|
|
19
19
|
|
|
20
20
|
if not 'S3_BUCKET' in os.environ:
|
|
21
21
|
os.environ['S3_BUCKET'] = 's3://deepportfolio'
|
shareddata-2.1.4/src/SharedData/SharedDataFeeder.py → shareddata-2.2.0/src/SharedData/Feeder.py
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
from SharedData.
|
|
2
|
-
from SharedData.
|
|
1
|
+
from SharedData.Period import SharedDataPeriod
|
|
2
|
+
from SharedData.Table import SharedDataTable
|
|
3
3
|
|
|
4
4
|
class SharedDataFeeder():
|
|
5
5
|
|
|
@@ -12,7 +12,7 @@ class SharedDataFeeder():
|
|
|
12
12
|
|
|
13
13
|
# DATA DICTIONARY
|
|
14
14
|
# data[period][tag]
|
|
15
|
-
self.data = {}
|
|
15
|
+
self.data = {}
|
|
16
16
|
|
|
17
17
|
def __setitem__(self, dataset, value):
|
|
18
18
|
if not dataset in self.data.keys():
|
|
@@ -24,7 +24,7 @@ class SharedDataFeeder():
|
|
|
24
24
|
return self.data[dataset]
|
|
25
25
|
|
|
26
26
|
def __getitem__(self, dataset):
|
|
27
|
-
if not dataset in self.data.keys():
|
|
27
|
+
if not dataset in self.data.keys():
|
|
28
28
|
if (dataset in SharedDataFeeder.dense_datasets.keys()):
|
|
29
29
|
period = dataset
|
|
30
30
|
self.data[period] = SharedDataPeriod(self, period)
|
|
@@ -34,14 +34,4 @@ class SharedDataFeeder():
|
|
|
34
34
|
if (dataset in SharedDataFeeder.dense_datasets.keys()):
|
|
35
35
|
return self.data[dataset]
|
|
36
36
|
else:
|
|
37
|
-
return self.data[dataset].records
|
|
38
|
-
|
|
39
|
-
def create_table(self,dataset,names,formats,size,overwrite=False):
|
|
40
|
-
self.data[dataset] = SharedDataTable(\
|
|
41
|
-
self,dataset,names=names,formats=formats,size=size,\
|
|
42
|
-
overwrite=overwrite)
|
|
43
|
-
return self.data[dataset].records
|
|
44
|
-
|
|
45
|
-
def load_table(self,dataset,size=None):
|
|
46
|
-
self.data[dataset] = SharedDataTable(self,dataset,size=size)
|
|
47
|
-
return self.data[dataset].records
|
|
37
|
+
return self.data[dataset].records
|
|
@@ -8,19 +8,18 @@ import pandas as pd
|
|
|
8
8
|
from pythonjsonlogger.jsonlogger import JsonFormatter
|
|
9
9
|
import boto3
|
|
10
10
|
|
|
11
|
-
from importlib.metadata import version
|
|
12
|
-
|
|
13
|
-
import SharedData.Defaults as Defaults
|
|
14
|
-
from SharedData.SharedDataAWSKinesis import KinesisLogStreamHandler
|
|
15
11
|
|
|
12
|
+
from SharedData.AWSKinesis import KinesisLogStreamHandler
|
|
16
13
|
|
|
17
14
|
class Logger:
|
|
18
15
|
|
|
19
16
|
log = None
|
|
20
|
-
user =
|
|
17
|
+
user = 'guest'
|
|
18
|
+
source = 'unknown'
|
|
21
19
|
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
@staticmethod
|
|
21
|
+
def connect(source,user=None):
|
|
22
|
+
if Logger.log is None:
|
|
24
23
|
if 'SOURCE_FOLDER' in os.environ:
|
|
25
24
|
try:
|
|
26
25
|
commompath = os.path.commonpath([source,os.environ['SOURCE_FOLDER']])
|
|
@@ -42,13 +41,10 @@ class Logger:
|
|
|
42
41
|
source = source.lstrip('src').lstrip('\\src')
|
|
43
42
|
source = source.lstrip('\\').lstrip('/')
|
|
44
43
|
source = source.replace('.py','')
|
|
45
|
-
|
|
44
|
+
Logger.source = source
|
|
46
45
|
|
|
47
46
|
if not user is None:
|
|
48
47
|
Logger.user = user
|
|
49
|
-
else:
|
|
50
|
-
user = 'guest'
|
|
51
|
-
Logger.user = 'guest'
|
|
52
48
|
|
|
53
49
|
path = Path(os.environ['DATABASE_FOLDER'])
|
|
54
50
|
path = path / 'Logs'
|
|
@@ -68,8 +64,8 @@ class Logger:
|
|
|
68
64
|
loglevel = logging.INFO
|
|
69
65
|
|
|
70
66
|
# Create Logger
|
|
71
|
-
|
|
72
|
-
|
|
67
|
+
Logger.log = logging.getLogger(source)
|
|
68
|
+
Logger.log.setLevel(logging.DEBUG)
|
|
73
69
|
formatter = logging.Formatter(os.environ['USERNAME']+'@'+os.environ['COMPUTERNAME'] +
|
|
74
70
|
';%(asctime)s;%(name)s;%(levelname)s;%(message)s',\
|
|
75
71
|
datefmt='%Y-%m-%dT%H:%M:%S%z')
|
|
@@ -77,12 +73,12 @@ class Logger:
|
|
|
77
73
|
handler = logging.StreamHandler()
|
|
78
74
|
handler.setLevel(loglevel)
|
|
79
75
|
handler.setFormatter(formatter)
|
|
80
|
-
|
|
81
|
-
#log file
|
|
82
|
-
fhandler = logging.FileHandler(os.environ['LOG_PATH'], mode='a')
|
|
83
|
-
fhandler.setLevel(loglevel)
|
|
84
|
-
fhandler.setFormatter(formatter)
|
|
85
|
-
|
|
76
|
+
Logger.log.addHandler(handler)
|
|
77
|
+
# #log file
|
|
78
|
+
# fhandler = logging.FileHandler(os.environ['LOG_PATH'], mode='a')
|
|
79
|
+
# fhandler.setLevel(loglevel)
|
|
80
|
+
# fhandler.setFormatter(formatter)
|
|
81
|
+
# Logger.log.addHandler(fhandler)
|
|
86
82
|
#log to aws kinesis
|
|
87
83
|
kinesishandler = KinesisLogStreamHandler(user=Logger.user)
|
|
88
84
|
kinesishandler.setLevel(logging.DEBUG)
|
|
@@ -90,15 +86,10 @@ class Logger:
|
|
|
90
86
|
';%(asctime)s;%(name)s;%(levelname)s;%(message)s',\
|
|
91
87
|
datefmt='%Y-%m-%dT%H:%M:%S%z')
|
|
92
88
|
kinesishandler.setFormatter(jsonformatter)
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
Logger.log = self.log
|
|
96
|
-
try:
|
|
97
|
-
Logger.log.debug('Logger initialized shareddata user %s version %s!' % \
|
|
98
|
-
(Logger.user,version('SharedData')))
|
|
99
|
-
except:
|
|
100
|
-
Logger.log.debug('Logger initialized shareddata!')
|
|
89
|
+
Logger.log.addHandler(kinesishandler)
|
|
90
|
+
|
|
101
91
|
|
|
92
|
+
@staticmethod
|
|
102
93
|
def readLogs(self):
|
|
103
94
|
logsdir = Path(os.environ['LOG_PATH']).parents[0]
|
|
104
95
|
lenlogsdir = len(str(logsdir))
|
|
@@ -9,7 +9,7 @@ from datetime import datetime, timedelta
|
|
|
9
9
|
import gzip,io,shutil,hashlib
|
|
10
10
|
|
|
11
11
|
from SharedData.Logger import Logger
|
|
12
|
-
from SharedData.
|
|
12
|
+
from SharedData.AWSS3 import S3Upload, S3ListFolder, S3Download, UpdateModTime
|
|
13
13
|
|
|
14
14
|
class Metadata():
|
|
15
15
|
|
shareddata-2.1.4/src/SharedData/SharedDataPeriod.py → shareddata-2.2.0/src/SharedData/Period.py
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import os,io,hashlib,gzip,shutil
|
|
1
|
+
import os,io,hashlib,gzip,shutil,time
|
|
2
2
|
import pandas as pd
|
|
3
3
|
import numpy as np
|
|
4
4
|
from datetime import datetime, timedelta
|
|
@@ -6,11 +6,10 @@ from pathlib import Path
|
|
|
6
6
|
from pandas.tseries.offsets import BDay
|
|
7
7
|
from threading import Thread
|
|
8
8
|
|
|
9
|
-
|
|
10
9
|
from SharedData.Logger import Logger
|
|
11
|
-
from SharedData.
|
|
12
|
-
from SharedData.
|
|
13
|
-
from SharedData.
|
|
10
|
+
from SharedData.DataFrame import SharedDataFrame
|
|
11
|
+
from SharedData.TimeSeries import SharedDataTimeSeries
|
|
12
|
+
from SharedData.AWSS3 import S3Upload,S3Download,UpdateModTime
|
|
14
13
|
|
|
15
14
|
class SharedDataPeriod:
|
|
16
15
|
|
|
@@ -41,16 +40,6 @@ class SharedDataPeriod:
|
|
|
41
40
|
self.getContinousTimeIndex(self.default_startDate)
|
|
42
41
|
self.loaded = False
|
|
43
42
|
|
|
44
|
-
|
|
45
|
-
def load(self):
|
|
46
|
-
# read if not loaded
|
|
47
|
-
shdatalist = self.sharedData.list()
|
|
48
|
-
path, shm_name = self.get_path()
|
|
49
|
-
idx = [shm_name in str(s) for s in shdatalist.index]
|
|
50
|
-
if not np.any(idx):
|
|
51
|
-
self.read()
|
|
52
|
-
|
|
53
|
-
|
|
54
43
|
def __setitem__(self, tag, df):
|
|
55
44
|
if not tag in self.tags.keys():
|
|
56
45
|
if isinstance(tag, pd.Timestamp):
|
|
@@ -63,9 +52,9 @@ class SharedDataPeriod:
|
|
|
63
52
|
icol = df.columns.intersection(data.columns)
|
|
64
53
|
data.loc[iidx, icol] = df.loc[iidx, icol].copy()
|
|
65
54
|
|
|
66
|
-
def __getitem__(self, tag):
|
|
55
|
+
def __getitem__(self, tag):
|
|
67
56
|
if not self.loaded:
|
|
68
|
-
self.load()
|
|
57
|
+
self.load()
|
|
69
58
|
self.loaded=True
|
|
70
59
|
if not tag in self.tags.keys():
|
|
71
60
|
if isinstance(tag, pd.Timestamp):
|
|
@@ -125,30 +114,6 @@ class SharedDataPeriod:
|
|
|
125
114
|
self.ctimeidx[startDate][periods.values] = np.arange(len(periods))
|
|
126
115
|
return self.ctimeidx[startDate]
|
|
127
116
|
|
|
128
|
-
def get(self, tag):
|
|
129
|
-
if isinstance(tag, pd.Timestamp):
|
|
130
|
-
df = SharedDataFrame(self, tag, malloc=False)
|
|
131
|
-
return df.data
|
|
132
|
-
else:
|
|
133
|
-
return pd.DataFrame([])
|
|
134
|
-
|
|
135
|
-
def exists(self, tag):
|
|
136
|
-
if isinstance(tag, pd.Timestamp):
|
|
137
|
-
path = Path(os.environ['DATABASE_FOLDER'])
|
|
138
|
-
path = path / self.sharedData.user
|
|
139
|
-
path = path / self.sharedData.database
|
|
140
|
-
path = path / self.sharedDataFeeder.feeder
|
|
141
|
-
path = path / self.period
|
|
142
|
-
fpath = path / (tag.strftime('%Y%m%d%H%M')+'.npy')
|
|
143
|
-
return fpath.is_file()
|
|
144
|
-
else:
|
|
145
|
-
return False
|
|
146
|
-
|
|
147
|
-
def create_timeseries(self,tag,startDate,columns,overwrite=False):
|
|
148
|
-
self.tags[tag] = SharedDataTimeSeries(\
|
|
149
|
-
self,tag,startDate=startDate,columns=columns,overwrite=overwrite)
|
|
150
|
-
return self.tags[tag].data
|
|
151
|
-
|
|
152
117
|
def get_path(self):
|
|
153
118
|
shm_name = self.sharedData.user + '/' + self.sharedData.database + '/' \
|
|
154
119
|
+ self.sharedDataFeeder.feeder + '/' + self.period
|
|
@@ -166,7 +131,31 @@ class SharedDataPeriod:
|
|
|
166
131
|
os.makedirs(path.parent)
|
|
167
132
|
return path , shm_name
|
|
168
133
|
|
|
134
|
+
#CREATE
|
|
135
|
+
def create_timeseries(self,tag,startDate,columns,overwrite=False):
|
|
136
|
+
self.tags[tag] = SharedDataTimeSeries(\
|
|
137
|
+
self,tag,startDate=startDate,columns=columns,overwrite=overwrite)
|
|
138
|
+
return self.tags[tag].data
|
|
139
|
+
|
|
140
|
+
# READ
|
|
141
|
+
def load(self):
|
|
142
|
+
# read if not loaded
|
|
143
|
+
shdatalist = self.sharedData.list()
|
|
144
|
+
path, shm_name = self.get_path()
|
|
145
|
+
idx = [shm_name in str(s) for s in shdatalist.index]
|
|
146
|
+
if not np.any(idx):
|
|
147
|
+
self.read()
|
|
148
|
+
else:
|
|
149
|
+
#map
|
|
150
|
+
self.map(shm_name,shdatalist.index[idx])
|
|
151
|
+
|
|
152
|
+
def map(self,shm_name,shm_name_list):
|
|
153
|
+
for shm in shm_name_list:
|
|
154
|
+
tag = shm.replace(shm_name,'')[1:]
|
|
155
|
+
self.tags[tag] = SharedDataTimeSeries(self, tag = tag)
|
|
156
|
+
|
|
169
157
|
def read(self):
|
|
158
|
+
tini = time.time()
|
|
170
159
|
datasize = 1
|
|
171
160
|
path, shm_name= self.get_path()
|
|
172
161
|
headpath = str(path)+'_head.bin'
|
|
@@ -209,20 +198,27 @@ class SharedDataPeriod:
|
|
|
209
198
|
tail_io = open(str(tailpath),'rb')
|
|
210
199
|
|
|
211
200
|
if not head_io is None:
|
|
212
|
-
self.read_io(head_io,headpath)
|
|
201
|
+
datasize += self.read_io(head_io,headpath)
|
|
213
202
|
|
|
214
203
|
if not tail_io is None:
|
|
215
|
-
self.read_io(tail_io,tailpath)
|
|
204
|
+
datasize += self.read_io(tail_io,tailpath)
|
|
205
|
+
|
|
206
|
+
te = time.time()-tini+0.000001
|
|
207
|
+
datasize = datasize/(1024*1024)
|
|
208
|
+
Logger.log.debug('read %s/%s %.2fMB in %.2fs %.2fMBps ' % \
|
|
209
|
+
(self.sharedDataFeeder,self.period,datasize,te,datasize/te))
|
|
216
210
|
|
|
217
211
|
def read_io(self,io_obj,path):
|
|
212
|
+
datasize = 0
|
|
218
213
|
#read
|
|
219
214
|
io_obj.seek(0)
|
|
220
215
|
io_data = io_obj.read()
|
|
216
|
+
datasize = len(io_data)
|
|
221
217
|
_m = hashlib.md5(io_data[:-24]).digest()
|
|
222
218
|
m = io_data[-16:]
|
|
223
219
|
if (m!=_m):
|
|
224
|
-
Logger.log.error('Timeseries
|
|
225
|
-
raise Exception('Timeseries
|
|
220
|
+
Logger.log.error('Timeseries file %s corrupted!' % (path))
|
|
221
|
+
raise Exception('Timeseries file %s corrupted!' % (path))
|
|
226
222
|
io_obj.seek(0)
|
|
227
223
|
separator = np.frombuffer(io_obj.read(8),dtype=np.int64)[0]
|
|
228
224
|
while (separator==1):
|
|
@@ -249,6 +245,9 @@ class SharedDataPeriod:
|
|
|
249
245
|
separator = np.frombuffer(io_obj.read(8),dtype=np.int64)[0]
|
|
250
246
|
io_obj.close()
|
|
251
247
|
|
|
248
|
+
return datasize
|
|
249
|
+
|
|
250
|
+
# WRITE
|
|
252
251
|
def write(self,startDate=None):
|
|
253
252
|
path , shm_name= self.get_path()
|
|
254
253
|
mtime = datetime.now().timestamp()
|
|
@@ -6,7 +6,7 @@ from pathlib import Path
|
|
|
6
6
|
from SharedData.Logger import Logger
|
|
7
7
|
logger = Logger(__file__)
|
|
8
8
|
from SharedData.SharedData import SharedData
|
|
9
|
-
from SharedData.
|
|
9
|
+
from SharedData.AWSKinesis import KinesisStreamConsumer
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
try:
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import os, psutil
|
|
2
|
+
import pandas as pd
|
|
3
|
+
from multiprocessing import shared_memory
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from importlib.metadata import version
|
|
6
|
+
|
|
7
|
+
import SharedData.Defaults as Defaults
|
|
8
|
+
from SharedData.Logger import Logger
|
|
9
|
+
from SharedData.Table import Table
|
|
10
|
+
from SharedData.TimeseriesContainer import TimeseriesContainer
|
|
11
|
+
from SharedData.TimeSeries import TimeSeries
|
|
12
|
+
from SharedData.DataFrame import SharedDataFrame
|
|
13
|
+
from SharedData.RealTime import SharedDataRealTime
|
|
14
|
+
from SharedData.Utils import remove_shm_from_resource_tracker
|
|
15
|
+
|
|
16
|
+
class SharedData:
|
|
17
|
+
|
|
18
|
+
def __init__(self,source,user='guest'):
|
|
19
|
+
self.source = source
|
|
20
|
+
self.user = user
|
|
21
|
+
|
|
22
|
+
# DATA DICTIONARY
|
|
23
|
+
self.data = {}
|
|
24
|
+
|
|
25
|
+
# LOGIN VARIABLES
|
|
26
|
+
self.islogged = False
|
|
27
|
+
self.source=source
|
|
28
|
+
self.user=user
|
|
29
|
+
self.mode='rw'
|
|
30
|
+
|
|
31
|
+
# S3 VARIABLES
|
|
32
|
+
self.s3read = True
|
|
33
|
+
self.s3write = True
|
|
34
|
+
|
|
35
|
+
# save files locally
|
|
36
|
+
self.save_local = (os.environ['SAVE_LOCAL'] == 'True')
|
|
37
|
+
|
|
38
|
+
self.databases = {
|
|
39
|
+
'MarketData' : ['date','symbol'],
|
|
40
|
+
'Relationships' : ['date','symbol1','symbol2'],
|
|
41
|
+
'Portfolios' : ['date','portfolio'],
|
|
42
|
+
'Signals' : ['date','portfolio','symbol'],
|
|
43
|
+
'Risk' : ['date','portfolio','symbol'],
|
|
44
|
+
'Positions' : ['date','portfolio','symbol'],
|
|
45
|
+
'Orders' : ['date','portfolio','symbol','clordid'],
|
|
46
|
+
'Trades' : ['date','portfolio','symbol','tradeid']
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
Logger.connect(self.source,self.user)
|
|
50
|
+
|
|
51
|
+
if (os.name == 'posix'):
|
|
52
|
+
remove_shm_from_resource_tracker()
|
|
53
|
+
|
|
54
|
+
if not self.islogged:
|
|
55
|
+
self.islogged = True
|
|
56
|
+
try:
|
|
57
|
+
Logger.log.debug('%s@%s CONNECTED!\nSharedData version %s, user %s' %
|
|
58
|
+
(os.environ['USERNAME'], os.environ['COMPUTERNAME'],version('SharedData'), self.user))
|
|
59
|
+
except:
|
|
60
|
+
Logger.log.debug('%s:%s CONNECTED!\nSharedData user %s!' %
|
|
61
|
+
(os.environ['USERNAME'], os.environ['COMPUTERNAME'],self.user))
|
|
62
|
+
|
|
63
|
+
###############################################
|
|
64
|
+
############# DATA CONTAINERS #################
|
|
65
|
+
###############################################
|
|
66
|
+
|
|
67
|
+
############# TABLE #################
|
|
68
|
+
def table(self,database,period,source,tablename,\
|
|
69
|
+
names=None,formats=None,size=None,value=None,user='master'):
|
|
70
|
+
|
|
71
|
+
path = user+'/'+database+'/'+period+'/'+source+'/table/'+tablename
|
|
72
|
+
if not path in self.data.keys():
|
|
73
|
+
self.data[path] = Table(self,database,period,source,\
|
|
74
|
+
tablename,records=value,names=names,formats=formats,size=size,user=user)
|
|
75
|
+
return self.data[path].records
|
|
76
|
+
|
|
77
|
+
############# TIMESERIES #################
|
|
78
|
+
def timeseries(self,database,period,source,tag=None,\
|
|
79
|
+
startDate=None,columns=None,value=None,user='master'):
|
|
80
|
+
|
|
81
|
+
path = user+'/'+database+'/'+period+'/'+source+'/timeseries'
|
|
82
|
+
if not path in self.data.keys():
|
|
83
|
+
self.data[path] = TimeseriesContainer(self, database, period, source,user=user)
|
|
84
|
+
if tag is None:
|
|
85
|
+
return self.data[path]
|
|
86
|
+
|
|
87
|
+
if not tag in self.data[path].tags.keys():
|
|
88
|
+
if (startDate is None) & (columns is None) & (value is None):
|
|
89
|
+
self.data[path].load()
|
|
90
|
+
if not tag in self.data[path].tags.keys():
|
|
91
|
+
Logger.log.error('Tag %s/%s doesnt exist' % (path,tag))
|
|
92
|
+
return None
|
|
93
|
+
else:
|
|
94
|
+
self.data[path].tags[tag] = TimeSeries(self, self.data[path],\
|
|
95
|
+
database, period, source, tag,\
|
|
96
|
+
value=value,startDate=startDate,columns=columns,user=user)
|
|
97
|
+
|
|
98
|
+
return self.data[path].tags[tag].data
|
|
99
|
+
|
|
100
|
+
############# DATAFRAME #################
|
|
101
|
+
def dataframe(self,database,period,source,\
|
|
102
|
+
date=None,value=None,user='master'):
|
|
103
|
+
pass
|
|
104
|
+
|
|
105
|
+
###############################################
|
|
106
|
+
######### SHARED MEMORY MANAGEMENT ############
|
|
107
|
+
###############################################
|
|
108
|
+
@staticmethod
|
|
109
|
+
def malloc(shm_name,create=False,size=None,overwrite=False):
|
|
110
|
+
ismalloc = False
|
|
111
|
+
shm = None
|
|
112
|
+
try:
|
|
113
|
+
shm = shared_memory.SharedMemory(\
|
|
114
|
+
name = shm_name,create=False)
|
|
115
|
+
ismalloc = True
|
|
116
|
+
except:
|
|
117
|
+
pass
|
|
118
|
+
|
|
119
|
+
if (not ismalloc) & (create) & (not size is None):
|
|
120
|
+
shm = shared_memory.SharedMemory(\
|
|
121
|
+
name=shm_name,create=True,size=size)
|
|
122
|
+
ismalloc = True
|
|
123
|
+
|
|
124
|
+
elif (create) & (size is None):
|
|
125
|
+
raise Exception('SharedData malloc must have a size when create=True')
|
|
126
|
+
|
|
127
|
+
elif (os.name=='posix')\
|
|
128
|
+
& (ismalloc) & (create) & (overwrite) & (not size is None):
|
|
129
|
+
SharedData.free(shm_name)
|
|
130
|
+
shm = shared_memory.SharedMemory(\
|
|
131
|
+
name=shm_name,create=True,size=size)
|
|
132
|
+
ismalloc = True
|
|
133
|
+
|
|
134
|
+
# register process id access to memory
|
|
135
|
+
if ismalloc:
|
|
136
|
+
fpath = Path(os.environ['DATABASE_FOLDER'])
|
|
137
|
+
fpath = fpath/('shm/'+shm_name.replace('\\','/')+'.csv')
|
|
138
|
+
os.makedirs(fpath.parent,exist_ok=True)
|
|
139
|
+
pid = os.getpid()
|
|
140
|
+
f = open(fpath, "a+")
|
|
141
|
+
f.write(str(pid)+',')
|
|
142
|
+
f.flush()
|
|
143
|
+
f.close()
|
|
144
|
+
|
|
145
|
+
return [shm, ismalloc]
|
|
146
|
+
|
|
147
|
+
@staticmethod
|
|
148
|
+
def free(shm_name):
|
|
149
|
+
if os.name=='posix':
|
|
150
|
+
try:
|
|
151
|
+
shm = shared_memory.SharedMemory(\
|
|
152
|
+
name = shm_name,create=False)
|
|
153
|
+
shm.close()
|
|
154
|
+
shm.unlink()
|
|
155
|
+
fpath = Path(os.environ['DATABASE_FOLDER'])
|
|
156
|
+
fpath = fpath/('shm/'+shm_name.replace('\\','/')+'.csv')
|
|
157
|
+
if fpath.is_file():
|
|
158
|
+
os.remove(fpath)
|
|
159
|
+
except:
|
|
160
|
+
pass
|
|
161
|
+
|
|
162
|
+
@staticmethod
|
|
163
|
+
def list():
|
|
164
|
+
folder = Path(os.environ['DATABASE_FOLDER'])/'shm'
|
|
165
|
+
shm_names = pd.DataFrame()
|
|
166
|
+
for root, _, filenames in os.walk(folder):
|
|
167
|
+
for filename in filenames:
|
|
168
|
+
if filename.endswith('.csv'):
|
|
169
|
+
fpath = os.path.join(root, filename)
|
|
170
|
+
shm_name = fpath.removeprefix(str(folder))[1:]
|
|
171
|
+
shm_name = shm_name.removesuffix('.csv')
|
|
172
|
+
shm_name = shm_name.replace('/','\\')
|
|
173
|
+
try:
|
|
174
|
+
shm = shared_memory.SharedMemory(\
|
|
175
|
+
name = shm_name,create=False)
|
|
176
|
+
shm_names.loc[shm_name,'size'] = shm.size
|
|
177
|
+
shm.close()
|
|
178
|
+
except:
|
|
179
|
+
try:
|
|
180
|
+
if fpath.is_file():
|
|
181
|
+
os.remove(fpath)
|
|
182
|
+
except:
|
|
183
|
+
pass
|
|
184
|
+
shm_names = shm_names.sort_index()
|
|
185
|
+
return shm_names
|
|
186
|
+
|
|
187
|
+
@staticmethod
|
|
188
|
+
def freeall():
|
|
189
|
+
shm_names = SharedData.list()
|
|
190
|
+
for shm_name in shm_names.index:
|
|
191
|
+
SharedData.free(shm_name)
|
|
192
|
+
|
|
193
|
+
###############################################
|
|
194
|
+
############# REAL TIME MANAGEMENT ############
|
|
195
|
+
###############################################
|
|
196
|
+
def subscribe(database,source,period):
|
|
197
|
+
SharedDataRealTime.subscribe(database,source,period)
|