wbfdm 1.55.7__py2.py3-none-any.whl → 1.55.9__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/metric/dispatch.py +3 -0
- wbfdm/contrib/metric/signals.py +7 -0
- wbfdm/contrib/metric/tasks.py +2 -3
- wbfdm/contrib/msci/client.py +3 -2
- wbfdm/migrations/0033_alter_controversy_review.py +18 -0
- wbfdm/models/esg/controversies.py +16 -23
- wbfdm/tasks.py +4 -0
- {wbfdm-1.55.7.dist-info → wbfdm-1.55.9.dist-info}/METADATA +1 -1
- {wbfdm-1.55.7.dist-info → wbfdm-1.55.9.dist-info}/RECORD +10 -8
- {wbfdm-1.55.7.dist-info → wbfdm-1.55.9.dist-info}/WHEEL +0 -0
wbfdm/contrib/metric/dispatch.py
CHANGED
|
@@ -2,6 +2,8 @@ from contextlib import suppress
|
|
|
2
2
|
from datetime import date
|
|
3
3
|
from typing import Any
|
|
4
4
|
|
|
5
|
+
from wbfdm.contrib.metric.signals import instrument_metric_updated
|
|
6
|
+
|
|
5
7
|
|
|
6
8
|
def compute_metrics(val_date: date, key: str | None = None, basket: Any | None = None, **kwargs):
|
|
7
9
|
"""
|
|
@@ -21,3 +23,4 @@ def compute_metrics(val_date: date, key: str | None = None, basket: Any | None =
|
|
|
21
23
|
with suppress(KeyError):
|
|
22
24
|
orchestrator = MetricOrchestrator(val_date, key=key, basket=basket, **kwargs)
|
|
23
25
|
orchestrator.process()
|
|
26
|
+
instrument_metric_updated.send(sender=basket.__class__, basket=basket, key=key, val_date=val_date)
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
from django.db.models.signals import ModelSignal
|
|
2
|
+
|
|
3
|
+
# this signal is triggered whenever all instruments metrics are updated. Temporary solution until we rework the framework for more dynamicity
|
|
4
|
+
|
|
5
|
+
instrument_metric_updated = ModelSignal(
|
|
6
|
+
use_caching=True
|
|
7
|
+
) # the sender model is the type model class being updated (e.g. Instrument), expect a "basket", "key" and "val_date" keyword argument (null if all are updated)
|
wbfdm/contrib/metric/tasks.py
CHANGED
|
@@ -3,7 +3,7 @@ from datetime import date
|
|
|
3
3
|
from celery import shared_task
|
|
4
4
|
from django.contrib.contenttypes.models import ContentType
|
|
5
5
|
|
|
6
|
-
from wbfdm.contrib.metric.
|
|
6
|
+
from wbfdm.contrib.metric.dispatch import compute_metrics
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
@shared_task(queue="portfolio")
|
|
@@ -24,5 +24,4 @@ def compute_metrics_as_task(
|
|
|
24
24
|
basket = None
|
|
25
25
|
if basket_content_type_id and basket_id:
|
|
26
26
|
basket = ContentType.objects.get(id=basket_content_type_id).get_object_for_this_type(pk=basket_id)
|
|
27
|
-
|
|
28
|
-
routine.process()
|
|
27
|
+
compute_metrics(val_date=val_date, key=key, basket=basket, **kwargs)
|
wbfdm/contrib/msci/client.py
CHANGED
|
@@ -66,6 +66,7 @@ class MSCIClient:
|
|
|
66
66
|
def controversies(self, identifiers: list[str], factors: list[str]) -> Generator[dict[str, str], None, None]:
|
|
67
67
|
next_url = "https://api2.msci.com/esg/data/v2.0/issuers"
|
|
68
68
|
offset = 0
|
|
69
|
+
limit = 100
|
|
69
70
|
while next_url:
|
|
70
71
|
with suppress(ConnectionError):
|
|
71
72
|
response = requests.post(
|
|
@@ -73,7 +74,7 @@ class MSCIClient:
|
|
|
73
74
|
json={
|
|
74
75
|
"issuer_identifier_list": identifiers,
|
|
75
76
|
"factor_name_list": factors,
|
|
76
|
-
"limit":
|
|
77
|
+
"limit": limit,
|
|
77
78
|
"offset": offset,
|
|
78
79
|
},
|
|
79
80
|
headers={"AUTHORIZATION": f"Bearer {self.oauth_token}"},
|
|
@@ -87,6 +88,6 @@ class MSCIClient:
|
|
|
87
88
|
next_url = json_res["paging"]["links"]["next"]
|
|
88
89
|
except KeyError:
|
|
89
90
|
next_url = None
|
|
90
|
-
offset +=
|
|
91
|
+
offset += limit
|
|
91
92
|
for row in json_res.get("result", {}).get("issuers", []):
|
|
92
93
|
yield row
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Generated by Django 5.0.12 on 2025-09-08 11:39
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
|
|
8
|
+
dependencies = [
|
|
9
|
+
('wbfdm', '0032_alter_instrumentprice_outstanding_shares'),
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
operations = [
|
|
13
|
+
migrations.AlterField(
|
|
14
|
+
model_name='controversy',
|
|
15
|
+
name='review',
|
|
16
|
+
field=models.DateField(blank=True, null=True, verbose_name='Reviewed'),
|
|
17
|
+
),
|
|
18
|
+
]
|
|
@@ -8,7 +8,6 @@ from wbfdm.enums import (
|
|
|
8
8
|
ESGControveryStatus,
|
|
9
9
|
ESGControveryType,
|
|
10
10
|
)
|
|
11
|
-
from wbfdm.models.instruments.instruments import Instrument
|
|
12
11
|
|
|
13
12
|
|
|
14
13
|
class Controversy(models.Model):
|
|
@@ -54,29 +53,23 @@ class Controversy(models.Model):
|
|
|
54
53
|
direct_involvement = models.BooleanField(default=True, verbose_name="Direct Involvement")
|
|
55
54
|
company_response = models.CharField(max_length=512, null=True, blank=True)
|
|
56
55
|
|
|
57
|
-
review = models.DateField(verbose_name="Reviewed")
|
|
56
|
+
review = models.DateField(verbose_name="Reviewed", null=True, blank=True)
|
|
58
57
|
initiated = models.DateField(verbose_name="initiated", null=True, blank=True)
|
|
59
58
|
|
|
60
59
|
@classmethod
|
|
61
|
-
def
|
|
62
|
-
|
|
63
|
-
pk=controversy["instrument_id"]
|
|
64
|
-
).get_root() # we link it only to root level
|
|
65
|
-
|
|
66
|
-
return cls.objects.update_or_create(
|
|
60
|
+
def dict_to_model(cls, controversy: dict[str, Any], instrument) -> Self:
|
|
61
|
+
return Controversy(
|
|
67
62
|
external_id=controversy["id"],
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
},
|
|
82
|
-
)[0]
|
|
63
|
+
instrument=instrument,
|
|
64
|
+
headline=controversy["headline"],
|
|
65
|
+
description=controversy["narrative"],
|
|
66
|
+
source=controversy["source"],
|
|
67
|
+
direct_involvement=controversy.get("direct_involvement", True),
|
|
68
|
+
company_response=controversy["response"],
|
|
69
|
+
review=controversy["review"],
|
|
70
|
+
initiated=controversy["initiated"],
|
|
71
|
+
flag=controversy["flag"],
|
|
72
|
+
status=controversy["status"],
|
|
73
|
+
type=controversy["type"],
|
|
74
|
+
severity=controversy["assessment"],
|
|
75
|
+
)
|
wbfdm/tasks.py
CHANGED
|
@@ -6,6 +6,7 @@ from django.db import transaction
|
|
|
6
6
|
from django.db.models import ProtectedError, Q
|
|
7
7
|
from pandas.tseries.offsets import BDay
|
|
8
8
|
from tqdm import tqdm
|
|
9
|
+
from wbcore.utils.cache import mapping
|
|
9
10
|
|
|
10
11
|
from wbfdm.models import Instrument, InstrumentPrice
|
|
11
12
|
from wbfdm.sync.runner import ( # noqa: F401
|
|
@@ -15,6 +16,7 @@ from wbfdm.sync.runner import ( # noqa: F401
|
|
|
15
16
|
synchronize_instruments,
|
|
16
17
|
)
|
|
17
18
|
|
|
19
|
+
from .contrib.metric.signals import instrument_metric_updated
|
|
18
20
|
from .signals import investable_universe_updated
|
|
19
21
|
|
|
20
22
|
|
|
@@ -71,6 +73,7 @@ def update_instrument_metrics_as_task():
|
|
|
71
73
|
instruments = Instrument.active_objects.filter(is_investable_universe=True)
|
|
72
74
|
for instrument in tqdm(instruments, total=instruments.count()):
|
|
73
75
|
instrument.update_last_valuation_date()
|
|
76
|
+
instrument_metric_updated.send(sender=Instrument, basket=None, date=None, key=None)
|
|
74
77
|
|
|
75
78
|
|
|
76
79
|
@shared_task(queue="portfolio")
|
|
@@ -92,6 +95,7 @@ def full_synchronization_as_task():
|
|
|
92
95
|
for instrument in qs:
|
|
93
96
|
with suppress(ProtectedError):
|
|
94
97
|
instrument.delete()
|
|
98
|
+
mapping.cache_clear() # we need to clear the mapping cache because we might have deleted parent instruments
|
|
95
99
|
initialize_exchanges()
|
|
96
100
|
initialize_instruments()
|
|
97
101
|
with transaction.atomic():
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: wbfdm
|
|
3
|
-
Version: 1.55.
|
|
3
|
+
Version: 1.55.9
|
|
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.*
|
|
@@ -5,7 +5,7 @@ wbfdm/enums.py,sha256=5AuUouk5uuSNmRc6e-SiBu4FPmHVTN60ol9ftiuVrAc,33041
|
|
|
5
5
|
wbfdm/jinja2.py,sha256=pkIC1U-0rf6vn0DDEUzZ8dPYiTGEPY8LBTRMi9wYiuc,199
|
|
6
6
|
wbfdm/preferences.py,sha256=8ghDcaapOMso1kjtNfKbSFykPUTxzqI5R77gM3BgiMs,927
|
|
7
7
|
wbfdm/signals.py,sha256=PhAsFpQZF1YVe5UpedaRelUD_TVjemqRYm1HzV-bhmY,597
|
|
8
|
-
wbfdm/tasks.py,sha256=
|
|
8
|
+
wbfdm/tasks.py,sha256=Q7iuSgV8LdPoKxgyMmTg5qukxHrM5XW1k1H_zI958zU,5104
|
|
9
9
|
wbfdm/urls.py,sha256=pDp9I0kktxicad8sXXEUT7402jZPMJNcE5R1doTlcMw,8887
|
|
10
10
|
wbfdm/utils.py,sha256=4cWrCpqXxHIjtSlt4DDPFvmtaqXw_H0nqhM6sGuXx0o,1938
|
|
11
11
|
wbfdm/admin/__init__.py,sha256=Z1VtH_gjD71K79KcD-2Q2Lu_p_7j0akMZj7gNxdz1CQ,1398
|
|
@@ -45,7 +45,7 @@ wbfdm/contrib/internal/dataloaders/market_data.py,sha256=QJx4DsGGN3yy0cjIRDEatt_
|
|
|
45
45
|
wbfdm/contrib/metric/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
46
46
|
wbfdm/contrib/metric/apps.py,sha256=T-Na_lyFeLR8ebGvaW-mcjKFLqiZcsPXnUlOuVPOiWw,297
|
|
47
47
|
wbfdm/contrib/metric/decorators.py,sha256=VPmyjEJaq5HqXOt_ZizqcXfRqSEXw4lanDmubUjb2GY,476
|
|
48
|
-
wbfdm/contrib/metric/dispatch.py,sha256=
|
|
48
|
+
wbfdm/contrib/metric/dispatch.py,sha256=GdJoYRFiZXWwo3hZeNTDxOUwg7iniv63ddb-A-7Pc6w,1090
|
|
49
49
|
wbfdm/contrib/metric/dto.py,sha256=vS93tUvfusWdE7gUJsp320GwfwWpb8bGJDdrb1GB6M8,3413
|
|
50
50
|
wbfdm/contrib/metric/exceptions.py,sha256=6IuEVde7aOyQaXHE817bCNdUw8LTI3sOSU9LiV3NZbM,200
|
|
51
51
|
wbfdm/contrib/metric/factories.py,sha256=b6-3fSERbZGjGw6QC0k3hhSpyQKVy2MJoZzX4y3GPEo,1123
|
|
@@ -54,7 +54,8 @@ wbfdm/contrib/metric/models.py,sha256=lI_ZmK7058GT_5ngC45UdXRc7ju-ULbcOtO5w_CMBw
|
|
|
54
54
|
wbfdm/contrib/metric/orchestrators.py,sha256=YyVVKKm3Sl1zVr2mw9A7LSJs6YnmElbg1yESREF3lFk,3736
|
|
55
55
|
wbfdm/contrib/metric/registry.py,sha256=SdZff6FIrtdbyAO0X0BpXndJAIhU6VVojNui_MEw7jI,3167
|
|
56
56
|
wbfdm/contrib/metric/serializers.py,sha256=FqX2pgP4SL1oteVrnAWQezBOJD6JyTidLBEK72GMxrM,1636
|
|
57
|
-
wbfdm/contrib/metric/
|
|
57
|
+
wbfdm/contrib/metric/signals.py,sha256=qe-CGNZEc7csseiGgNbz8legvz0EM3e31k8kPQ19Zyw,417
|
|
58
|
+
wbfdm/contrib/metric/tasks.py,sha256=yMgPvDSKUtJy6wFMGP8tdymO2vZGSaqIxKliGrrvzHE,907
|
|
58
59
|
wbfdm/contrib/metric/urls.py,sha256=hAYOvH50S9k6EJdE_2DP6oCmt0WT314iaXRtNqQnRJo,459
|
|
59
60
|
wbfdm/contrib/metric/admin/__init__.py,sha256=FW3qhfmS5tA4RNOv9Zse56dICDG7zgdHgBJ-MvT7VKM,125
|
|
60
61
|
wbfdm/contrib/metric/admin/instruments.py,sha256=mPwwdwxeuo6nvyJ2_xolVdlpK05KMlzOPLaSlh1PtHE,419
|
|
@@ -84,7 +85,7 @@ wbfdm/contrib/metric/viewsets/configs/display.py,sha256=aZLy3wSCgJlfrS71qxjPfT56
|
|
|
84
85
|
wbfdm/contrib/metric/viewsets/configs/menus.py,sha256=GJbDm3p6qeobet09kpQSSuJT3Bs14gYpXxQ1P16b5VM,422
|
|
85
86
|
wbfdm/contrib/metric/viewsets/configs/utils.py,sha256=SREiSRS4faohL6lVxmeD3zJN8bb-C-PlANUr8AgpIkI,5009
|
|
86
87
|
wbfdm/contrib/msci/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
87
|
-
wbfdm/contrib/msci/client.py,sha256=
|
|
88
|
+
wbfdm/contrib/msci/client.py,sha256=XnPATwQKaPc48uvB_BnbxwZuoyQkA1kVNp_-48A0irY,3633
|
|
88
89
|
wbfdm/contrib/msci/sync.py,sha256=StD2TliqxVnZ7YsITjYvdh7E95USS3_P9j8KgRlcDKY,2289
|
|
89
90
|
wbfdm/contrib/msci/dataloaders/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
90
91
|
wbfdm/contrib/msci/dataloaders/esg.py,sha256=VM2zprCC0q0CYSwGPA252czcVx9QpmxYv8FsLTKCGAI,4820
|
|
@@ -225,13 +226,14 @@ wbfdm/migrations/0029_alter_instrumentprice_volume.py,sha256=0UFUwEaBcqiWjKw6un1
|
|
|
225
226
|
wbfdm/migrations/0030_alter_relatedinstrumentthroughmodel_related_type.py,sha256=10-89NB7-T7t3xFPpd4fYQkKejNR36UewIhe5_20QCo,565
|
|
226
227
|
wbfdm/migrations/0031_exchange_apply_round_lot_size_and_more.py,sha256=MqcHxgJIt67BEuEYK8vnJHhx_cGFw9Ca9Az2EvsDy1o,863
|
|
227
228
|
wbfdm/migrations/0032_alter_instrumentprice_outstanding_shares.py,sha256=uRgkf6j97kNaXAo0-_V3XzHNE59hvxSruJB18g53YwU,570
|
|
229
|
+
wbfdm/migrations/0033_alter_controversy_review.py,sha256=A9npErIpE0QUEjqIqpxmO5GMi0VA2Id8whn1nswWXpU,445
|
|
228
230
|
wbfdm/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
229
231
|
wbfdm/models/__init__.py,sha256=PWsLtlKJFDYycCohPbjsRLeWi1xaxEkZbaoUKo0yOBU,96
|
|
230
232
|
wbfdm/models/fields.py,sha256=eQ_6EnDBMy0U7WzE2DsdXIXOJH5dFiIN2VbO2Svw4R0,3942
|
|
231
233
|
wbfdm/models/fk_fields.py,sha256=XuOGN0Fnq4Hld9IcBKSpeSSrfAQD91B-HNYNVd69fAk,15041
|
|
232
234
|
wbfdm/models/indicators.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
233
235
|
wbfdm/models/esg/__init__.py,sha256=FEYbRFSdfoWRsfKVxM-h6TLobj5P8bYQlZPG1iD9RMQ,29
|
|
234
|
-
wbfdm/models/esg/controversies.py,sha256=
|
|
236
|
+
wbfdm/models/esg/controversies.py,sha256=ioAlytF3H_IKGtYfkDWyo7Xj6S4z7vvuyd5rgOed50s,2632
|
|
235
237
|
wbfdm/models/exchanges/__init__.py,sha256=sScz2KX9fxhhmi4CEUssC8HCL4ENvrIqSSwk0_J7v-g,32
|
|
236
238
|
wbfdm/models/exchanges/exchanges.py,sha256=RmM5shyyuxEGN2Y3JmeSWyU-SbpVARrvVFW72HtHwfg,7502
|
|
237
239
|
wbfdm/models/instruments/__init__.py,sha256=OvEkECJaCubBQC7B9yUrx15V982labvegeGXyEASVno,636
|
|
@@ -362,6 +364,6 @@ wbfdm/viewsets/statements/__init__.py,sha256=odxtFYUDICPmz8WCE3nx93EvKZLSPBEI4d7
|
|
|
362
364
|
wbfdm/viewsets/statements/statements.py,sha256=gA6RCI8-B__JwjEb6OZxpn8Y-9aF-YQ3HIQ7e1vfJMw,4304
|
|
363
365
|
wbfdm/viewsets/technical_analysis/__init__.py,sha256=qtCIBg0uSiZeJq_1tEQFilnorMBkMe6uCMfqar6-cLE,77
|
|
364
366
|
wbfdm/viewsets/technical_analysis/monthly_performances.py,sha256=O1j8CGfOranL74LqVvcf7jERaDIboEJZiBf_AbbVDQ8,3974
|
|
365
|
-
wbfdm-1.55.
|
|
366
|
-
wbfdm-1.55.
|
|
367
|
-
wbfdm-1.55.
|
|
367
|
+
wbfdm-1.55.9.dist-info/METADATA,sha256=E3b45elSBbWIPyhnD0hVdM1Si0l7QDhYEiMXdHX4A2E,768
|
|
368
|
+
wbfdm-1.55.9.dist-info/WHEEL,sha256=tkmg4JIqwd9H8mL30xA7crRmoStyCtGp0VWshokd1Jc,105
|
|
369
|
+
wbfdm-1.55.9.dist-info/RECORD,,
|
|
File without changes
|