wbfdm 1.55.10rc0__py2.py3-none-any.whl → 1.56.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.
- wbfdm/contrib/qa/dataloaders/market_data.py +1 -1
- wbfdm/contrib/qa/sync/utils.py +11 -8
- wbfdm/filters/instrument_prices.py +0 -1
- wbfdm/import_export/handlers/instrument.py +15 -7
- wbfdm/models/instruments/instruments.py +3 -3
- wbfdm/viewsets/financial_analysis/statement_with_estimates.py +1 -1
- wbfdm/viewsets/instruments/financials_analysis.py +1 -1
- {wbfdm-1.55.10rc0.dist-info → wbfdm-1.56.1.dist-info}/METADATA +1 -1
- {wbfdm-1.55.10rc0.dist-info → wbfdm-1.56.1.dist-info}/RECORD +10 -10
- {wbfdm-1.55.10rc0.dist-info → wbfdm-1.56.1.dist-info}/WHEEL +0 -0
wbfdm/contrib/qa/sync/utils.py
CHANGED
|
@@ -148,12 +148,15 @@ def _delist_existing_duplicates(instrument: Instrument) -> None:
|
|
|
148
148
|
|
|
149
149
|
for identifier_field in unique_identifiers:
|
|
150
150
|
if identifier := getattr(instrument, identifier_field):
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
)
|
|
155
|
-
|
|
156
|
-
|
|
151
|
+
if instrument.delisted_date: # if delisted, we unset the identifier that can lead to constraint error
|
|
152
|
+
setattr(instrument, identifier_field, None)
|
|
153
|
+
else:
|
|
154
|
+
with suppress(Instrument.DoesNotExist):
|
|
155
|
+
duplicate = Instrument.objects.get(
|
|
156
|
+
is_security=True, delisted_date__isnull=True, **{identifier_field: identifier}
|
|
157
|
+
)
|
|
158
|
+
duplicate.delisted_date = date.today() - timedelta(days=1)
|
|
159
|
+
duplicate.save()
|
|
157
160
|
|
|
158
161
|
|
|
159
162
|
def _save_single_instrument(instrument: Instrument) -> None:
|
|
@@ -211,7 +214,7 @@ def _bulk_create_instruments_chunk(instruments: list[Instrument], update_unique_
|
|
|
211
214
|
)
|
|
212
215
|
except IntegrityError:
|
|
213
216
|
# we caught an integrity error on the bulk save, so we try to save one by one
|
|
214
|
-
logger.
|
|
217
|
+
logger.error(
|
|
215
218
|
"we detected an integrity error while bulk saving instruments. We save them one by one and delist the already existing instrument from the db if we can. "
|
|
216
219
|
)
|
|
217
220
|
for instrument in instruments:
|
|
@@ -290,7 +293,7 @@ def trigger_partial_update(
|
|
|
290
293
|
else:
|
|
291
294
|
with connections["qa"].cursor() as cursor:
|
|
292
295
|
cursor.execute(
|
|
293
|
-
"SELECT MAX(last_user_update) FROM sys.dm_db_index_usage_stats WHERE OBJECT_NAME(object_id) = %
|
|
296
|
+
"SELECT MAX(last_user_update) FROM sys.dm_db_index_usage_stats WHERE OBJECT_NAME(object_id) = %s'",
|
|
294
297
|
(table_change_name,),
|
|
295
298
|
)
|
|
296
299
|
max_last_updated_qa = (
|
|
@@ -26,7 +26,6 @@ class FakeDateRange(wb_filters.FilterSet):
|
|
|
26
26
|
|
|
27
27
|
class InstrumentPriceFilterSet(wb_filters.FilterSet):
|
|
28
28
|
date = wb_filters.FinancialPerformanceDateRangeFilter(
|
|
29
|
-
method=wb_filters.DateRangeFilter.base_date_range_filter_method,
|
|
30
29
|
label="Date Range",
|
|
31
30
|
required=True,
|
|
32
31
|
clearable=False,
|
|
@@ -46,7 +46,7 @@ class InstrumentLookup:
|
|
|
46
46
|
cache_key = self._get_cache_key(**kwargs)
|
|
47
47
|
self.cache[cache_key] = instrument
|
|
48
48
|
|
|
49
|
-
def _lookup_security(
|
|
49
|
+
def _lookup_security( # noqa: C901
|
|
50
50
|
self,
|
|
51
51
|
instrument_type=None,
|
|
52
52
|
currency=None,
|
|
@@ -57,7 +57,6 @@ class InstrumentLookup:
|
|
|
57
57
|
**identifiers,
|
|
58
58
|
):
|
|
59
59
|
identifiers = {k: v for k, v in identifiers.items() if v is not None}
|
|
60
|
-
|
|
61
60
|
instrument = None
|
|
62
61
|
|
|
63
62
|
# We need to lookup ticker because some provider gives us ticker with or without space in it
|
|
@@ -113,33 +112,41 @@ class InstrumentLookup:
|
|
|
113
112
|
conditions.append(Q(**{f"{field}": field_value}))
|
|
114
113
|
if field == "isin":
|
|
115
114
|
conditions.append(Q(old_isins__contains=[field_value]))
|
|
115
|
+
if field == "ticker":
|
|
116
|
+
conditions.append(Q(ticker__regex=rf"^{field_value}([A-Za-z]?|\.?[A-Za-z])$"))
|
|
117
|
+
conditions.append(Q(refinitiv_mnemonic_code=f"@{field_value}"))
|
|
118
|
+
|
|
116
119
|
if conditions:
|
|
117
120
|
instruments = instruments.filter(reduce(operator.or_, conditions))
|
|
118
|
-
|
|
119
|
-
|
|
121
|
+
if (
|
|
122
|
+
currency and instruments.filter(currency=currency).exists()
|
|
123
|
+
): # if currency is provides, we use it as validator
|
|
120
124
|
instruments = instruments.filter(currency=currency)
|
|
121
|
-
|
|
122
125
|
if exchange:
|
|
123
126
|
instruments_tmp = instruments.filter(exchange=exchange)
|
|
124
127
|
if instruments_tmp.exists():
|
|
125
128
|
instruments = instruments_tmp
|
|
129
|
+
|
|
126
130
|
# last chance
|
|
127
131
|
if name and instruments.count() > 1:
|
|
128
132
|
instruments = instruments.annotate(similarity_score=TrigramSimilarity("name", name))
|
|
129
133
|
if instruments.filter(similarity_score__gt=self.trigram_similarity_min_score).count() == 1:
|
|
130
134
|
instruments = instruments.filter(similarity_score__gt=self.trigram_similarity_min_score)
|
|
135
|
+
|
|
131
136
|
if instruments.count() == 1:
|
|
132
137
|
instrument = instruments.first()
|
|
133
|
-
elif instrument_type and identifiers:
|
|
138
|
+
elif instrument_type and (name or identifiers):
|
|
134
139
|
# if instrument type was provided but we still didn't find the security, we try without the instrument type in case it was mislabeled
|
|
135
140
|
instrument = self._lookup_security(
|
|
136
141
|
only_investable_universe=only_investable_universe,
|
|
137
142
|
exact_lookup=exact_lookup,
|
|
138
143
|
currency=currency,
|
|
139
144
|
exchange=exchange,
|
|
145
|
+
name=name,
|
|
140
146
|
**identifiers,
|
|
141
147
|
)
|
|
142
|
-
if not instrument and
|
|
148
|
+
if not instrument and identifiers:
|
|
149
|
+
identifiers.pop(list(identifiers.keys())[0])
|
|
143
150
|
# Sometime, identifier provided emptied the queryset of possible instruments. In a last chance approach, we try to only look for security with the given name
|
|
144
151
|
instrument = self._lookup_security(
|
|
145
152
|
only_investable_universe=only_investable_universe,
|
|
@@ -148,6 +155,7 @@ class InstrumentLookup:
|
|
|
148
155
|
currency=currency,
|
|
149
156
|
exchange=exchange,
|
|
150
157
|
name=name,
|
|
158
|
+
**identifiers,
|
|
151
159
|
)
|
|
152
160
|
if instrument and only_investable_universe and not instrument.is_security and instrument.parent:
|
|
153
161
|
instrument = instrument.parent
|
|
@@ -671,11 +671,11 @@ class Instrument(ComplexToStringMixin, TagModelMixin, ImportMixin, InstrumentPMS
|
|
|
671
671
|
raise ValidationError("An instrument in the investable universe cannot have children")
|
|
672
672
|
return self
|
|
673
673
|
|
|
674
|
-
def pre_save(self):
|
|
674
|
+
def pre_save(self): # noqa: C901
|
|
675
675
|
if self.instrument_type:
|
|
676
676
|
self.is_security = self.instrument_type.is_security
|
|
677
|
-
if self.delisted_date:
|
|
678
|
-
|
|
677
|
+
# if self.delisted_date:
|
|
678
|
+
# self.is_security = False
|
|
679
679
|
if not self.name_repr:
|
|
680
680
|
self.name_repr = self.name
|
|
681
681
|
if not self.founded_year and self.inception_date:
|
|
@@ -139,7 +139,7 @@ class StatementWithEstimatesPandasViewSet(InstrumentMixin, ExportPandasAPIViewSe
|
|
|
139
139
|
return self.df.columns
|
|
140
140
|
|
|
141
141
|
def get_ordering_fields(self):
|
|
142
|
-
return self.columns
|
|
142
|
+
return [x for x in self.columns if x != "progress"]
|
|
143
143
|
|
|
144
144
|
@cached_property
|
|
145
145
|
def year_columns(self):
|
|
@@ -118,7 +118,7 @@ class ValuationRatiosChartView(InstrumentMixin, viewsets.ChartViewSet):
|
|
|
118
118
|
filterset_class = FinancialAnalysisValuationRatiosFilterSet
|
|
119
119
|
LIST_DOCUMENTATION = "wbfdm/markdown/documentation/financial_analysis_instrument_ratios.md"
|
|
120
120
|
|
|
121
|
-
def get_plotly(self, queryset):
|
|
121
|
+
def get_plotly(self, queryset): # noqa: C901
|
|
122
122
|
# Set plotly as the default plotting lib
|
|
123
123
|
pd.options.plotting.backend = "plotly"
|
|
124
124
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: wbfdm
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.56.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.*
|
|
@@ -102,7 +102,7 @@ wbfdm/contrib/qa/dataloaders/adjustments.py,sha256=YAYAiCm71QjPt5dZwzezgCQpm5zRW
|
|
|
102
102
|
wbfdm/contrib/qa/dataloaders/corporate_actions.py,sha256=NWk8OCem9niwY5mJCIR11_Wq2gVBbtcrAZedTpzQDYc,2964
|
|
103
103
|
wbfdm/contrib/qa/dataloaders/financials.py,sha256=xUHpvhUkvmdPL_RyWCrs7XgChgTklX5qemmaXMedgkY,3475
|
|
104
104
|
wbfdm/contrib/qa/dataloaders/fx_rates.py,sha256=IYkUV8_8Vmvm4_K9xJpz7VaTgjQUz0y4pb3KyaoiqCM,1985
|
|
105
|
-
wbfdm/contrib/qa/dataloaders/market_data.py,sha256=
|
|
105
|
+
wbfdm/contrib/qa/dataloaders/market_data.py,sha256=whb3xE0A36xly2_bCImgesgYjETOwTYB1DVDXBRz2UI,8009
|
|
106
106
|
wbfdm/contrib/qa/dataloaders/officers.py,sha256=s3kW3sgsXuGE0T-TaZwxrF3YrUN-2v-_hN4ugupryic,2944
|
|
107
107
|
wbfdm/contrib/qa/dataloaders/reporting_dates.py,sha256=q25ccB0pbGfLJLV1A1_AY1XYWJ_Fa10egY09L1J-C5A,2628
|
|
108
108
|
wbfdm/contrib/qa/dataloaders/statements.py,sha256=6k8dDwJPLY6XE3G5ZA03_4wRvT7XduRsro4lzuAWCvM,10337
|
|
@@ -117,7 +117,7 @@ wbfdm/contrib/qa/jinja2/qa/sql/ibes/estimates.sql,sha256=OWgeogSFj7-OdXvJTvNsThN
|
|
|
117
117
|
wbfdm/contrib/qa/jinja2/qa/sql/ibes/financials.sql,sha256=i8esPCG_ARiXlfSKajqBRH0jiXT_efOvw3No6zEvwn4,2612
|
|
118
118
|
wbfdm/contrib/qa/sync/exchanges.py,sha256=XU7dj-rQzMlDku9lnmAACaTRoxx8pFSyr5kCK79cYAc,3124
|
|
119
119
|
wbfdm/contrib/qa/sync/instruments.py,sha256=8aTQVJ_cw1phe4FWikn79pjCfUijaTcwkdhQCtSXKH0,3156
|
|
120
|
-
wbfdm/contrib/qa/sync/utils.py,sha256=
|
|
120
|
+
wbfdm/contrib/qa/sync/utils.py,sha256=CwcUJoCjLBY7brx4KdgNw2JdVw9dklvt8JMaWCfnnQ0,12204
|
|
121
121
|
wbfdm/dataloaders/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
122
122
|
wbfdm/dataloaders/cache.py,sha256=K9BeVxT7p-BMvjurINt18bfrUDccp840uIjfDBLJRNk,4841
|
|
123
123
|
wbfdm/dataloaders/protocols.py,sha256=QLa0y890gwnTeDGTnM58iNEYxugzj9Q9bmIRoapzc_0,3211
|
|
@@ -141,7 +141,7 @@ wbfdm/filters/classifications.py,sha256=8tKTAPwMzOIXkGWa4ez1layLBAlkDtdG53-75Rg0
|
|
|
141
141
|
wbfdm/filters/exchanges.py,sha256=84N4AQoCwgdnxTxmhMob5Yndfr5gy_DRQ_-m2ilVLVM,835
|
|
142
142
|
wbfdm/filters/financials.py,sha256=jdubT5xfFTMcwJSbC_z0WkF8KlO6eAxkaMS7-oQFFp0,2512
|
|
143
143
|
wbfdm/filters/financials_analysis.py,sha256=aDA33RhKCOmA62GwuAr5xDK71T0racdyDUEaxOBp4Oc,4401
|
|
144
|
-
wbfdm/filters/instrument_prices.py,sha256=
|
|
144
|
+
wbfdm/filters/instrument_prices.py,sha256=R1K8xrvOgPB4m3tWItz_3TMUw7a7UeKe4D3h28xe_3w,3637
|
|
145
145
|
wbfdm/filters/instruments.py,sha256=giL1QaJqGPRV1BBzmsPjxgCOCPuSNT5HkO27Q0kF-i4,7967
|
|
146
146
|
wbfdm/filters/utils.py,sha256=6IpNoZ_yjRUCdpVXrj3kriTceAX-VGrS5NpZA2NgSmY,1870
|
|
147
147
|
wbfdm/import_export/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -165,7 +165,7 @@ wbfdm/import_export/backends/refinitiv/mixin.py,sha256=DlNHOWOO71PgY0umaZd0Nbbjs
|
|
|
165
165
|
wbfdm/import_export/backends/refinitiv/utils/__init__.py,sha256=Rz38xsLAHEyEwIuJksejYExEznlPJb9tRzwJ7JG9L1s,35
|
|
166
166
|
wbfdm/import_export/backends/refinitiv/utils/controller.py,sha256=SCmVSyHo-NHDL1mzneS_Gl4JYrvEUhahOQfBmNSKnI8,7354
|
|
167
167
|
wbfdm/import_export/handlers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
168
|
-
wbfdm/import_export/handlers/instrument.py,sha256=
|
|
168
|
+
wbfdm/import_export/handlers/instrument.py,sha256=BeDhlwoMXLREH7wno7mcpaAKj4Vg0SpHEKiIr0dgTl0,13134
|
|
169
169
|
wbfdm/import_export/handlers/instrument_list.py,sha256=mZRfpJFi6BhhrjH2qaFEPqqCK2ybg-DQm43Uck7G9_w,4864
|
|
170
170
|
wbfdm/import_export/handlers/instrument_price.py,sha256=RbNTo78zZuttzlVFKxJrHcW7DRfcsta7QDEI8OiiDrA,3498
|
|
171
171
|
wbfdm/import_export/handlers/option.py,sha256=MPzluMPJ3Yu7Ahmw9BA7-ssAbvPDdyca_rC-YVhU8bY,2378
|
|
@@ -242,7 +242,7 @@ wbfdm/models/instruments/instrument_lists.py,sha256=GxfFyfYxEcJS36LAarHja49TOM8f
|
|
|
242
242
|
wbfdm/models/instruments/instrument_prices.py,sha256=K7oMIz76WSrLmpNwcabThvtrP6WpBZZnrE9CHB5-UPQ,22345
|
|
243
243
|
wbfdm/models/instruments/instrument_relationships.py,sha256=orBZY46jDvPfgkXakBRiByib5M_Iyeyelzg3CZWozSM,10777
|
|
244
244
|
wbfdm/models/instruments/instrument_requests.py,sha256=XbpofRS8WHadHlTFjvXJyd0o7K9r2pzJtnpjVQZOLdI,7832
|
|
245
|
-
wbfdm/models/instruments/instruments.py,sha256=
|
|
245
|
+
wbfdm/models/instruments/instruments.py,sha256=TbSOdQOzIcuS1KdPlFnpQmbrdv6NNzieQ26m-OoV-3Y,44551
|
|
246
246
|
wbfdm/models/instruments/options.py,sha256=AW6mwvVL8IN9K6dEApJsGgDz7T8SBIxQrJvQZ804oas,7286
|
|
247
247
|
wbfdm/models/instruments/private_equities.py,sha256=-MYXLLvcOO3JVvSpT2H_HxbQzZasipPUQyUgwoaW5xw,2275
|
|
248
248
|
wbfdm/models/instruments/querysets.py,sha256=7r3pXNlpROkYgKc6gQH07RNeWX6jGeBAPUabUevE6Jo,11587
|
|
@@ -350,10 +350,10 @@ wbfdm/viewsets/financial_analysis/__init__.py,sha256=cTTcvGnhz2Ep9RpkyUyTOpjTXJz
|
|
|
350
350
|
wbfdm/viewsets/financial_analysis/financial_metric_analysis.py,sha256=ISG53diS2LcjxH7Fex1wsMGHTHoRdLDHwLDKn3qA4UE,3328
|
|
351
351
|
wbfdm/viewsets/financial_analysis/financial_ratio_analysis.py,sha256=szq78oFKCxVjUkCVzsU7Ditq0qQlwcrnvnXVIao18Ic,3122
|
|
352
352
|
wbfdm/viewsets/financial_analysis/financial_summary.py,sha256=MWz5Nip5ePKkHX3W7bYJRvzY_hCvSsHmKd0gvvPtXL8,9245
|
|
353
|
-
wbfdm/viewsets/financial_analysis/statement_with_estimates.py,sha256=
|
|
353
|
+
wbfdm/viewsets/financial_analysis/statement_with_estimates.py,sha256=rhGxXFjTcDZ9zq0e9Djh2x9p7iBZUQ9Al-mdAvg2bBI,6248
|
|
354
354
|
wbfdm/viewsets/instruments/__init__.py,sha256=uydDdU6oZ6W2lgFkr3-cU7WZU7TeokXAA1J0xEgiLD0,2826
|
|
355
355
|
wbfdm/viewsets/instruments/classifications.py,sha256=CMRTeI6hUClXzZUr7PeRWBXhT9fMiPiu-FvNP_jUQkM,11947
|
|
356
|
-
wbfdm/viewsets/instruments/financials_analysis.py,sha256=
|
|
356
|
+
wbfdm/viewsets/instruments/financials_analysis.py,sha256=bobhqY23m83v53BJIe8mWz99ZpaT7u4Y6zgPS9-ozBs,29088
|
|
357
357
|
wbfdm/viewsets/instruments/instrument_lists.py,sha256=hwwHDNpHjjffxw08N_1LtkL5Fdi8c1Om-PLz6pTu4Ok,2878
|
|
358
358
|
wbfdm/viewsets/instruments/instrument_prices.py,sha256=9mdNPU1D6ZFS5Bf0U1d3c6ZlYSCjrNMWv6Vhas3D8Ns,24075
|
|
359
359
|
wbfdm/viewsets/instruments/instrument_requests.py,sha256=mmaARNl6ymDdlcLzcu16vVfFsunhtJkMw2r2NBfUp9U,1839
|
|
@@ -364,6 +364,6 @@ wbfdm/viewsets/statements/__init__.py,sha256=odxtFYUDICPmz8WCE3nx93EvKZLSPBEI4d7
|
|
|
364
364
|
wbfdm/viewsets/statements/statements.py,sha256=gA6RCI8-B__JwjEb6OZxpn8Y-9aF-YQ3HIQ7e1vfJMw,4304
|
|
365
365
|
wbfdm/viewsets/technical_analysis/__init__.py,sha256=qtCIBg0uSiZeJq_1tEQFilnorMBkMe6uCMfqar6-cLE,77
|
|
366
366
|
wbfdm/viewsets/technical_analysis/monthly_performances.py,sha256=O1j8CGfOranL74LqVvcf7jERaDIboEJZiBf_AbbVDQ8,3974
|
|
367
|
-
wbfdm-1.
|
|
368
|
-
wbfdm-1.
|
|
369
|
-
wbfdm-1.
|
|
367
|
+
wbfdm-1.56.1.dist-info/METADATA,sha256=1amTw1NVPFrkD5-cfIQg7dYw5VmkqfEgLy_PFrz546c,768
|
|
368
|
+
wbfdm-1.56.1.dist-info/WHEEL,sha256=tkmg4JIqwd9H8mL30xA7crRmoStyCtGp0VWshokd1Jc,105
|
|
369
|
+
wbfdm-1.56.1.dist-info/RECORD,,
|
|
File without changes
|