wbportfolio 1.54.13__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} +289 -245
- wbportfolio/models/orders/orders.py +243 -0
- wbportfolio/models/portfolio.py +17 -20
- 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} +22 -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 -45
- 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.13.dist-info → wbportfolio-1.54.15.dist-info}/METADATA +1 -1
- {wbportfolio-1.54.13.dist-info → wbportfolio-1.54.15.dist-info}/RECORD +85 -58
- wbportfolio/viewsets/configs/endpoints/trade_proposals.py +0 -18
- {wbportfolio-1.54.13.dist-info → wbportfolio-1.54.15.dist-info}/WHEEL +0 -0
- {wbportfolio-1.54.13.dist-info → wbportfolio-1.54.15.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
from typing import Optional
|
|
2
2
|
|
|
3
|
-
from django.shortcuts import get_object_or_404
|
|
4
3
|
from wbcore.contrib.color.enums import WBColor
|
|
5
4
|
from wbcore.contrib.icons import WBIcon
|
|
6
5
|
from wbcore.enums import Unit
|
|
@@ -12,8 +11,6 @@ from wbcore.metadata.configs.display.instance_display.shortcuts import (
|
|
|
12
11
|
from wbcore.metadata.configs.display.instance_display.utils import repeat_field
|
|
13
12
|
from wbcore.metadata.configs.display.view_config import DisplayViewConfig
|
|
14
13
|
|
|
15
|
-
from wbportfolio.models import Trade, TradeProposal
|
|
16
|
-
|
|
17
14
|
NEGATIVE_RED_FORMATTING = [
|
|
18
15
|
dp.FormattingRule(
|
|
19
16
|
style={
|
|
@@ -37,63 +34,6 @@ SHARE_FORMATTING = dp.Formatting(
|
|
|
37
34
|
],
|
|
38
35
|
)
|
|
39
36
|
|
|
40
|
-
TRADE_STATUS_LEGENDS = dp.Legend(
|
|
41
|
-
key="status",
|
|
42
|
-
items=[
|
|
43
|
-
dp.LegendItem(
|
|
44
|
-
icon=WBColor.RED_LIGHT.value,
|
|
45
|
-
label=Trade.Status.FAILED.label,
|
|
46
|
-
value=Trade.Status.FAILED.value,
|
|
47
|
-
),
|
|
48
|
-
dp.LegendItem(
|
|
49
|
-
icon=WBColor.BLUE_LIGHT.value,
|
|
50
|
-
label=Trade.Status.DRAFT.label,
|
|
51
|
-
value=Trade.Status.DRAFT.value,
|
|
52
|
-
),
|
|
53
|
-
dp.LegendItem(
|
|
54
|
-
icon=WBColor.YELLOW_LIGHT.value,
|
|
55
|
-
label=Trade.Status.SUBMIT.label,
|
|
56
|
-
value=Trade.Status.SUBMIT.value,
|
|
57
|
-
),
|
|
58
|
-
dp.LegendItem(
|
|
59
|
-
icon=WBColor.GREEN_LIGHT.value,
|
|
60
|
-
label=Trade.Status.EXECUTED.label,
|
|
61
|
-
value=Trade.Status.EXECUTED.value,
|
|
62
|
-
),
|
|
63
|
-
dp.LegendItem(
|
|
64
|
-
icon=WBColor.GREEN.value,
|
|
65
|
-
label=Trade.Status.CONFIRMED.label,
|
|
66
|
-
value=Trade.Status.CONFIRMED.value,
|
|
67
|
-
),
|
|
68
|
-
],
|
|
69
|
-
)
|
|
70
|
-
|
|
71
|
-
TRADE_STATUS_FORMATTING = dp.Formatting(
|
|
72
|
-
column="status",
|
|
73
|
-
formatting_rules=[
|
|
74
|
-
dp.FormattingRule(
|
|
75
|
-
style={"backgroundColor": WBColor.RED_LIGHT.value},
|
|
76
|
-
condition=("==", Trade.Status.FAILED.value),
|
|
77
|
-
),
|
|
78
|
-
dp.FormattingRule(
|
|
79
|
-
style={"backgroundColor": WBColor.BLUE_LIGHT.value},
|
|
80
|
-
condition=("==", Trade.Status.DRAFT.value),
|
|
81
|
-
),
|
|
82
|
-
dp.FormattingRule(
|
|
83
|
-
style={"backgroundColor": WBColor.YELLOW_LIGHT.value},
|
|
84
|
-
condition=("==", Trade.Status.SUBMIT.value),
|
|
85
|
-
),
|
|
86
|
-
dp.FormattingRule(
|
|
87
|
-
style={"backgroundColor": WBColor.GREEN_LIGHT.value},
|
|
88
|
-
condition=("==", Trade.Status.EXECUTED.value),
|
|
89
|
-
),
|
|
90
|
-
dp.FormattingRule(
|
|
91
|
-
style={"backgroundColor": WBColor.GREEN.value},
|
|
92
|
-
condition=("==", Trade.Status.CONFIRMED.value),
|
|
93
|
-
),
|
|
94
|
-
],
|
|
95
|
-
)
|
|
96
|
-
|
|
97
37
|
|
|
98
38
|
class TradeDisplayConfig(DisplayViewConfig):
|
|
99
39
|
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
@@ -145,8 +85,7 @@ class TradeDisplayConfig(DisplayViewConfig):
|
|
|
145
85
|
),
|
|
146
86
|
),
|
|
147
87
|
],
|
|
148
|
-
|
|
149
|
-
formatting=[SHARE_FORMATTING, TRADE_STATUS_FORMATTING],
|
|
88
|
+
formatting=[SHARE_FORMATTING],
|
|
150
89
|
)
|
|
151
90
|
|
|
152
91
|
def get_instance_display(self) -> Display:
|
|
@@ -285,166 +224,3 @@ class SubscriptionRedemptionDisplayConfig(TradeDisplayConfig):
|
|
|
285
224
|
|
|
286
225
|
class TradePortfolioDisplayConfig(TradeDisplayConfig):
|
|
287
226
|
pass
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
class TradeTradeProposalDisplayConfig(DisplayViewConfig):
|
|
291
|
-
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
292
|
-
trade_proposal = get_object_or_404(TradeProposal, pk=self.view.kwargs.get("trade_proposal_id", None))
|
|
293
|
-
fields = [
|
|
294
|
-
dp.Field(
|
|
295
|
-
label="Instrument",
|
|
296
|
-
open_by_default=True,
|
|
297
|
-
key=None,
|
|
298
|
-
children=[
|
|
299
|
-
dp.Field(key="underlying_instrument", label="Name", width=Unit.PIXEL(250)),
|
|
300
|
-
dp.Field(key="underlying_instrument_isin", label="ISIN", width=Unit.PIXEL(125)),
|
|
301
|
-
dp.Field(key="underlying_instrument_ticker", label="Ticker", width=Unit.PIXEL(100)),
|
|
302
|
-
dp.Field(
|
|
303
|
-
key="underlying_instrument_refinitiv_identifier_code", label="RIC", width=Unit.PIXEL(100)
|
|
304
|
-
),
|
|
305
|
-
dp.Field(key="underlying_instrument_instrument_type", label="Asset Class", width=Unit.PIXEL(125)),
|
|
306
|
-
],
|
|
307
|
-
),
|
|
308
|
-
dp.Field(
|
|
309
|
-
label="Weight",
|
|
310
|
-
open_by_default=False,
|
|
311
|
-
key=None,
|
|
312
|
-
children=[
|
|
313
|
-
dp.Field(key="effective_weight", label="Effective Weight", show="open", width=Unit.PIXEL(150)),
|
|
314
|
-
dp.Field(key="target_weight", label="Target Weight", show="open", width=Unit.PIXEL(150)),
|
|
315
|
-
dp.Field(
|
|
316
|
-
key="weighting",
|
|
317
|
-
label="Delta Weight",
|
|
318
|
-
formatting_rules=[
|
|
319
|
-
dp.FormattingRule(
|
|
320
|
-
style={"color": WBColor.RED_DARK.value, "fontWeight": "bold"},
|
|
321
|
-
condition=("<", 0),
|
|
322
|
-
),
|
|
323
|
-
dp.FormattingRule(
|
|
324
|
-
style={"color": WBColor.GREEN_DARK.value, "fontWeight": "bold"},
|
|
325
|
-
condition=(">", 0),
|
|
326
|
-
),
|
|
327
|
-
],
|
|
328
|
-
width=Unit.PIXEL(150),
|
|
329
|
-
),
|
|
330
|
-
],
|
|
331
|
-
),
|
|
332
|
-
]
|
|
333
|
-
if not trade_proposal.portfolio.only_weighting:
|
|
334
|
-
fields.append(
|
|
335
|
-
dp.Field(
|
|
336
|
-
label="Shares",
|
|
337
|
-
open_by_default=False,
|
|
338
|
-
key=None,
|
|
339
|
-
children=[
|
|
340
|
-
dp.Field(key="effective_shares", label="Effective Shares", show="open", width=Unit.PIXEL(150)),
|
|
341
|
-
dp.Field(key="target_shares", label="Target Shares", show="open", width=Unit.PIXEL(150)),
|
|
342
|
-
dp.Field(
|
|
343
|
-
key="shares",
|
|
344
|
-
label="Shares",
|
|
345
|
-
formatting_rules=[
|
|
346
|
-
dp.FormattingRule(
|
|
347
|
-
style={"color": WBColor.RED_DARK.value, "fontWeight": "bold"},
|
|
348
|
-
condition=("<", 0),
|
|
349
|
-
),
|
|
350
|
-
dp.FormattingRule(
|
|
351
|
-
style={"color": WBColor.GREEN_DARK.value, "fontWeight": "bold"},
|
|
352
|
-
condition=(">", 0),
|
|
353
|
-
),
|
|
354
|
-
],
|
|
355
|
-
width=Unit.PIXEL(150),
|
|
356
|
-
),
|
|
357
|
-
],
|
|
358
|
-
)
|
|
359
|
-
)
|
|
360
|
-
fields.append(
|
|
361
|
-
dp.Field(
|
|
362
|
-
label="Total Value",
|
|
363
|
-
open_by_default=False,
|
|
364
|
-
key=None,
|
|
365
|
-
children=[
|
|
366
|
-
dp.Field(
|
|
367
|
-
key="effective_total_value_fx_portfolio",
|
|
368
|
-
label="Effective Total Value",
|
|
369
|
-
show="open",
|
|
370
|
-
width=Unit.PIXEL(150),
|
|
371
|
-
),
|
|
372
|
-
dp.Field(
|
|
373
|
-
key="target_total_value_fx_portfolio",
|
|
374
|
-
label="Target Total Value",
|
|
375
|
-
show="open",
|
|
376
|
-
width=Unit.PIXEL(150),
|
|
377
|
-
),
|
|
378
|
-
dp.Field(
|
|
379
|
-
key="total_value_fx_portfolio",
|
|
380
|
-
label="Total Value",
|
|
381
|
-
formatting_rules=[
|
|
382
|
-
dp.FormattingRule(
|
|
383
|
-
style={"color": WBColor.RED_DARK.value, "fontWeight": "bold"},
|
|
384
|
-
condition=("<", 0),
|
|
385
|
-
),
|
|
386
|
-
dp.FormattingRule(
|
|
387
|
-
style={"color": WBColor.GREEN_DARK.value, "fontWeight": "bold"},
|
|
388
|
-
condition=(">", 0),
|
|
389
|
-
),
|
|
390
|
-
],
|
|
391
|
-
width=Unit.PIXEL(150),
|
|
392
|
-
),
|
|
393
|
-
],
|
|
394
|
-
)
|
|
395
|
-
)
|
|
396
|
-
fields.append(
|
|
397
|
-
dp.Field(
|
|
398
|
-
label="Information",
|
|
399
|
-
open_by_default=False,
|
|
400
|
-
key=None,
|
|
401
|
-
children=[
|
|
402
|
-
dp.Field(
|
|
403
|
-
key="transaction_subtype",
|
|
404
|
-
label="Direction",
|
|
405
|
-
formatting_rules=[
|
|
406
|
-
dp.FormattingRule(
|
|
407
|
-
style={"color": WBColor.RED_DARK.value, "fontWeight": "bold"},
|
|
408
|
-
condition=("==", Trade.Type.SELL.name),
|
|
409
|
-
),
|
|
410
|
-
dp.FormattingRule(
|
|
411
|
-
style={"color": WBColor.RED_DARK.value, "fontWeight": "bold"},
|
|
412
|
-
condition=("==", Trade.Type.DECREASE.name),
|
|
413
|
-
),
|
|
414
|
-
dp.FormattingRule(
|
|
415
|
-
style={"color": WBColor.GREEN_DARK.value, "fontWeight": "bold"},
|
|
416
|
-
condition=("==", Trade.Type.INCREASE.name),
|
|
417
|
-
),
|
|
418
|
-
dp.FormattingRule(
|
|
419
|
-
style={"color": WBColor.GREEN_DARK.value, "fontWeight": "bold"},
|
|
420
|
-
condition=("==", Trade.Type.BUY.name),
|
|
421
|
-
),
|
|
422
|
-
dp.FormattingRule(
|
|
423
|
-
style={"color": WBColor.GREY.value, "fontWeight": "bold"},
|
|
424
|
-
condition=("==", Trade.Type.NO_CHANGE.name),
|
|
425
|
-
),
|
|
426
|
-
],
|
|
427
|
-
width=Unit.PIXEL(125),
|
|
428
|
-
),
|
|
429
|
-
dp.Field(key="comment", label="Comment", width=Unit.PIXEL(250)),
|
|
430
|
-
dp.Field(key="order", label="Order", show="open", width=Unit.PIXEL(100)),
|
|
431
|
-
],
|
|
432
|
-
)
|
|
433
|
-
)
|
|
434
|
-
return dp.ListDisplay(
|
|
435
|
-
fields=fields,
|
|
436
|
-
legends=[TRADE_STATUS_LEGENDS],
|
|
437
|
-
formatting=[TRADE_STATUS_FORMATTING],
|
|
438
|
-
)
|
|
439
|
-
|
|
440
|
-
def get_instance_display(self) -> Display:
|
|
441
|
-
trade_proposal = get_object_or_404(TradeProposal, pk=self.view.kwargs.get("trade_proposal_id", None))
|
|
442
|
-
|
|
443
|
-
fields = [
|
|
444
|
-
["company", "security", "underlying_instrument"],
|
|
445
|
-
["effective_weight", "target_weight", "weighting"],
|
|
446
|
-
]
|
|
447
|
-
if not trade_proposal.portfolio.only_weighting:
|
|
448
|
-
fields.append(["effective_shares", "target_shares", "shares"])
|
|
449
|
-
fields.append([repeat_field(3, "comment")])
|
|
450
|
-
return create_simple_display(fields)
|
|
@@ -62,9 +62,6 @@ from .trades import (
|
|
|
62
62
|
TradeEndpointConfig,
|
|
63
63
|
TradeInstrumentEndpointConfig,
|
|
64
64
|
TradePortfolioEndpointConfig,
|
|
65
|
-
TradeProposalEndpointConfig,
|
|
66
|
-
TradeProposalPortfolioEndpointConfig,
|
|
67
|
-
TradeTradeProposalEndpointConfig,
|
|
68
65
|
SubscriptionRedemptionEndpointConfig,
|
|
69
66
|
)
|
|
70
67
|
from .portfolio_relationship import (
|
|
@@ -1,11 +1,6 @@
|
|
|
1
|
-
from contextlib import suppress
|
|
2
|
-
|
|
3
|
-
from django.shortcuts import get_object_or_404
|
|
4
1
|
from rest_framework.reverse import reverse
|
|
5
2
|
from wbcore.metadata.configs.endpoints import EndpointViewConfig
|
|
6
3
|
|
|
7
|
-
from wbportfolio.models import TradeProposal
|
|
8
|
-
|
|
9
4
|
|
|
10
5
|
class TradeEndpointConfig(EndpointViewConfig):
|
|
11
6
|
def get_endpoint(self, **kwargs):
|
|
@@ -50,42 +45,6 @@ class CustodianDistributionInstrumentEndpointConfig(EndpointViewConfig):
|
|
|
50
45
|
)
|
|
51
46
|
|
|
52
47
|
|
|
53
|
-
class TradeProposalEndpointConfig(EndpointViewConfig):
|
|
54
|
-
def get_delete_endpoint(self, **kwargs):
|
|
55
|
-
if pk := self.view.kwargs.get("pk", None):
|
|
56
|
-
trade_proposal = get_object_or_404(TradeProposal, pk=pk)
|
|
57
|
-
if trade_proposal.status == TradeProposal.Status.DRAFT:
|
|
58
|
-
return super().get_endpoint()
|
|
59
|
-
return None
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
class TradeProposalPortfolioEndpointConfig(TradeProposalEndpointConfig):
|
|
63
|
-
def get_endpoint(self, **kwargs):
|
|
64
|
-
return reverse(
|
|
65
|
-
"wbportfolio:portfolio-tradeproposal-list", args=[self.view.kwargs["portfolio_id"]], request=self.request
|
|
66
|
-
)
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
class TradeTradeProposalEndpointConfig(EndpointViewConfig):
|
|
70
|
-
def get_endpoint(self, **kwargs):
|
|
71
|
-
if trade_proposal_id := self.view.kwargs.get("trade_proposal_id", None):
|
|
72
|
-
trade_proposal = TradeProposal.objects.get(id=trade_proposal_id)
|
|
73
|
-
if trade_proposal.status == TradeProposal.Status.DRAFT:
|
|
74
|
-
return reverse(
|
|
75
|
-
"wbportfolio:tradeproposal-trade-list",
|
|
76
|
-
args=[self.view.kwargs["trade_proposal_id"]],
|
|
77
|
-
request=self.request,
|
|
78
|
-
)
|
|
79
|
-
return None
|
|
80
|
-
|
|
81
|
-
def get_delete_endpoint(self, **kwargs):
|
|
82
|
-
with suppress(AttributeError, AssertionError):
|
|
83
|
-
trade = self.view.get_object()
|
|
84
|
-
if trade._effective_weight: # we make sure trade with a valid effective position cannot be deleted
|
|
85
|
-
return None
|
|
86
|
-
return super().get_delete_endpoint(**kwargs)
|
|
87
|
-
|
|
88
|
-
|
|
89
48
|
class SubscriptionRedemptionEndpointConfig(TradeEndpointConfig):
|
|
90
49
|
def get_endpoint(self, **kwargs):
|
|
91
50
|
return reverse("wbportfolio:subscriptionredemption-list", args=[], request=self.request)
|
|
@@ -10,7 +10,7 @@ class NormalizeSerializer(wb_serializers.Serializer):
|
|
|
10
10
|
total_cash_weight = wb_serializers.FloatField(default=0, precision=4, percent=True)
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
class
|
|
13
|
+
class OrderProposalButtonConfig(ButtonViewConfig):
|
|
14
14
|
def get_custom_list_instance_buttons(self):
|
|
15
15
|
return {
|
|
16
16
|
bt.DropDownButton(
|
|
@@ -18,53 +18,54 @@ class TradeProposalButtonConfig(ButtonViewConfig):
|
|
|
18
18
|
buttons=(
|
|
19
19
|
bt.ActionButton(
|
|
20
20
|
method=RequestType.PATCH,
|
|
21
|
-
identifiers=("wbportfolio:
|
|
21
|
+
identifiers=("wbportfolio:orderproposal",),
|
|
22
22
|
key="replay",
|
|
23
23
|
icon=WBIcon.SYNCHRONIZE.icon,
|
|
24
|
-
label="Replay
|
|
24
|
+
label="Replay Orders",
|
|
25
25
|
description_fields="""
|
|
26
|
-
<p>Replay
|
|
26
|
+
<p>Replay Orders. It will recompute all assets positions until next order proposal day (or today otherwise) </p>
|
|
27
27
|
""",
|
|
28
|
-
action_label="Replay
|
|
29
|
-
title="Replay
|
|
28
|
+
action_label="Replay Order",
|
|
29
|
+
title="Replay Order",
|
|
30
30
|
),
|
|
31
31
|
bt.ActionButton(
|
|
32
32
|
method=RequestType.PATCH,
|
|
33
|
-
identifiers=("wbportfolio:
|
|
33
|
+
identifiers=("wbportfolio:orderproposal",),
|
|
34
34
|
key="reset",
|
|
35
35
|
icon=WBIcon.REGENERATE.icon,
|
|
36
|
-
label="Reset
|
|
36
|
+
label="Reset Orders",
|
|
37
37
|
description_fields="""
|
|
38
|
-
<p>
|
|
38
|
+
<p><strong>Warning:</strong> This action will delete all current orders and recreate initial orders based on your last effective portfolio.</p>
|
|
39
|
+
<p><strong>Note:</strong> All delta weights will be permanently removed. This operation cannot be undone.</p>
|
|
39
40
|
""",
|
|
40
|
-
action_label="Reset
|
|
41
|
-
title="Reset
|
|
41
|
+
action_label="Reset Orders",
|
|
42
|
+
title="Reset Orders",
|
|
42
43
|
),
|
|
43
44
|
bt.ActionButton(
|
|
44
45
|
method=RequestType.PATCH,
|
|
45
|
-
identifiers=("wbportfolio:
|
|
46
|
+
identifiers=("wbportfolio:orderproposal",),
|
|
46
47
|
key="normalize",
|
|
47
48
|
icon=WBIcon.EDIT.icon,
|
|
48
|
-
label="Normalize
|
|
49
|
+
label="Normalize Orders",
|
|
49
50
|
description_fields="""
|
|
50
|
-
<p>Make sure all
|
|
51
|
+
<p>Make sure all orders normalize to a total target weight of (100 - {{total_cash_weight}})%</p>
|
|
51
52
|
""",
|
|
52
|
-
action_label="Normalize
|
|
53
|
-
title="Normalize
|
|
53
|
+
action_label="Normalize Orders",
|
|
54
|
+
title="Normalize Orders",
|
|
54
55
|
serializer=NormalizeSerializer,
|
|
55
56
|
instance_display=create_simple_display([["total_cash_weight"]]),
|
|
56
57
|
),
|
|
57
58
|
bt.ActionButton(
|
|
58
59
|
method=RequestType.PATCH,
|
|
59
|
-
identifiers=("wbportfolio:
|
|
60
|
+
identifiers=("wbportfolio:orderproposal",),
|
|
60
61
|
key="deleteall",
|
|
61
62
|
icon=WBIcon.DELETE.icon,
|
|
62
|
-
label="Delete All
|
|
63
|
+
label="Delete All Orders",
|
|
63
64
|
description_fields="""
|
|
64
|
-
<p>Delete all
|
|
65
|
+
<p>Delete all orders from this order proposal?</p>
|
|
65
66
|
""",
|
|
66
|
-
action_label="Delete All
|
|
67
|
-
title="Delete All
|
|
67
|
+
action_label="Delete All Orders",
|
|
68
|
+
title="Delete All Orders",
|
|
68
69
|
),
|
|
69
70
|
),
|
|
70
71
|
),
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
from wbcore.metadata.configs.buttons.enums import Button
|
|
2
|
+
from wbcore.metadata.configs.buttons.view_config import ButtonViewConfig
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class OrderOrderProposalButtonConfig(ButtonViewConfig):
|
|
6
|
+
def get_create_buttons(self):
|
|
7
|
+
return {
|
|
8
|
+
Button.SAVE_AND_CLOSE.value,
|
|
9
|
+
}
|
|
@@ -7,14 +7,14 @@ from wbcore.metadata.configs.display.instance_display.operators import default
|
|
|
7
7
|
from wbcore.metadata.configs.display.instance_display.shortcuts import Display
|
|
8
8
|
from wbcore.metadata.configs.display.view_config import DisplayViewConfig
|
|
9
9
|
|
|
10
|
-
from wbportfolio.models import
|
|
10
|
+
from wbportfolio.models import OrderProposal
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
class
|
|
13
|
+
class OrderProposalDisplayConfig(DisplayViewConfig):
|
|
14
14
|
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
15
15
|
return dp.ListDisplay(
|
|
16
16
|
fields=[
|
|
17
|
-
dp.Field(key="trade_date", label="
|
|
17
|
+
dp.Field(key="trade_date", label="Order Date"),
|
|
18
18
|
dp.Field(key="comment", label="Comment"),
|
|
19
19
|
],
|
|
20
20
|
legends=[
|
|
@@ -23,28 +23,28 @@ class TradeProposalDisplayConfig(DisplayViewConfig):
|
|
|
23
23
|
items=[
|
|
24
24
|
dp.LegendItem(
|
|
25
25
|
icon=WBColor.BLUE_LIGHT.value,
|
|
26
|
-
label=
|
|
27
|
-
value=
|
|
26
|
+
label=OrderProposal.Status.DRAFT.label,
|
|
27
|
+
value=OrderProposal.Status.DRAFT.value,
|
|
28
28
|
),
|
|
29
29
|
dp.LegendItem(
|
|
30
30
|
icon=WBColor.YELLOW_LIGHT.value,
|
|
31
|
-
label=
|
|
32
|
-
value=
|
|
31
|
+
label=OrderProposal.Status.SUBMIT.label,
|
|
32
|
+
value=OrderProposal.Status.SUBMIT.value,
|
|
33
33
|
),
|
|
34
34
|
dp.LegendItem(
|
|
35
35
|
icon=WBColor.GREEN_LIGHT.value,
|
|
36
|
-
label=
|
|
37
|
-
value=
|
|
36
|
+
label=OrderProposal.Status.APPROVED.label,
|
|
37
|
+
value=OrderProposal.Status.APPROVED.value,
|
|
38
38
|
),
|
|
39
39
|
dp.LegendItem(
|
|
40
40
|
icon=WBColor.RED_LIGHT.value,
|
|
41
|
-
label=
|
|
42
|
-
value=
|
|
41
|
+
label=OrderProposal.Status.DENIED.label,
|
|
42
|
+
value=OrderProposal.Status.DENIED.value,
|
|
43
43
|
),
|
|
44
44
|
dp.LegendItem(
|
|
45
45
|
icon=WBColor.RED_DARK.value,
|
|
46
|
-
label=
|
|
47
|
-
value=
|
|
46
|
+
label=OrderProposal.Status.FAILED.label,
|
|
47
|
+
value=OrderProposal.Status.FAILED.value,
|
|
48
48
|
),
|
|
49
49
|
],
|
|
50
50
|
),
|
|
@@ -55,23 +55,23 @@ class TradeProposalDisplayConfig(DisplayViewConfig):
|
|
|
55
55
|
formatting_rules=[
|
|
56
56
|
dp.FormattingRule(
|
|
57
57
|
style={"backgroundColor": WBColor.BLUE_LIGHT.value},
|
|
58
|
-
condition=("==",
|
|
58
|
+
condition=("==", OrderProposal.Status.DRAFT.value),
|
|
59
59
|
),
|
|
60
60
|
dp.FormattingRule(
|
|
61
61
|
style={"backgroundColor": WBColor.YELLOW_LIGHT.value},
|
|
62
|
-
condition=("==",
|
|
62
|
+
condition=("==", OrderProposal.Status.SUBMIT.value),
|
|
63
63
|
),
|
|
64
64
|
dp.FormattingRule(
|
|
65
65
|
style={"backgroundColor": WBColor.GREEN_LIGHT.value},
|
|
66
|
-
condition=("==",
|
|
66
|
+
condition=("==", OrderProposal.Status.APPROVED.value),
|
|
67
67
|
),
|
|
68
68
|
dp.FormattingRule(
|
|
69
69
|
style={"backgroundColor": WBColor.RED_LIGHT.value},
|
|
70
|
-
condition=("==",
|
|
70
|
+
condition=("==", OrderProposal.Status.DENIED.value),
|
|
71
71
|
),
|
|
72
72
|
dp.FormattingRule(
|
|
73
73
|
style={"backgroundColor": WBColor.RED_DARK.value},
|
|
74
|
-
condition=("==",
|
|
74
|
+
condition=("==", OrderProposal.Status.FAILED.value),
|
|
75
75
|
),
|
|
76
76
|
],
|
|
77
77
|
)
|
|
@@ -97,12 +97,12 @@ class TradeProposalDisplayConfig(DisplayViewConfig):
|
|
|
97
97
|
},
|
|
98
98
|
),
|
|
99
99
|
Page(
|
|
100
|
-
title="
|
|
100
|
+
title="Orders",
|
|
101
101
|
layouts={
|
|
102
102
|
default(): Layout(
|
|
103
|
-
grid_template_areas=[["
|
|
103
|
+
grid_template_areas=[["orders"]],
|
|
104
104
|
grid_template_rows=["1fr"],
|
|
105
|
-
inlines=[Inline(key="
|
|
105
|
+
inlines=[Inline(key="orders", endpoint="orders")],
|
|
106
106
|
),
|
|
107
107
|
},
|
|
108
108
|
),
|