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.
@@ -0,0 +1,5 @@
1
+ __version__ = "1.0.4"
2
+
3
+
4
+
5
+
@@ -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
+