wbportfolio 1.54.20__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.

@@ -5,7 +5,6 @@ from unittest.mock import patch
5
5
 
6
6
  import pandas as pd
7
7
  import pytest
8
- from django.contrib.contenttypes.models import ContentType
9
8
  from django.db.models import F, Sum
10
9
  from django.forms.models import model_to_dict
11
10
  from faker import Faker
@@ -20,9 +19,8 @@ from wbportfolio.models import (
20
19
  PortfolioPortfolioThroughModel,
21
20
  Trade,
22
21
  )
23
- from wbportfolio.models.asset import AssetPositionIterator
24
22
 
25
- from ...models.portfolio import get_returns, update_portfolio_after_investable_universe
23
+ from ...models.portfolio import update_portfolio_after_investable_universe
26
24
  from .utils import PortfolioTestMixin
27
25
 
28
26
  fake = Faker()
@@ -264,7 +262,9 @@ class TestPortfolioModel(PortfolioTestMixin):
264
262
  for pos in AssetPosition.objects.all():
265
263
  assert float(pos.weighting) == pytest.approx(float(pos.total_value_fx_portfolio / total_value), rel=1e-2)
266
264
 
267
- mock_estimate_net_asset_values.assert_called_once_with(portfolio, (weekday + BDay(1)).date(), weights=None)
265
+ mock_estimate_net_asset_values.assert_called_once_with(
266
+ portfolio, (weekday + BDay(1)).date(), analytic_portfolio=None
267
+ )
268
268
 
269
269
  @patch.object(Portfolio, "compute_lookthrough", autospec=True)
270
270
  def test_change_at_date_with_dependent_portfolio(
@@ -285,9 +285,6 @@ class TestPortfolioModel(PortfolioTestMixin):
285
285
  mock_compute_lookthrough.assert_called_once_with(
286
286
  dependent_portfolio,
287
287
  weekday,
288
- recompute_weighting=False,
289
- force_recompute_weighting=False,
290
- changed_weights=None,
291
288
  )
292
289
 
293
290
  def test_is_active_at_date(
@@ -1005,12 +1002,10 @@ class TestPortfolioModel(PortfolioTestMixin):
1005
1002
  fx_instrument = currency_fx_rates_factory.create(currency=instrument.currency, date=weekday)
1006
1003
  instrument_id: int = instrument.id
1007
1004
  weights = {instrument_id: random.random()}
1008
- positions = AssetPositionIterator(
1009
- portfolio, prices={weekday: {instrument_id: p.net_value}}, infer_underlying_quote_price=False
1010
- )
1011
- positions.add((weekday, weights))
1005
+ portfolio.builder.set_prices({weekday: {instrument_id: p.net_value}})
1006
+ portfolio.builder.add((weekday, weights), infer_underlying_quote_price=False)
1012
1007
 
1013
- res = list(positions)
1008
+ res = list(portfolio.builder.get_positions())
1014
1009
  a = res[0]
1015
1010
  assert len(res) == 1
1016
1011
  assert a.date == weekday
@@ -1053,35 +1048,34 @@ class TestPortfolioModel(PortfolioTestMixin):
1053
1048
  asset_position_factory.create(date=weekday, portfolio=portfolio, underlying_instrument=i2, weighting=0.3)
1054
1049
 
1055
1050
  rebalancer_factory.create(portfolio=portfolio, frequency="RRULE:FREQ=DAILY;", activation_date=rebalancing_date)
1056
- positions, rebalancing_order_proposal = portfolio.drift_weights(
1057
- weekday, (rebalancing_date + BDay(1)).date(), stop_at_rebalancing=True
1058
- )
1059
- assert rebalancing_order_proposal.trade_date == rebalancing_date
1060
- assert rebalancing_order_proposal.status == "SUBMIT"
1061
- assert set(positions.get_weights().keys()) == {
1062
- middle_date,
1063
- }, "Drifting weight with a non automatic rebalancer stops the iteration"
1064
-
1065
- # we expect a equally rebalancing (default) so both orders needs to be created
1066
- orders = rebalancing_order_proposal.get_orders()
1067
- t1 = orders.get(value_date=rebalancing_date, underlying_instrument=i1)
1068
- t2 = orders.get(value_date=rebalancing_date, underlying_instrument=i2)
1069
- assert t1._target_weight == Decimal("0.5")
1070
- assert t2._target_weight == Decimal("0.5")
1071
-
1072
- # we approve the rebalancing order proposal
1073
- assert rebalancing_order_proposal.status == "SUBMIT"
1074
- rebalancing_order_proposal.approve(replay=False)
1075
- rebalancing_order_proposal.save()
1051
+ portfolio.load_builder_returns(weekday, rebalancing_date)
1052
+ gen = portfolio.drift_weights(weekday, (rebalancing_date + BDay(1)).date(), stop_at_rebalancing=True)
1053
+ assert next(gen)[0] == middle_date, "Drifting weight with a non automatic rebalancer stops the iteration"
1054
+ try:
1055
+ next(gen)
1056
+ assert False, "the next iteration should stop and return the rebalancing"
1057
+ except StopIteration as e:
1058
+ rebalancing_order_proposal = e.value
1059
+ assert rebalancing_order_proposal.trade_date == rebalancing_date
1060
+ assert rebalancing_order_proposal.status == "SUBMIT"
1061
+
1062
+ # we expect a equally rebalancing (default) so both orders needs to be created
1063
+ orders = rebalancing_order_proposal.get_orders()
1064
+ t1 = orders.get(value_date=rebalancing_date, underlying_instrument=i1)
1065
+ t2 = orders.get(value_date=rebalancing_date, underlying_instrument=i2)
1066
+ assert t1._target_weight == Decimal("0.5")
1067
+ assert t2._target_weight == Decimal("0.5")
1068
+
1069
+ # we approve the rebalancing order proposal
1070
+ assert rebalancing_order_proposal.status == "SUBMIT"
1071
+ rebalancing_order_proposal.approve(replay=False)
1072
+ rebalancing_order_proposal.save()
1076
1073
 
1077
1074
  # check that the rebalancing was applied and position reflect that
1078
1075
  assert portfolio.assets.get(date=rebalancing_date, underlying_instrument=i1).weighting == Decimal("0.5")
1079
1076
  assert portfolio.assets.get(date=rebalancing_date, underlying_instrument=i2).weighting == Decimal("0.5")
1080
1077
 
1081
- @patch("wbportfolio.models.portfolio.compute_metrics_as_task.delay")
1082
- def test_bulk_create_positions(
1083
- self, mock_compute_metrics, portfolio, weekday, asset_position_factory, instrument_factory
1084
- ):
1078
+ def test_bulk_create_positions(self, portfolio, weekday, asset_position_factory, instrument_factory):
1085
1079
  portfolio.is_manageable = False
1086
1080
  portfolio.save()
1087
1081
  i1 = instrument_factory.create()
@@ -1090,21 +1084,17 @@ class TestPortfolioModel(PortfolioTestMixin):
1090
1084
  a1 = asset_position_factory.build(date=weekday, portfolio=portfolio, underlying_instrument=i1)
1091
1085
 
1092
1086
  # check initial creation
1093
- portfolio.bulk_create_positions(AssetPositionIterator(portfolio).add([a1]), compute_metrics=True)
1087
+ portfolio.builder.add([a1]).bulk_create_positions(compute_metrics=True)
1094
1088
  assert AssetPosition.objects.get(portfolio=portfolio, date=weekday).weighting == a1.weighting
1095
1089
  assert AssetPosition.objects.get(portfolio=portfolio, date=weekday).underlying_instrument == i1
1096
1090
 
1097
- mock_compute_metrics.assert_called_once_with(
1098
- weekday, basket_id=portfolio.id, basket_content_type_id=ContentType.objects.get_for_model(Portfolio).id
1099
- )
1100
-
1101
1091
  # check that if we change key value, an already exising position will be updated accordingly
1102
1092
  a1.weighting = Decimal(0.5)
1103
- portfolio.bulk_create_positions(AssetPositionIterator(portfolio).add([a1]))
1093
+ portfolio.builder.add([a1]).bulk_create_positions()
1104
1094
  assert AssetPosition.objects.get(portfolio=portfolio, date=weekday).weighting == Decimal(0.5)
1105
1095
 
1106
1096
  a2 = asset_position_factory.build(date=weekday, portfolio=portfolio, underlying_instrument=i2)
1107
- portfolio.bulk_create_positions(AssetPositionIterator(portfolio).add([a2]))
1097
+ portfolio.builder.add([a2]).bulk_create_positions()
1108
1098
  assert (
1109
1099
  AssetPosition.objects.get(portfolio=portfolio, date=weekday, underlying_instrument=i1).weighting
1110
1100
  == a1.weighting
@@ -1115,7 +1105,7 @@ class TestPortfolioModel(PortfolioTestMixin):
1115
1105
  )
1116
1106
 
1117
1107
  a3 = asset_position_factory.build(date=weekday, portfolio=portfolio, underlying_instrument=i3)
1118
- portfolio.bulk_create_positions(AssetPositionIterator(portfolio).add([a3]), delete_leftovers=True)
1108
+ portfolio.builder.add([a3]).bulk_create_positions(delete_leftovers=True)
1119
1109
  assert AssetPosition.objects.get(portfolio=portfolio, date=weekday).weighting == a3.weighting
1120
1110
  assert AssetPosition.objects.get(portfolio=portfolio, date=weekday).underlying_instrument == i3
1121
1111
 
@@ -1134,83 +1124,6 @@ class TestPortfolioModel(PortfolioTestMixin):
1134
1124
  res = list(Portfolio.objects.all().to_dependency_iterator(weekday))
1135
1125
  assert res == [index_portfolio, dependency_portfolio, dependant_portfolio, undependant_portfolio]
1136
1126
 
1137
- def test_get_returns(self, instrument_factory, instrument_price_factory, asset_position_factory, portfolio):
1138
- v1 = date(2024, 12, 31)
1139
- v2 = date(2025, 1, 1)
1140
- v3 = date(2025, 1, 2)
1141
- v4 = date(2025, 1, 3)
1142
-
1143
- i1 = instrument_factory.create()
1144
- i2 = instrument_factory.create()
1145
-
1146
- i11 = instrument_price_factory.create(date=v1, instrument=i1)
1147
- i12 = instrument_price_factory.create(date=v2, instrument=i1)
1148
- i14 = instrument_price_factory.create(date=v4, instrument=i1)
1149
- i21 = instrument_price_factory.create(date=v1, instrument=i2)
1150
- i11.refresh_from_db()
1151
- i12.refresh_from_db()
1152
- i14.refresh_from_db()
1153
- prices, returns = get_returns([i1.id, i2.id], from_date=v1, to_date=v4)
1154
-
1155
- expected_returns = pd.DataFrame(
1156
- [[i12.net_value / i11.net_value - 1, 0.0], [0.0, 0.0], [i14.net_value / i12.net_value - 1, 0.0]],
1157
- index=[v2, v3, v4],
1158
- columns=[i1.id, i2.id],
1159
- dtype="float64",
1160
- )
1161
- expected_returns.index = pd.to_datetime(expected_returns.index)
1162
- pd.testing.assert_frame_equal(returns, expected_returns, check_names=False, check_freq=False, atol=1e-6)
1163
- assert prices[v1][i1.id] == float(i11.net_value)
1164
- assert prices[v2][i1.id] == float(i12.net_value)
1165
- assert prices[v3][i1.id] == float(i12.net_value)
1166
- assert prices[v4][i1.id] == float(i14.net_value)
1167
- # test that the returned price are ffill
1168
- assert prices[v1][i2.id] == float(i21.net_value)
1169
- assert prices[v2][i2.id] == float(i21.net_value)
1170
- assert prices[v3][i2.id] == float(i21.net_value)
1171
- assert prices[v4][i2.id] == float(i21.net_value)
1172
-
1173
- def test_get_returns_fix_forex_on_holiday(
1174
- self, instrument, instrument_price_factory, currency_fx_rates_factory, currency_factory
1175
- ):
1176
- v1 = date(2024, 12, 31)
1177
- v2 = date(2025, 1, 1)
1178
- v3 = date(2025, 1, 2)
1179
-
1180
- target_currency = currency_factory.create()
1181
- fx_target1 = currency_fx_rates_factory.create(currency=target_currency, date=v1)
1182
- fx_target2 = currency_fx_rates_factory.create(currency=target_currency, date=v2) # noqa
1183
- fx_target3 = currency_fx_rates_factory.create(currency=target_currency, date=v3)
1184
-
1185
- fx1 = currency_fx_rates_factory.create(currency=instrument.currency, date=v1)
1186
- fx2 = currency_fx_rates_factory.create(currency=instrument.currency, date=v2) # noqa
1187
- fx3 = currency_fx_rates_factory.create(currency=instrument.currency, date=v3)
1188
-
1189
- i1 = instrument_price_factory.create(net_value=Decimal("100"), date=v1, instrument=instrument)
1190
- i2 = instrument_price_factory.create(net_value=Decimal("100"), date=v2, instrument=instrument, calculated=True)
1191
- i3 = instrument_price_factory.create(net_value=Decimal("200"), date=v3, instrument=instrument)
1192
-
1193
- prices, returns = get_returns([instrument.id], from_date=v1, to_date=v3, to_currency=target_currency)
1194
- returns.index = pd.to_datetime(returns.index)
1195
- assert prices[v1][instrument.id] == float(i1.net_value)
1196
- assert prices[v2][instrument.id] == float(i2.net_value)
1197
- assert prices[v3][instrument.id] == float(i3.net_value)
1198
-
1199
- assert returns.loc[pd.Timestamp(v2), instrument.id] == pytest.approx(
1200
- float(
1201
- (i2.net_value * fx_target1.value / fx1.value) / (i1.net_value * fx_target1.value / fx1.value)
1202
- - Decimal("1")
1203
- ),
1204
- abs=10e-8,
1205
- ) # as v2 as a calculated price, the forex won't apply to it
1206
- assert returns.loc[pd.Timestamp(v3), instrument.id] == pytest.approx(
1207
- float(
1208
- (i3.net_value * fx_target3.value / fx3.value) / (i2.net_value * fx_target1.value / fx1.value)
1209
- - Decimal("1")
1210
- ),
1211
- abs=10e-8,
1212
- )
1213
-
1214
1127
  @patch.object(Portfolio, "compute_lookthrough", autospec=True)
1215
1128
  def test_handle_controlling_portfolio_change_at_date(self, mock_compute_lookthrough, weekday, portfolio_factory):
1216
1129
  primary_portfolio = portfolio_factory.create(only_weighting=True)
@@ -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"],
@@ -15,6 +15,7 @@ class OrderProposalDisplayConfig(DisplayViewConfig):
15
15
  return dp.ListDisplay(
16
16
  fields=[
17
17
  dp.Field(key="trade_date", label="Order Date"),
18
+ dp.Field(key="rebalancing_model", label="Rebalancing Model"),
18
19
  dp.Field(key="comment", label="Comment"),
19
20
  ],
20
21
  legends=[
@@ -86,12 +87,12 @@ class OrderProposalDisplayConfig(DisplayViewConfig):
86
87
  layouts={
87
88
  default(): Layout(
88
89
  grid_template_areas=[
89
- ["status", "status"],
90
- ["trade_date", "total_cash_weight"],
91
- ["rebalancing_model", "target_portfolio"]
90
+ ["status", "status", "status"],
91
+ ["trade_date", "total_cash_weight", "min_order_value"],
92
+ ["rebalancing_model", "target_portfolio", "target_portfolio"]
92
93
  if self.view.new_mode
93
- else ["rebalancing_model", "rebalancing_model"],
94
- ["comment", "comment"],
94
+ else ["rebalancing_model", "rebalancing_model", "rebalancing_model"],
95
+ ["comment", "comment", "comment"],
95
96
  ],
96
97
  ),
97
98
  },
@@ -150,7 +150,7 @@ class OrderOrderProposalModelViewSet(
150
150
  },
151
151
  "weighting": {
152
152
  "Cash Flow": format_number(
153
- cash_sum_target_cash_weight - cash_sum_effective_weight,
153
+ sum_sell_weight + sum_buy_weight,
154
154
  decimal=Order.ORDER_WEIGHTING_PRECISION,
155
155
  ),
156
156
  "Buy": format_number(sum_buy_weight, decimal=Order.ORDER_WEIGHTING_PRECISION),
@@ -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.20
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
@@ -262,14 +263,17 @@ wbportfolio/migrations/0080_alter_trade_drift_factor_alter_trade_weighting.py,sh
262
263
  wbportfolio/migrations/0081_alter_trade_drift_factor.py,sha256=rF3HA1MQJ0hltr0dExJAx47w8XxUCWRbDUyxQLoQB2I,656
263
264
  wbportfolio/migrations/0082_remove_tradeproposal_creator_and_more.py,sha256=DZBKD0LG1aXQ2bR7UwYwdVobiCCtKDBMLHDZRmFQRKQ,4108
264
265
  wbportfolio/migrations/0083_order_alter_trade_options_and_more.py,sha256=oFYG2cVf2CFKFJX84eUSmGJdK1BHY_QcVm_hmAIbVNg,9952
266
+ wbportfolio/migrations/0084_orderproposal_min_order_value.py,sha256=bJPpPX7PQmlWAIyLzZ6ca6K0paGTRbzS8AkyOHDoGMc,925
267
+ wbportfolio/migrations/0085_order_desired_target_weight.py,sha256=L8p5t4PqjWIwqwiqt-ofdfGkBhm-7dtbg52cIkxNnDs,803
265
268
  wbportfolio/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
266
269
  wbportfolio/models/__init__.py,sha256=qU4e7HKyh8NL_0Mg92PcbHTewCv7Ya2gei1DMGe1LWE,980
267
270
  wbportfolio/models/adjustments.py,sha256=osXWkJZOiansPWYPyHtl7Z121zDWi7u1YMtrBQtbHVo,10272
268
- wbportfolio/models/asset.py,sha256=b0vPt4LwNrxcMiK7UmBKViYnbNNlZzPTagvU5vFuyrc,45685
271
+ wbportfolio/models/asset.py,sha256=PwL16w2Rw_rJL73e0vCWMlRqsCxKW4zA9bf1EgTzD60,39574
272
+ wbportfolio/models/builder.py,sha256=gGBlU0s5kvMxUas2lil0n98BxVjVocUDfU9oHKgkkJY,11622
269
273
  wbportfolio/models/custodians.py,sha256=owTiS2Vm5CRKzh9M_P9GOVg-s-ndQ9UvRmw3yZP7cw0,3815
270
274
  wbportfolio/models/exceptions.py,sha256=3ix0tWUO-O6jpz8f07XIwycw2x3JFRoWzjwil8FVA2Q,52
271
275
  wbportfolio/models/indexes.py,sha256=gvW4K9U9Bj8BmVCqFYdWiXvDWhjHINRON8XhNsZUiQY,639
272
- wbportfolio/models/portfolio.py,sha256=b0YL4dytrEeHRt7VLn1uJYb_47vRKFYiq9Y_6JLrIJU,58419
276
+ wbportfolio/models/portfolio.py,sha256=7PRPI8sNe4Ehe39-VJ14uPyG4gXqc3uMvwqS7pCy9yg,53266
273
277
  wbportfolio/models/portfolio_cash_flow.py,sha256=uElG7IJUBY8qvtrXftOoskX6EA-dKgEG1JJdvHeWV7g,7336
274
278
  wbportfolio/models/portfolio_cash_targets.py,sha256=WmgG-etPisZsh2yaFQpz7EkpvAudKBEzqPsO715w52U,1498
275
279
  wbportfolio/models/portfolio_relationship.py,sha256=ZGECiPZiLdlk4uSamOrEfuzO0hduK6OMKJLUSnh5_kc,5190
@@ -289,8 +293,8 @@ wbportfolio/models/mixins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJW
289
293
  wbportfolio/models/mixins/instruments.py,sha256=SgBreTpa_X3uyCWo7t8B0VaTtl49IjmBMe4Pab6TjAM,6796
290
294
  wbportfolio/models/mixins/liquidity_stress_test.py,sha256=iQVzT3QM7VtHnqfj9gT6KUIe4wC4MJXery-AXJHUYns,58820
291
295
  wbportfolio/models/orders/__init__.py,sha256=EH9UacGR3npBMje5FGTeLOh1xqFBh9kc24WbGmBIA3g,69
292
- wbportfolio/models/orders/order_proposals.py,sha256=uAOPhCUPcCBkAwGPCS0b9JEpwLfnGdJfXM6z8btfzvg,39882
293
- wbportfolio/models/orders/orders.py,sha256=5XKU5NNLlrB0ydQtVGm_woDagt_Qo7IMZhc7GcrQ_lI,9481
296
+ wbportfolio/models/orders/order_proposals.py,sha256=nKzeHPcSQav4KkaUXUBWJVxd8ku3GmG5KQKyQ3cvIUM,40467
297
+ wbportfolio/models/orders/orders.py,sha256=8vYyAV1S2ATVD3Ve_Cjtms_mj564yu5pvfK6wtqQx3A,9664
294
298
  wbportfolio/models/reconciliations/__init__.py,sha256=MXH5fZIPGDRBgJkO6wVu_NLRs8fkP1im7G6d-h36lQY,127
295
299
  wbportfolio/models/reconciliations/account_reconciliation_lines.py,sha256=QP6M7hMcyFbuXBa55Y-azui6Dl_WgbzMntEqWzQkbfM,7394
296
300
  wbportfolio/models/reconciliations/account_reconciliations.py,sha256=rofSxetFfEJov6mPyoTvGxELA16HILyJZtQvm_kwYU0,4405
@@ -361,7 +365,7 @@ wbportfolio/serializers/registers.py,sha256=zhdKH_mHEBE0VOhm6xpY54bTMtcSaY5BskEa
361
365
  wbportfolio/serializers/roles.py,sha256=T-9NqTldpvaEMFy-Bib5MB6MeboygEOqcMP61mzzD3Q,2146
362
366
  wbportfolio/serializers/signals.py,sha256=hD6R4oFtwhvnsJPteytPKy2JwEelmxrapdfoLSnluaE,7053
363
367
  wbportfolio/serializers/orders/__init__.py,sha256=PKJRksA1pWsh8nVfGASoB0m3LyUzVRnq1m9VPp90J7k,271
364
- wbportfolio/serializers/orders/order_proposals.py,sha256=FegiVe1d1AZoLtOuNOUfLN7HwGy4mKGrdYHKDwuUjPY,4430
368
+ wbportfolio/serializers/orders/order_proposals.py,sha256=MmL8noS2qqyKKXiYLLPRS4_Cz1RhlfdFwkCKZiqRyxQ,4461
365
369
  wbportfolio/serializers/orders/orders.py,sha256=pAKjJLRANOo1iMlcv18twuQ0aAVDVKYt-pPx6avnWRQ,7464
366
370
  wbportfolio/serializers/transactions/__init__.py,sha256=-7Pan4n7YI3iDvGXff6okzk4ycEURRxp5n_SHCY_g_I,493
367
371
  wbportfolio/serializers/transactions/claim.py,sha256=kC4E2RZRrpd9i8tGfoiV-gpWDk3ikR5F1Wf0v_IGIvw,11599
@@ -397,14 +401,14 @@ wbportfolio/tests/models/test_merge.py,sha256=sdsjiZsmR6vsUKwTa5kkvL6QTeAZqtd_EP
397
401
  wbportfolio/tests/models/test_portfolio_cash_flow.py,sha256=X8dsXexsb1b0lBiuGzu40ps_Az_1UmmKT0eo1vbXH94,5792
398
402
  wbportfolio/tests/models/test_portfolio_cash_targets.py,sha256=q8QWAwt-kKRkLC0E05GyRhF_TTQXIi8bdHjXVU0fCV0,965
399
403
  wbportfolio/tests/models/test_portfolio_swing_pricings.py,sha256=kr2AOcQkyg2pX3ULjU-o9ye-NVpjMrrfoe-DVbYCbjs,1656
400
- wbportfolio/tests/models/test_portfolios.py,sha256=yh5CgeDH15zFxgnV1KzPl_YQTfaH3hRIG3mXLs9GfRU,56156
404
+ wbportfolio/tests/models/test_portfolios.py,sha256=VdfkblwSow1w-HLFto8wssuBTjSqaCBpE1_Tf6wb0R0,51878
401
405
  wbportfolio/tests/models/test_product_groups.py,sha256=AcdxhurV-n_bBuUsfD1GqVtwLFcs7VI2CRrwzsIUWbU,3337
402
406
  wbportfolio/tests/models/test_products.py,sha256=IcBzw9hrGiWFMRwPBTMukCMWrhqnjOVA2hhb90xYOW8,9580
403
407
  wbportfolio/tests/models/test_roles.py,sha256=4Cn7WyrA2ztJNeWLk5cy9kYo5XLWMbFSvo1O-9JYxeA,3323
404
408
  wbportfolio/tests/models/test_splits.py,sha256=ytKcHsI_90kj1L4s8It-KEcc24rkDcElxwQ8q0QxEvk,9689
405
409
  wbportfolio/tests/models/utils.py,sha256=ORNJq6NMo1Za22jGZXfTfKeNEnTRlfEt_8SJ6xLaQWg,325
406
410
  wbportfolio/tests/models/orders/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
407
- wbportfolio/tests/models/orders/test_order_proposals.py,sha256=FJCP2Gj1eRQb1X7pqiWxGJk4a1qOdVTzE-aRL71fOYk,30773
411
+ wbportfolio/tests/models/orders/test_order_proposals.py,sha256=T0vo7D65E0Cyqhwq3QK_Fd6RlCzCJRZSbA0PSZft0k4,31316
408
412
  wbportfolio/tests/models/transactions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
409
413
  wbportfolio/tests/models/transactions/test_claim.py,sha256=NG3BKB-FVcIDgHSJHCjImxgMM3ISVUMl24xUPmEcPec,5570
410
414
  wbportfolio/tests/models/transactions/test_fees.py,sha256=tAp18x2wCNQr11LUnLtHNbBDbbX0v1DZnmW7i-cEi5Q,2423
@@ -434,7 +438,7 @@ wbportfolio/viewsets/portfolio_cash_targets.py,sha256=CvHlrDE8qnnnfRpTYnFu-Uu15M
434
438
  wbportfolio/viewsets/portfolio_relationship.py,sha256=RGyvxd8NfFEs8YdqEvVD3VbrISvAO5UtCTlocSIuWQw,2109
435
439
  wbportfolio/viewsets/portfolio_swing_pricing.py,sha256=-57l3WLQZRslIV67OT0ucHE5JXTtTtLvd3t7MppdVn8,357
436
440
  wbportfolio/viewsets/portfolios.py,sha256=6aF2Uh0EAdHdX1mMTQrFBlXZ5kmlaCPz49iDvT2CnYM,14438
437
- wbportfolio/viewsets/positions.py,sha256=2rzFHB_SI09rXC_EYi58G_eqvzONbk8z61JDkkjt3Ew,13207
441
+ wbportfolio/viewsets/positions.py,sha256=fYmkcYwNybeEZejMZVvel8yFdr7ob_jG8t6ar7snD58,13236
438
442
  wbportfolio/viewsets/product_groups.py,sha256=YvmuXPPy98K1J_rz6YPsx9gNK-tCS2P-wc1uRYgfyo0,2399
439
443
  wbportfolio/viewsets/product_performance.py,sha256=dRfRgifjGS1RgZSu9uJRM0SmB7eLnNUkPuqARMO4gyo,28371
440
444
  wbportfolio/viewsets/products.py,sha256=V8UFtfqxzs67XaU1JZcJJms1WzeNPeXtNBrQuz4B5mk,20414
@@ -444,7 +448,7 @@ wbportfolio/viewsets/registers.py,sha256=eOuEhW2McHsOapCKue7M4eazrJnVpCBVxImpFcc
444
448
  wbportfolio/viewsets/roles.py,sha256=vnzS1mlJMZS3GObrss6SfXOr3KRb-OHB1s4Msvtn7xQ,1556
445
449
  wbportfolio/viewsets/signals.py,sha256=URxNz-7tKNBgvaFIE3FItfao3Md0dKQN_eVFwxxiErk,2125
446
450
  wbportfolio/viewsets/charts/__init__.py,sha256=mNSpDrsqK-afRxGBfEsfgupUc20xU-JW08FpxIyudok,71
447
- wbportfolio/viewsets/charts/assets.py,sha256=rZM4Ul0ZXVr7uz3SU44J5IYU7-FivjDgR1it_4ewk2o,10547
451
+ wbportfolio/viewsets/charts/assets.py,sha256=d8y_9N3D3a41S-XUg7AV5GjLHoW44kRJOHTkzpeuemU,10573
448
452
  wbportfolio/viewsets/configs/__init__.py,sha256=K5opfVQvgGwSyw3XwDGkv3lo5i9jBxOJXYhLqyCdfeQ,137
449
453
  wbportfolio/viewsets/configs/buttons/__init__.py,sha256=hyvpxwh9ss8Q0xcE006qsTLuSsJeWt9saHRcU4g96tA,791
450
454
  wbportfolio/viewsets/configs/buttons/adjustments.py,sha256=sUY_3vxqP0kuqs8i5hklfboZI6QiAOrmu30eb29Xupo,492
@@ -533,13 +537,13 @@ wbportfolio/viewsets/configs/titles/roles.py,sha256=9LoJa3jgenXJ5UWRlIErTzdbjpSW
533
537
  wbportfolio/viewsets/configs/titles/trades.py,sha256=29XCLxvY0Xe3a2tjCno3tN2rRXCr9RWpbWnzurJfnYI,1986
534
538
  wbportfolio/viewsets/orders/__init__.py,sha256=N8v9jdEXryOzrLlc7ML3iBCO2lmNXph9_TWoQ7PTvi4,195
535
539
  wbportfolio/viewsets/orders/order_proposals.py,sha256=mw385zzU52nCq8p6xgionh43xLmOn5aX-2BPlCHnqlE,6214
536
- wbportfolio/viewsets/orders/orders.py,sha256=uqEE22CZkcatSWtZgoqskK_7tV8m_-rTfH75_jFb5Lc,10874
540
+ wbportfolio/viewsets/orders/orders.py,sha256=u3tRqio-oCnmqhC5jmn_EDKoNrF1xXMgOu2c2BfqNS8,10851
537
541
  wbportfolio/viewsets/orders/configs/__init__.py,sha256=5MU57JXiKi32_PicHtiNr7YHmMN020FrlF5NFJf_Wds,94
538
542
  wbportfolio/viewsets/orders/configs/buttons/__init__.py,sha256=EHzNmAfa0UQFITEF-wxj_s4wn3Y5DE3DCbEUmmvCTIs,106
539
543
  wbportfolio/viewsets/orders/configs/buttons/order_proposals.py,sha256=Q_7LrsuLzjSXCIoscFQXMMHl8cuCporDNM5k735W7d8,3584
540
544
  wbportfolio/viewsets/orders/configs/buttons/orders.py,sha256=GDO4Y33wkjhDxzpf7B1d_rKzAixegLv5rHam1DV3WkM,290
541
545
  wbportfolio/viewsets/orders/configs/displays/__init__.py,sha256=__YJBbz_ZnKpE8WMMDR2PC9Nng-EVlRpGTEQucdrhRA,108
542
- wbportfolio/viewsets/orders/configs/displays/order_proposals.py,sha256=UL6yaNh9DuUFSSwur4brMBPyjKGxxtZg-W8iZxuB3Y0,4826
546
+ wbportfolio/viewsets/orders/configs/displays/order_proposals.py,sha256=Iy195FwD2KGxxNWYspAj7CKQ0assL_wtQx0hN7KMz9o,4985
543
547
  wbportfolio/viewsets/orders/configs/displays/orders.py,sha256=8YW5Sncmowl5eLbnuUkD5xQXnP4P3vM6aBXNvolFG1s,7007
544
548
  wbportfolio/viewsets/orders/configs/endpoints/__init__.py,sha256=IB8GEadiEtBDclhkgpcJGXWfCF6qRK_42hxJ4pcdZDU,148
545
549
  wbportfolio/viewsets/orders/configs/endpoints/order_proposals.py,sha256=fY3y2YWR9nY-KE8k078NszDsnwOgqOIjHUgLvQjDivU,822
@@ -551,7 +555,7 @@ wbportfolio/viewsets/transactions/claim.py,sha256=Pb1WftoO-w-ZSTbLRhmQubhy7hgd68
551
555
  wbportfolio/viewsets/transactions/fees.py,sha256=WT2bWWfgozz4_rpyTKX7dgBBTXD-gu0nlsd2Nk2Zh1Q,7028
552
556
  wbportfolio/viewsets/transactions/mixins.py,sha256=WipvJoi5hylkpD0y9VATe30WAcwIHUIroVkK10FYw7k,636
553
557
  wbportfolio/viewsets/transactions/trades.py,sha256=xBgOGaJ8aEg-2RxEJ4FDaBs4SGwuLasun3nhpis0WQY,12363
554
- wbportfolio-1.54.20.dist-info/METADATA,sha256=btEl2kgx_48zUSM1dteAkvv7d9dhxE7CC7bIN1idLl0,703
555
- wbportfolio-1.54.20.dist-info/WHEEL,sha256=tkmg4JIqwd9H8mL30xA7crRmoStyCtGp0VWshokd1Jc,105
556
- wbportfolio-1.54.20.dist-info/licenses/LICENSE,sha256=jvfVH0SY8_YMHlsJHKe_OajiscQDz4lpTlqT6x24sVw,172
557
- wbportfolio-1.54.20.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,,