wbfdm 1.44.0__py2.py3-none-any.whl → 1.44.1__py2.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.
Potentially problematic release.
This version of wbfdm might be problematic. Click here for more details.
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import pandas as pd
|
|
2
|
+
from django.contrib.messages import warning
|
|
2
3
|
from django.utils.functional import cached_property
|
|
3
4
|
from wbcore.contrib.io.viewsets import ExportPandasAPIViewSet
|
|
4
5
|
from wbcore.metadata.configs.endpoints import NoEndpointViewConfig
|
|
@@ -40,6 +41,11 @@ class FinancialSummary(InstrumentMixin, ExportPandasAPIViewSet):
|
|
|
40
41
|
]
|
|
41
42
|
)
|
|
42
43
|
|
|
44
|
+
def add_messages(self, request, instance=None, **kwargs):
|
|
45
|
+
super().add_messages(request, instance=instance, **kwargs)
|
|
46
|
+
if self.df.empty:
|
|
47
|
+
warning(request, "There is no data available for the Financial Summary table", extra_tags="auto_close=0")
|
|
48
|
+
|
|
43
49
|
def get_dataframe(self, request, queryset, **kwargs):
|
|
44
50
|
# Get all necessary data from the dataloader and load a dataframe
|
|
45
51
|
df = pd.DataFrame(
|
|
@@ -49,123 +55,127 @@ class FinancialSummary(InstrumentMixin, ExportPandasAPIViewSet):
|
|
|
49
55
|
to_index=3,
|
|
50
56
|
)
|
|
51
57
|
)
|
|
58
|
+
if not df.empty:
|
|
59
|
+
# Pivot the data
|
|
60
|
+
df = df.pivot_table(
|
|
61
|
+
columns="financial",
|
|
62
|
+
index=["year", "period_end_date", "estimate"],
|
|
63
|
+
values="value",
|
|
64
|
+
).rename_axis(columns=None)
|
|
52
65
|
|
|
53
|
-
|
|
54
|
-
df = df.pivot_table(
|
|
55
|
-
columns="financial",
|
|
56
|
-
index=["year", "period_end_date", "estimate"],
|
|
57
|
-
values="value",
|
|
58
|
-
).rename_axis(columns=None)
|
|
59
|
-
|
|
60
|
-
sanitize_fields(df, map(lambda enum: enum.value, self.FINANCIAL_VALUES))
|
|
66
|
+
sanitize_fields(df, map(lambda enum: enum.value, self.FINANCIAL_VALUES))
|
|
61
67
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
68
|
+
# Compute all necessary fields
|
|
69
|
+
df["revenue_growth"] = df["revenue"].pct_change() * 100
|
|
70
|
+
df["gross_profit_pct"] = df["gross_profit"] / df["revenue"] * 100
|
|
71
|
+
df["ebitda_pct"] = df["ebitda"] / df["revenue"] * 100
|
|
72
|
+
df["ebit_pct"] = df["ebit"] / df["revenue"] * 100
|
|
73
|
+
df["net_income_pct"] = df["net_income"] / df["revenue"] * 100
|
|
74
|
+
df["eps_growth"] = pct_change_with_negative_values(df, "eps") * 100
|
|
69
75
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
76
|
+
df["net_debt_ebitda"] = df["net_debt"] / df["ebitda"]
|
|
77
|
+
df["debt_assets"] = df["total_debt"] / df["total_assets"] * 100
|
|
78
|
+
df["debt_equity"] = df["total_debt"] / df["total_assets"] * 100
|
|
73
79
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
80
|
+
df["interest_coverage_ratio"] = df["ebit"] / df["interest_expense"]
|
|
81
|
+
df["free_cash_flow_per_share"] = df["free_cash_flow"] / df["shares_outstanding"]
|
|
82
|
+
df["free_cash_flow_per_share_growth"] = (
|
|
83
|
+
pct_change_with_negative_values(df, "free_cash_flow_per_share") * 100
|
|
84
|
+
)
|
|
77
85
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
86
|
+
# Normalize data
|
|
87
|
+
df["revenue"] = df["revenue"] / 1_000_000
|
|
88
|
+
df["net_income"] = df["net_income"] / 1_000_000
|
|
81
89
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
90
|
+
# Sort the columns into the desired order
|
|
91
|
+
# Reset the index to get the period end date as a column
|
|
92
|
+
# Pivot back to have the dates on top
|
|
93
|
+
df = df[self.FIELDS]
|
|
86
94
|
|
|
87
|
-
|
|
88
|
-
|
|
95
|
+
# Reset the 2 indices and transpose back
|
|
96
|
+
df = df.reset_index(level=[0, 2]).sort_index()
|
|
89
97
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
98
|
+
# Adjust the columns to be in a different format
|
|
99
|
+
df.index = df.index.map(lambda x: x.strftime("%b/%y"))
|
|
100
|
+
MAX_ROW = 8
|
|
101
|
+
if df.shape[0] > MAX_ROW:
|
|
102
|
+
df = df.iloc[1:] # remove first row
|
|
103
|
+
df = df.iloc[0 : min([df.shape[0], MAX_ROW])] # keep only 8 row maximum
|
|
96
104
|
|
|
97
|
-
|
|
98
|
-
|
|
105
|
+
self._estimate_columns = df["estimate"].to_dict()
|
|
106
|
+
df = df.drop(columns=["estimate"], errors="ignore")
|
|
99
107
|
return df
|
|
100
108
|
|
|
101
109
|
def manipulate_dataframe(self, df):
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
110
|
+
if not df.empty:
|
|
111
|
+
df = df.T
|
|
112
|
+
# Add labels for human readable output
|
|
113
|
+
df["label"] = self.LABELS
|
|
105
114
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
115
|
+
override_number_to_percent(
|
|
116
|
+
df,
|
|
117
|
+
*list(
|
|
118
|
+
map(
|
|
119
|
+
lambda x: df.index == x,
|
|
120
|
+
[
|
|
121
|
+
"revenue_growth",
|
|
122
|
+
"gross_profit_pct",
|
|
123
|
+
"ebitda_pct",
|
|
124
|
+
"ebit_pct",
|
|
125
|
+
"net_income_pct",
|
|
126
|
+
"eps_growth",
|
|
127
|
+
"roe",
|
|
128
|
+
"roic",
|
|
129
|
+
"roc",
|
|
130
|
+
"roa",
|
|
131
|
+
"debt_equity",
|
|
132
|
+
"debt_assets",
|
|
133
|
+
"free_cash_flow_per_share_growth",
|
|
134
|
+
],
|
|
135
|
+
)
|
|
136
|
+
),
|
|
137
|
+
)
|
|
129
138
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
139
|
+
override_number_to_x(
|
|
140
|
+
df,
|
|
141
|
+
*list(
|
|
142
|
+
map(
|
|
143
|
+
lambda x: df.index == x,
|
|
144
|
+
[
|
|
145
|
+
"net_debt_ebitda",
|
|
146
|
+
"interest_coverage_ratio",
|
|
147
|
+
],
|
|
148
|
+
)
|
|
149
|
+
),
|
|
150
|
+
)
|
|
142
151
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
152
|
+
override_number_to_decimal(
|
|
153
|
+
df,
|
|
154
|
+
*list(
|
|
155
|
+
map(
|
|
156
|
+
lambda x: df.index == x,
|
|
157
|
+
[
|
|
158
|
+
"revenue",
|
|
159
|
+
"net_income",
|
|
160
|
+
],
|
|
161
|
+
)
|
|
162
|
+
),
|
|
163
|
+
)
|
|
155
164
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
165
|
+
override_number_to_integer_without_decorations(
|
|
166
|
+
df,
|
|
167
|
+
*list(
|
|
168
|
+
map(
|
|
169
|
+
lambda x: df.index == x,
|
|
170
|
+
[
|
|
171
|
+
"year",
|
|
172
|
+
],
|
|
173
|
+
)
|
|
174
|
+
),
|
|
175
|
+
)
|
|
167
176
|
|
|
168
|
-
|
|
177
|
+
df = df.reset_index(names="id")
|
|
178
|
+
return df
|
|
169
179
|
|
|
170
180
|
@cached_property
|
|
171
181
|
def fiscal_columns(self) -> list:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: wbfdm
|
|
3
|
-
Version: 1.44.
|
|
3
|
+
Version: 1.44.1
|
|
4
4
|
Summary: The workbench module ensures rapid access to diverse financial data (market, fundamental, forecasts, ESG), with features for storing instruments, classifying them, and conducting financial analysis.
|
|
5
5
|
Author-email: Christopher Wittlinger <c.wittlinger@stainly.com>
|
|
6
6
|
Requires-Dist: roman==4.*
|
|
@@ -334,7 +334,7 @@ wbfdm/viewsets/configs/titles/statement_with_estimates.py,sha256=ZL4K0hOM0dVBplu
|
|
|
334
334
|
wbfdm/viewsets/financial_analysis/__init__.py,sha256=cTTcvGnhz2Ep9RpkyUyTOpjTXJz7BWt1AGAMjiIY9C8,263
|
|
335
335
|
wbfdm/viewsets/financial_analysis/financial_metric_analysis.py,sha256=ZO3iUExFu5BUK8a_wRu9ldOvRKc70l8Jpdjl2_4hp7s,3315
|
|
336
336
|
wbfdm/viewsets/financial_analysis/financial_ratio_analysis.py,sha256=YtsSJUnqHjTpiarZcqo14IhWDXF3UXc_zla-slDpqiU,3097
|
|
337
|
-
wbfdm/viewsets/financial_analysis/financial_summary.py,sha256=
|
|
337
|
+
wbfdm/viewsets/financial_analysis/financial_summary.py,sha256=GHXIBZ6lHmFGxqAT6YMVB7f86BsGu6K--CbUECj0xfY,9245
|
|
338
338
|
wbfdm/viewsets/financial_analysis/statement_with_estimates.py,sha256=1GiSgKZR8iyNK6yJs79eLSt7bo60KQoTv4o3vBsc9xU,6098
|
|
339
339
|
wbfdm/viewsets/instruments/__init__.py,sha256=uydDdU6oZ6W2lgFkr3-cU7WZU7TeokXAA1J0xEgiLD0,2826
|
|
340
340
|
wbfdm/viewsets/instruments/classifications.py,sha256=pDQG9rlXUbc4LvWgVOGTir0Dcp02z-78AODNH-SjynA,11440
|
|
@@ -349,6 +349,6 @@ wbfdm/viewsets/statements/__init__.py,sha256=odxtFYUDICPmz8WCE3nx93EvKZLSPBEI4d7
|
|
|
349
349
|
wbfdm/viewsets/statements/statements.py,sha256=AVU5A7p63uWITEcMDl95iKyN-fBO5RwJlbxHrJZvz7o,4083
|
|
350
350
|
wbfdm/viewsets/technical_analysis/__init__.py,sha256=qtCIBg0uSiZeJq_1tEQFilnorMBkMe6uCMfqar6-cLE,77
|
|
351
351
|
wbfdm/viewsets/technical_analysis/monthly_performances.py,sha256=8VgafjW4efEJKTfBqUvAu-EG2eNawl2Cmh9QFt4sN8w,3973
|
|
352
|
-
wbfdm-1.44.
|
|
353
|
-
wbfdm-1.44.
|
|
354
|
-
wbfdm-1.44.
|
|
352
|
+
wbfdm-1.44.1.dist-info/METADATA,sha256=DI-CEs_MXLDyJDmT3IotMf4wBDpD9CVO8Y2_-ghaQfU,736
|
|
353
|
+
wbfdm-1.44.1.dist-info/WHEEL,sha256=tkmg4JIqwd9H8mL30xA7crRmoStyCtGp0VWshokd1Jc,105
|
|
354
|
+
wbfdm-1.44.1.dist-info/RECORD,,
|
|
File without changes
|