tesorotools-python 0.0.18__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.
Files changed (53) hide show
  1. tesorotools/__init__.py +6 -0
  2. tesorotools/artists/__init__.py +5 -0
  3. tesorotools/artists/barh_plot.py +310 -0
  4. tesorotools/artists/line_plot.py +245 -0
  5. tesorotools/artists/table.py +200 -0
  6. tesorotools/artists/type_curve.py +218 -0
  7. tesorotools/assets/README.md +5 -0
  8. tesorotools/assets/fonts/CabinetGrotesk-Black.otf +0 -0
  9. tesorotools/assets/fonts/CabinetGrotesk-Bold.otf +0 -0
  10. tesorotools/assets/fonts/CabinetGrotesk-Extrabold.otf +0 -0
  11. tesorotools/assets/fonts/CabinetGrotesk-Extralight.otf +0 -0
  12. tesorotools/assets/fonts/CabinetGrotesk-Light.otf +0 -0
  13. tesorotools/assets/fonts/CabinetGrotesk-Medium.otf +0 -0
  14. tesorotools/assets/fonts/CabinetGrotesk-Regular.otf +0 -0
  15. tesorotools/assets/fonts/CabinetGrotesk-Thin.otf +0 -0
  16. tesorotools/assets/fonts/README.md +1 -0
  17. tesorotools/assets/plots.yaml +43 -0
  18. tesorotools/assets/tesoro.mplstyle +21 -0
  19. tesorotools/convert.py +99 -0
  20. tesorotools/data_sources/README.md +14 -0
  21. tesorotools/data_sources/__init__.py +0 -0
  22. tesorotools/data_sources/debug.py +26 -0
  23. tesorotools/data_sources/lseg.py +117 -0
  24. tesorotools/database/__init__.py +0 -0
  25. tesorotools/database/push.py +70 -0
  26. tesorotools/dependencies/__init__.py +0 -0
  27. tesorotools/dependencies/functions.py +11 -0
  28. tesorotools/dependencies/node.py +34 -0
  29. tesorotools/dependencies/resolution.py +118 -0
  30. tesorotools/main.py +37 -0
  31. tesorotools/offsets/__init__.py +0 -0
  32. tesorotools/offsets/offsets.py +439 -0
  33. tesorotools/offsets/outliers.py +15 -0
  34. tesorotools/render/__init__.py +17 -0
  35. tesorotools/render/content/__init__.py +0 -0
  36. tesorotools/render/content/content.py +17 -0
  37. tesorotools/render/content/images.py +147 -0
  38. tesorotools/render/content/section.py +53 -0
  39. tesorotools/render/content/subtitle.py +53 -0
  40. tesorotools/render/content/table.py +308 -0
  41. tesorotools/render/content/text.py +23 -0
  42. tesorotools/render/content/title.py +40 -0
  43. tesorotools/render/report.py +31 -0
  44. tesorotools/utils/__init__.py +0 -0
  45. tesorotools/utils/config.py +35 -0
  46. tesorotools/utils/globals.py +14 -0
  47. tesorotools/utils/matplotlib.py +38 -0
  48. tesorotools/utils/series.py +40 -0
  49. tesorotools/utils/shortcuts.py +32 -0
  50. tesorotools/utils/template.py +126 -0
  51. tesorotools_python-0.0.18.dist-info/METADATA +16 -0
  52. tesorotools_python-0.0.18.dist-info/RECORD +53 -0
  53. tesorotools_python-0.0.18.dist-info/WHEEL +4 -0
@@ -0,0 +1,200 @@
1
+ from math import floor
2
+ from pathlib import Path
3
+ from typing import Any
4
+
5
+ import pandas as pd
6
+
7
+ from tesorotools.dependencies.resolution import collect_series
8
+ from tesorotools.offsets.outliers import flag_outliers
9
+ from tesorotools.utils.globals import DEBUG
10
+ from tesorotools.utils.matplotlib import format_annotation, is_zero
11
+
12
+ # this file is by far the worst and most spaghettified, must be rewritten
13
+
14
+ # to global config
15
+ GOOD: str = "00c800"
16
+ BAD: str = "c80000"
17
+ THRESHOLD: float = 1
18
+ SHADE_LEVELS = 2
19
+
20
+
21
+ def _shade_intensity(
22
+ ratio: float, shade_levels: int = 2, continuous: bool = False
23
+ ) -> str:
24
+ # intensity may vary from 150 (highest) to 255 (lowest), a grand difference of 105
25
+ # there are SHADE_LEVELS levels, so increments will be of 105/SHADE_LEVELS
26
+ corrected_ratio: float = min(ratio, shade_levels)
27
+ corrected_ratio: float = (
28
+ floor(corrected_ratio) if not continuous else corrected_ratio
29
+ )
30
+ increment: float = (corrected_ratio - 1) * (105 / shade_levels)
31
+ intensity: float = 255 - increment
32
+ intensity_hex: str = f"{int(intensity):x}"
33
+ return intensity_hex
34
+
35
+
36
+ def _generate_column(
37
+ column_data: pd.Series,
38
+ column_cfg: dict[str, Any],
39
+ outliers_flags: pd.Series | None = None,
40
+ ):
41
+ # TODO: factor out
42
+ # data
43
+ if column_cfg["show_units_in_title"]:
44
+ column_data.name = f"{column_cfg["name"]} ({column_cfg["unit"]})"
45
+ else:
46
+ column_data.name = column_cfg["name"]
47
+ column_cfg["formatted_name"] = column_data.name
48
+
49
+ unit = (
50
+ column_cfg["unit"]
51
+ if column_cfg["show_units_in_cell"] and column_cfg["unit"] is not None
52
+ else ""
53
+ )
54
+ scaled_data: pd.Series = column_data * column_cfg["scale"]
55
+ formatted_data = scaled_data.apply(
56
+ lambda x: format_annotation(
57
+ x, decimals=column_cfg["decimals"], units=unit
58
+ )
59
+ )
60
+ zeros: pd.Series = scaled_data.apply(
61
+ lambda x: is_zero(x, decimals=column_cfg["decimals"])
62
+ )
63
+ positives: pd.Series = scaled_data > 0
64
+ negatives: pd.Series = scaled_data < 0
65
+
66
+ # colors
67
+ colors_cfg: bool = column_cfg["colors"]
68
+ color_data: pd.Series = pd.Series(
69
+ index=formatted_data.index, name=column_data.name, dtype=str
70
+ )
71
+ if colors_cfg:
72
+ positive_good: bool = column_cfg["positive_good"]
73
+ color_data[positives] = GOOD if positive_good else BAD
74
+ color_data.loc[negatives] = BAD if positive_good else GOOD
75
+ color_data.loc[zeros.values] = pd.NA
76
+
77
+ # shades
78
+ shade_data: pd.Series = pd.Series(
79
+ index=formatted_data.index, name=column_data.name, dtype=str
80
+ )
81
+ if outliers_flags is not None:
82
+ thresholds: pd.Series = abs(outliers_flags / THRESHOLD)
83
+ intensities: pd.Series = thresholds.apply(
84
+ lambda x: _shade_intensity(x, SHADE_LEVELS)
85
+ )
86
+ shade_data[(thresholds >= 1) & (outliers_flags > 0)] = intensities[
87
+ (thresholds >= 1) & (outliers_flags > 0)
88
+ ].apply(lambda x: f"00{x}00" if positive_good else f"{x}0000")
89
+ shade_data[(thresholds >= 1) & (outliers_flags < 0)] = intensities[
90
+ (thresholds >= 1) & (outliers_flags < 0)
91
+ ].apply(lambda x: f"{x}0000" if positive_good else f"00{x}00")
92
+
93
+ return formatted_data, color_data, shade_data
94
+
95
+
96
+ def _generate_block(block_data: pd.DataFrame, block_cfg: dict[str, Any]):
97
+ columns: dict[str, Any] = block_cfg["columns"]
98
+ formatted_columns: list[pd.Series] = []
99
+ color_columns: list[pd.Series] = []
100
+ shade_columns: list[pd.Series] = []
101
+ sort_idx: pd.Index | None = None
102
+ for column_name, column_cfg in columns.items():
103
+ last_date: pd.Timestamp = block_data.index.get_level_values(
104
+ level=0
105
+ ).max()
106
+ block_data = block_data.rename(columns=block_cfg["series"])
107
+ offset: str = column_cfg["offset"]
108
+ difference: str = column_cfg["difference"]
109
+ stat: str = column_cfg["stat"]
110
+ outliers: bool = column_cfg["outliers"]
111
+
112
+ stat_data = block_data.loc[
113
+ (last_date, offset, difference, slice(None)), :
114
+ ]
115
+ stat_data.index = stat_data.index.get_level_values(level=-1)
116
+
117
+ outliers_flags: pd.Series | None = None
118
+ if outliers:
119
+ outliers_flags = flag_outliers(stat_data.T)
120
+
121
+ column_data: pd.Series = stat_data.loc[stat, :]
122
+ # sort capability
123
+ sort: str = block_cfg.get("sort", None)
124
+ if sort is not None and column_name == sort:
125
+ column_data: pd.Series = column_data.sort_values(ascending=False)
126
+ sort_idx = column_data.index
127
+ formatted_column, color_column, shade_column = _generate_column(
128
+ column_data, column_cfg, outliers_flags
129
+ )
130
+ formatted_columns.append(formatted_column)
131
+ color_columns.append(color_column)
132
+ shade_columns.append(shade_column)
133
+
134
+ if sort_idx is not None:
135
+ formatted_columns = [s.reindex(sort_idx) for s in formatted_columns]
136
+ color_columns = [s.reindex(sort_idx) for s in color_columns]
137
+ shade_columns = [s.reindex(sort_idx) for s in shade_columns]
138
+
139
+ formatted_block: pd.DataFrame = pd.concat(formatted_columns, axis=1)
140
+ color_block: pd.DataFrame = pd.concat(color_columns, axis=1)
141
+ shade_block: pd.DataFrame = pd.concat(shade_columns, axis=1)
142
+
143
+ formatted_block.columns.name = block_cfg["title"]
144
+ color_block.columns.name = block_cfg["title"]
145
+ shade_block.columns.name = block_cfg["title"]
146
+ return formatted_block, color_block, shade_block
147
+
148
+
149
+ def generate_table(table_data: pd.DataFrame, table_cfg: dict[str, Any]):
150
+ blocks: dict[str, dict] = table_cfg["blocks"]
151
+ formatted_blocks: list[pd.DataFrame] = []
152
+ color_blocks: list[pd.DataFrame] = []
153
+ shade_blocks: list[pd.DataFrame] = []
154
+ axis = 0 if table_cfg["axis"] == "vertical" else 1
155
+ # sorting capabilities
156
+ for block_name, block_cfg in blocks.items():
157
+ series_dict: dict[str, str] = block_cfg["series"]
158
+ block_data: pd.DataFrame = table_data.loc[:, series_dict.keys()]
159
+ formatted_block, color_block, shade_block = _generate_block(
160
+ block_data, block_cfg
161
+ )
162
+ formatted_blocks.append(formatted_block)
163
+ color_blocks.append(color_block)
164
+ shade_blocks.append(shade_block)
165
+ formatted_table = pd.concat(
166
+ formatted_blocks,
167
+ axis=axis,
168
+ keys=[
169
+ formatted_block.columns.name for formatted_block in formatted_blocks
170
+ ],
171
+ )
172
+ color_table = pd.concat(
173
+ color_blocks,
174
+ axis=axis,
175
+ keys=[
176
+ formatted_block.columns.name for formatted_block in formatted_blocks
177
+ ],
178
+ )
179
+ shade_table = pd.concat(
180
+ shade_blocks,
181
+ axis=axis,
182
+ keys=[
183
+ formatted_block.columns.name for formatted_block in formatted_blocks
184
+ ],
185
+ )
186
+ return formatted_table, color_table, shade_table
187
+
188
+
189
+ def generate_tables_from_flash(
190
+ out_path: Path, flash: pd.DataFrame, config_dicts: dict[str, dict]
191
+ ):
192
+ for table_name, table_cfg in config_dicts.items():
193
+ series: list[str] = list(collect_series(table_cfg))
194
+ table_data: pd.DataFrame = flash.loc[:, series]
195
+ formatted_table, color_table, shade_table = generate_table(
196
+ table_data, table_cfg
197
+ )
198
+ formatted_table.to_feather(out_path / f"{table_name}.feather")
199
+ color_table.to_feather(out_path / f"{table_name}_color.feather")
200
+ shade_table.to_feather(out_path / f"{table_name}_shade.feather")
@@ -0,0 +1,218 @@
1
+ # pending to assure stylesheet data and fonts are only loaded once
2
+
3
+ from pathlib import Path
4
+ from typing import Any
5
+
6
+ import matplotlib.pyplot as plt
7
+ import pandas as pd
8
+ from matplotlib.ticker import FuncFormatter
9
+ from pandas import Timestamp
10
+
11
+ from tesorotools.utils.config import merge
12
+ from tesorotools.utils.globals import DEBUG
13
+ from tesorotools.utils.matplotlib import (
14
+ PLOT_CONFIG,
15
+ format_annotation,
16
+ load_fonts,
17
+ )
18
+
19
+ TYPE_CURVE_CONFIG: dict[str, Any] = PLOT_CONFIG["type_curve"]
20
+ AX_CONFIG: dict[str, Any] = PLOT_CONFIG["ax"]
21
+ FIG_CONFIG: dict[str, Any] = PLOT_CONFIG["figure"]
22
+
23
+ load_fonts()
24
+
25
+
26
+ def _style_spines(
27
+ ax: plt.Axes,
28
+ decimals: int,
29
+ units: str,
30
+ *,
31
+ color: str,
32
+ linewidth: str,
33
+ ):
34
+ ax.grid(visible=True, axis="y")
35
+ for spine in ax.spines.values():
36
+ spine.set_color(color)
37
+ spine.set_linewidth(linewidth)
38
+ ax.yaxis.tick_right()
39
+ ax.yaxis.set_major_formatter(
40
+ FuncFormatter(lambda y, _: format_annotation(y, decimals, units))
41
+ )
42
+ ax.tick_params(axis="both", which="major")
43
+ ax.set_xticks(
44
+ ax.get_xticks(), ax.get_xticklabels(), rotation=45, ha="right"
45
+ )
46
+ for tick in ax.get_xticklines():
47
+ tick.set_markeredgecolor(color)
48
+ for tick in ax.get_yticklines():
49
+ tick.set_markeredgecolor(color)
50
+
51
+
52
+ def _style_baseline(ax: plt.Axes, **baseline_config):
53
+ color: str = baseline_config["color"]
54
+ bottom_lim, top_lim = ax.get_ylim()
55
+ ax.set_ylim(bottom=min(0, bottom_lim), top=max(0, top_lim))
56
+ bottom_lim, top_lim = ax.get_ylim()
57
+ if bottom_lim == 0:
58
+ ax.spines["bottom"].set_edgecolor(color)
59
+ elif top_lim == 0:
60
+ ax.spines["top"].set_edgecolor(color)
61
+ else:
62
+ ax.axhline(y=0, **baseline_config)
63
+
64
+
65
+ def _format_data(data: pd.DataFrame) -> dict[str, Any]:
66
+ # metadata
67
+ date_index: pd.DatetimeIndex = data.index
68
+ current_date: Timestamp = date_index.max()
69
+ current_year: int = current_date.year
70
+ last_year: int = (current_date - pd.DateOffset(years=1)).year
71
+
72
+ # current data
73
+ current_data: pd.Series = data.loc[current_date, :]
74
+ current_data.name = "current_data"
75
+
76
+ # current year
77
+ current_year_data: pd.DataFrame = data.loc[
78
+ date_index.year == current_year, :
79
+ ]
80
+ current_year_max: pd.Series = current_year_data.max()
81
+ current_year_max.name = "current_year_max"
82
+ current_year_min: pd.Series = current_year_data.min()
83
+ current_year_min.name = "current_year_min"
84
+
85
+ # last year
86
+ last_year_data: pd.DataFrame = data.loc[date_index.year == last_year, :]
87
+ last_year_max: pd.Series = last_year_data.max()
88
+ last_year_max.name = "last_year_max"
89
+ last_year_min: pd.Series = last_year_data.min()
90
+ last_year_min.name = "last_year_min"
91
+
92
+ formatted_data: pd.DataFrame = pd.concat(
93
+ [
94
+ last_year_max,
95
+ last_year_min,
96
+ current_year_max,
97
+ current_year_min,
98
+ current_data,
99
+ ],
100
+ axis=1,
101
+ )
102
+
103
+ return {
104
+ "data": formatted_data,
105
+ "current_date": current_date.strftime("%d/%m/%Y"),
106
+ "current_year": current_year,
107
+ "last_year": last_year,
108
+ }
109
+
110
+
111
+ def _plot_current_data(
112
+ ax: plt.Axes,
113
+ data: pd.DataFrame,
114
+ date_fmt: str,
115
+ *,
116
+ linewidth: float,
117
+ marker: str,
118
+ points_to_mark: list[str],
119
+ color: str,
120
+ decimals: int,
121
+ units: str,
122
+ ):
123
+ data.plot(
124
+ ax=ax,
125
+ color=color,
126
+ linewidth=linewidth,
127
+ label=date_fmt,
128
+ )
129
+ for point in points_to_mark:
130
+ value = data.loc[point]
131
+ ax.plot(
132
+ point,
133
+ value,
134
+ marker=marker,
135
+ color=color,
136
+ )
137
+ ax.annotate(
138
+ format_annotation(value, decimals, units),
139
+ (point, value),
140
+ textcoords="offset points",
141
+ xytext=(0, 10),
142
+ ha="center",
143
+ )
144
+
145
+
146
+ def plot_type_curve(
147
+ data: pd.DataFrame,
148
+ out_file: Path,
149
+ **config,
150
+ ):
151
+ config: dict[str, Any] = merge(config, TYPE_CURVE_CONFIG)
152
+
153
+ if config["yaxis"]["units"] == "p.b.":
154
+ data = data * 100
155
+
156
+ formatted_assets: dict[str, Any] = _format_data(data)
157
+ formatted_data: pd.DataFrame = formatted_assets["data"]
158
+ due_index: pd.Index = formatted_data.index
159
+
160
+ fig = plt.figure(**FIG_CONFIG)
161
+ ax: plt.Axes = fig.add_subplot()
162
+
163
+ last_config: dict[str, Any] = config["last"]
164
+ ax.fill_between(
165
+ due_index,
166
+ formatted_data["last_year_min"],
167
+ formatted_data["last_year_max"],
168
+ alpha=last_config["alpha"],
169
+ color=last_config["color"],
170
+ edgecolor=None,
171
+ label=f"Rango {formatted_assets['last_year']}",
172
+ )
173
+
174
+ current_config: dict[str, Any] = config["current"]
175
+ ax.fill_between(
176
+ due_index,
177
+ formatted_data["current_year_min"],
178
+ formatted_data["current_year_max"],
179
+ alpha=current_config["alpha"],
180
+ color=current_config["color"],
181
+ edgecolor=None,
182
+ label=f"Rango {formatted_assets['current_year']}",
183
+ )
184
+
185
+ _plot_current_data(
186
+ ax,
187
+ formatted_data["current_data"],
188
+ formatted_assets["current_date"],
189
+ **config["line"],
190
+ )
191
+ _style_spines(ax, **config["yaxis"], **AX_CONFIG["spines"])
192
+ _style_baseline(ax, **AX_CONFIG["baseline"])
193
+ ax.legend(
194
+ loc="upper center",
195
+ bbox_to_anchor=(0.5, config["legend_sep"]),
196
+ ncol=3,
197
+ )
198
+ fig.savefig(out_file)
199
+
200
+
201
+ # data is expected to be a simple time series data, columns are series and rows represents dates
202
+ def plot_type_curves(
203
+ out_path: Path, data: pd.DataFrame, config_dicts: dict[str, Any]
204
+ ):
205
+ for name, config in config_dicts.items():
206
+ if not name.startswith("."): # aux entries
207
+ series: dict[str, str] = config["series"]
208
+ if len(series) < 2:
209
+ raise ValueError(
210
+ f"In plot {name}: A type curve must have at least two due periods. Given periods: {series.keys()}"
211
+ )
212
+ trimmed_data: pd.DataFrame = data.loc[:, series.keys()]
213
+ trimmed_data: pd.DataFrame = trimmed_data.rename(columns=series)
214
+ plot_type_curve(
215
+ data=trimmed_data,
216
+ out_file=out_path / f"{name}.png",
217
+ **config,
218
+ )
@@ -0,0 +1,5 @@
1
+ En esta carpeta se guardarán todos los *assets* del proyecto, como
2
+
3
+ - [fonts](fonts/): Fuentes (archivos *.otf).
4
+ - [plots.yaml](plots.yaml): Archivo de configuración general para los gráficos.
5
+ - [tesoro.mplstyle](tesoro.mplstyle): Archivo de estilos *matplotlib* para los gráficos.
@@ -0,0 +1 @@
1
+ Archivos *.otf de fuentes. No los incluimos en el control de versiones.
@@ -0,0 +1,43 @@
1
+ # general plot config file
2
+
3
+ style:
4
+ font: Cabinet Grotesk
5
+
6
+ figure:
7
+ dpi: 500
8
+ layout: constrained
9
+
10
+ ax:
11
+ spines:
12
+ color: gray
13
+ linewidth: 1
14
+ baseline:
15
+ color: "#d9e1fc"
16
+ linestyle: solid
17
+ linewidth: 1
18
+ zorder: 1
19
+
20
+ type_curve:
21
+ last:
22
+ alpha: 0.2
23
+ color: C1
24
+ current:
25
+ alpha: 0.3
26
+ color: C0
27
+ line:
28
+ linewidth: 2
29
+ marker: D
30
+ color: C0
31
+ legend_sep: -0.1
32
+
33
+ barh:
34
+ highlight_factor: 0.4
35
+ padding: 5
36
+
37
+ line:
38
+ legend_sep: -0.125
39
+ ncol: 5
40
+
41
+ table:
42
+ style: Light Shading Accent 1
43
+ autofit: False
@@ -0,0 +1,21 @@
1
+ # fonts
2
+ font.size: 12.0
3
+ xtick.labelsize: 12.0
4
+ ytick.labelsize: 12.0
5
+ legend.fontsize: 12.0
6
+
7
+ # modified dashed_pattern
8
+ lines.dashed_pattern: 10, 5
9
+
10
+ # markers
11
+ lines.markersize: 8
12
+
13
+ # grids
14
+ grid.color: d9e1fc
15
+ grid.linestyle: dashed
16
+ grid.linewidth: 0.5
17
+ grid.alpha: 0.5
18
+
19
+ # color palette
20
+ axes.prop_cycle: cycler('color', ['001e93', 'ffbd4c', '6d6d6d', '000000', 'e6821e', '2957ff', 'fba737', '5da6ff', '00ebb2', '6d0000', '009200', 'df2871', 'd9e1fc', 'ffddab'])
21
+
tesorotools/convert.py ADDED
@@ -0,0 +1,99 @@
1
+ # this file may migrate to the utils package
2
+
3
+ from pathlib import Path
4
+
5
+ import pandas as pd
6
+
7
+ from tesorotools.artists.barh_plot import plot_barh_charts_from_flash
8
+ from tesorotools.artists.line_plot import plot_line_charts
9
+ from tesorotools.artists.table import generate_tables_from_flash
10
+ from tesorotools.artists.type_curve import plot_type_curves
11
+ from tesorotools.dependencies.resolution import (
12
+ compute_derivate_series,
13
+ concat_derivate_series,
14
+ resolve_series,
15
+ )
16
+ from tesorotools.offsets.offsets import trim
17
+ from tesorotools.utils.config import read_config
18
+
19
+
20
+ def index_replace(old: str, new: str, index: pd.MultiIndex) -> pd.MultiIndex:
21
+ return pd.MultiIndex.from_tuples(
22
+ [
23
+ tuple(
24
+ [
25
+ x.replace(old, new) if isinstance(x, str) else x
26
+ for x in tuple_index
27
+ ]
28
+ )
29
+ for tuple_index in index
30
+ ]
31
+ )
32
+
33
+
34
+ def cheap_convert(old_file: Path) -> pd.DataFrame:
35
+ old = pd.read_feather(old_file)
36
+
37
+ trimmed = old.loc[(slice(None), "no", "absolute", "value"), :].copy()
38
+
39
+ old = old.loc[
40
+ (
41
+ slice(None),
42
+ ["day", "mtd", "week", "year", "tariff_crisis"],
43
+ slice(None),
44
+ slice(None),
45
+ ),
46
+ :,
47
+ ]
48
+ old.index = index_replace("day", "bday", old.index)
49
+ old.index = index_replace("week", "ftd", old.index)
50
+ old.index = index_replace("year", "ytd", old.index)
51
+ old.index = index_replace("roll_var", "roll_std", old.index)
52
+ old.index = index_replace("tariff_crisis", "2025-04-02", old.index)
53
+
54
+ trimmed.index = index_replace("absolute", "no", trimmed.index)
55
+
56
+ new = pd.concat([old, trimmed])
57
+ return new
58
+
59
+
60
+ if __name__ == "__main__":
61
+ preprocess = True
62
+ barh_config_dicts = read_config(Path("examples") / "barh_plots.yaml")
63
+ line_config_dicts = read_config(Path("examples") / "line_plots.yaml")
64
+ type_config_dicts = read_config(Path("examples") / "type_curves.yaml")
65
+ table_config_dicts = read_config(Path("examples") / "tables.yaml")
66
+
67
+ if preprocess:
68
+ old_file: Path = Path("debug") / "flash.feather"
69
+ dependencies_cfg = read_config(Path("examples") / "dependencies.yaml")
70
+ flash: pd.DataFrame = cheap_convert(old_file)
71
+ resolved_dict = resolve_series(
72
+ [
73
+ barh_config_dicts,
74
+ line_config_dicts,
75
+ type_config_dicts,
76
+ table_config_dicts,
77
+ ],
78
+ dependencies_cfg,
79
+ )
80
+ independent_full_df = flash.loc[:, list(resolved_dict["independent"])]
81
+ independent_trimmed_df = trim(independent_full_df)
82
+ dependent_trimmed_df = compute_derivate_series(
83
+ resolved_dict["dependent"], independent_trimmed_df
84
+ )
85
+ offsets_config = read_config(Path("examples") / "offsets.yaml")
86
+ full_df = concat_derivate_series(
87
+ independent_full_df,
88
+ dependent_trimmed_df,
89
+ offsets_config,
90
+ # force_trim=True,
91
+ )
92
+ full_df.to_feather("derivates.feather")
93
+
94
+ full_df = pd.read_feather("derivates.feather")
95
+ trimmed_df = trim(full_df)
96
+ plot_barh_charts_from_flash(full_df, barh_config_dicts)
97
+ plot_line_charts(trimmed_df, line_config_dicts)
98
+ plot_type_curves(trimmed_df, type_config_dicts)
99
+ generate_tables_from_flash(full_df, table_config_dicts)
@@ -0,0 +1,14 @@
1
+ # LSEG Data Library for Python
2
+
3
+ ## Capa de acceso
4
+
5
+ ## Capa de contenido
6
+
7
+ ## Capa de reparto
8
+
9
+ ## Capa de sesión
10
+
11
+ ## Referencias
12
+
13
+ - https://cdn.refinitiv.com/public/lseg-lib-python-doc/2.0.0.2/book/en/index.html
14
+ - https://pypi.org/project/lseg-data/
File without changes
@@ -0,0 +1,26 @@
1
+ import numpy as np
2
+ import pandas as pd
3
+
4
+ from tesorotools.utils.config import read_config
5
+ from tesorotools.utils.globals import DEBUG, EXAMPLES
6
+
7
+ # just mocking
8
+ CATALOG: dict[str, str] = read_config(EXAMPLES / "data.yaml")["debug"]
9
+
10
+
11
+ def get_series(start: str, end: str, series: list[str]) -> pd.DataFrame:
12
+ # series is a list of agnostic ids
13
+ specific_ids = []
14
+ for agnostic_id in series:
15
+ specific_id: str | None = CATALOG.get(agnostic_id, None)
16
+ if specific_id is None:
17
+ raise KeyError(f"{agnostic_id} not found in debug configuration")
18
+ specific_ids.append(specific_id)
19
+
20
+ index: pd.DatetimeIndex = pd.date_range(start=start, end=end).sort_values()
21
+ df: pd.DataFrame = pd.DataFrame(
22
+ data=np.random.randn(len(index), len(series)),
23
+ index=index,
24
+ columns=series,
25
+ )
26
+ return df