trendvisdata 1.0.4__py3-none-any.whl
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.
- trendvisdata/__init__.py +5 -0
- trendvisdata/chart_data.py +400 -0
- trendvisdata/chart_prep.py +637 -0
- trendvisdata/market_data.py +541 -0
- trendvisdata/sector_mappings.py +666 -0
- trendvisdata/trend.py +316 -0
- trendvisdata/trend_data.py +785 -0
- trendvisdata/trend_params.py +197 -0
- trendvisdata-1.0.4.dist-info/LICENSE +21 -0
- trendvisdata-1.0.4.dist-info/METADATA +29 -0
- trendvisdata-1.0.4.dist-info/RECORD +13 -0
- trendvisdata-1.0.4.dist-info/WHEEL +5 -0
- trendvisdata-1.0.4.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
import datetime as dt
|
|
2
|
+
import numpy as np
|
|
3
|
+
import pandas as pd
|
|
4
|
+
import collections
|
|
5
|
+
from trendvisdata.chart_prep import Formatting
|
|
6
|
+
|
|
7
|
+
class Data():
|
|
8
|
+
"""
|
|
9
|
+
Create data dictionaries to display various charts of Trend Strength
|
|
10
|
+
|
|
11
|
+
"""
|
|
12
|
+
@classmethod
|
|
13
|
+
def get_all_data(cls, params, tables):
|
|
14
|
+
"""
|
|
15
|
+
Create data dictionary for graphing of barchart, returns and market charts.
|
|
16
|
+
|
|
17
|
+
Parameters
|
|
18
|
+
----------
|
|
19
|
+
params : Dict
|
|
20
|
+
mkts : Int
|
|
21
|
+
Number of markets to chart. The default is 20.
|
|
22
|
+
chart_mkts : Int (Optional)
|
|
23
|
+
Number of markets to chart. The default is None.
|
|
24
|
+
chart_dimensions : Tuple
|
|
25
|
+
Width and height to determine the number of markets to chart. The
|
|
26
|
+
default is (8, 5)
|
|
27
|
+
trend : Str
|
|
28
|
+
Flag to select most or least trending markets.
|
|
29
|
+
Select from: 'up' - strongly trending upwards,
|
|
30
|
+
'down - strongly trending downwards,
|
|
31
|
+
'neutral' - weak trend,
|
|
32
|
+
'strong' - up and down trends,
|
|
33
|
+
'all' - up down and weak trends
|
|
34
|
+
The default is 'strong' which displays both up-trending
|
|
35
|
+
and down-trending markets.
|
|
36
|
+
days : Int
|
|
37
|
+
Number of days of history. The default is 60.
|
|
38
|
+
tables : Dict
|
|
39
|
+
Dictionary of key tables.
|
|
40
|
+
|
|
41
|
+
Returns
|
|
42
|
+
-------
|
|
43
|
+
data_dict : Dict
|
|
44
|
+
Data dictionary for graphing of barchart, returns and market charts.
|
|
45
|
+
|
|
46
|
+
"""
|
|
47
|
+
#start = dt.datetime.strptime(params['start_date'], "%Y-%m-%d").date()
|
|
48
|
+
#end = dt.datetime.strptime(params['end_date'], "%Y-%m-%d").date()
|
|
49
|
+
|
|
50
|
+
data_dict = {}
|
|
51
|
+
barometer = tables['barometer']
|
|
52
|
+
|
|
53
|
+
data_dict['bar_dict'] = cls.get_bar_data(barometer=barometer, params=params)
|
|
54
|
+
data_dict['returns_dict'] = {}
|
|
55
|
+
data_dict['returns_dict']['unfiltered_dict'] = cls.get_returns_data(
|
|
56
|
+
params=params, tables=tables, flag='Unfiltered')
|
|
57
|
+
|
|
58
|
+
data_dict['returns_dict']['high_returns_dict'] = cls.get_returns_data(
|
|
59
|
+
params=params, tables=tables, flag='High Returns')
|
|
60
|
+
|
|
61
|
+
if params['source'] == 'norgate':
|
|
62
|
+
sectors = list(set(
|
|
63
|
+
tables['barometer'][params['returns_sector_name']]))
|
|
64
|
+
else:
|
|
65
|
+
sectors = list(set(
|
|
66
|
+
tables['barometer'][params['returns_sector_name']]))
|
|
67
|
+
data_dict['returns_dict']['sectors'] = {}
|
|
68
|
+
for sector in sectors:
|
|
69
|
+
returns_data = cls.get_returns_data(
|
|
70
|
+
params=params, tables=tables, flag=sector)
|
|
71
|
+
if (returns_data['title'] != 'Error'):
|
|
72
|
+
data_dict['returns_dict']['sectors'][sector] = returns_data
|
|
73
|
+
data_dict['returns_dict']['sectors'][sector]['sector'] = sector
|
|
74
|
+
|
|
75
|
+
data_dict['market_dict'] = cls.get_market_chart_data(
|
|
76
|
+
params=params, tables=tables)
|
|
77
|
+
|
|
78
|
+
return data_dict
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
@classmethod
|
|
82
|
+
def get_bar_data(cls, barometer: pd.DataFrame, params: dict) -> dict:
|
|
83
|
+
"""
|
|
84
|
+
Create data dictionary for plotting barchart trends.
|
|
85
|
+
|
|
86
|
+
Parameters
|
|
87
|
+
----------
|
|
88
|
+
barometer : DataFrame
|
|
89
|
+
DataFrame showing trend strength for each ticker.
|
|
90
|
+
mkts : Int
|
|
91
|
+
Number of markets to chart. The default is 20.
|
|
92
|
+
|
|
93
|
+
Returns
|
|
94
|
+
-------
|
|
95
|
+
bar_dict : Dict
|
|
96
|
+
Data dictionary for plotting barchart trends.
|
|
97
|
+
|
|
98
|
+
"""
|
|
99
|
+
# Create default dict to add keys not found
|
|
100
|
+
bar_dict = collections.defaultdict(dict)
|
|
101
|
+
mkts = params['mkts']
|
|
102
|
+
|
|
103
|
+
# Create entries for up trend
|
|
104
|
+
bar_dict = cls._barometer_up(barometer, mkts, bar_dict)
|
|
105
|
+
|
|
106
|
+
# Create entries for down trend
|
|
107
|
+
bar_dict = cls._barometer_down(barometer, mkts, bar_dict)
|
|
108
|
+
|
|
109
|
+
# Create entries for neutral trend
|
|
110
|
+
bar_dict = cls._barometer_neutral(barometer, mkts, bar_dict)
|
|
111
|
+
|
|
112
|
+
# Create entries for strong trend
|
|
113
|
+
bar_dict = cls._barometer_strong(barometer, mkts, bar_dict)
|
|
114
|
+
|
|
115
|
+
# Convert back to regular dict
|
|
116
|
+
bar_dict = dict(bar_dict)
|
|
117
|
+
|
|
118
|
+
return bar_dict
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
@classmethod
|
|
122
|
+
def _barometer_up(cls, barometer, mkts, bar_dict):
|
|
123
|
+
# Create entries for up trend
|
|
124
|
+
barometer_up = barometer.sort_values(
|
|
125
|
+
by=['Trend Strength %'], ascending=True)
|
|
126
|
+
short_name = list(barometer_up['Short_name'].iloc[-mkts:])
|
|
127
|
+
trend_strength = np.round(
|
|
128
|
+
np.array(barometer_up['Trend Strength %'].iloc[-mkts:]), 4)
|
|
129
|
+
trend_color = list(barometer_up['Trend Color'].iloc[-mkts:])
|
|
130
|
+
bar_dict = cls._bar_arrays(
|
|
131
|
+
bar_dict, short_name, trend_strength, trend_color, direction='up')
|
|
132
|
+
|
|
133
|
+
return bar_dict
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
@classmethod
|
|
137
|
+
def _barometer_down(cls, barometer, mkts, bar_dict):
|
|
138
|
+
# Create entries for down trend
|
|
139
|
+
barometer_down = barometer.sort_values(
|
|
140
|
+
by=['Trend Strength %'], ascending=False)
|
|
141
|
+
short_name = list(barometer_down['Short_name'].iloc[-mkts:])
|
|
142
|
+
trend_strength = np.round(
|
|
143
|
+
np.array(barometer_down['Trend Strength %'].iloc[-mkts:]), 4)
|
|
144
|
+
trend_color = list(
|
|
145
|
+
barometer_down['Trend Color'].iloc[-mkts:])
|
|
146
|
+
bar_dict = cls._bar_arrays(
|
|
147
|
+
bar_dict, short_name, trend_strength, trend_color, direction='down')
|
|
148
|
+
|
|
149
|
+
return bar_dict
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
@classmethod
|
|
153
|
+
def _barometer_neutral(cls, barometer, mkts, bar_dict):
|
|
154
|
+
# Create entries for neutral trend
|
|
155
|
+
barometer_neutral = barometer.sort_values(
|
|
156
|
+
by=['Absolute Trend Strength %'], ascending=True)
|
|
157
|
+
short_name = list(barometer_neutral['Short_name'].iloc[:mkts])
|
|
158
|
+
trend_strength = np.round(
|
|
159
|
+
np.array(barometer_neutral['Trend Strength %'].iloc[:mkts]), 4)
|
|
160
|
+
trend_color = list(barometer_neutral['Trend Color'].iloc[:mkts])
|
|
161
|
+
bar_dict = cls._bar_arrays(
|
|
162
|
+
bar_dict, short_name, trend_strength, trend_color, direction='neutral')
|
|
163
|
+
|
|
164
|
+
return bar_dict
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
@classmethod
|
|
168
|
+
def _barometer_strong(cls, barometer, mkts, bar_dict):
|
|
169
|
+
# Create entries for strong trend
|
|
170
|
+
barometer_neutral = barometer.sort_values(
|
|
171
|
+
by=['Absolute Trend Strength %'], ascending=True)
|
|
172
|
+
short_name = list(
|
|
173
|
+
barometer_neutral['Short_name'].iloc[-mkts:])
|
|
174
|
+
trend_strength = np.round(
|
|
175
|
+
np.array(barometer_neutral['Trend Strength %'].iloc[-mkts:]), 4)
|
|
176
|
+
trend_color = list(
|
|
177
|
+
barometer_neutral['Trend Color'].iloc[-mkts:])
|
|
178
|
+
bar_dict = cls._bar_arrays(
|
|
179
|
+
bar_dict, short_name, trend_strength, trend_color, direction='strongly')
|
|
180
|
+
|
|
181
|
+
return bar_dict
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
@classmethod
|
|
185
|
+
def _bar_arrays(
|
|
186
|
+
cls,
|
|
187
|
+
bar_dict,
|
|
188
|
+
short_name,
|
|
189
|
+
trend_strength,
|
|
190
|
+
trend_color,
|
|
191
|
+
direction
|
|
192
|
+
):
|
|
193
|
+
bar_dict[direction] = collections.defaultdict(dict)
|
|
194
|
+
bar_dict[direction]['arrays']['short_name'] = short_name
|
|
195
|
+
bar_dict[direction]['arrays']['trend_strength'] = trend_strength
|
|
196
|
+
bar_dict[direction]['arrays']['trend_color'] = trend_color
|
|
197
|
+
bar_dict[direction]['json'] = cls._json_array(
|
|
198
|
+
short_name, trend_strength, trend_color)
|
|
199
|
+
bar_dict[direction]['titlestr'] = direction.capitalize()
|
|
200
|
+
|
|
201
|
+
bar_dict[direction] = dict(bar_dict[direction])
|
|
202
|
+
|
|
203
|
+
return bar_dict
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
@staticmethod
|
|
207
|
+
def _json_array(short_name, trend_strength, trend_color):
|
|
208
|
+
bar_trim = pd.DataFrame()
|
|
209
|
+
bar_trim['Short Name'] = short_name
|
|
210
|
+
bar_trim['Trend Strength'] = trend_strength
|
|
211
|
+
bar_trim['Trend Color'] = trend_color
|
|
212
|
+
|
|
213
|
+
json_dict = bar_trim.to_dict(orient='index')
|
|
214
|
+
|
|
215
|
+
json_array = []
|
|
216
|
+
for key in json_dict.keys():
|
|
217
|
+
json_array.append(json_dict[key])
|
|
218
|
+
|
|
219
|
+
return json_array
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
@classmethod
|
|
223
|
+
def get_returns_data(
|
|
224
|
+
cls,
|
|
225
|
+
params: dict,
|
|
226
|
+
tables: dict,
|
|
227
|
+
flag: str) -> dict:
|
|
228
|
+
"""
|
|
229
|
+
Create data dictionary for plotting line graph trends.
|
|
230
|
+
|
|
231
|
+
Parameters
|
|
232
|
+
----------
|
|
233
|
+
params : Dict
|
|
234
|
+
mkts : Int
|
|
235
|
+
Number of markets to chart. The default is 5.
|
|
236
|
+
trend : Str
|
|
237
|
+
Flag to select most or least trending markets.
|
|
238
|
+
Select from: 'up' - strongly trending upwards,
|
|
239
|
+
'down - strongly trending downwards,
|
|
240
|
+
'neutral' - weak trend,
|
|
241
|
+
'strong' - up and down trends,
|
|
242
|
+
'all' - up down and weak trends
|
|
243
|
+
The default is 'strong' which displays both up-trending
|
|
244
|
+
and down-trending markets.
|
|
245
|
+
days : Int
|
|
246
|
+
Number of days of history. The default is 60.
|
|
247
|
+
tables : Dict
|
|
248
|
+
Dictionary of key tables.
|
|
249
|
+
|
|
250
|
+
Returns
|
|
251
|
+
-------
|
|
252
|
+
returns_dict : Dict
|
|
253
|
+
Dictionary of data to create a line graph of normalised price history.
|
|
254
|
+
|
|
255
|
+
"""
|
|
256
|
+
# Generate DataFrame of normalized returns
|
|
257
|
+
raw_tenor = Formatting.create_normalized_data(
|
|
258
|
+
params=params,
|
|
259
|
+
tables=tables,
|
|
260
|
+
flag=flag
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
# Drop any columns containing nan values
|
|
264
|
+
tenor = raw_tenor.dropna(axis=1)
|
|
265
|
+
|
|
266
|
+
returns_dict = {}
|
|
267
|
+
try:
|
|
268
|
+
#tenor.index = tenor.index.astype(pd.DatetimeIndex)
|
|
269
|
+
tenor.index = tenor.index.date.astype(str) # type: ignore comment;
|
|
270
|
+
|
|
271
|
+
# Create empty returns dict & add returns and labels
|
|
272
|
+
returns_dict['time_series'] = {}
|
|
273
|
+
for num, label in enumerate(tenor.columns):
|
|
274
|
+
returns_dict['time_series'][num] = {}
|
|
275
|
+
returns_dict['time_series'][num]['label'] = label
|
|
276
|
+
returns_dict['time_series'][num]['data'] = tenor[label].to_dict()
|
|
277
|
+
|
|
278
|
+
returns_dict['time_series'] = cls._round_floats(
|
|
279
|
+
returns_dict['time_series']
|
|
280
|
+
)
|
|
281
|
+
returns_dict['start'] = dt.datetime.strptime(
|
|
282
|
+
tenor.index[0], "%Y-%m-%d").date()
|
|
283
|
+
returns_dict['end'] = dt.datetime.strptime(
|
|
284
|
+
tenor.index[-1], "%Y-%m-%d").date()
|
|
285
|
+
returns_dict['xlabel'] = 'Date'
|
|
286
|
+
returns_dict['ylabel'] = 'Return %'
|
|
287
|
+
returns_dict['line_labels'] = tenor.columns.to_list()
|
|
288
|
+
returns_dict['chart_title'] = (
|
|
289
|
+
'Relative Return Over Last ' +
|
|
290
|
+
str(len(tenor)) +
|
|
291
|
+
' Trading Days' +
|
|
292
|
+
' - ' +
|
|
293
|
+
params['end_date']
|
|
294
|
+
)
|
|
295
|
+
returns_dict['title'] = (
|
|
296
|
+
flag +
|
|
297
|
+
" : " +
|
|
298
|
+
returns_dict['start'].strftime("%B") +
|
|
299
|
+
" " +
|
|
300
|
+
str(returns_dict['start'].year) +
|
|
301
|
+
" - " +
|
|
302
|
+
returns_dict['end'].strftime("%B") +
|
|
303
|
+
" " +
|
|
304
|
+
str(returns_dict['end'].year)
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
return returns_dict
|
|
308
|
+
|
|
309
|
+
except AttributeError:
|
|
310
|
+
returns_dict['title'] = 'Error'
|
|
311
|
+
return returns_dict
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
@classmethod
|
|
315
|
+
def get_market_chart_data(cls, params: dict, tables: dict) -> dict:
|
|
316
|
+
"""
|
|
317
|
+
Create a data dictionary for plotting a summary of the strength of trend
|
|
318
|
+
across markets.
|
|
319
|
+
|
|
320
|
+
Parameters
|
|
321
|
+
----------
|
|
322
|
+
params : Dict
|
|
323
|
+
chart_mkts : Int (Optional)
|
|
324
|
+
Number of markets to chart. The default is None.
|
|
325
|
+
chart_dimensions : Tuple
|
|
326
|
+
Width and height to determine the number of markets to chart. The
|
|
327
|
+
default is (8, 5)
|
|
328
|
+
trend : Str
|
|
329
|
+
Flag to select most or least trending markets.
|
|
330
|
+
Select from: 'up' - strongly trending upwards,
|
|
331
|
+
'down - strongly trending downwards,
|
|
332
|
+
'neutral' - weak trend,
|
|
333
|
+
'strong' - up and down trends,
|
|
334
|
+
'all' - up down and weak trends
|
|
335
|
+
The default is 'strong' which displays both up-trending
|
|
336
|
+
and down-trending markets.
|
|
337
|
+
days : Int
|
|
338
|
+
Number of days of history. The default is 60.
|
|
339
|
+
tables : Dict
|
|
340
|
+
Dictionary of key tables.
|
|
341
|
+
|
|
342
|
+
Returns
|
|
343
|
+
-------
|
|
344
|
+
market_dict : Dict
|
|
345
|
+
Data dictionary for plotting a summary of the strength of trend across
|
|
346
|
+
markets
|
|
347
|
+
|
|
348
|
+
"""
|
|
349
|
+
if params['chart_mkts'] is not None:
|
|
350
|
+
params = Formatting.create_mkt_dims(params)
|
|
351
|
+
|
|
352
|
+
params['num_charts'] = int(
|
|
353
|
+
params['chart_dimensions'][0] * params['chart_dimensions'][1])
|
|
354
|
+
|
|
355
|
+
data_list = Formatting.create_data_list(
|
|
356
|
+
params=params, barometer=tables['barometer'], market_chart=True,
|
|
357
|
+
num_charts=params['num_charts'])
|
|
358
|
+
|
|
359
|
+
market_dict = collections.defaultdict(dict)
|
|
360
|
+
market_dict['tickers'] = collections.defaultdict(dict)
|
|
361
|
+
|
|
362
|
+
for num, ticker in enumerate(data_list):
|
|
363
|
+
market_dict['tickers'][num]['label'] = params[
|
|
364
|
+
'ticker_short_name_dict'][ticker]
|
|
365
|
+
market_dict['tickers'][num]['ticker'] = ticker
|
|
366
|
+
|
|
367
|
+
market_dict['tickers'][num]['axis_dates'] = (
|
|
368
|
+
tables['ticker_dict'][ticker].index[-params['days']:]
|
|
369
|
+
).date.tolist()
|
|
370
|
+
market_dict['tickers'][num][
|
|
371
|
+
'axis_prices_norm'] = cls._round_floats(
|
|
372
|
+
np.array(tables['ticker_dict'][ticker]['Close'][
|
|
373
|
+
-params['days']:].div(tables['ticker_dict'][
|
|
374
|
+
ticker]['Close'][-params['days']:].iloc[0])
|
|
375
|
+
.mul(100)).tolist()
|
|
376
|
+
)
|
|
377
|
+
|
|
378
|
+
market_dict['tickers'][num]['axis_prices'] = cls._round_floats(
|
|
379
|
+
np.array(tables['ticker_dict'][ticker]['Close'][
|
|
380
|
+
-params['days']:]).tolist())
|
|
381
|
+
|
|
382
|
+
market_dict = dict(market_dict)
|
|
383
|
+
market_dict['tickers'] = dict(market_dict['tickers'])
|
|
384
|
+
market_dict['chart_title'] = Formatting.get_chart_title(params=params) # type: ignore comment;
|
|
385
|
+
|
|
386
|
+
return market_dict
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
@classmethod
|
|
390
|
+
def _round_floats(cls, obj):
|
|
391
|
+
if isinstance(obj, float): return round(obj, 2)
|
|
392
|
+
if isinstance(obj, dict): return {
|
|
393
|
+
k: cls._round_floats(v) for k, v in obj.items()
|
|
394
|
+
}
|
|
395
|
+
if isinstance(obj, (list, tuple)): return [
|
|
396
|
+
cls._round_floats(x) for x in obj
|
|
397
|
+
]
|
|
398
|
+
|
|
399
|
+
return obj
|
|
400
|
+
|