wbfdm 1.50.0__py2.py3-none-any.whl → 1.50.2__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.

@@ -32,7 +32,8 @@ class QAExchangeSync(Sync[Exchange]):
32
32
 
33
33
  def update_or_create_item(self, external_id: int) -> Exchange:
34
34
  defaults = self.get_item(external_id)
35
- defaults["country_id"] = mapping(Geography.countries, "code_2").get(defaults["country_id"])
35
+ if country_id := defaults.get("country_id"):
36
+ defaults["country_id"] = mapping(Geography.countries, "code_2").get(country_id)
36
37
  exchange, _ = Exchange.objects.update_or_create(
37
38
  source=self.SOURCE,
38
39
  source_id=external_id,
@@ -175,9 +175,9 @@ class Exchange(WBModel):
175
175
  def __str__(self) -> str:
176
176
  repr = self.identifier_repr
177
177
  if self.name:
178
- repr = f"{self.name} ({self.identifier_repr})"
178
+ repr = f"{self.name} - {self.identifier_repr}"
179
179
  elif self.mic_name:
180
- repr = f"{self.mic_name} ({self.identifier_repr})"
180
+ repr = f"{self.mic_name} - {self.identifier_repr}"
181
181
  return repr
182
182
 
183
183
  class Meta:
@@ -215,7 +215,7 @@ class Exchange(WBModel):
215
215
 
216
216
  @classmethod
217
217
  def get_representation_label_key(cls):
218
- return "{{name}} ({{mic_code}})"
218
+ return "{{name}}"
219
219
 
220
220
  @property
221
221
  def time_zone(self):
@@ -598,12 +598,17 @@ class Instrument(ComplexToStringMixin, TagModelMixin, ImportMixin, InstrumentPMS
598
598
  if self.instrument_type and self.instrument_type.key == "product":
599
599
  # Then we prioritize ISIN over ticker
600
600
  identifiers = ["isin", "ticker", "refinitiv_identifier_code", "refinitiv_mnemonic_code"]
601
+ elif self.is_security:
602
+ identifiers = ["ticker", "refinitiv_identifier_code", "refinitiv_mnemonic_code"]
601
603
  else:
602
- identifiers = ["ticker", "isin", "refinitiv_identifier_code", "refinitiv_mnemonic_code"]
604
+ identifiers = ["refinitiv_mnemonic_code"]
603
605
  for identifier in identifiers:
604
606
  if v := getattr(self, identifier, None):
605
607
  identifier_repr = v
606
608
  break
609
+ if self.isin and self.is_security:
610
+ identifier_repr += f" - {self.isin}"
611
+
607
612
  return identifier_repr.replace(":", "-")
608
613
 
609
614
  @property
@@ -701,13 +706,16 @@ class Instrument(ComplexToStringMixin, TagModelMixin, ImportMixin, InstrumentPMS
701
706
  super().save(*args, **kwargs)
702
707
 
703
708
  def compute_str(self):
704
- repr = self.name_repr # we follow bloomberg instrument representation format
705
- if self.instrument_type:
709
+ repr = self.name_repr or self.name or ""
710
+ repr = repr.title() # we follow bloomberg instrument representation format
711
+ if self.instrument_type and self.is_security:
706
712
  repr += f" {self.instrument_type.short_name}"
707
- if self.identifier_repr:
708
- repr += f" - {self.identifier_repr}"
709
- if self.exchange:
710
- repr += f" ({str(self.exchange)})"
713
+ if self.is_security or not self.level == 0:
714
+ if self.identifier_repr:
715
+ repr += f" - {self.identifier_repr}"
716
+ # if the object has an exchange and is not a security nor a company (a quote then), we append the exchange representation
717
+ if self.exchange and self.parent is not None and not self.is_security:
718
+ repr += f" ({str(self.exchange)})"
711
719
  return repr
712
720
 
713
721
  def is_active_at_date(self, today: date) -> bool:
@@ -4,6 +4,7 @@ from .instruments import (
4
4
  InstrumentRepresentationSerializer,
5
5
  InstrumentTypeRepresentationSerializer,
6
6
  InvestableUniverseRepresentationSerializer,
7
+ CompanyRepresentationSerializer,
7
8
  ClassifiableInstrumentRepresentationSerializer,
8
9
  SecurityRepresentationSerializer,
9
10
  InvestableInstrumentRepresentationSerializer,
@@ -51,6 +51,13 @@ class ClassifiableInstrumentRepresentationSerializer(InstrumentRepresentationSer
51
51
  return filter_params
52
52
 
53
53
 
54
+ class CompanyRepresentationSerializer(InstrumentRepresentationSerializer):
55
+ def get_filter_params(self, request):
56
+ filter_params = super().get_filter_params(request)
57
+ filter_params["level"] = 0
58
+ return filter_params
59
+
60
+
54
61
  class SecurityRepresentationSerializer(InstrumentRepresentationSerializer):
55
62
  def get_filter_params(self, request):
56
63
  filter_params = super().get_filter_params(request)
@@ -2,6 +2,7 @@ from django.db.models import Case, Exists, F, IntegerField, OuterRef, When
2
2
  from rest_framework.filters import OrderingFilter
3
3
  from wbcore import viewsets
4
4
  from wbcore.contrib.guardian.filters import ObjectPermissionsFilter
5
+ from wbcore.pagination import LimitOffsetPagination
5
6
  from wbcore.viewsets.mixins import DjangoFilterBackend
6
7
 
7
8
  from wbfdm.contrib.metric.backends.performances import PERFORMANCE_METRIC
@@ -35,21 +36,21 @@ class InstrumentTypeRepresentationViewSet(viewsets.RepresentationViewSet):
35
36
 
36
37
 
37
38
  class InstrumentRepresentationViewSet(viewsets.RepresentationViewSet):
38
- filter_backends = (InstrumentSearchFilter, ObjectPermissionsFilter, DjangoFilterBackend, OrderingFilter)
39
-
39
+ filter_backends = (ObjectPermissionsFilter, DjangoFilterBackend, OrderingFilter, InstrumentSearchFilter)
40
+ pagination_class = LimitOffsetPagination
40
41
  queryset = Instrument.objects.annotate_base_data().exclude(name="")
41
42
  serializer_class = InstrumentRepresentationSerializer
42
43
  search_fields = ("name", "name_repr", "isin", "ticker")
43
44
 
44
45
  filterset_class = InstrumentFilterSet
45
46
  ordering_fields = ("title", "ticker")
46
- ordering = ["-search_rank"]
47
+ ordering = ["name_repr"]
47
48
 
48
49
 
49
50
  class InstrumentModelViewSet(InstrumentMetricMixin, viewsets.ModelViewSet):
50
51
  METRIC_KEYS = (PERFORMANCE_METRIC, STATISTICS_METRIC)
51
52
  METRIC_SHOW_AGGREGATES = False
52
- filter_backends = (InstrumentSearchFilter, ObjectPermissionsFilter, DjangoFilterBackend, OrderingFilter)
53
+ filter_backends = (ObjectPermissionsFilter, DjangoFilterBackend, OrderingFilter, InstrumentSearchFilter)
53
54
 
54
55
  queryset = Instrument.objects.annotate_all()
55
56
  serializer_class = InstrumentModelListSerializer
@@ -70,7 +71,7 @@ class InstrumentModelViewSet(InstrumentMetricMixin, viewsets.ModelViewSet):
70
71
  "refinitiv_identifier_code",
71
72
  "refinitiv_mnemonic_code",
72
73
  )
73
- ordering = ["-search_rank"]
74
+ ordering = ["name_repr"]
74
75
 
75
76
  def get_serializer_class(self):
76
77
  if self.get_action() in ["list", "list-metadata"]:
@@ -102,6 +103,7 @@ class InstrumentModelViewSet(InstrumentMetricMixin, viewsets.ModelViewSet):
102
103
 
103
104
  class ChildrenInstrumentModelViewSet(InstrumentMixin, InstrumentModelViewSet):
104
105
  button_config_class = ChildrenInstrumentModelViewConfig
106
+ ordering = ("-is_primary", "computed_str")
105
107
 
106
108
  def get_queryset(self):
107
109
  return super().get_queryset().filter(parent=self.instrument)
@@ -12,7 +12,7 @@ class InstrumentSearchFilter:
12
12
  if search := request.GET.get("search", None):
13
13
  min_search_rank = self.get_min_search_rank(view)
14
14
  query = SearchQuery(search, search_type="phrase")
15
- queryset = (
15
+ return (
16
16
  queryset.annotate(search_rank=Coalesce(SearchRank(F("search_vector"), query), Value(-1.0)))
17
17
  .filter(
18
18
  (Q(search_vector=query) & Q(search_rank__gte=min_search_rank))
@@ -22,6 +22,6 @@ class InstrumentSearchFilter:
22
22
  )
23
23
  .order_by("-search_rank")
24
24
  ).distinct()
25
- else:
26
- queryset = queryset.annotate(search_rank=Value(-1.0))
25
+ elif "parent" in request.GET:
26
+ return queryset.order_by("-is_primary", "computed_str")
27
27
  return queryset
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wbfdm
3
- Version: 1.50.0
3
+ Version: 1.50.2
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.*
@@ -113,7 +113,7 @@ wbfdm/contrib/qa/jinja2/qa/sql/ibes/calendarized.sql,sha256=w2vi0lgNDDMoFB07bNv4
113
113
  wbfdm/contrib/qa/jinja2/qa/sql/ibes/complete.sql,sha256=bkF1h7FcLdeXmmKy2W4rdnBZw9xRVIo_Cu1sVobU-RM,328
114
114
  wbfdm/contrib/qa/jinja2/qa/sql/ibes/estimates.sql,sha256=OWgeogSFj7-OdXvJTvNsThNBz-7kxtygKYvS7dkU3aw,156
115
115
  wbfdm/contrib/qa/jinja2/qa/sql/ibes/financials.sql,sha256=0jXNMdX8ixVRJ8YyvtoJRQ510pHFYEioMy7NTp5ecck,2582
116
- wbfdm/contrib/qa/sync/exchanges.py,sha256=831-0bqxq4LaHEkyvMGfEBkNFm5LyLCSpjZbPdTEF0A,3079
116
+ wbfdm/contrib/qa/sync/exchanges.py,sha256=XU7dj-rQzMlDku9lnmAACaTRoxx8pFSyr5kCK79cYAc,3124
117
117
  wbfdm/contrib/qa/sync/instruments.py,sha256=8aTQVJ_cw1phe4FWikn79pjCfUijaTcwkdhQCtSXKH0,3156
118
118
  wbfdm/contrib/qa/sync/utils.py,sha256=1diZFEMQwjdGhfL6jv2xX7N_-TyO0Fwtnqw_3K5ykYI,9326
119
119
  wbfdm/dataloaders/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -224,14 +224,14 @@ wbfdm/models/indicators.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
224
224
  wbfdm/models/esg/__init__.py,sha256=FEYbRFSdfoWRsfKVxM-h6TLobj5P8bYQlZPG1iD9RMQ,29
225
225
  wbfdm/models/esg/controversies.py,sha256=OnswX0ZXdO37h-AWpr5aTJXhyT3MTwAOwt5ZV25t5BY,2950
226
226
  wbfdm/models/exchanges/__init__.py,sha256=sScz2KX9fxhhmi4CEUssC8HCL4ENvrIqSSwk0_J7v-g,32
227
- wbfdm/models/exchanges/exchanges.py,sha256=j-C22QPZEg-Mb6KCer7RRMVOcP1mprTc380zFtGJlhs,7272
227
+ wbfdm/models/exchanges/exchanges.py,sha256=FSxjEh3k2KLDJyJfzZg7iGUFZIxzQt__FYaDyPA66D0,7257
228
228
  wbfdm/models/instruments/__init__.py,sha256=OvEkECJaCubBQC7B9yUrx15V982labvegeGXyEASVno,636
229
229
  wbfdm/models/instruments/classifications.py,sha256=EeZ_P8f1F1NfjUmLf9fDMF0iPM73qxQoArUfvjuCwHg,10906
230
230
  wbfdm/models/instruments/instrument_lists.py,sha256=GxfFyfYxEcJS36LAarHja49TOM8ffhIivpZX2-tPtZg,4234
231
231
  wbfdm/models/instruments/instrument_prices.py,sha256=WCaFMZ9sF7xeGTp9jkq7TA8RfYHrwvTjujzqgCKj9SI,22070
232
232
  wbfdm/models/instruments/instrument_relationships.py,sha256=zpCZCnt5CqIg5bd6le_6TyirsSwGV2NaqTVKw3bd5vM,10660
233
233
  wbfdm/models/instruments/instrument_requests.py,sha256=XbpofRS8WHadHlTFjvXJyd0o7K9r2pzJtnpjVQZOLdI,7832
234
- wbfdm/models/instruments/instruments.py,sha256=T0Ey5tMbUnA8DMroY1c959hOL9bI-CwTZnq5XhxCmi4,39934
234
+ wbfdm/models/instruments/instruments.py,sha256=fXsYow-aLMJ8jFiFRJsoERDD0ouNsXMwoina0SkOAcI,40427
235
235
  wbfdm/models/instruments/options.py,sha256=hFprq7B5t4ctz8nVqzFsBEzftq_KDUSsSXl1zJyh7tE,7094
236
236
  wbfdm/models/instruments/private_equities.py,sha256=uzwZi8IkmCKAHVTxnuFya9tehx7kh57sTlTEi1ieDaM,2198
237
237
  wbfdm/models/instruments/querysets.py,sha256=c9fbHVvIRyaFU7jm_CM90lfIVzB8beOD8YII9-FqdT4,7191
@@ -246,13 +246,13 @@ wbfdm/serializers/__init__.py,sha256=AXb03RKHo6B0ts_IQOvx89n9wKG8pxiumYv9cr4EhvA
246
246
  wbfdm/serializers/esg.py,sha256=epoX8cjkPuVv45aW-Jf85-rSO_ZrSnXcTxMcadKdC-I,1086
247
247
  wbfdm/serializers/exchanges.py,sha256=vi5kFadYRQo-6CV2b56nrABpt80LPtjZumJVaBE4bcc,1175
248
248
  wbfdm/serializers/officers.py,sha256=yrBJqnwxS5Eq0aGcRKe0FbEYEvDFpZlb8gzgfU9pRyk,473
249
- wbfdm/serializers/instruments/__init__.py,sha256=7WX6P7Fzyc_E59CpJ1RBAPptIOPXOHn9FScvGY8qWjo,1662
249
+ wbfdm/serializers/instruments/__init__.py,sha256=bLgyuwpGN5Vq2PO5ueErXWHDInPy_191kieaV0_MAI4,1699
250
250
  wbfdm/serializers/instruments/classifications.py,sha256=DsrKkF0lFBTtNrVs0vhjkjjlK8mDSbGfvQODarYPbDA,5669
251
251
  wbfdm/serializers/instruments/instrument_lists.py,sha256=M9RnH-Iy095m5xgkVcPHfvKiyHgCy8kIIN9cdqOf20I,1916
252
252
  wbfdm/serializers/instruments/instrument_prices.py,sha256=de-IlwUJC6gSYVztuTmOXQK3r-Gjn8tVWaSCx0PXh_Q,2593
253
253
  wbfdm/serializers/instruments/instrument_relationships.py,sha256=3hChFzdekoPtMYolEhWafcb9nTLPmx6WGEq_Hgck8jA,6454
254
254
  wbfdm/serializers/instruments/instrument_requests.py,sha256=Sl4gfkUu63zk4o2iGFVE59wx1rKkLUG6SPYCE7Dqrs4,2176
255
- wbfdm/serializers/instruments/instruments.py,sha256=EX2T2fqYN1l8lzbgyl0cxFs2bDIf0ydGRAVWkB5ISzU,11831
255
+ wbfdm/serializers/instruments/instruments.py,sha256=hrCNjOzd3R1c9XRcrO-lmizQmOJDA-p-Hw40eZYzyL0,12073
256
256
  wbfdm/serializers/instruments/mixins.py,sha256=qcznDMwPu8VbeAF7IArNyNcrdpjJJffNn07ifoIqM10,4396
257
257
  wbfdm/sync/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
258
258
  wbfdm/sync/abstract.py,sha256=u1zjHT0ZJabUZpy3_EUCTtEig0p5Fuhlx69O9BsV_Gs,849
@@ -345,13 +345,13 @@ wbfdm/viewsets/instruments/financials_analysis.py,sha256=xcVKR2H0P07NIyxFwPPPmVi
345
345
  wbfdm/viewsets/instruments/instrument_lists.py,sha256=hwwHDNpHjjffxw08N_1LtkL5Fdi8c1Om-PLz6pTu4Ok,2878
346
346
  wbfdm/viewsets/instruments/instrument_prices.py,sha256=WGUe5WUl9PqulWSPCZgWcBWCmgxtu4lhm-UeAa4ngyg,24008
347
347
  wbfdm/viewsets/instruments/instrument_requests.py,sha256=mmaARNl6ymDdlcLzcu16vVfFsunhtJkMw2r2NBfUp9U,1839
348
- wbfdm/viewsets/instruments/instruments.py,sha256=eI0sP0B1wN8ImuACP_OIbv4n1IZQ5iT5zJyrFm9t8E4,3867
348
+ wbfdm/viewsets/instruments/instruments.py,sha256=UtsLAxf7v_tdpmT16UWSUa834Yq2wYJXztiKrdsBrmw,4004
349
349
  wbfdm/viewsets/instruments/instruments_relationships.py,sha256=D2Ym84zXBFegQC9nMThKSWqSAcWa0WvcS_GXxM2po68,11076
350
- wbfdm/viewsets/instruments/utils.py,sha256=SQAdQSgYwUwhlFBbYkZd1VMDmtfoj9XLj1RGBUzzre8,1144
350
+ wbfdm/viewsets/instruments/utils.py,sha256=kr5HwkSaWp-6GHVEQIb3CnIspDGSxfqghyOqg0oHO-A,1166
351
351
  wbfdm/viewsets/statements/__init__.py,sha256=odxtFYUDICPmz8WCE3nx93EvKZLSPBEI4d7pozcQz2A,47
352
352
  wbfdm/viewsets/statements/statements.py,sha256=kmtM0uZ3f7eJJe5gVmd-iVra9dHwTB9x12p7f5qTEx8,4084
353
353
  wbfdm/viewsets/technical_analysis/__init__.py,sha256=qtCIBg0uSiZeJq_1tEQFilnorMBkMe6uCMfqar6-cLE,77
354
354
  wbfdm/viewsets/technical_analysis/monthly_performances.py,sha256=O1j8CGfOranL74LqVvcf7jERaDIboEJZiBf_AbbVDQ8,3974
355
- wbfdm-1.50.0.dist-info/METADATA,sha256=4keXBSdPU5RJhz98q04zYSIicl4cVxFJPXOTUTJkbcw,737
356
- wbfdm-1.50.0.dist-info/WHEEL,sha256=tkmg4JIqwd9H8mL30xA7crRmoStyCtGp0VWshokd1Jc,105
357
- wbfdm-1.50.0.dist-info/RECORD,,
355
+ wbfdm-1.50.2.dist-info/METADATA,sha256=BKdLuzNfsUz7PdiQnrcBBncwKE8UcbhCPOlBvntgvic,737
356
+ wbfdm-1.50.2.dist-info/WHEEL,sha256=tkmg4JIqwd9H8mL30xA7crRmoStyCtGp0VWshokd1Jc,105
357
+ wbfdm-1.50.2.dist-info/RECORD,,
File without changes