wbportfolio 1.54.14__py2.py3-none-any.whl → 1.54.15__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.
- wbportfolio/admin/__init__.py +2 -0
- wbportfolio/admin/orders/__init__.py +2 -0
- wbportfolio/admin/orders/order_proposals.py +14 -0
- wbportfolio/admin/orders/orders.py +30 -0
- wbportfolio/admin/{transactions/rebalancing.py → rebalancing.py} +1 -1
- wbportfolio/admin/transactions/__init__.py +0 -1
- wbportfolio/admin/transactions/trades.py +2 -17
- wbportfolio/contrib/company_portfolio/tests/conftest.py +2 -2
- wbportfolio/factories/__init__.py +2 -1
- wbportfolio/factories/orders/__init__.py +2 -0
- wbportfolio/factories/orders/order_proposals.py +17 -0
- wbportfolio/factories/orders/orders.py +21 -0
- wbportfolio/factories/rebalancing.py +1 -1
- wbportfolio/factories/trades.py +2 -13
- wbportfolio/filters/orders/__init__.py +1 -0
- wbportfolio/filters/orders/orders.py +11 -0
- wbportfolio/import_export/handlers/trade.py +20 -20
- wbportfolio/import_export/resources/trades.py +2 -2
- wbportfolio/migrations/0082_remove_tradeproposal_creator_and_more.py +93 -0
- wbportfolio/migrations/0083_order_alter_trade_options_and_more.py +181 -0
- wbportfolio/models/__init__.py +2 -0
- wbportfolio/models/orders/__init__.py +2 -0
- wbportfolio/models/{transactions/trade_proposals.py → orders/order_proposals.py} +288 -244
- wbportfolio/models/orders/orders.py +243 -0
- wbportfolio/models/portfolio.py +16 -19
- wbportfolio/models/{transactions/rebalancing.py → rebalancing.py} +18 -18
- wbportfolio/models/transactions/__init__.py +0 -2
- wbportfolio/models/transactions/trades.py +10 -450
- wbportfolio/pms/analytics/portfolio.py +10 -6
- wbportfolio/pms/analytics/utils.py +9 -0
- wbportfolio/pms/trading/handler.py +6 -4
- wbportfolio/pms/typing.py +18 -7
- wbportfolio/rebalancing/decorators.py +1 -1
- wbportfolio/rebalancing/models/composite.py +3 -7
- wbportfolio/rebalancing/models/market_capitalization_weighted.py +3 -1
- wbportfolio/serializers/__init__.py +1 -0
- wbportfolio/serializers/orders/__init__.py +2 -0
- wbportfolio/serializers/{transactions/trade_proposals.py → orders/order_proposals.py} +23 -15
- wbportfolio/serializers/orders/orders.py +187 -0
- wbportfolio/serializers/portfolios.py +7 -7
- wbportfolio/serializers/rebalancing.py +1 -1
- wbportfolio/serializers/transactions/__init__.py +1 -5
- wbportfolio/serializers/transactions/trades.py +1 -182
- wbportfolio/tests/conftest.py +4 -2
- wbportfolio/tests/models/orders/__init__.py +0 -0
- wbportfolio/tests/models/{transactions/test_trade_proposals.py → orders/test_order_proposals.py} +218 -246
- wbportfolio/tests/models/test_portfolios.py +11 -10
- wbportfolio/tests/models/transactions/test_rebalancing.py +5 -5
- wbportfolio/tests/models/transactions/test_trades.py +0 -20
- wbportfolio/tests/rebalancing/test_models.py +24 -28
- wbportfolio/tests/signals.py +10 -10
- wbportfolio/tests/tests.py +1 -1
- wbportfolio/urls.py +7 -7
- wbportfolio/viewsets/__init__.py +2 -0
- wbportfolio/viewsets/configs/buttons/__init__.py +2 -3
- wbportfolio/viewsets/configs/buttons/trades.py +0 -8
- wbportfolio/viewsets/configs/display/__init__.py +0 -2
- wbportfolio/viewsets/configs/display/portfolios.py +5 -5
- wbportfolio/viewsets/configs/display/rebalancing.py +2 -2
- wbportfolio/viewsets/configs/display/trades.py +1 -225
- wbportfolio/viewsets/configs/endpoints/__init__.py +0 -3
- wbportfolio/viewsets/configs/endpoints/trades.py +0 -41
- wbportfolio/viewsets/orders/__init__.py +6 -0
- wbportfolio/viewsets/orders/configs/__init__.py +4 -0
- wbportfolio/viewsets/orders/configs/buttons/__init__.py +2 -0
- wbportfolio/viewsets/{configs/buttons/trade_proposals.py → orders/configs/buttons/order_proposals.py} +21 -21
- wbportfolio/viewsets/orders/configs/buttons/orders.py +9 -0
- wbportfolio/viewsets/orders/configs/displays/__init__.py +2 -0
- wbportfolio/viewsets/{configs/display/trade_proposals.py → orders/configs/displays/order_proposals.py} +21 -21
- wbportfolio/viewsets/orders/configs/displays/orders.py +180 -0
- wbportfolio/viewsets/orders/configs/endpoints/__init__.py +2 -0
- wbportfolio/viewsets/orders/configs/endpoints/order_proposals.py +21 -0
- wbportfolio/viewsets/orders/configs/endpoints/orders.py +26 -0
- wbportfolio/viewsets/orders/configs/titles/__init__.py +0 -0
- wbportfolio/viewsets/orders/configs/titles/orders.py +0 -0
- wbportfolio/viewsets/{transactions/trade_proposals.py → orders/order_proposals.py} +46 -46
- wbportfolio/viewsets/orders/orders.py +219 -0
- wbportfolio/viewsets/portfolios.py +12 -12
- wbportfolio/viewsets/{transactions/rebalancing.py → rebalancing.py} +2 -2
- wbportfolio/viewsets/transactions/__init__.py +1 -7
- wbportfolio/viewsets/transactions/trades.py +1 -199
- {wbportfolio-1.54.14.dist-info → wbportfolio-1.54.15.dist-info}/METADATA +1 -1
- {wbportfolio-1.54.14.dist-info → wbportfolio-1.54.15.dist-info}/RECORD +85 -58
- wbportfolio/viewsets/configs/endpoints/trade_proposals.py +0 -18
- {wbportfolio-1.54.14.dist-info → wbportfolio-1.54.15.dist-info}/WHEEL +0 -0
- {wbportfolio-1.54.14.dist-info → wbportfolio-1.54.15.dist-info}/licenses/LICENSE +0 -0
|
@@ -1053,25 +1053,26 @@ class TestPortfolioModel(PortfolioTestMixin):
|
|
|
1053
1053
|
asset_position_factory.create(date=weekday, portfolio=portfolio, underlying_instrument=i2, weighting=0.3)
|
|
1054
1054
|
|
|
1055
1055
|
rebalancer_factory.create(portfolio=portfolio, frequency="RRULE:FREQ=DAILY;", activation_date=rebalancing_date)
|
|
1056
|
-
positions,
|
|
1056
|
+
positions, rebalancing_order_proposal = portfolio.drift_weights(
|
|
1057
1057
|
weekday, (rebalancing_date + BDay(1)).date(), stop_at_rebalancing=True
|
|
1058
1058
|
)
|
|
1059
|
-
assert
|
|
1060
|
-
assert
|
|
1059
|
+
assert rebalancing_order_proposal.trade_date == rebalancing_date
|
|
1060
|
+
assert rebalancing_order_proposal.status == "SUBMIT"
|
|
1061
1061
|
assert set(positions.get_weights().keys()) == {
|
|
1062
1062
|
middle_date,
|
|
1063
1063
|
}, "Drifting weight with a non automatic rebalancer stops the iteration"
|
|
1064
1064
|
|
|
1065
|
-
# we expect a equally rebalancing (default) so both
|
|
1066
|
-
|
|
1067
|
-
|
|
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)
|
|
1068
1069
|
assert t1._target_weight == Decimal("0.5")
|
|
1069
1070
|
assert t2._target_weight == Decimal("0.5")
|
|
1070
1071
|
|
|
1071
|
-
# we approve the rebalancing
|
|
1072
|
-
assert
|
|
1073
|
-
|
|
1074
|
-
|
|
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()
|
|
1075
1076
|
|
|
1076
1077
|
# check that the rebalancing was applied and position reflect that
|
|
1077
1078
|
assert portfolio.assets.get(date=rebalancing_date, underlying_instrument=i1).weighting == Decimal("0.5")
|
|
@@ -6,7 +6,7 @@ import pytest
|
|
|
6
6
|
from django.core.exceptions import ValidationError
|
|
7
7
|
from pandas._libs.tslibs.offsets import BDay
|
|
8
8
|
|
|
9
|
-
from wbportfolio.models import AssetPosition,
|
|
9
|
+
from wbportfolio.models import AssetPosition, OrderProposal
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
@pytest.mark.django_db
|
|
@@ -47,7 +47,7 @@ class TestRebalancer:
|
|
|
47
47
|
def test_evaluate_rebalancing(
|
|
48
48
|
self, weekday, rebalancer_factory, asset_position_factory, instrument_factory, instrument_price_factory
|
|
49
49
|
):
|
|
50
|
-
rebalancer = rebalancer_factory.create(
|
|
50
|
+
rebalancer = rebalancer_factory.create(approve_order_proposal_automatically=True)
|
|
51
51
|
trade_date = (weekday + BDay(1)).date()
|
|
52
52
|
|
|
53
53
|
i1 = instrument_factory.create()
|
|
@@ -63,9 +63,9 @@ class TestRebalancer:
|
|
|
63
63
|
a2 = asset_position_factory.create(
|
|
64
64
|
portfolio=rebalancer.portfolio, date=weekday, weighting=0.3, underlying_instrument=i2
|
|
65
65
|
)
|
|
66
|
-
|
|
67
|
-
assert
|
|
68
|
-
assert
|
|
66
|
+
order_proposal = rebalancer.evaluate_rebalancing(trade_date)
|
|
67
|
+
assert order_proposal.orders.count() == 2
|
|
68
|
+
assert order_proposal.status == OrderProposal.Status.APPROVED
|
|
69
69
|
assert AssetPosition.objects.get(
|
|
70
70
|
portfolio=rebalancer.portfolio, date=trade_date, underlying_quote=a1.underlying_instrument
|
|
71
71
|
).weighting == Decimal(0.5)
|
|
@@ -3,7 +3,6 @@ from decimal import Decimal
|
|
|
3
3
|
|
|
4
4
|
import pytest
|
|
5
5
|
from faker import Faker
|
|
6
|
-
from pandas._libs.tslibs.offsets import BDay
|
|
7
6
|
|
|
8
7
|
from wbportfolio.models import Product, Trade
|
|
9
8
|
|
|
@@ -103,12 +102,6 @@ class TestTradeModel:
|
|
|
103
102
|
assert customer_trade.claimed_shares == c2.shares
|
|
104
103
|
|
|
105
104
|
|
|
106
|
-
@pytest.mark.django_db
|
|
107
|
-
class TestTradeProposalModel:
|
|
108
|
-
def test_init(self, trade_proposal):
|
|
109
|
-
assert trade_proposal.id is not None
|
|
110
|
-
|
|
111
|
-
|
|
112
105
|
@pytest.mark.django_db
|
|
113
106
|
class TestTradeInstrumentPrice:
|
|
114
107
|
def test_shares(self, portfolio, product_factory, trade_factory, instrument_price_factory):
|
|
@@ -204,16 +197,3 @@ class TestTradeInstrumentPrice:
|
|
|
204
197
|
subscription_trade1.refresh_from_db()
|
|
205
198
|
assert subscription_trade1.internal_trade == internal_trade
|
|
206
199
|
assert subscription_trade1.marked_as_internal is True
|
|
207
|
-
|
|
208
|
-
def test_last_underlying_quote_price(self, weekday, trade_factory, instrument_price_factory):
|
|
209
|
-
trade = trade_factory.create(transaction_date=weekday, value_date=(weekday - BDay(1)).date())
|
|
210
|
-
assert trade.last_underlying_quote_price is None
|
|
211
|
-
del trade.last_underlying_quote_price
|
|
212
|
-
|
|
213
|
-
# test that underlying quote price returns any price found at transaction_date, or then at value_date (in that order)
|
|
214
|
-
p0 = instrument_price_factory.create(instrument=trade.underlying_instrument, date=trade.value_date)
|
|
215
|
-
assert trade.last_underlying_quote_price == p0
|
|
216
|
-
del trade.last_underlying_quote_price
|
|
217
|
-
|
|
218
|
-
p1 = instrument_price_factory.create(instrument=trade.underlying_instrument, date=trade.transaction_date)
|
|
219
|
-
assert trade.last_underlying_quote_price == p1
|
|
@@ -4,8 +4,8 @@ import pytest
|
|
|
4
4
|
from pandas._libs.tslibs.offsets import BDay
|
|
5
5
|
from wbfdm.models import InstrumentPrice
|
|
6
6
|
|
|
7
|
-
from wbportfolio.factories import
|
|
8
|
-
from wbportfolio.models import
|
|
7
|
+
from wbportfolio.factories import OrderFactory, OrderProposalFactory, PortfolioFactory
|
|
8
|
+
from wbportfolio.models import Order, OrderProposal, PortfolioPortfolioThroughModel
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
@pytest.mark.django_db
|
|
@@ -83,50 +83,46 @@ class TestCompositeRebalancing:
|
|
|
83
83
|
def test_is_valid(self, portfolio, weekday, model, asset_position_factory, instrument_price_factory):
|
|
84
84
|
assert not model.is_valid()
|
|
85
85
|
|
|
86
|
-
|
|
87
|
-
portfolio=model.portfolio, trade_date=model.last_effective_date, status=
|
|
86
|
+
order_proposal = OrderProposalFactory.create(
|
|
87
|
+
portfolio=model.portfolio, trade_date=model.last_effective_date, status=OrderProposal.Status.APPROVED
|
|
88
88
|
)
|
|
89
|
-
t1 =
|
|
89
|
+
t1 = OrderFactory.create(
|
|
90
90
|
portfolio=model.portfolio,
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
91
|
+
value_date=model.last_effective_date,
|
|
92
|
+
order_type=Order.Type.BUY,
|
|
93
|
+
order_proposal=order_proposal,
|
|
94
94
|
weighting=Decimal(0.7),
|
|
95
|
-
status=Trade.Status.EXECUTED,
|
|
96
95
|
)
|
|
97
|
-
|
|
96
|
+
OrderFactory.create(
|
|
98
97
|
portfolio=model.portfolio,
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
98
|
+
value_date=model.last_effective_date,
|
|
99
|
+
order_type=Order.Type.BUY,
|
|
100
|
+
order_proposal=order_proposal,
|
|
102
101
|
weighting=Decimal(0.3),
|
|
103
|
-
status=Trade.Status.EXECUTED,
|
|
104
102
|
)
|
|
105
103
|
assert not model.is_valid()
|
|
106
104
|
instrument_price_factory.create(instrument=t1.underlying_instrument, date=model.trade_date)
|
|
107
105
|
assert model.is_valid()
|
|
108
106
|
|
|
109
107
|
def test_get_target_portfolio(self, portfolio, weekday, model, asset_position_factory):
|
|
110
|
-
|
|
111
|
-
portfolio=model.portfolio, trade_date=model.last_effective_date, status=
|
|
108
|
+
order_proposal = OrderProposalFactory.create(
|
|
109
|
+
portfolio=model.portfolio, trade_date=model.last_effective_date, status=OrderProposal.Status.APPROVED
|
|
112
110
|
)
|
|
113
111
|
asset_position_factory(portfolio=portfolio, date=model.last_effective_date) # noise
|
|
114
112
|
asset_position_factory(portfolio=portfolio, date=model.last_effective_date) # noise
|
|
115
|
-
t1 =
|
|
113
|
+
t1 = OrderFactory.create(
|
|
116
114
|
portfolio=model.portfolio,
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
115
|
+
value_date=model.last_effective_date,
|
|
116
|
+
order_type=Order.Type.BUY,
|
|
117
|
+
order_proposal=order_proposal,
|
|
120
118
|
weighting=Decimal(0.8),
|
|
121
|
-
status=Trade.Status.EXECUTED,
|
|
122
119
|
)
|
|
123
|
-
t2 =
|
|
120
|
+
t2 = OrderFactory.create(
|
|
124
121
|
portfolio=model.portfolio,
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
122
|
+
value_date=model.last_effective_date,
|
|
123
|
+
order_type=Order.Type.BUY,
|
|
124
|
+
order_proposal=order_proposal,
|
|
128
125
|
weighting=Decimal(0.2),
|
|
129
|
-
status=Trade.Status.EXECUTED,
|
|
130
126
|
)
|
|
131
127
|
target_portfolio = model.get_target_portfolio()
|
|
132
128
|
target_positions = target_portfolio.positions_map
|
|
@@ -162,5 +158,5 @@ class TestMarketCapitalizationRebalancing:
|
|
|
162
158
|
|
|
163
159
|
target_portfolio = model.get_target_portfolio()
|
|
164
160
|
target_positions = target_portfolio.positions_map
|
|
165
|
-
assert target_positions[i1].weighting == mkt12 / (mkt12 + mkt21)
|
|
166
|
-
assert target_positions[i2].weighting == mkt21 / (mkt12 + mkt21)
|
|
161
|
+
assert target_positions[i1].weighting == pytest.approx(Decimal(mkt12 / (mkt12 + mkt21)), abs=Decimal(1e-8))
|
|
162
|
+
assert target_positions[i2].weighting == pytest.approx(Decimal(mkt21 / (mkt12 + mkt21)), abs=Decimal(1e-8))
|
wbportfolio/tests/signals.py
CHANGED
|
@@ -6,9 +6,9 @@ from wbfdm.factories import InstrumentPriceFactory
|
|
|
6
6
|
|
|
7
7
|
from wbportfolio.factories import (
|
|
8
8
|
CustomerTradeFactory,
|
|
9
|
+
OrderProposalFactory,
|
|
9
10
|
ProductFactory,
|
|
10
11
|
ProductPortfolioRoleFactory,
|
|
11
|
-
TradeProposalFactory,
|
|
12
12
|
)
|
|
13
13
|
from wbportfolio.viewsets import (
|
|
14
14
|
AssetPositionInstrumentModelViewSet,
|
|
@@ -20,14 +20,14 @@ from wbportfolio.viewsets import (
|
|
|
20
20
|
DistributionChartViewSet,
|
|
21
21
|
DistributionTableViewSet,
|
|
22
22
|
NominalProductChartView,
|
|
23
|
+
OrderOrderProposalModelViewSet,
|
|
24
|
+
OrderProposalPortfolioModelViewSet,
|
|
23
25
|
PortfolioRoleInstrumentModelViewSet,
|
|
24
26
|
ProductCustomerModelViewSet,
|
|
25
27
|
ProductPerformanceFeesModelViewSet,
|
|
26
28
|
SubscriptionRedemptionInstrumentModelViewSet,
|
|
27
29
|
SubscriptionRedemptionModelViewSet,
|
|
28
30
|
TradeInstrumentModelViewSet,
|
|
29
|
-
TradeProposalPortfolioModelViewSet,
|
|
30
|
-
TradeTradeProposalModelViewSet,
|
|
31
31
|
)
|
|
32
32
|
|
|
33
33
|
# =================================================================================================================
|
|
@@ -54,18 +54,18 @@ def receive_factory_product_portfolio_role(sender, *args, **kwargs):
|
|
|
54
54
|
# =================================================================================================================
|
|
55
55
|
# UPDATE KWARGS
|
|
56
56
|
# =================================================================================================================
|
|
57
|
-
@receiver(custom_update_kwargs, sender=
|
|
58
|
-
def
|
|
57
|
+
@receiver(custom_update_kwargs, sender=OrderOrderProposalModelViewSet)
|
|
58
|
+
def receive_kwargs_trade_order_proposal_product(sender, *args, **kwargs):
|
|
59
59
|
if obj := kwargs.get("obj_factory"):
|
|
60
|
-
|
|
61
|
-
obj.
|
|
60
|
+
order_proposal = OrderProposalFactory.create()
|
|
61
|
+
obj.order_proposal = order_proposal
|
|
62
62
|
obj.save()
|
|
63
|
-
return {"
|
|
63
|
+
return {"order_proposal_id": order_proposal.id}
|
|
64
64
|
return {}
|
|
65
65
|
|
|
66
66
|
|
|
67
|
-
@receiver(custom_update_kwargs, sender=
|
|
68
|
-
def
|
|
67
|
+
@receiver(custom_update_kwargs, sender=OrderProposalPortfolioModelViewSet)
|
|
68
|
+
def receive_kwargs_trade_order_proposal_portfolio(sender, *args, **kwargs):
|
|
69
69
|
if obj := kwargs.get("obj_factory"):
|
|
70
70
|
return {"portfolio_id": obj.portfolio.id}
|
|
71
71
|
return {}
|
wbportfolio/tests/tests.py
CHANGED
|
@@ -9,7 +9,7 @@ for key, value in default_config.items():
|
|
|
9
9
|
and x.__name__
|
|
10
10
|
not in [
|
|
11
11
|
"AggregatedAssetPositionLiquidityPandasView",
|
|
12
|
-
"
|
|
12
|
+
"OrderOrderProposalModelViewSet",
|
|
13
13
|
"PortfolioSwingPricing",
|
|
14
14
|
"PortfolioCashTarget",
|
|
15
15
|
"PortfolioSwingPricingModelViewSet",
|
wbportfolio/urls.py
CHANGED
|
@@ -38,7 +38,7 @@ router.register(
|
|
|
38
38
|
|
|
39
39
|
router.register(r"traderepresentation", viewsets.TradeRepresentationViewSet, basename="traderepresentation")
|
|
40
40
|
router.register(
|
|
41
|
-
r"
|
|
41
|
+
r"orderproposalrepresentation", viewsets.OrderProposalRepresentationViewSet, basename="orderproposalrepresentation"
|
|
42
42
|
)
|
|
43
43
|
router.register(
|
|
44
44
|
r"rebalancingmodelrepresentation",
|
|
@@ -62,7 +62,7 @@ router.register(r"aumchart", viewsets.InstrumentPriceAUMDataChartView, basename=
|
|
|
62
62
|
|
|
63
63
|
router.register(r"custodian", viewsets.CustodianModelViewSet, basename="custodian")
|
|
64
64
|
|
|
65
|
-
router.register(r"
|
|
65
|
+
router.register(r"orderproposal", viewsets.OrderProposalModelViewSet, basename="orderproposal")
|
|
66
66
|
|
|
67
67
|
router.register(
|
|
68
68
|
r"assetandnetnewmoneyprogression",
|
|
@@ -88,7 +88,7 @@ portfolio_router.register(
|
|
|
88
88
|
basename="portfolio-preferredclassification",
|
|
89
89
|
)
|
|
90
90
|
portfolio_router.register(
|
|
91
|
-
r"
|
|
91
|
+
r"orderproposal", viewsets.OrderProposalPortfolioModelViewSet, basename="portfolio-orderproposal"
|
|
92
92
|
)
|
|
93
93
|
portfolio_router.register(
|
|
94
94
|
r"dependencyportfolio", viewsets.PortfolioPortfolioThroughModelViewSet, basename="portfolio-dependencyportfolio"
|
|
@@ -137,9 +137,9 @@ product_router.register(r"claim", viewsets.ClaimProductModelViewSet, basename="p
|
|
|
137
137
|
product_router.register(r"feesaggregated", viewsets.FeesAggregatedProductPandasView, basename="product-feesaggregated")
|
|
138
138
|
product_router.register(r"fees", viewsets.FeesProductModelViewSet, basename="product-fees")
|
|
139
139
|
|
|
140
|
-
# Subrouter for
|
|
141
|
-
|
|
142
|
-
|
|
140
|
+
# Subrouter for Order Proposal
|
|
141
|
+
order_proposal_router = WBCoreRouter()
|
|
142
|
+
order_proposal_router.register(r"trade", viewsets.OrderOrderProposalModelViewSet, basename="orderproposal-order")
|
|
143
143
|
|
|
144
144
|
trade_router = WBCoreRouter()
|
|
145
145
|
trade_router.register(r"claim", viewsets.ClaimTradeModelViewSet, basename="trade-claim")
|
|
@@ -250,7 +250,7 @@ urlpatterns = [
|
|
|
250
250
|
path("product/<int:product_id>/", include(product_router.urls)),
|
|
251
251
|
path("trade/<int:trade_id>/", include(trade_router.urls)),
|
|
252
252
|
path("portfolio/<int:portfolio_id>/", include(portfolio_router.urls)),
|
|
253
|
-
path("
|
|
253
|
+
path("orderproposal/<int:order_proposal_id>/", include(order_proposal_router.urls)),
|
|
254
254
|
path("instrument/<int:instrument_id>/", include(instrument_router.urls)),
|
|
255
255
|
path("account/<int:account_id>/", include(account_router.urls)),
|
|
256
256
|
path("entry/<int:entry_id>/", include(entry_router.urls)),
|
wbportfolio/viewsets/__init__.py
CHANGED
|
@@ -24,7 +24,9 @@ from .positions import (
|
|
|
24
24
|
from .registers import RegisterModelViewSet, RegisterRepresentationViewSet
|
|
25
25
|
from .roles import PortfolioRoleInstrumentModelViewSet, PortfolioRoleModelViewSet
|
|
26
26
|
from .signals import *
|
|
27
|
+
from .rebalancing import RebalancingModelRepresentationViewSet, RebalancerRepresentationViewSet, RebalancerModelViewSet
|
|
27
28
|
from .transactions import *
|
|
29
|
+
from .orders import *
|
|
28
30
|
from .adjustments import AdjustmentEquityModelViewSet, AdjustmentModelViewSet
|
|
29
31
|
from .product_groups import ProductGroupModelViewSet, ProductGroupRepresentationViewSet
|
|
30
32
|
from .product_performance import (
|
|
@@ -15,9 +15,8 @@ from .products import ProductButtonConfig, ProductCustomerButtonConfig
|
|
|
15
15
|
from .registers import RegisterButtonConfig
|
|
16
16
|
from .trades import (
|
|
17
17
|
TradeButtonConfig,
|
|
18
|
-
TradeInstrumentButtonConfig
|
|
19
|
-
TradeTradeProposalButtonConfig
|
|
18
|
+
TradeInstrumentButtonConfig
|
|
20
19
|
)
|
|
21
|
-
|
|
20
|
+
|
|
22
21
|
from .reconciliations import AccountReconciliationButtonViewConfig, AccountReconciliationLineButtonViewConfig
|
|
23
22
|
from .signals import *
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
from rest_framework.reverse import reverse
|
|
2
2
|
from wbcore.contrib.icons import WBIcon
|
|
3
3
|
from wbcore.metadata.configs import buttons as bt
|
|
4
|
-
from wbcore.metadata.configs.buttons.enums import Button
|
|
5
4
|
from wbcore.metadata.configs.buttons.view_config import ButtonViewConfig
|
|
6
5
|
from wbfdm.models import Instrument
|
|
7
6
|
|
|
@@ -59,10 +58,3 @@ class TradeInstrumentButtonConfig(TradeButtonConfig):
|
|
|
59
58
|
)
|
|
60
59
|
)
|
|
61
60
|
return res
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
class TradeTradeProposalButtonConfig(ButtonViewConfig):
|
|
65
|
-
def get_create_buttons(self):
|
|
66
|
-
return {
|
|
67
|
-
Button.SAVE_AND_CLOSE.value,
|
|
68
|
-
}
|
|
@@ -49,9 +49,7 @@ from .trades import (
|
|
|
49
49
|
SubscriptionRedemptionDisplayConfig,
|
|
50
50
|
TradeDisplayConfig,
|
|
51
51
|
TradePortfolioDisplayConfig,
|
|
52
|
-
TradeTradeProposalDisplayConfig,
|
|
53
52
|
)
|
|
54
|
-
from .trade_proposals import TradeProposalDisplayConfig
|
|
55
53
|
from .portfolio_relationship import (
|
|
56
54
|
PortfolioInstrumentPreferredClassificationThroughDisplayConfig,
|
|
57
55
|
InstrumentPortfolioThroughPortfolioModelDisplayConfig,
|
|
@@ -51,9 +51,9 @@ class PortfolioDisplayConfig(DisplayViewConfig):
|
|
|
51
51
|
key=None,
|
|
52
52
|
children=[
|
|
53
53
|
dp.Field(key="automatic_rebalancer", label="Automatic Rebalancer"),
|
|
54
|
-
dp.Field(key="
|
|
54
|
+
dp.Field(key="last_order_proposal_date", label="Last Rebalance", width=Unit.PIXEL(250)),
|
|
55
55
|
dp.Field(
|
|
56
|
-
key="
|
|
56
|
+
key="next_expected_order_proposal_date",
|
|
57
57
|
label="Next Rebalancing",
|
|
58
58
|
width=Unit.PIXEL(250),
|
|
59
59
|
show="open",
|
|
@@ -126,15 +126,15 @@ class PortfolioDisplayConfig(DisplayViewConfig):
|
|
|
126
126
|
},
|
|
127
127
|
),
|
|
128
128
|
Page(
|
|
129
|
-
title="
|
|
129
|
+
title="Order",
|
|
130
130
|
layouts={
|
|
131
131
|
default(): dp.Layout(
|
|
132
132
|
grid_template_areas=[
|
|
133
|
-
["
|
|
133
|
+
["order_proposals"],
|
|
134
134
|
],
|
|
135
135
|
grid_template_rows=["auto"],
|
|
136
136
|
inlines=[
|
|
137
|
-
dp.Inline(key="
|
|
137
|
+
dp.Inline(key="order_proposals", endpoint="order_proposals"),
|
|
138
138
|
],
|
|
139
139
|
)
|
|
140
140
|
},
|
|
@@ -11,7 +11,7 @@ class RebalancerDisplayConfig(DisplayViewConfig):
|
|
|
11
11
|
fields=[
|
|
12
12
|
dp.Field(key="portfolio", label="Portfolio"),
|
|
13
13
|
dp.Field(key="rebalancing_model", label="Rebalancing Model"),
|
|
14
|
-
dp.Field(key="
|
|
14
|
+
dp.Field(key="approve_order_proposal_automatically", label="Approve automatically"),
|
|
15
15
|
dp.Field(key="frequency_repr", label="Frequency"),
|
|
16
16
|
dp.Field(key="activation_date", label="Activation Date"),
|
|
17
17
|
],
|
|
@@ -20,7 +20,7 @@ class RebalancerDisplayConfig(DisplayViewConfig):
|
|
|
20
20
|
def get_instance_display(self) -> Display:
|
|
21
21
|
return create_simple_display(
|
|
22
22
|
[
|
|
23
|
-
["rebalancing_model", "
|
|
23
|
+
["rebalancing_model", "approve_order_proposal_automatically"],
|
|
24
24
|
["frequency", "activation_date"],
|
|
25
25
|
["rebalancing_dates", "rebalancing_dates"],
|
|
26
26
|
]
|