wbportfolio 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 wbportfolio might be problematic. Click here for more details.

@@ -10,10 +10,6 @@ from wbportfolio.models import (
10
10
  PortfolioSwingPricing,
11
11
  )
12
12
 
13
- from .portfolio_relationships import (
14
- PortfolioInstrumentPreferredClassificationThroughInlineModelAdmin,
15
- )
16
-
17
13
 
18
14
  @admin.register(PortfolioBankAccountThroughModel)
19
15
  class PortfolioBankAccountThroughModelModelAdmin(admin.ModelAdmin):
@@ -64,6 +60,16 @@ class PortfolioModelAdmin(admin.ModelAdmin):
64
60
  )
65
61
  },
66
62
  ),
63
+ (
64
+ "OMS",
65
+ {
66
+ "fields": (
67
+ "default_order_proposal_min_order_value",
68
+ "default_order_proposal_min_weighting",
69
+ "default_order_proposal_total_cash_weight",
70
+ )
71
+ },
72
+ ),
67
73
  )
68
74
  readonly_fields = ["updated_at"]
69
75
  list_display = (
@@ -78,7 +84,7 @@ class PortfolioModelAdmin(admin.ModelAdmin):
78
84
  inlines = [
79
85
  PortfolioBankAccountThroughModelAdmin,
80
86
  InstrumentPortfolioThroughModelAdmin,
81
- PortfolioInstrumentPreferredClassificationThroughInlineModelAdmin,
87
+ # PortfolioInstrumentPreferredClassificationThroughInlineModelAdmin,
82
88
  PortfolioPortfolioThroughModelInlineAdmin,
83
89
  ]
84
90
  raw_id_fields = [
@@ -0,0 +1,71 @@
1
+ # Generated by Django 5.0.12 on 2025-09-15 13:45
2
+
3
+ import django.core.validators
4
+ from decimal import Decimal
5
+ from django.db import migrations, models
6
+
7
+
8
+ class Migration(migrations.Migration):
9
+
10
+ dependencies = [
11
+ ('wbportfolio', '0088_orderproposal_total_effective_portfolio_contribution'),
12
+ ]
13
+
14
+ operations = [
15
+ migrations.AddField(
16
+ model_name='orderproposal',
17
+ name='min_weighting',
18
+ field=models.DecimalField(decimal_places=8, default=Decimal('0'), help_text='The minimum weight allowed for this order proposal ', max_digits=9, verbose_name='Minimum Weight'),
19
+ ),
20
+ migrations.AddField(
21
+ model_name='portfolio',
22
+ name='default_order_proposal_min_order_value',
23
+ field=models.IntegerField(default=0, verbose_name='Default Order Proposal Minimum Order Value'),
24
+ ),
25
+ migrations.AddField(
26
+ model_name='portfolio',
27
+ name='default_order_proposal_min_weighting',
28
+ field=models.DecimalField(decimal_places=8, default=Decimal('0'), max_digits=9,
29
+ verbose_name='Default Order Proposal Minimum Weight'),
30
+ ),
31
+ migrations.AddField(
32
+ model_name='portfolio',
33
+ name='default_order_proposal_total_cash_weight',
34
+ field=models.DecimalField(decimal_places=4, default=Decimal('0'), max_digits=5,
35
+ verbose_name='Default Order Proposal Total Cash Weight'),
36
+ ),
37
+ migrations.AlterField(
38
+ model_name='orderproposal',
39
+ name='min_weighting',
40
+ field=models.DecimalField(decimal_places=8, default=Decimal('0'),
41
+ help_text='The minimum weight allowed for this order proposal ', max_digits=9,
42
+ validators=[django.core.validators.MinValueValidator(Decimal('0')),
43
+ django.core.validators.MaxValueValidator(Decimal('1'))],
44
+ verbose_name='Minimum Weight'),
45
+ ),
46
+ migrations.AlterField(
47
+ model_name='orderproposal',
48
+ name='total_cash_weight',
49
+ field=models.DecimalField(decimal_places=4, default=Decimal('0'),
50
+ help_text='The desired percentage for the cash component. The remaining percentage (100% minus this value) will be allocated to total target weighting. Default is 0%.',
51
+ max_digits=5, validators=[django.core.validators.MinValueValidator(Decimal('0')),
52
+ django.core.validators.MaxValueValidator(Decimal('1'))],
53
+ verbose_name='Total Cash Weight'),
54
+ ),
55
+ migrations.AlterField(
56
+ model_name='portfolio',
57
+ name='default_order_proposal_min_weighting',
58
+ field=models.DecimalField(decimal_places=8, default=Decimal('0'), max_digits=9,
59
+ validators=[django.core.validators.MinValueValidator(Decimal('0')),
60
+ django.core.validators.MaxValueValidator(Decimal('1'))],
61
+ verbose_name='Default Order Proposal Minimum Weight'),
62
+ ),
63
+ migrations.AlterField(
64
+ model_name='portfolio',
65
+ name='default_order_proposal_total_cash_weight',
66
+ field=models.DecimalField(decimal_places=4, default=Decimal('0'), max_digits=5,
67
+ validators=[django.core.validators.MinValueValidator(Decimal('0')),
68
+ django.core.validators.MaxValueValidator(Decimal('1'))],
69
+ verbose_name='Default Order Proposal Total Cash Weight'),
70
+ ),
71
+ ]
@@ -7,6 +7,7 @@ from typing import Any, TypeVar
7
7
 
8
8
  from celery import shared_task
9
9
  from django.core.exceptions import ValidationError
10
+ from django.core.validators import MaxValueValidator, MinValueValidator
10
11
  from django.db import DatabaseError, models
11
12
  from django.db.models import (
12
13
  F,
@@ -96,12 +97,22 @@ class OrderProposal(CloneMixin, RiskCheckMixin, WBModel):
96
97
  min_order_value = models.IntegerField(
97
98
  default=0, verbose_name="Minimum Order Value", help_text="Minimum Order Value in the Portfolio currency"
98
99
  )
100
+ min_weighting = models.DecimalField(
101
+ max_digits=9,
102
+ decimal_places=Order.ORDER_WEIGHTING_PRECISION,
103
+ default=Decimal(0),
104
+ help_text="The minimum weight allowed for this order proposal ",
105
+ verbose_name="Minimum Weight",
106
+ validators=[MinValueValidator(Decimal("0")), MaxValueValidator(Decimal("1"))],
107
+ )
108
+
99
109
  total_cash_weight = models.DecimalField(
100
110
  default=Decimal("0"),
101
111
  decimal_places=4,
102
112
  max_digits=5,
103
113
  verbose_name="Total Cash Weight",
104
114
  help_text="The desired percentage for the cash component. The remaining percentage (100% minus this value) will be allocated to total target weighting. Default is 0%.",
115
+ validators=[MinValueValidator(Decimal("0")), MaxValueValidator(Decimal("1"))],
105
116
  )
106
117
  total_effective_portfolio_contribution = models.DecimalField(
107
118
  default=Decimal("1"),
@@ -136,6 +147,13 @@ class OrderProposal(CloneMixin, RiskCheckMixin, WBModel):
136
147
  ]
137
148
 
138
149
  def save(self, *args, **kwargs):
150
+ # if the order proposal is created, we default these fields with the portfolio default value for automatic value assignement
151
+ if not self.id and not self.min_order_value:
152
+ self.min_order_value = self.portfolio.default_order_proposal_min_order_value
153
+ if not self.id and not self.min_weighting:
154
+ self.min_weighting = self.portfolio.default_order_proposal_min_weighting
155
+ if not self.id and not self.total_cash_weight:
156
+ self.total_cash_weight = self.portfolio.default_order_proposal_total_cash_weight
139
157
  # if a order proposal is created before the existing earliest order proposal, we automatically shift the linked instruments inception date to allow automatic NAV computation since the new inception date
140
158
  if not self.portfolio.order_proposals.filter(trade_date__lt=self.trade_date).exists():
141
159
  # we need to set the inception date as the first order proposal trade date (and thus, the first position date). We expect a NAV at 100 then
@@ -87,6 +87,12 @@ class Order(TransactionMixin, ImportMixin, OrderedModel, models.Model):
87
87
  self.shares = shares
88
88
  if portfolio_total_asset_value:
89
89
  self.weighting = self.shares * self.price * self.currency_fx_rate / portfolio_total_asset_value
90
+ if abs(self.weighting) < self.order_proposal.min_weighting:
91
+ warnings.append(
92
+ f"Weighting for order {self.underlying_instrument.computed_str} ({self.weighting}) is bellow the allowed Minimum Weighting ({self.order_proposal.min_weighting})"
93
+ )
94
+ self.shares = Decimal("0")
95
+ self.weighting = Decimal("0")
90
96
  if self.shares and abs(self.total_value_fx_portfolio) < self.order_proposal.min_order_value:
91
97
  warnings.append(
92
98
  f"Total Value for order {self.underlying_instrument.computed_str} ({self.total_value_fx_portfolio}) is bellow the allowed Minimum Order Value ({self.order_proposal.min_order_value})"
@@ -9,6 +9,7 @@ import pandas as pd
9
9
  from celery import shared_task
10
10
  from django.contrib.postgres.fields import DateRangeField
11
11
  from django.core.exceptions import ObjectDoesNotExist
12
+ from django.core.validators import MaxValueValidator, MinValueValidator
12
13
  from django.db import models
13
14
  from django.db.models import Exists, F, OuterRef, Q, QuerySet, Sum
14
15
  from django.db.models.signals import post_save
@@ -233,6 +234,25 @@ class Portfolio(DeleteToDisableMixin, WBModel):
233
234
  blank=True,
234
235
  )
235
236
 
237
+ # OMS default parameters. Used to seed order proposal default value upon creation
238
+ default_order_proposal_min_order_value = models.IntegerField(
239
+ default=0, verbose_name="Default Order Proposal Minimum Order Value"
240
+ )
241
+ default_order_proposal_min_weighting = models.DecimalField(
242
+ max_digits=9,
243
+ decimal_places=8,
244
+ default=Decimal(0),
245
+ verbose_name="Default Order Proposal Minimum Weight",
246
+ validators=[MinValueValidator(Decimal("0")), MaxValueValidator(Decimal("1"))],
247
+ )
248
+ default_order_proposal_total_cash_weight = models.DecimalField(
249
+ default=Decimal("0"),
250
+ decimal_places=4,
251
+ max_digits=5,
252
+ verbose_name="Default Order Proposal Total Cash Weight",
253
+ validators=[MinValueValidator(Decimal("0")), MaxValueValidator(Decimal("1"))],
254
+ )
255
+
236
256
  objects = DefaultPortfolioManager()
237
257
  tracked_objects = ActiveTrackedPortfolioManager()
238
258
 
@@ -90,6 +90,7 @@ class OrderProposalModelSerializer(wb_serializers.ModelSerializer):
90
90
  "comment",
91
91
  "status",
92
92
  "min_order_value",
93
+ "min_weighting",
93
94
  "_rebalancing_model",
94
95
  "rebalancing_model",
95
96
  "target_portfolio",
wbportfolio/tasks.py CHANGED
@@ -1,12 +1,12 @@
1
1
  from contextlib import suppress
2
2
  from datetime import date, timedelta
3
3
 
4
+ from celery import shared_task
4
5
  from django.db.models import ProtectedError, Q
6
+ from tqdm import tqdm
7
+ from wbfdm.models import Controversy, Instrument
5
8
 
6
- from wbportfolio.models import Portfolio, Trade
7
- from wbportfolio.models.products import Product
8
-
9
- from .fdm.tasks import * # noqa
9
+ from wbportfolio.models import AssetPosition, Portfolio, Product, Trade
10
10
 
11
11
 
12
12
  @shared_task(queue="portfolio")
@@ -49,3 +49,41 @@ def update_preferred_classification_per_instrument_and_portfolio_as_task():
49
49
  # - propagate (or update) t-2 asset positions into t-1
50
50
  # - Synchronize wbportfolio at t-1
51
51
  # - Compute Instrument Price estimate at t-1
52
+
53
+
54
+ @shared_task(queue="portfolio")
55
+ def synchronize_portfolio_controversies():
56
+ active_portfolios = Portfolio.objects.filter_active_and_tracked()
57
+ qs = (
58
+ AssetPosition.objects.filter(portfolio__in=active_portfolios)
59
+ .values("underlying_instrument")
60
+ .distinct("underlying_instrument")
61
+ )
62
+ objs = {}
63
+ securities = Instrument.objects.filter(id__in=qs.values("underlying_instrument"))
64
+ securities_mapping = {security.id: security.get_root() for security in securities}
65
+ for controversy in securities.dl.esg_controversies():
66
+ instrument = securities_mapping[controversy["instrument_id"]]
67
+ obj = Controversy.dict_to_model(controversy, instrument)
68
+ objs[obj.external_id] = obj
69
+
70
+ Controversy.objects.bulk_create(
71
+ objs.values(),
72
+ update_fields=[
73
+ "instrument",
74
+ "headline",
75
+ "description",
76
+ "source",
77
+ "direct_involvement",
78
+ "company_response",
79
+ "review",
80
+ "initiated",
81
+ "flag",
82
+ "status",
83
+ "type",
84
+ "severity",
85
+ ],
86
+ unique_fields=["external_id"],
87
+ update_conflicts=True,
88
+ batch_size=10000,
89
+ )
@@ -695,6 +695,38 @@ class TestOrderProposal:
695
695
  assert order.shares == Decimal(0)
696
696
  assert order.weighting == Decimal(0)
697
697
 
698
+ def test_order_submit_bellow_minimum_weighting(self, order_factory, order_proposal):
699
+ o1 = order_factory.create(order_proposal=order_proposal, price=Decimal(1), weighting=Decimal("0.8"))
700
+ o2 = order_factory.create(order_proposal=order_proposal, price=Decimal(1), weighting=Decimal("0.2"))
701
+ order_proposal.submit()
702
+ order_proposal.save()
703
+
704
+ o1.refresh_from_db()
705
+ o2.refresh_from_db()
706
+ assert o1.weighting == Decimal("0.8")
707
+ assert o2.weighting == Decimal("0.2")
708
+
709
+ order_proposal.min_weighting = Decimal("0.21")
710
+ order_proposal.backtodraft()
711
+ order_proposal.submit()
712
+ order_proposal.save()
713
+
714
+ o1.refresh_from_db()
715
+ o2.refresh_from_db()
716
+ assert o1.weighting == Decimal("0.8")
717
+ assert o2.weighting == Decimal("0")
718
+
719
+ order_proposal.approve()
720
+ order_proposal.apply()
721
+ order_proposal.save()
722
+
723
+ assert order_proposal.portfolio.assets.get(
724
+ date=order_proposal.trade_date, underlying_quote=o1.underlying_instrument
725
+ ).weighting == Decimal("0.8")
726
+ assert order_proposal.portfolio.assets.get(
727
+ date=order_proposal.trade_date, underlying_quote=order_proposal.cash_component
728
+ ).weighting == Decimal("0.2")
729
+
698
730
  def test_reset_order_use_desired_target_weight(self, order_proposal, order_factory):
699
731
  order1 = order_factory.create(
700
732
  order_proposal=order_proposal, weighting=Decimal("0.5"), desired_target_weight=Decimal("0.7")
@@ -132,12 +132,12 @@ class OrderProposalDisplayConfig(DisplayViewConfig):
132
132
  layouts={
133
133
  default(): Layout(
134
134
  grid_template_areas=[
135
- ["status", "status", "status"],
136
- ["trade_date", "total_cash_weight", "min_order_value"],
137
- ["rebalancing_model", "target_portfolio", "target_portfolio"]
135
+ ["status", "status", "status", "status"],
136
+ ["trade_date", "total_cash_weight", "min_order_value", "min_weighting"],
137
+ ["rebalancing_model", "rebalancing_model", "target_portfolio", "target_portfolio"]
138
138
  if self.view.new_mode
139
- else ["rebalancing_model", "creator", "approver"],
140
- ["comment", "comment", "comment"],
139
+ else ["rebalancing_model", "rebalancing_model", "creator", "approver"],
140
+ ["comment", "comment", "comment", "comment"],
141
141
  ],
142
142
  ),
143
143
  },
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wbportfolio
3
- Version: 1.55.7
3
+ Version: 1.55.9
4
4
  Author-email: Christopher Wittlinger <c.wittlinger@stainly.com>
5
5
  License-File: LICENSE
6
6
  Requires-Dist: cryptography==3.4.*
@@ -4,14 +4,14 @@ wbportfolio/constants.py,sha256=86bfJ-xAyJQGv8DDxhVP_BM7Jr_lxQMhe4SkrxpfN_c,119
4
4
  wbportfolio/dynamic_preferences_registry.py,sha256=SV-4JWBZBYhXt5cNMglx-yRJhxpejP_jo157ghjq2q0,2294
5
5
  wbportfolio/permissions.py,sha256=F147DXfitbw6IdMQGEFfymCJkiG5YGkWKsLdVVliPyw,320
6
6
  wbportfolio/preferences.py,sha256=JpowIFTrnjfomogJNrYmmfv7V35bRZNNGL_zooKzEhc,465
7
- wbportfolio/tasks.py,sha256=619LS4AN1-5RqdtwwLODdXA-IJKs5OA93JyLEnIJy4g,1969
7
+ wbportfolio/tasks.py,sha256=fjmG0FrCkwoHKDk7re6-vjKpI0q_HFtYLF8cddZHvnw,3243
8
8
  wbportfolio/urls.py,sha256=PE9UwW2RR8FEUnPc3foaDIW7T49vTwO1TyBPYaSorw0,10539
9
9
  wbportfolio/utils.py,sha256=QZ4t0j2NwKYmgWJM77yvXSp-8wVcZmFvNi5_v7YA3ac,750
10
10
  wbportfolio/admin/__init__.py,sha256=oTmHrq_4H4OyEna3R_3tIh7pyCyNYVsMDD8y06IYMfQ,675
11
11
  wbportfolio/admin/asset.py,sha256=Nukw4axCnctQFlAtPkPJyalEga7RtTp7jr138MOdWSM,1254
12
12
  wbportfolio/admin/custodians.py,sha256=rJ9wFdiFM5t3WrmAfNXWzjxDAWrbnlSstfNjQxSmTNE,332
13
13
  wbportfolio/admin/indexes.py,sha256=XPiVGBRDD7SV7YvSDv9pAo513IjIbEOBS_pcvVP_UfQ,440
14
- wbportfolio/admin/portfolio.py,sha256=ihAYlvx7vvRbFMIKobo-VokYfvlTowGDzcSmlXHCJDY,3873
14
+ wbportfolio/admin/portfolio.py,sha256=OiUFpxqK7V0iL8dO6LxE_LOepvr20b2CIDRiKPkdEns,4063
15
15
  wbportfolio/admin/portfolio_relationships.py,sha256=mLRQUvezcUQfEls0p6pe0P1qVf335zD5pX4eRVf119M,711
16
16
  wbportfolio/admin/product_groups.py,sha256=0iXpoj-gGwLeF6BmCohX7d5qrVhCgIxNWUQmJcM67q0,1391
17
17
  wbportfolio/admin/products.py,sha256=vEtUpSlnCLLCs4SXkI5UFO7iPsXhRUk7PsNvfD7FS40,2550
@@ -79,8 +79,6 @@ wbportfolio/factories/trades.py,sha256=ZHfj20KjeTu57sNaZzfSw2JqCoI9q4BjfPp5qRMVs
79
79
  wbportfolio/factories/orders/__init__.py,sha256=QG7on_F9GiuJgvGbM0BNDVdfGwwBz_WGbmCFNbKPZzc,83
80
80
  wbportfolio/factories/orders/order_proposals.py,sha256=3QGG6eI2sWYGJenn17gz37A2PJgjZLlPqAsqci1lFXI,702
81
81
  wbportfolio/factories/orders/orders.py,sha256=tTw2U-xvUsFpG4zad3KCHZPQx1FVg-zPjwEN73XEOjg,907
82
- wbportfolio/fdm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
83
- wbportfolio/fdm/tasks.py,sha256=59hXt3TOJaM8KpUaKdBNAGsO7NFMHaAlNA0T3FTUau0,533
84
82
  wbportfolio/filters/__init__.py,sha256=m44CdyYMtku8rMGyiX8KSmMdvyqaElKW4UMkEqOC1VM,1374
85
83
  wbportfolio/filters/assets.py,sha256=rvBNtQ8OcvYXSmaVdgjH7IITvaBZ558Y9sCj0B_WDpw,18866
86
84
  wbportfolio/filters/assets_and_net_new_money_progression.py,sha256=IYl_qMFO9QKhXhCTtz2JrOjlAKdEkykNlu4DO_H7HkQ,1403
@@ -271,6 +269,7 @@ wbportfolio/migrations/0085_order_desired_target_weight.py,sha256=L8p5t4PqjWIwqw
271
269
  wbportfolio/migrations/0086_orderproposal_total_cash_weight.py,sha256=IE65OYYBOSQjj6znl9jmsMalxDmKdnHV1DbVz_ZX_M4,689
272
270
  wbportfolio/migrations/0087_product_order_routing_custodian_adapter.py,sha256=4OHTjdXNwJ-My8EgUGYWM_vRBccjYgghjN4fLV0n1yQ,4564
273
271
  wbportfolio/migrations/0088_orderproposal_total_effective_portfolio_contribution.py,sha256=6Q41GSbWg_L8r6FUcQ9MrdpRazOdUlc7tD8_bmg8a3Y,521
272
+ wbportfolio/migrations/0089_orderproposal_min_weighting.py,sha256=DgJdIRka1eZSrEZqkUBHiVPpCfOvChWPrWdx-ZExO6Q,3906
274
273
  wbportfolio/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
275
274
  wbportfolio/models/__init__.py,sha256=qU4e7HKyh8NL_0Mg92PcbHTewCv7Ya2gei1DMGe1LWE,980
276
275
  wbportfolio/models/adjustments.py,sha256=osXWkJZOiansPWYPyHtl7Z121zDWi7u1YMtrBQtbHVo,10272
@@ -279,7 +278,7 @@ wbportfolio/models/builder.py,sha256=txZE_gEDgkPgSxSF0AlvZiRyhRQixD4Ame0wEF6Fjoo
279
278
  wbportfolio/models/custodians.py,sha256=owTiS2Vm5CRKzh9M_P9GOVg-s-ndQ9UvRmw3yZP7cw0,3815
280
279
  wbportfolio/models/exceptions.py,sha256=3ix0tWUO-O6jpz8f07XIwycw2x3JFRoWzjwil8FVA2Q,52
281
280
  wbportfolio/models/indexes.py,sha256=gvW4K9U9Bj8BmVCqFYdWiXvDWhjHINRON8XhNsZUiQY,639
282
- wbportfolio/models/portfolio.py,sha256=fuYvHx4D3GqHjO0cBqe09M-t-t6jUzuOMh2ikTbykMo,54640
281
+ wbportfolio/models/portfolio.py,sha256=zgismDA7dXSvX7b_1h9jOdYeilg9qv5mI0mQcy7aRW0,55547
283
282
  wbportfolio/models/portfolio_cash_flow.py,sha256=uElG7IJUBY8qvtrXftOoskX6EA-dKgEG1JJdvHeWV7g,7336
284
283
  wbportfolio/models/portfolio_cash_targets.py,sha256=WmgG-etPisZsh2yaFQpz7EkpvAudKBEzqPsO715w52U,1498
285
284
  wbportfolio/models/portfolio_relationship.py,sha256=ZGECiPZiLdlk4uSamOrEfuzO0hduK6OMKJLUSnh5_kc,5190
@@ -299,8 +298,8 @@ wbportfolio/models/mixins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJW
299
298
  wbportfolio/models/mixins/instruments.py,sha256=SuMPquQ93D4pZMK-4hQbJtV58_NOyf3wVOctQq7LNXQ,7054
300
299
  wbportfolio/models/mixins/liquidity_stress_test.py,sha256=iQVzT3QM7VtHnqfj9gT6KUIe4wC4MJXery-AXJHUYns,58820
301
300
  wbportfolio/models/orders/__init__.py,sha256=EH9UacGR3npBMje5FGTeLOh1xqFBh9kc24WbGmBIA3g,69
302
- wbportfolio/models/orders/order_proposals.py,sha256=1ce97DXjzZ4MsUAgA_GlnofnztAf0Y6zR1etZs-LrFI,57120
303
- wbportfolio/models/orders/orders.py,sha256=kiVmVeW2D1bAuT983nSeIug6uoZ78IZovuAgls-CO8w,10150
301
+ wbportfolio/models/orders/order_proposals.py,sha256=u-RNtSw-psb8BGeE7Lkbet5UQnCL_hacyhX3he0PxZQ,58191
302
+ wbportfolio/models/orders/orders.py,sha256=OpUbKzY2g6XA3n8hyU-FTauEQE5UKLEdOPQkdi4rktU,10520
304
303
  wbportfolio/models/orders/routing.py,sha256=OpeP-rfMm1UN7a3vbNxBEQxqtGfE57AeGWnbTZa1fRQ,2223
305
304
  wbportfolio/models/reconciliations/__init__.py,sha256=MXH5fZIPGDRBgJkO6wVu_NLRs8fkP1im7G6d-h36lQY,127
306
305
  wbportfolio/models/reconciliations/account_reconciliation_lines.py,sha256=QP6M7hMcyFbuXBa55Y-azui6Dl_WgbzMntEqWzQkbfM,7394
@@ -375,7 +374,7 @@ wbportfolio/serializers/registers.py,sha256=zhdKH_mHEBE0VOhm6xpY54bTMtcSaY5BskEa
375
374
  wbportfolio/serializers/roles.py,sha256=T-9NqTldpvaEMFy-Bib5MB6MeboygEOqcMP61mzzD3Q,2146
376
375
  wbportfolio/serializers/signals.py,sha256=hD6R4oFtwhvnsJPteytPKy2JwEelmxrapdfoLSnluaE,7053
377
376
  wbportfolio/serializers/orders/__init__.py,sha256=PKJRksA1pWsh8nVfGASoB0m3LyUzVRnq1m9VPp90J7k,271
378
- wbportfolio/serializers/orders/order_proposals.py,sha256=wIxnTY35dn7gH1kj9wGHnl2lOrR6ikRdqxXrSf85tT0,4762
377
+ wbportfolio/serializers/orders/order_proposals.py,sha256=Jxea2-Ze8Id5URv4UV-vTfCQGt11tjR27vRRfCs0gXU,4791
379
378
  wbportfolio/serializers/orders/orders.py,sha256=7zIl5lwt7RatSVcrmNmLpWX2r2VkND33HQOUkryGjYo,7582
380
379
  wbportfolio/serializers/transactions/__init__.py,sha256=-7Pan4n7YI3iDvGXff6okzk4ycEURRxp5n_SHCY_g_I,493
381
380
  wbportfolio/serializers/transactions/claim.py,sha256=kC4E2RZRrpd9i8tGfoiV-gpWDk3ikR5F1Wf0v_IGIvw,11599
@@ -420,7 +419,7 @@ wbportfolio/tests/models/test_roles.py,sha256=4Cn7WyrA2ztJNeWLk5cy9kYo5XLWMbFSvo
420
419
  wbportfolio/tests/models/test_splits.py,sha256=ytKcHsI_90kj1L4s8It-KEcc24rkDcElxwQ8q0QxEvk,9689
421
420
  wbportfolio/tests/models/utils.py,sha256=ORNJq6NMo1Za22jGZXfTfKeNEnTRlfEt_8SJ6xLaQWg,325
422
421
  wbportfolio/tests/models/orders/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
423
- wbportfolio/tests/models/orders/test_order_proposals.py,sha256=WxZgoN0J7rF5TVa_hmXZdYnUXtrU0eH-U9CW1NWNBIM,34123
422
+ wbportfolio/tests/models/orders/test_order_proposals.py,sha256=N_l7wgFgd-1uFCE6ZbWCzXEOmOgWaiee-w1VCqKxLnw,35401
424
423
  wbportfolio/tests/models/transactions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
425
424
  wbportfolio/tests/models/transactions/test_claim.py,sha256=NG3BKB-FVcIDgHSJHCjImxgMM3ISVUMl24xUPmEcPec,5570
426
425
  wbportfolio/tests/models/transactions/test_fees.py,sha256=tAp18x2wCNQr11LUnLtHNbBDbbX0v1DZnmW7i-cEi5Q,2423
@@ -555,7 +554,7 @@ wbportfolio/viewsets/orders/configs/buttons/__init__.py,sha256=EHzNmAfa0UQFITEF-
555
554
  wbportfolio/viewsets/orders/configs/buttons/order_proposals.py,sha256=1BPkIYv0-K2DDGa4Gua2_Pxsx7fNurTZ2tYNdL66On0,6495
556
555
  wbportfolio/viewsets/orders/configs/buttons/orders.py,sha256=GDO4Y33wkjhDxzpf7B1d_rKzAixegLv5rHam1DV3WkM,290
557
556
  wbportfolio/viewsets/orders/configs/displays/__init__.py,sha256=__YJBbz_ZnKpE8WMMDR2PC9Nng-EVlRpGTEQucdrhRA,108
558
- wbportfolio/viewsets/orders/configs/displays/order_proposals.py,sha256=1HnQGR8WFSWHfugEhbTrCaxZ5pabzH8iaLKVBb_Fowc,7282
557
+ wbportfolio/viewsets/orders/configs/displays/order_proposals.py,sha256=zLoLEw4N1i_LD0e3hJnxzO8ORN2byFZoCxWnAz8DBx0,7362
559
558
  wbportfolio/viewsets/orders/configs/displays/orders.py,sha256=R1oaDTGosL430xnYZpJz7ihnCOCO6eAFhDQz-wGYT24,7611
560
559
  wbportfolio/viewsets/orders/configs/endpoints/__init__.py,sha256=IB8GEadiEtBDclhkgpcJGXWfCF6qRK_42hxJ4pcdZDU,148
561
560
  wbportfolio/viewsets/orders/configs/endpoints/order_proposals.py,sha256=fY3y2YWR9nY-KE8k078NszDsnwOgqOIjHUgLvQjDivU,822
@@ -567,7 +566,7 @@ wbportfolio/viewsets/transactions/claim.py,sha256=Pb1WftoO-w-ZSTbLRhmQubhy7hgd68
567
566
  wbportfolio/viewsets/transactions/fees.py,sha256=WT2bWWfgozz4_rpyTKX7dgBBTXD-gu0nlsd2Nk2Zh1Q,7028
568
567
  wbportfolio/viewsets/transactions/mixins.py,sha256=WipvJoi5hylkpD0y9VATe30WAcwIHUIroVkK10FYw7k,636
569
568
  wbportfolio/viewsets/transactions/trades.py,sha256=xBgOGaJ8aEg-2RxEJ4FDaBs4SGwuLasun3nhpis0WQY,12363
570
- wbportfolio-1.55.7.dist-info/METADATA,sha256=9eoQ7L-xn-ibW7TppMry72I4MkZPJdB-mpICz2TiB5E,751
571
- wbportfolio-1.55.7.dist-info/WHEEL,sha256=tkmg4JIqwd9H8mL30xA7crRmoStyCtGp0VWshokd1Jc,105
572
- wbportfolio-1.55.7.dist-info/licenses/LICENSE,sha256=jvfVH0SY8_YMHlsJHKe_OajiscQDz4lpTlqT6x24sVw,172
573
- wbportfolio-1.55.7.dist-info/RECORD,,
569
+ wbportfolio-1.55.9.dist-info/METADATA,sha256=n1wrT55caQrYOtnWIcc_-bZdvHAjIDCO0rDr92VeroM,751
570
+ wbportfolio-1.55.9.dist-info/WHEEL,sha256=tkmg4JIqwd9H8mL30xA7crRmoStyCtGp0VWshokd1Jc,105
571
+ wbportfolio-1.55.9.dist-info/licenses/LICENSE,sha256=jvfVH0SY8_YMHlsJHKe_OajiscQDz4lpTlqT6x24sVw,172
572
+ wbportfolio-1.55.9.dist-info/RECORD,,
File without changes
wbportfolio/fdm/tasks.py DELETED
@@ -1,13 +0,0 @@
1
- from celery import shared_task
2
- from tqdm import tqdm
3
- from wbfdm.models import Controversy, Instrument
4
-
5
- from wbportfolio.models import AssetPosition
6
-
7
-
8
- @shared_task(queue="portfolio")
9
- def synchronize_portfolio_controversies():
10
- qs = AssetPosition.objects.values("underlying_instrument").distinct("underlying_instrument")
11
- for row in tqdm(qs, total=qs.count()):
12
- for controversy in Instrument.objects.filter(id=row["underlying_instrument"]).dl.esg_controversies():
13
- Controversy.sync_from_dataloader(controversy)