wbportfolio 1.49.1__py2.py3-none-any.whl → 1.49.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 wbportfolio might be problematic. Click here for more details.

@@ -853,7 +853,6 @@ class Portfolio(DeleteToDisableMixin, WBModel):
853
853
  adjusted_weighting,
854
854
  adjusted_currency_fx_rate,
855
855
  adjusted_is_estimated,
856
- portfolio_created=None,
857
856
  path=None,
858
857
  ):
859
858
  if not path:
@@ -866,7 +865,18 @@ class Portfolio(DeleteToDisableMixin, WBModel):
866
865
  position.is_estimated = (adjusted_is_estimated or position.is_estimated) and not (
867
866
  position.weighting == 1.0
868
867
  )
869
- position.portfolio_created = portfolio_created
868
+ # to get from which portfolio this position is created, we need to differantiate between:
869
+ # * Composition portfolio: where the portfolio created is the second encountered portfolio
870
+ # * Other: portfolio created is the last encountered portfolio
871
+ # If `path` is empty, we use None as portfolio_created
872
+ try:
873
+ if self.is_composition:
874
+ position.portfolio_created = path[1]
875
+ else:
876
+ position.portfolio_created = path[-1]
877
+ except IndexError:
878
+ position.portfolio_created = None
879
+
870
880
  setattr(position, "path", path)
871
881
  position.initial_shares = None
872
882
  if portfolio_total_asset_value:
@@ -881,7 +891,6 @@ class Portfolio(DeleteToDisableMixin, WBModel):
881
891
  position.weighting,
882
892
  position.currency_fx_rate,
883
893
  position.is_estimated,
884
- portfolio_created=child_portfolio,
885
894
  path=path.copy(),
886
895
  )
887
896
  elif position.weighting: # we do not yield position with weight 0 because of issue with certain multi-thematic portfolios which contain duplicates
@@ -167,7 +167,7 @@ class TradeProposal(CloneMixin, RiskCheckMixin, WBModel):
167
167
  Returns:
168
168
  The cloned trade proposal
169
169
  """
170
- trade_date = kwargs.get("trade_date", self.trade_date)
170
+ trade_date = kwargs.get("clone_date", self.trade_date)
171
171
 
172
172
  # Find the next valid trade date
173
173
  while TradeProposal.objects.filter(portfolio=self.portfolio, trade_date=trade_date).exists():
@@ -175,7 +175,7 @@ class TradeProposal(CloneMixin, RiskCheckMixin, WBModel):
175
175
 
176
176
  trade_proposal_clone = TradeProposal.objects.create(
177
177
  trade_date=trade_date,
178
- comment=kwargs.get("comment", self.comment),
178
+ comment=kwargs.get("clone_comment", self.comment),
179
179
  status=TradeProposal.Status.DRAFT,
180
180
  rebalancing_model=self.rebalancing_model,
181
181
  portfolio=self.portfolio,
@@ -2,13 +2,12 @@ from decimal import Decimal
2
2
 
3
3
  import numpy as np
4
4
  import pandas as pd
5
- from django.db.models import Q, QuerySet
5
+ from django.db.models import QuerySet
6
6
  from wbfdm.enums import MarketData
7
7
  from wbfdm.models import (
8
8
  Classification,
9
9
  Exchange,
10
10
  Instrument,
11
- InstrumentClassificationThroughModel,
12
11
  InstrumentListThroughModel,
13
12
  )
14
13
 
@@ -31,9 +30,11 @@ class MarketCapitalizationRebalancing(AbstractRebalancingModel):
31
30
  target_currency=self.TARGET_CURRENCY,
32
31
  )
33
32
  )
34
- self.exchange_df = pd.DataFrame(
35
- instruments.values_list("id", "exchange"), columns=["id", "exchange"]
36
- ).set_index("id")
33
+ self.exchange_df = (
34
+ pd.DataFrame(instruments.values_list("id", "exchange"), columns=["id", "exchange"])
35
+ .set_index("id")
36
+ .replace({np.nan: None})
37
+ )
37
38
  instrument_ids = list(instruments.values_list("id", flat=True))
38
39
  try:
39
40
  self.market_cap_df = (
@@ -41,6 +42,7 @@ class MarketCapitalizationRebalancing(AbstractRebalancingModel):
41
42
  .set_index("instrument_id")["market_capitalization"]
42
43
  .reindex(instrument_ids)
43
44
  )
45
+ self.market_cap_df = self.market_cap_df
44
46
  except (IndexError, KeyError):
45
47
  self.market_cap_df = pd.Series(dtype="float64", index=instrument_ids)
46
48
 
@@ -59,17 +61,10 @@ class MarketCapitalizationRebalancing(AbstractRebalancingModel):
59
61
  if not instrument_ids:
60
62
  instrument_ids = []
61
63
  if classification_ids:
62
- classifications = set()
63
64
  for classification in Classification.objects.filter(id__in=classification_ids):
64
65
  for children in classification.get_descendants(include_self=True):
65
- classifications.add(children)
66
- instrument_ids.extend(
67
- list(
68
- InstrumentClassificationThroughModel.objects.filter(
69
- classification__in=classifications
70
- ).values_list("id", flat=True)
71
- )
72
- )
66
+ for company in children.instruments.all():
67
+ instrument_ids.append(company.get_primary_quote().id)
73
68
  if instrument_list_id:
74
69
  instrument_ids.extend(
75
70
  list(
@@ -84,8 +79,10 @@ class MarketCapitalizationRebalancing(AbstractRebalancingModel):
84
79
  self.portfolio.assets.filter(date=self.trade_date).values_list("underlying_instrument", flat=True)
85
80
  )
86
81
 
87
- return Instrument.objects.filter(id__in=instrument_ids).filter(
88
- (Q(delisted_date__isnull=True) | Q(delisted_date__gt=self.trade_date))
82
+ return (
83
+ Instrument.objects.filter(id__in=instrument_ids)
84
+ .filter(exchange__isnull=False)
85
+ .filter_active_at_date(self.trade_date)
89
86
  )
90
87
 
91
88
  def is_valid(self) -> bool:
@@ -85,7 +85,7 @@ class PortfolioModelSerializer(wb_serializers.ModelSerializer):
85
85
  request=request,
86
86
  )
87
87
  if user.profile.is_internal:
88
- additional_resources["instruments"] = reverse(
88
+ additional_resources["instruments_list"] = reverse(
89
89
  "wbportfolio:portfolio-instrument-list",
90
90
  args=[instance.id],
91
91
  request=request,
@@ -136,8 +136,8 @@ class TestMarketCapitalizationRebalancing:
136
136
 
137
137
  last_effective_date = (weekday - BDay(1)).date()
138
138
 
139
- i1 = instrument_factory()
140
- i2 = instrument_factory()
139
+ i1 = instrument_factory(inception_date=weekday)
140
+ i2 = instrument_factory(inception_date=weekday)
141
141
  instrument_price_factory.create(instrument=i1, date=weekday)
142
142
  instrument_price_factory.create(instrument=i2, date=weekday)
143
143
  return MarketCapitalizationRebalancing(portfolio, weekday, last_effective_date, instrument_ids=[i1.id, i2.id])
@@ -323,7 +323,7 @@ class CashPositionPortfolioPandasAPIView(
323
323
  val_date = datetime.strptime(date_str, "%Y-%m-%d").date()
324
324
  else:
325
325
  val_date = date.today()
326
- active_products = Product.active_objects.get_queryset_at_date(val_date)
326
+ active_products = Product.active_objects.filter_active_at_date(val_date)
327
327
  return (
328
328
  super()
329
329
  .get_queryset()
@@ -103,8 +103,8 @@ class PortfolioDisplayConfig(DisplayViewConfig):
103
103
  create_simple_section(
104
104
  "instruments_section",
105
105
  _("Linked Instruments"),
106
- [["instruments"]],
107
- "instruments",
106
+ [["instruments_list"]],
107
+ "instruments_list",
108
108
  collapsed=True,
109
109
  ),
110
110
  create_simple_section(
@@ -65,16 +65,18 @@ class TradeProposalModelViewSet(CloneMixin, RiskCheckViewSetMixin, InternalUserP
65
65
  # 2 methods to parametrize the clone button functionality
66
66
  def get_clone_button_serializer_class(self, instance):
67
67
  class CloneSerializer(wb_serializers.Serializer):
68
- trade_date = wb_serializers.DateField(default=(instance.trade_date + BDay(1)).date(), label="Trade Date")
69
- comment = wb_serializers.TextField(label="Comment")
68
+ clone_date = wb_serializers.DateField(
69
+ default=(instance.trade_date + BDay(1)).date(), label="Trade Date"
70
+ ) # we need to change the field name from the trade proposa fields, otherwise fontend conflicts
71
+ clone_comment = wb_serializers.TextField(label="Comment")
70
72
 
71
73
  return CloneSerializer
72
74
 
73
75
  def get_clone_button_instance_display(self) -> Display:
74
76
  return create_simple_display(
75
77
  [
76
- ["comment"],
77
- ["trade_date"],
78
+ ["clone_comment"],
79
+ ["clone_date"],
78
80
  ]
79
81
  )
80
82
 
@@ -382,7 +382,7 @@ class TradeTradeProposalModelViewSet(
382
382
  )
383
383
  IDENTIFIER = "wbportfolio:tradeproposal"
384
384
  search_fields = ("underlying_instrument__name",)
385
- filterset_fields = {}
385
+ filterset_fields = {"status": ["exact"]}
386
386
  queryset = Trade.objects.all()
387
387
 
388
388
  display_config_class = TradeTradeProposalDisplayConfig
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wbportfolio
3
- Version: 1.49.1
3
+ Version: 1.49.2
4
4
  Author-email: Christopher Wittlinger <c.wittlinger@stainly.com>
5
5
  License-File: LICENSE
6
6
  Requires-Dist: cryptography==3.4.*
@@ -249,7 +249,7 @@ wbportfolio/models/asset.py,sha256=yf4vBPfN1eZlWXG9SowQwr5-goG8rO1yYDitHDLZCBs,3
249
249
  wbportfolio/models/custodians.py,sha256=owTiS2Vm5CRKzh9M_P9GOVg-s-ndQ9UvRmw3yZP7cw0,3815
250
250
  wbportfolio/models/exceptions.py,sha256=3ix0tWUO-O6jpz8f07XIwycw2x3JFRoWzjwil8FVA2Q,52
251
251
  wbportfolio/models/indexes.py,sha256=iLYF2gzNzX4GLj_Nh3fybUcAQ1TslnT0wgQ6mN164QI,728
252
- wbportfolio/models/portfolio.py,sha256=cW27PFaQDpdd-UxHNgJ6sUBzit013-Rkr2J3aULoITo,59086
252
+ wbportfolio/models/portfolio.py,sha256=KtuPMWtYoKrIOwp9T_REnOjT9CI2kjtEijF3uA0Twsc,59595
253
253
  wbportfolio/models/portfolio_cash_flow.py,sha256=2blPiXSw7dbhUVd-7LcxDBb4v0SheNOdvRK3MFYiChA,7273
254
254
  wbportfolio/models/portfolio_cash_targets.py,sha256=WmgG-etPisZsh2yaFQpz7EkpvAudKBEzqPsO715w52U,1498
255
255
  wbportfolio/models/portfolio_relationship.py,sha256=mMb18UMRWg9kx_9uIPkMktwORuXXLjKdgRPQQvB6fVE,5486
@@ -276,7 +276,7 @@ wbportfolio/models/transactions/dividends.py,sha256=92-jG8bZN9nU9oDubpu-UDH43Ri7
276
276
  wbportfolio/models/transactions/expiry.py,sha256=vnNHdcC1hf2HP4rAbmoGgOfagBYKNFytqOwzOI0MlVI,144
277
277
  wbportfolio/models/transactions/fees.py,sha256=ffvqo8I4A0l5rLi00jJ6sGot0jmnkoxaNsbDzdPLwCg,5712
278
278
  wbportfolio/models/transactions/rebalancing.py,sha256=nrBi6x6PssCtkLtOpV-2OoAHDUKnnYyrM6xH1PmnjSo,7240
279
- wbportfolio/models/transactions/trade_proposals.py,sha256=CMeo_5KM58j1VU8bgA_r2uhvi3z6X_jqey4WKzwN8_E,26724
279
+ wbportfolio/models/transactions/trade_proposals.py,sha256=9ggUkwzDgMKa8cC8dNZ4IHlleiGpRN0WU-oXGDSiuaw,26730
280
280
  wbportfolio/models/transactions/trades.py,sha256=P9cSTEpZBsqKBvw25XY_RNctTiOBEzCvcuy0r8IkedE,28013
281
281
  wbportfolio/models/transactions/transactions.py,sha256=fWoDf0TSV0L0gLUDOQpCRLzjMt1H4MUvUHGEaMsilCc,7027
282
282
  wbportfolio/pms/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -292,7 +292,7 @@ wbportfolio/rebalancing/decorators.py,sha256=JhQ2vkcIuGBTGvNmpkQerdw2-vLq-RAb0KA
292
292
  wbportfolio/rebalancing/models/__init__.py,sha256=AQjG7Tu5vlmhqncVoYOjpBKU2UIvgo9FuP2_jD2w-UI,232
293
293
  wbportfolio/rebalancing/models/composite.py,sha256=uyF1n3NAFprnAZ3Gl5pNJl0GajelqJspC2NufZ7Tf0s,1636
294
294
  wbportfolio/rebalancing/models/equally_weighted.py,sha256=U29MOHJMQMIg7Y7W_8t5K3nXjaznzt4ArIxQSiv0Xok,863
295
- wbportfolio/rebalancing/models/market_capitalization_weighted.py,sha256=LvzV7a8fNbpsRahysvKbE6oNSQccWpnnne-rlDj3uzU,4928
295
+ wbportfolio/rebalancing/models/market_capitalization_weighted.py,sha256=7vdr7SMNswi3Emc8RpLPJQqQw39xrznp3Ps9Pf9YEZ4,4789
296
296
  wbportfolio/rebalancing/models/model_portfolio.py,sha256=XQdvs03-0M9YUnL4DidwZC4E6k-ANCNcZ--T_aaOXTQ,1233
297
297
  wbportfolio/reports/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
298
298
  wbportfolio/reports/monthly_position_report.py,sha256=e7BzjDd6eseUOwLwQJXKvWErQ58YnCsznHU2VtR6izM,2981
@@ -328,7 +328,7 @@ wbportfolio/serializers/portfolio_cash_flow.py,sha256=vBRZnUKq4XAqcvjyk-xMsw5v4x
328
328
  wbportfolio/serializers/portfolio_cash_targets.py,sha256=_GdsFXoBda1JHJnfZbaVlNFdnXlvGuy_FEcEZH-UThY,605
329
329
  wbportfolio/serializers/portfolio_relationship.py,sha256=UR_GIF2LHw82a8mv6L8OXYvoCp5-QWtubt33Y4mqFow,1933
330
330
  wbportfolio/serializers/portfolio_swing_pricing.py,sha256=a21st7MmcugbAO_xc90QWSeXwU1ivk-y2PWlMGKySJY,655
331
- wbportfolio/serializers/portfolios.py,sha256=ZowvB0T38tuXVQI-O9pEsPdLfG1hrW6aMZ1DBVnPbuE,7679
331
+ wbportfolio/serializers/portfolios.py,sha256=qEbrTAVepeVIPcs9XaWCDJ0ZxSQX8-M9HmRh6ky4KuY,7684
332
332
  wbportfolio/serializers/positions.py,sha256=UK9dvE1wiILw2E209InrsUhme52vfUYDDERBeKCcn_k,2415
333
333
  wbportfolio/serializers/product_group.py,sha256=klPGmAb1MvJpyiKKMRb8uYFIMm6SCZkMFQDu5EH-mkY,3680
334
334
  wbportfolio/serializers/products.py,sha256=BDMizM77Iohe7JEUncll2ET4GtU8hicQ6c4Vm0srqd4,12374
@@ -389,7 +389,7 @@ wbportfolio/tests/models/transactions/test_trades.py,sha256=vqvOqUY_uXvBp8YOKR0W
389
389
  wbportfolio/tests/pms/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
390
390
  wbportfolio/tests/pms/test_analytics.py,sha256=fAuY1zcXibttFpBh2GhKVyzdYfi1kz_b7SPa9xZQXY0,1086
391
391
  wbportfolio/tests/rebalancing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
392
- wbportfolio/tests/rebalancing/test_models.py,sha256=mhhuIWPZF2SQHzVdotp90eIrfmnMGQNu5YTGcMDjlIY,7505
392
+ wbportfolio/tests/rebalancing/test_models.py,sha256=qyZkNG1WF1lZdYwvjUElkkNey8b5ZMGSlWpzxujCuNg,7549
393
393
  wbportfolio/tests/serializers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
394
394
  wbportfolio/tests/serializers/test_claims.py,sha256=vQrg73xQXRFEgvx3KI9ivFre_wpBFzdO0p0J13PkvdY,582
395
395
  wbportfolio/tests/viewsets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -400,7 +400,7 @@ wbportfolio/tests/viewsets/transactions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5J
400
400
  wbportfolio/tests/viewsets/transactions/test_claims.py,sha256=QEZfMAW07dyoZ63t2umSwGOqvaTULfYfbN_F4ZoSAcw,6368
401
401
  wbportfolio/viewsets/__init__.py,sha256=3kUaQ66ybvROwejd3bEcSt4XKzfOlPDaeoStMvlz7qY,2294
402
402
  wbportfolio/viewsets/adjustments.py,sha256=5hWCjxSgUIsrPOmJKoDYK3gywdMTI0aYDorEj1FXRVc,1429
403
- wbportfolio/viewsets/assets.py,sha256=vwfrJaws7aVOUd-4FTlZVahpiMGgIEt1rcUumvWIKss,22734
403
+ wbportfolio/viewsets/assets.py,sha256=CrAMuyJDyUcSZlckrhy5D6-vVRXD7I4EG9C3ZKA5Z08,22735
404
404
  wbportfolio/viewsets/assets_and_net_new_money_progression.py,sha256=Jl4vEQP4N2OFL5IGBXoKcj-0qaPviU0I8npvQLw4Io0,4464
405
405
  wbportfolio/viewsets/custodians.py,sha256=CTFqkqVP1R3AV7lhdvcdICxB5DfwDYCyikNSI5kbYEo,2322
406
406
  wbportfolio/viewsets/esg.py,sha256=27MxxdXQH3Cq_1UEYmcrF7htUOg6i81fUpbVQXAAKJI,6985
@@ -444,7 +444,7 @@ wbportfolio/viewsets/configs/display/esg.py,sha256=W8uetCPN2TjHtU2kvQjKOmkq7uoaY
444
444
  wbportfolio/viewsets/configs/display/fees.py,sha256=_8HDJADh5bA5VMVPkhKObPmNNdPHWR8Oz23PEgd04F0,5834
445
445
  wbportfolio/viewsets/configs/display/portfolio_cash_flow.py,sha256=CS_UGhKZSXnX-0SZ0RXzbG1WMJm6NX3GUljwIa4RWBk,5025
446
446
  wbportfolio/viewsets/configs/display/portfolio_relationship.py,sha256=8DvsYWFCX29qj5wUf1wCtjlPwzKRd_E7JDuo_CopaJ0,1294
447
- wbportfolio/viewsets/configs/display/portfolios.py,sha256=ke60jc2yUjEHjkyt4yruM3LXnKC63oO2RMmaj_4ljks,10716
447
+ wbportfolio/viewsets/configs/display/portfolios.py,sha256=HFUFYajD7l-7WhwsxEeBp8QvJ5ZZY03EA8Am-DQ6f6w,10726
448
448
  wbportfolio/viewsets/configs/display/positions.py,sha256=yolWLxzGPIpSQSiVhVQChURqbomPt5kSjkYrmXT1Mik,3123
449
449
  wbportfolio/viewsets/configs/display/product_groups.py,sha256=PwI-A0_ofShT2pub9-C1HqreiqpHxKMHd51JYwEzvbM,2500
450
450
  wbportfolio/viewsets/configs/display/product_performance.py,sha256=6Mme48JBn_okwClR44dBK2OK26ejvdasDvBa5DI33_0,10070
@@ -518,10 +518,10 @@ wbportfolio/viewsets/transactions/claim.py,sha256=m_Fy4J_QZSve1VlR_sPQrVBDopgCqq
518
518
  wbportfolio/viewsets/transactions/fees.py,sha256=7VUXIogmRrXCz_D9tvDiiTae0t5j09W9zPUzxXzBGTE,7031
519
519
  wbportfolio/viewsets/transactions/mixins.py,sha256=WipvJoi5hylkpD0y9VATe30WAcwIHUIroVkK10FYw7k,636
520
520
  wbportfolio/viewsets/transactions/rebalancing.py,sha256=6rIrdK0rtKL1afJ-tYfAGdQVTN2MH1kG_yCeVkmyK8k,1263
521
- wbportfolio/viewsets/transactions/trade_proposals.py,sha256=nZsomopPfeLg1owPpOdIbhdHfCFa3-Qh-uyqoSATOjw,5821
522
- wbportfolio/viewsets/transactions/trades.py,sha256=D5-Qk8_OJze_6aNqeMCNjgcAz5B9dIP2M_8m_PCAtXI,21475
521
+ wbportfolio/viewsets/transactions/trade_proposals.py,sha256=iQpC_Thbj56SmM05vPRsF1JZguGBDaTUH3I-_iCHCV0,5958
522
+ wbportfolio/viewsets/transactions/trades.py,sha256=xeEzx7GP34aBNPlDmiUmT86labsbb8_f1U2RCN1Jatg,21494
523
523
  wbportfolio/viewsets/transactions/transactions.py,sha256=ixDp-nsNA8t_A06rBCT19hOMJHy0iRmdz1XKdV1OwAs,4450
524
- wbportfolio-1.49.1.dist-info/METADATA,sha256=HuQ5d8oOm9My1liVRK4vyUE6Z3ZbSlmiNHPloBz_5Yg,734
525
- wbportfolio-1.49.1.dist-info/WHEEL,sha256=tkmg4JIqwd9H8mL30xA7crRmoStyCtGp0VWshokd1Jc,105
526
- wbportfolio-1.49.1.dist-info/licenses/LICENSE,sha256=jvfVH0SY8_YMHlsJHKe_OajiscQDz4lpTlqT6x24sVw,172
527
- wbportfolio-1.49.1.dist-info/RECORD,,
524
+ wbportfolio-1.49.2.dist-info/METADATA,sha256=cFNyn_eGy7Dwxdfb_oqZH6Z2zj79fYUOsKj6cTy5XNo,734
525
+ wbportfolio-1.49.2.dist-info/WHEEL,sha256=tkmg4JIqwd9H8mL30xA7crRmoStyCtGp0VWshokd1Jc,105
526
+ wbportfolio-1.49.2.dist-info/licenses/LICENSE,sha256=jvfVH0SY8_YMHlsJHKe_OajiscQDz4lpTlqT6x24sVw,172
527
+ wbportfolio-1.49.2.dist-info/RECORD,,