wbportfolio 1.54.21__py2.py3-none-any.whl → 1.54.22__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.

@@ -0,0 +1 @@
1
+ EQUITY_TYPE_KEYS = ["american_depository_receipt", "equity"] # TODO might want to move this into a dynamic preference
@@ -10,7 +10,10 @@ def parse(import_source):
10
10
  with suppress(KeyError):
11
11
  series_data = json.loads(import_source.file.read())["payload"]["series"]
12
12
  for series in series_data:
13
- isin = series["item"]["priceIdentifier"]
13
+ try:
14
+ isin = series["key"]["priceIdentifier"]
15
+ except KeyError:
16
+ isin = series["priceIdentifier"]
14
17
  if Product.objects.filter(isin=isin).exists(): # ensure the timeseries contain data for products we handle
15
18
  for point in series["points"]:
16
19
  data.append(
@@ -130,9 +130,9 @@ class AssetPositionBuilder:
130
130
  def set_prices(self, prices: dict[date, dict[int, float]] | None = None):
131
131
  self.prices = prices
132
132
 
133
- def load_returns(self, instrument_ids: list[int], from_date: date, to_date: date):
133
+ def load_returns(self, instrument_ids: list[int], from_date: date, to_date: date, use_dl: bool = True):
134
134
  self.prices, self.returns = Instrument.objects.filter(id__in=instrument_ids).get_returns_df(
135
- from_date=from_date, to_date=to_date, to_currency=self.portfolio.currency, use_dl=True
135
+ from_date=from_date, to_date=to_date, to_currency=self.portfolio.currency, use_dl=use_dl
136
136
  )
137
137
 
138
138
  def add(
@@ -221,9 +221,11 @@ class AssetPositionBuilder:
221
221
 
222
222
  for val_date in self.get_dates():
223
223
  if self.portfolio.is_tracked:
224
- with suppress(KeyError):
224
+ try:
225
225
  changed_portfolio = self._get_portfolio(val_date)
226
- self._change_at_date_tasks[val_date] = changed_portfolio
226
+ except KeyError:
227
+ changed_portfolio = None
228
+ self._change_at_date_tasks[val_date] = changed_portfolio
227
229
  self._compute_metrics_tasks.add(val_date)
228
230
  self._positions = defaultdict(dict)
229
231
 
@@ -237,7 +239,7 @@ class AssetPositionBuilder:
237
239
  for d in self._compute_metrics_tasks
238
240
  ]
239
241
  ).apply_async()
240
- self._change_at_date_tasks = set()
242
+ self._change_at_date_tasks = dict()
241
243
 
242
244
  def schedule_change_at_dates(self, synchronous: bool = True, **task_kwargs):
243
245
  from wbportfolio.models.portfolio import trigger_portfolio_change_as_task
@@ -38,6 +38,7 @@ from wbportfolio.pms.analytics.portfolio import Portfolio as AnalyticPortfolio
38
38
  from wbportfolio.pms.typing import Portfolio as PortfolioDTO
39
39
  from wbportfolio.pms.typing import Position as PositionDTO
40
40
 
41
+ from ..constants import EQUITY_TYPE_KEYS
41
42
  from . import ProductGroup
42
43
 
43
44
  logger = logging.getLogger("pms")
@@ -337,8 +338,12 @@ class Portfolio(DeleteToDisableMixin, WBModel):
337
338
  weights = self.get_weights(val_date)
338
339
  return_date = (val_date + BDay(1)).date()
339
340
  returns = self.builder.returns
340
- if pd.Timestamp(return_date) not in returns.index or not set(weights.keys()).issubset(set(returns.columns)):
341
- returns = self.load_builder_returns(val_date, return_date)
341
+ if (
342
+ return_date <= date.today()
343
+ and pd.Timestamp(return_date) not in returns.index
344
+ or not set(weights.keys()).issubset(set(returns.columns))
345
+ ):
346
+ returns = self.load_builder_returns(val_date, return_date, use_dl=use_dl)
342
347
  if pd.Timestamp(return_date) not in returns.index:
343
348
  raise ValueError()
344
349
  returns = returns.loc[:return_date, :]
@@ -507,7 +512,7 @@ class Portfolio(DeleteToDisableMixin, WBModel):
507
512
  val_date=val_date,
508
513
  exclude_cash=True,
509
514
  exclude_index=True,
510
- extra_filter_parameters={"underlying_instrument__instrument_type": InstrumentType.EQUITY},
515
+ extra_filter_parameters={"underlying_instrument__instrument_type__key__in": EQUITY_TYPE_KEYS},
511
516
  **kwargs,
512
517
  )
513
518
  if not df.empty:
@@ -520,7 +525,7 @@ class Portfolio(DeleteToDisableMixin, WBModel):
520
525
  val_date=val_date,
521
526
  exclude_cash=True,
522
527
  exclude_index=True,
523
- extra_filter_parameters={"underlying_instrument__instrument_type": InstrumentType.EQUITY},
528
+ extra_filter_parameters={"underlying_instrument__instrument_type__key__in": EQUITY_TYPE_KEYS},
524
529
  **kwargs,
525
530
  )
526
531
  if not df.empty:
@@ -592,7 +597,7 @@ class Portfolio(DeleteToDisableMixin, WBModel):
592
597
  ) -> pd.DataFrame:
593
598
  qs = self._get_assets(with_cash=with_cash).filter(date__gte=start, date__lte=end)
594
599
  if only_equity:
595
- qs = qs.filter(underlying_instrument__instrument_type=InstrumentType.EQUITY)
600
+ qs = qs.filter(underlying_instrument__instrument_type__key__in=EQUITY_TYPE_KEYS)
596
601
  qs = qs.annotate_hedged_currency_fx_rate(hedged_currency)
597
602
  df = Portfolio.get_contribution_df(
598
603
  qs.select_related("underlying_instrument").values_list(
@@ -725,7 +730,7 @@ class Portfolio(DeleteToDisableMixin, WBModel):
725
730
  effective_portfolio_date = (val_date - BDay(1)).date()
726
731
  with suppress(ValueError):
727
732
  if not analytic_portfolio:
728
- analytic_portfolio = self.get_analytic_portfolio(effective_portfolio_date)
733
+ analytic_portfolio = self.get_analytic_portfolio(effective_portfolio_date, use_dl=False)
729
734
  for instrument in self.pms_instruments:
730
735
  # we assume that in t-1 we will have a portfolio (with at least estimate position). If we use the latest position date before val_date, we run into the problem of being able to compute nav at every date
731
736
  last_price = instrument.get_latest_price(effective_portfolio_date)
@@ -839,11 +844,13 @@ class Portfolio(DeleteToDisableMixin, WBModel):
839
844
  self.builder.schedule_change_at_dates(evaluate_rebalancer=False)
840
845
  self.builder.schedule_metric_computation()
841
846
 
842
- def load_builder_returns(self, from_date: date, to_date: date) -> pd.DataFrame:
847
+ def load_builder_returns(self, from_date: date, to_date: date, use_dl: bool = True) -> pd.DataFrame:
843
848
  instruments_ids = list(self.get_weights(from_date).keys())
844
849
  for tp in self.order_proposals.filter(trade_date__gte=from_date, trade_date__lte=to_date, status="APPROVED"):
845
850
  instruments_ids.extend(tp.orders.values_list("underlying_instrument", flat=True))
846
- self.builder.load_returns(set(instruments_ids), (from_date - BDay(1)).date(), (to_date + BDay(1)).date())
851
+ self.builder.load_returns(
852
+ set(instruments_ids), (from_date - BDay(1)).date(), (to_date + BDay(1)).date(), use_dl=use_dl
853
+ )
847
854
  return self.builder.returns
848
855
 
849
856
  def get_lookthrough_positions(
@@ -15,7 +15,6 @@ from wbfdm.models import (
15
15
  ClassificationGroup,
16
16
  Instrument,
17
17
  InstrumentClassificationThroughModel,
18
- InstrumentType,
19
18
  )
20
19
 
21
20
  from wbportfolio.filters.assets import DistributionFilter
@@ -26,6 +25,7 @@ from wbportfolio.models import (
26
25
  PortfolioRole,
27
26
  )
28
27
 
28
+ from ...constants import EQUITY_TYPE_KEYS
29
29
  from ..configs.buttons.assets import (
30
30
  DistributionChartButtonConfig,
31
31
  DistributionTableButtonConfig,
@@ -70,7 +70,7 @@ class AbstractDistributionMixin:
70
70
 
71
71
  def _generate_classification_df(self, queryset):
72
72
  df = pd.DataFrame(
73
- queryset.filter(underlying_instrument__instrument_type=InstrumentType.EQUITY).values(
73
+ queryset.filter(underlying_instrument__instrument_type__key__in=EQUITY_TYPE_KEYS).values(
74
74
  "weighting", "underlying_instrument"
75
75
  ),
76
76
  columns=["weighting", "underlying_instrument"],
@@ -10,7 +10,7 @@ from wbcore.pandas import fields as pf
10
10
  from wbcore.permissions.permissions import InternalUserPermissionMixin
11
11
  from wbcore.serializers import decorator
12
12
  from wbcore.utils.strings import format_number
13
- from wbfdm.models import Classification, ClassificationGroup, Instrument, InstrumentType
13
+ from wbfdm.models import Classification, ClassificationGroup, Instrument
14
14
 
15
15
  from wbportfolio.filters import (
16
16
  AggregatedAssetPositionLiquidityFilter,
@@ -19,6 +19,7 @@ from wbportfolio.filters import (
19
19
  from wbportfolio.filters.positions import GroupbyChoice
20
20
  from wbportfolio.models import AssetPosition, Portfolio
21
21
 
22
+ from ..constants import EQUITY_TYPE_KEYS
22
23
  from .configs import (
23
24
  AggregatedAssetPositionLiquidityDisplayConfig,
24
25
  AggregatedAssetPositionLiquidityEndpointConfig,
@@ -212,7 +213,7 @@ class AggregatedAssetPositionLiquidityPandasView(InternalUserPermissionMixin, Ex
212
213
 
213
214
  # Take the liquidity query for the two dates.
214
215
  qs_assets = queryset.filter(
215
- underlying_instrument__instrument_type=InstrumentType.EQUITY,
216
+ underlying_instrument__instrument_type__key__in=EQUITY_TYPE_KEYS,
216
217
  date__in=[historic_date, compared_date],
217
218
  ).values(
218
219
  "date",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wbportfolio
3
- Version: 1.54.21
3
+ Version: 1.54.22
4
4
  Author-email: Christopher Wittlinger <c.wittlinger@stainly.com>
5
5
  License-File: LICENSE
6
6
  Requires-Dist: cryptography==3.4.*
@@ -1,5 +1,6 @@
1
1
  wbportfolio/__init__.py,sha256=J-j-u0itpEFT6irdmWmixQqYMadNl1X91TxUmoiLHMI,22
2
2
  wbportfolio/apps.py,sha256=tybcoLFiw5tLdGHYV68X96n6jNZqx4BYx7Ao8mPflH8,749
3
+ wbportfolio/constants.py,sha256=86bfJ-xAyJQGv8DDxhVP_BM7Jr_lxQMhe4SkrxpfN_c,119
3
4
  wbportfolio/dynamic_preferences_registry.py,sha256=SV-4JWBZBYhXt5cNMglx-yRJhxpejP_jo157ghjq2q0,2294
4
5
  wbportfolio/permissions.py,sha256=F147DXfitbw6IdMQGEFfymCJkiG5YGkWKsLdVVliPyw,320
5
6
  wbportfolio/preferences.py,sha256=JpowIFTrnjfomogJNrYmmfv7V35bRZNNGL_zooKzEhc,465
@@ -194,7 +195,7 @@ wbportfolio/import_export/parsers/vontobel/performance_fees.py,sha256=K-E7bRs7Lx
194
195
  wbportfolio/import_export/parsers/vontobel/trade.py,sha256=Xc0ttSkdLm-ZIHtXOyHxHr3FuR89T87I9hXqiTMU1Hk,1566
195
196
  wbportfolio/import_export/parsers/vontobel/utils.py,sha256=3-g2Jep9SxvqqQff8_3FjIeiPxSJCEfXBiBHIk0TiXQ,225
196
197
  wbportfolio/import_export/parsers/vontobel/valuation.py,sha256=iav8_xYpTJchmTa7KOPmFr1gi9xxLwq3e-VcZ9MDiRk,1220
197
- wbportfolio/import_export/parsers/vontobel/valuation_api.py,sha256=WLkZ5z-WqhFraNorWlOhIpSx1pQ2fnjdsLHwSTA7O2o,882
198
+ wbportfolio/import_export/parsers/vontobel/valuation_api.py,sha256=z9b5zKS-Dz907Mrbg7rJjFVJocSutEiS6oo2ICTjpUI,980
198
199
  wbportfolio/import_export/resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
199
200
  wbportfolio/import_export/resources/assets.py,sha256=zjgHlQWpud41jHrKdRyqGUt1KUJQm9Z7pt0uVh4qBWQ,2234
200
201
  wbportfolio/import_export/resources/trades.py,sha256=-HJPVYNuMRmCu4XpD00fYlRYu3N-Ys_JpyxE0HIU5bM,1723
@@ -268,11 +269,11 @@ wbportfolio/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3
268
269
  wbportfolio/models/__init__.py,sha256=qU4e7HKyh8NL_0Mg92PcbHTewCv7Ya2gei1DMGe1LWE,980
269
270
  wbportfolio/models/adjustments.py,sha256=osXWkJZOiansPWYPyHtl7Z121zDWi7u1YMtrBQtbHVo,10272
270
271
  wbportfolio/models/asset.py,sha256=PwL16w2Rw_rJL73e0vCWMlRqsCxKW4zA9bf1EgTzD60,39574
271
- wbportfolio/models/builder.py,sha256=n4__dW8L3hiM8U2_xhUPmR3Gt67pDI0vv5fejzoqah8,11536
272
+ wbportfolio/models/builder.py,sha256=gGBlU0s5kvMxUas2lil0n98BxVjVocUDfU9oHKgkkJY,11622
272
273
  wbportfolio/models/custodians.py,sha256=owTiS2Vm5CRKzh9M_P9GOVg-s-ndQ9UvRmw3yZP7cw0,3815
273
274
  wbportfolio/models/exceptions.py,sha256=3ix0tWUO-O6jpz8f07XIwycw2x3JFRoWzjwil8FVA2Q,52
274
275
  wbportfolio/models/indexes.py,sha256=gvW4K9U9Bj8BmVCqFYdWiXvDWhjHINRON8XhNsZUiQY,639
275
- wbportfolio/models/portfolio.py,sha256=XIRR2r0yDgE1zdZ5WZUeaas0ZdRGOm0Ps6bvkgg7fQc,53046
276
+ wbportfolio/models/portfolio.py,sha256=7PRPI8sNe4Ehe39-VJ14uPyG4gXqc3uMvwqS7pCy9yg,53266
276
277
  wbportfolio/models/portfolio_cash_flow.py,sha256=uElG7IJUBY8qvtrXftOoskX6EA-dKgEG1JJdvHeWV7g,7336
277
278
  wbportfolio/models/portfolio_cash_targets.py,sha256=WmgG-etPisZsh2yaFQpz7EkpvAudKBEzqPsO715w52U,1498
278
279
  wbportfolio/models/portfolio_relationship.py,sha256=ZGECiPZiLdlk4uSamOrEfuzO0hduK6OMKJLUSnh5_kc,5190
@@ -437,7 +438,7 @@ wbportfolio/viewsets/portfolio_cash_targets.py,sha256=CvHlrDE8qnnnfRpTYnFu-Uu15M
437
438
  wbportfolio/viewsets/portfolio_relationship.py,sha256=RGyvxd8NfFEs8YdqEvVD3VbrISvAO5UtCTlocSIuWQw,2109
438
439
  wbportfolio/viewsets/portfolio_swing_pricing.py,sha256=-57l3WLQZRslIV67OT0ucHE5JXTtTtLvd3t7MppdVn8,357
439
440
  wbportfolio/viewsets/portfolios.py,sha256=6aF2Uh0EAdHdX1mMTQrFBlXZ5kmlaCPz49iDvT2CnYM,14438
440
- wbportfolio/viewsets/positions.py,sha256=2rzFHB_SI09rXC_EYi58G_eqvzONbk8z61JDkkjt3Ew,13207
441
+ wbportfolio/viewsets/positions.py,sha256=fYmkcYwNybeEZejMZVvel8yFdr7ob_jG8t6ar7snD58,13236
441
442
  wbportfolio/viewsets/product_groups.py,sha256=YvmuXPPy98K1J_rz6YPsx9gNK-tCS2P-wc1uRYgfyo0,2399
442
443
  wbportfolio/viewsets/product_performance.py,sha256=dRfRgifjGS1RgZSu9uJRM0SmB7eLnNUkPuqARMO4gyo,28371
443
444
  wbportfolio/viewsets/products.py,sha256=V8UFtfqxzs67XaU1JZcJJms1WzeNPeXtNBrQuz4B5mk,20414
@@ -447,7 +448,7 @@ wbportfolio/viewsets/registers.py,sha256=eOuEhW2McHsOapCKue7M4eazrJnVpCBVxImpFcc
447
448
  wbportfolio/viewsets/roles.py,sha256=vnzS1mlJMZS3GObrss6SfXOr3KRb-OHB1s4Msvtn7xQ,1556
448
449
  wbportfolio/viewsets/signals.py,sha256=URxNz-7tKNBgvaFIE3FItfao3Md0dKQN_eVFwxxiErk,2125
449
450
  wbportfolio/viewsets/charts/__init__.py,sha256=mNSpDrsqK-afRxGBfEsfgupUc20xU-JW08FpxIyudok,71
450
- wbportfolio/viewsets/charts/assets.py,sha256=rZM4Ul0ZXVr7uz3SU44J5IYU7-FivjDgR1it_4ewk2o,10547
451
+ wbportfolio/viewsets/charts/assets.py,sha256=d8y_9N3D3a41S-XUg7AV5GjLHoW44kRJOHTkzpeuemU,10573
451
452
  wbportfolio/viewsets/configs/__init__.py,sha256=K5opfVQvgGwSyw3XwDGkv3lo5i9jBxOJXYhLqyCdfeQ,137
452
453
  wbportfolio/viewsets/configs/buttons/__init__.py,sha256=hyvpxwh9ss8Q0xcE006qsTLuSsJeWt9saHRcU4g96tA,791
453
454
  wbportfolio/viewsets/configs/buttons/adjustments.py,sha256=sUY_3vxqP0kuqs8i5hklfboZI6QiAOrmu30eb29Xupo,492
@@ -554,7 +555,7 @@ wbportfolio/viewsets/transactions/claim.py,sha256=Pb1WftoO-w-ZSTbLRhmQubhy7hgd68
554
555
  wbportfolio/viewsets/transactions/fees.py,sha256=WT2bWWfgozz4_rpyTKX7dgBBTXD-gu0nlsd2Nk2Zh1Q,7028
555
556
  wbportfolio/viewsets/transactions/mixins.py,sha256=WipvJoi5hylkpD0y9VATe30WAcwIHUIroVkK10FYw7k,636
556
557
  wbportfolio/viewsets/transactions/trades.py,sha256=xBgOGaJ8aEg-2RxEJ4FDaBs4SGwuLasun3nhpis0WQY,12363
557
- wbportfolio-1.54.21.dist-info/METADATA,sha256=5NHNRB4-w5pyBzzP936g_zkFz86kNs3OXQBj7qBTNa8,703
558
- wbportfolio-1.54.21.dist-info/WHEEL,sha256=tkmg4JIqwd9H8mL30xA7crRmoStyCtGp0VWshokd1Jc,105
559
- wbportfolio-1.54.21.dist-info/licenses/LICENSE,sha256=jvfVH0SY8_YMHlsJHKe_OajiscQDz4lpTlqT6x24sVw,172
560
- wbportfolio-1.54.21.dist-info/RECORD,,
558
+ wbportfolio-1.54.22.dist-info/METADATA,sha256=dHZzJlBfD3drPh9scLSxGZPJNFdLDG_zEIqSzdyiMbo,703
559
+ wbportfolio-1.54.22.dist-info/WHEEL,sha256=tkmg4JIqwd9H8mL30xA7crRmoStyCtGp0VWshokd1Jc,105
560
+ wbportfolio-1.54.22.dist-info/licenses/LICENSE,sha256=jvfVH0SY8_YMHlsJHKe_OajiscQDz4lpTlqT6x24sVw,172
561
+ wbportfolio-1.54.22.dist-info/RECORD,,