wbportfolio 1.52.0__py2.py3-none-any.whl → 1.52.2__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of wbportfolio might be problematic. Click here for more details.
- wbportfolio/admin/__init__.py +1 -1
- wbportfolio/admin/transactions/__init__.py +0 -1
- wbportfolio/admin/transactions/dividends.py +40 -4
- wbportfolio/admin/transactions/fees.py +24 -14
- wbportfolio/admin/transactions/trades.py +34 -12
- wbportfolio/defaults/fees/default.py +7 -15
- wbportfolio/factories/__init__.py +0 -1
- wbportfolio/factories/dividends.py +8 -3
- wbportfolio/factories/fees.py +8 -4
- wbportfolio/factories/trades.py +10 -3
- wbportfolio/filters/transactions/__init__.py +1 -2
- wbportfolio/filters/transactions/fees.py +5 -10
- wbportfolio/filters/transactions/trades.py +17 -8
- wbportfolio/filters/transactions/utils.py +42 -0
- wbportfolio/import_export/handlers/dividend.py +7 -7
- wbportfolio/import_export/handlers/fees.py +11 -21
- wbportfolio/import_export/handlers/trade.py +5 -7
- wbportfolio/import_export/parsers/jpmorgan/fees.py +2 -2
- wbportfolio/import_export/parsers/leonteq/customer_trade.py +5 -5
- wbportfolio/import_export/parsers/leonteq/fees.py +11 -7
- wbportfolio/import_export/parsers/leonteq/trade.py +0 -5
- wbportfolio/import_export/parsers/natixis/d1_fees.py +2 -2
- wbportfolio/import_export/parsers/natixis/dividend.py +4 -9
- wbportfolio/import_export/parsers/natixis/fees.py +7 -9
- wbportfolio/import_export/parsers/sg_lux/customer_trade_pending_slk.py +1 -1
- wbportfolio/import_export/parsers/sg_lux/fees.py +2 -2
- wbportfolio/import_export/parsers/sg_lux/perf_fees.py +2 -2
- wbportfolio/import_export/parsers/sg_lux/utils.py +2 -2
- wbportfolio/import_export/parsers/ubs/api/fees.py +2 -2
- wbportfolio/import_export/parsers/vontobel/customer_trade.py +2 -3
- wbportfolio/import_export/parsers/vontobel/historical_customer_trade.py +0 -1
- wbportfolio/import_export/parsers/vontobel/management_fees.py +7 -7
- wbportfolio/import_export/parsers/vontobel/performance_fees.py +3 -3
- wbportfolio/jinja2/wbportfolio/sql/aum_nnm.sql +2 -2
- wbportfolio/migrations/0059_fees_unique_fees.py +1 -1
- wbportfolio/migrations/0077_remove_transaction_currency_and_more.py +622 -0
- wbportfolio/models/mixins/liquidity_stress_test.py +3 -3
- wbportfolio/models/transactions/__init__.py +0 -2
- wbportfolio/models/transactions/claim.py +1 -1
- wbportfolio/models/transactions/dividends.py +41 -5
- wbportfolio/models/transactions/fees.py +55 -22
- wbportfolio/models/transactions/trade_proposals.py +26 -6
- wbportfolio/models/transactions/trades.py +111 -50
- wbportfolio/models/transactions/transactions.py +60 -156
- wbportfolio/serializers/signals.py +15 -10
- wbportfolio/serializers/transactions/__init__.py +0 -5
- wbportfolio/serializers/transactions/dividends.py +37 -9
- wbportfolio/serializers/transactions/fees.py +39 -10
- wbportfolio/serializers/transactions/trades.py +56 -16
- wbportfolio/tasks.py +2 -2
- wbportfolio/tests/conftest.py +2 -8
- wbportfolio/tests/models/test_imports.py +2 -7
- wbportfolio/tests/models/transactions/test_fees.py +7 -13
- wbportfolio/tests/models/transactions/test_trade_proposals.py +4 -2
- wbportfolio/urls.py +3 -6
- wbportfolio/viewsets/configs/buttons/__init__.py +1 -0
- wbportfolio/viewsets/configs/buttons/mixins.py +2 -2
- wbportfolio/viewsets/configs/buttons/trades.py +8 -0
- wbportfolio/viewsets/configs/display/__init__.py +2 -3
- wbportfolio/viewsets/configs/display/fees.py +3 -3
- wbportfolio/viewsets/configs/endpoints/__init__.py +3 -4
- wbportfolio/viewsets/configs/endpoints/fees.py +2 -2
- wbportfolio/viewsets/configs/menu/__init__.py +0 -1
- wbportfolio/viewsets/configs/titles/__init__.py +2 -3
- wbportfolio/viewsets/configs/titles/fees.py +4 -8
- wbportfolio/viewsets/mixins.py +5 -1
- wbportfolio/viewsets/products.py +6 -6
- wbportfolio/viewsets/transactions/__init__.py +2 -7
- wbportfolio/viewsets/transactions/fees.py +22 -22
- wbportfolio/viewsets/transactions/trade_proposals.py +1 -0
- wbportfolio/viewsets/transactions/trades.py +2 -0
- {wbportfolio-1.52.0.dist-info → wbportfolio-1.52.2.dist-info}/METADATA +1 -1
- {wbportfolio-1.52.0.dist-info → wbportfolio-1.52.2.dist-info}/RECORD +75 -84
- wbportfolio/admin/transactions/transactions.py +0 -38
- wbportfolio/factories/transactions.py +0 -22
- wbportfolio/filters/transactions/transactions.py +0 -99
- wbportfolio/models/transactions/expiry.py +0 -7
- wbportfolio/serializers/transactions/expiry.py +0 -18
- wbportfolio/serializers/transactions/transactions.py +0 -85
- wbportfolio/viewsets/configs/display/transactions.py +0 -55
- wbportfolio/viewsets/configs/endpoints/transactions.py +0 -14
- wbportfolio/viewsets/configs/menu/transactions.py +0 -9
- wbportfolio/viewsets/configs/titles/transactions.py +0 -9
- wbportfolio/viewsets/transactions/transactions.py +0 -122
- {wbportfolio-1.52.0.dist-info → wbportfolio-1.52.2.dist-info}/WHEEL +0 -0
- {wbportfolio-1.52.0.dist-info → wbportfolio-1.52.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
from wbcore import serializers as wb_serializers
|
|
2
|
-
from wbcore.contrib.currency.serializers import CurrencyRepresentationSerializer
|
|
3
|
-
from wbfdm.serializers import InvestableUniverseRepresentationSerializer
|
|
4
|
-
|
|
5
|
-
from wbportfolio.models import Transaction
|
|
6
|
-
from wbportfolio.serializers.portfolios import PortfolioRepresentationSerializer
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class TransactionRepresentationSerializer(wb_serializers.RepresentationSerializer):
|
|
10
|
-
_detail = wb_serializers.HyperlinkField(reverse_name="wbportfolio:transaction-detail")
|
|
11
|
-
|
|
12
|
-
class Meta:
|
|
13
|
-
model = Transaction
|
|
14
|
-
fields = ("id", "transaction_date", "total_value", "_detail")
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
class TransactionModelSerializer(wb_serializers.ModelSerializer):
|
|
18
|
-
external_id = wb_serializers.CharField(required=False, read_only=True)
|
|
19
|
-
value_date = wb_serializers.DateField(required=False, read_only=True)
|
|
20
|
-
total_value_usd = wb_serializers.FloatField(default=0, read_only=True, label="Total Value ($)")
|
|
21
|
-
total_value_gross_usd = wb_serializers.FloatField(default=0, read_only=True, label="Total Value Gross ($)")
|
|
22
|
-
transaction_underlying_type = wb_serializers.CharField(read_only=True)
|
|
23
|
-
transaction_url_type = wb_serializers.SerializerMethodField()
|
|
24
|
-
_portfolio = PortfolioRepresentationSerializer(source="portfolio")
|
|
25
|
-
_underlying_instrument = InvestableUniverseRepresentationSerializer(source="underlying_instrument")
|
|
26
|
-
_currency = CurrencyRepresentationSerializer(source="currency")
|
|
27
|
-
|
|
28
|
-
total_value = wb_serializers.DecimalField(max_digits=14, decimal_places=2, read_only=True)
|
|
29
|
-
total_value_fx_portfolio = wb_serializers.DecimalField(max_digits=14, decimal_places=2, read_only=True)
|
|
30
|
-
total_value_gross = wb_serializers.DecimalField(max_digits=14, decimal_places=2, read_only=True)
|
|
31
|
-
total_value_gross_fx_portfolio = wb_serializers.DecimalField(max_digits=14, decimal_places=2, read_only=True)
|
|
32
|
-
|
|
33
|
-
def get_transaction_url_type(self, obj):
|
|
34
|
-
return obj.transaction_type.lower()
|
|
35
|
-
|
|
36
|
-
# def get_transaction_underlying_type(self, obj):
|
|
37
|
-
# try:
|
|
38
|
-
# casted_transaction = obj.get_casted_transaction()
|
|
39
|
-
# return casted_transaction.Type[casted_transaction.transaction_subtype].label
|
|
40
|
-
# except Exception as e:
|
|
41
|
-
# return ""
|
|
42
|
-
class Meta:
|
|
43
|
-
model = Transaction
|
|
44
|
-
decorators = {
|
|
45
|
-
"total_value": wb_serializers.decorator(
|
|
46
|
-
decorator_type="text", position="left", value="{{_currency.symbol}}"
|
|
47
|
-
),
|
|
48
|
-
"total_value_gross": wb_serializers.decorator(
|
|
49
|
-
decorator_type="text", position="left", value="{{_currency.symbol}}"
|
|
50
|
-
),
|
|
51
|
-
"total_value_usd": wb_serializers.decorator(decorator_type="text", position="left", value="{{$}}"),
|
|
52
|
-
"total_value_gross_usd": wb_serializers.decorator(decorator_type="text", position="left", value="{{$}}"),
|
|
53
|
-
"total_value_fx_portfolio": wb_serializers.decorator(
|
|
54
|
-
position="left", value="{{_portfolio.currency_symbol}}"
|
|
55
|
-
),
|
|
56
|
-
"total_value_gross_fx_portfolio": wb_serializers.decorator(
|
|
57
|
-
position="left", value="{{_portfolio.currency_symbol}}"
|
|
58
|
-
),
|
|
59
|
-
# "total_value_fx_portfolio": wb_serializers.decorator(decorator_type="text", position="left", value="{{_portfolio.currency_symbol}}}"),
|
|
60
|
-
# "total_value_gross_fx_portfolio": wb_serializers.decorator(decorator_type="text", position="left", value="{{_portfolio.currency_symbol}}"),
|
|
61
|
-
}
|
|
62
|
-
fields = (
|
|
63
|
-
"id",
|
|
64
|
-
"transaction_type",
|
|
65
|
-
"transaction_url_type",
|
|
66
|
-
"transaction_underlying_type",
|
|
67
|
-
"portfolio",
|
|
68
|
-
"_portfolio",
|
|
69
|
-
"underlying_instrument",
|
|
70
|
-
"_underlying_instrument",
|
|
71
|
-
"transaction_date",
|
|
72
|
-
"book_date",
|
|
73
|
-
"value_date",
|
|
74
|
-
"currency",
|
|
75
|
-
"_currency",
|
|
76
|
-
"currency_fx_rate",
|
|
77
|
-
"total_value",
|
|
78
|
-
"total_value_fx_portfolio",
|
|
79
|
-
"total_value_gross",
|
|
80
|
-
"total_value_gross_fx_portfolio",
|
|
81
|
-
"external_id",
|
|
82
|
-
"comment",
|
|
83
|
-
"total_value_usd",
|
|
84
|
-
"total_value_gross_usd",
|
|
85
|
-
)
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
from typing import Optional
|
|
2
|
-
|
|
3
|
-
from wbcore.metadata.configs import display as dp
|
|
4
|
-
from wbcore.metadata.configs.display.instance_display.shortcuts import (
|
|
5
|
-
Display,
|
|
6
|
-
create_simple_display,
|
|
7
|
-
)
|
|
8
|
-
from wbcore.metadata.configs.display.instance_display.utils import repeat_field
|
|
9
|
-
from wbcore.metadata.configs.display.view_config import DisplayViewConfig
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class TransactionDisplayConfig(DisplayViewConfig):
|
|
13
|
-
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
14
|
-
return dp.ListDisplay(
|
|
15
|
-
fields=[
|
|
16
|
-
dp.Field(key="transaction_type", label="Type"),
|
|
17
|
-
dp.Field(key="transaction_underlying_type", label="Underlying Type"),
|
|
18
|
-
dp.Field(key="transaction_date", label="Transaction Date"),
|
|
19
|
-
dp.Field(key="portfolio", label="Portfolio"),
|
|
20
|
-
dp.Field(key="underlying_instrument", label="Instrument"),
|
|
21
|
-
dp.Field(key="currency_fx_rate", label="FX Rate"),
|
|
22
|
-
dp.Field(key="currency", label="Currency"),
|
|
23
|
-
dp.Field(key="total_value", label="Total Value"),
|
|
24
|
-
dp.Field(key="total_value_fx_portfolio", label="Total Value (Portfolio)"),
|
|
25
|
-
dp.Field(key="total_value_usd", label="Total Value ($)"),
|
|
26
|
-
]
|
|
27
|
-
)
|
|
28
|
-
|
|
29
|
-
def get_instance_display(self) -> Display:
|
|
30
|
-
return create_simple_display(
|
|
31
|
-
[
|
|
32
|
-
["transaction_type", "underlying_instrument", "external_id"],
|
|
33
|
-
["transaction_date", "book_date", "value_date"],
|
|
34
|
-
["currency", "total_value", "total_value_fx_portfolio"],
|
|
35
|
-
[".", "total_value_gross", "total_value_gross_fx_portfolio"],
|
|
36
|
-
[repeat_field(3, "comment")],
|
|
37
|
-
]
|
|
38
|
-
)
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
class TransactionPortfolioDisplayConfig(TransactionDisplayConfig):
|
|
42
|
-
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
43
|
-
return dp.ListDisplay(
|
|
44
|
-
fields=[
|
|
45
|
-
dp.Field(key="transaction_type", label="Type"),
|
|
46
|
-
dp.Field(key="transaction_underlying_type", label="Underlying Type"),
|
|
47
|
-
dp.Field(key="transaction_date", label="Transaction Date"),
|
|
48
|
-
dp.Field(key="underlying_instrument", label="Instrument"),
|
|
49
|
-
dp.Field(key="currency_fx_rate", label="FX Rate"),
|
|
50
|
-
dp.Field(key="currency", label="Currency"),
|
|
51
|
-
dp.Field(key="total_value", label="Total Value"),
|
|
52
|
-
dp.Field(key="total_value_fx_portfolio", label="Total Value (Portfolio)"),
|
|
53
|
-
dp.Field(key="total_value_usd", label="Total Value ($)"),
|
|
54
|
-
]
|
|
55
|
-
)
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
from wbcore.metadata.configs.endpoints import EndpointViewConfig
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class TransactionEndpointConfig(EndpointViewConfig):
|
|
5
|
-
def get_endpoint(self, **kwargs):
|
|
6
|
-
return None
|
|
7
|
-
|
|
8
|
-
def get_instance_endpoint(self, **kwargs):
|
|
9
|
-
model = "{{transaction_url_type}}"
|
|
10
|
-
return f"{self.request.scheme}://{self.request.get_host()}/api/portfolio/{model}/"
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class TransactionPortfolioEndpointConfig(TransactionEndpointConfig):
|
|
14
|
-
pass
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
from wbcore.menus import ItemPermission, MenuItem
|
|
2
|
-
|
|
3
|
-
from wbportfolio.permissions import is_manager
|
|
4
|
-
|
|
5
|
-
TRANSACTION_MENUITEM = MenuItem(
|
|
6
|
-
label="Transactions",
|
|
7
|
-
endpoint="wbportfolio:transaction-list",
|
|
8
|
-
permission=ItemPermission(method=is_manager, permissions=["wbportfolio.view_transaction"]),
|
|
9
|
-
)
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
from wbcore.metadata.configs.titles import TitleViewConfig
|
|
2
|
-
|
|
3
|
-
from wbportfolio.models import Portfolio
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class TransactionPortfolioTitleConfig(TitleViewConfig):
|
|
7
|
-
def get_list_title(self):
|
|
8
|
-
portfolio = Portfolio.objects.get(id=self.view.kwargs["portfolio_id"])
|
|
9
|
-
return f"Transactions for Product {str(portfolio)}"
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
from decimal import Decimal
|
|
2
|
-
|
|
3
|
-
from django.db.models import (
|
|
4
|
-
Case,
|
|
5
|
-
DecimalField,
|
|
6
|
-
ExpressionWrapper,
|
|
7
|
-
F,
|
|
8
|
-
OuterRef,
|
|
9
|
-
Subquery,
|
|
10
|
-
Sum,
|
|
11
|
-
When,
|
|
12
|
-
)
|
|
13
|
-
from wbcore import viewsets
|
|
14
|
-
from wbcore.contrib.currency.models import CurrencyFXRates
|
|
15
|
-
from wbcore.permissions.permissions import InternalUserPermissionMixin
|
|
16
|
-
from wbcore.utils.strings import format_number
|
|
17
|
-
|
|
18
|
-
from wbportfolio.filters import TransactionFilterSet, TransactionPortfolioFilterSet
|
|
19
|
-
from wbportfolio.models import Fees, Trade, Transaction
|
|
20
|
-
from wbportfolio.serializers import (
|
|
21
|
-
TransactionModelSerializer,
|
|
22
|
-
TransactionRepresentationSerializer,
|
|
23
|
-
)
|
|
24
|
-
|
|
25
|
-
from ..configs import (
|
|
26
|
-
TransactionDisplayConfig,
|
|
27
|
-
TransactionEndpointConfig,
|
|
28
|
-
TransactionPortfolioDisplayConfig,
|
|
29
|
-
TransactionPortfolioEndpointConfig,
|
|
30
|
-
TransactionPortfolioTitleConfig,
|
|
31
|
-
)
|
|
32
|
-
from ..mixins import UserPortfolioRequestPermissionMixin
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
class TransactionRepresentationViewSet(InternalUserPermissionMixin, viewsets.RepresentationViewSet):
|
|
36
|
-
IDENTIFIER = "wbportfolio:transaction"
|
|
37
|
-
filterset_class = TransactionFilterSet
|
|
38
|
-
search_fields = ("portfolio__name", "underlying_instrument__name", "comment")
|
|
39
|
-
ordering_fields = (
|
|
40
|
-
"transaction_date",
|
|
41
|
-
"currency__key",
|
|
42
|
-
"underlying_instrument__name",
|
|
43
|
-
"portfolio__name",
|
|
44
|
-
"transaction_type",
|
|
45
|
-
"book_date",
|
|
46
|
-
"value_date",
|
|
47
|
-
"currency_fx_rate",
|
|
48
|
-
"total_value",
|
|
49
|
-
"total_value_fx_portfolio",
|
|
50
|
-
"total_value_gross",
|
|
51
|
-
"total_value_gross_fx_portfolio",
|
|
52
|
-
)
|
|
53
|
-
ordering = ["-transaction_date"]
|
|
54
|
-
|
|
55
|
-
serializer_class = TransactionRepresentationSerializer
|
|
56
|
-
queryset = Transaction.objects.all()
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
class TransactionModelViewSet(UserPortfolioRequestPermissionMixin, InternalUserPermissionMixin, viewsets.ModelViewSet):
|
|
60
|
-
IDENTIFIER = "wbportfolio:transaction"
|
|
61
|
-
|
|
62
|
-
serializer_class = TransactionModelSerializer
|
|
63
|
-
|
|
64
|
-
filterset_class = TransactionFilterSet
|
|
65
|
-
ordering_fields = TransactionRepresentationViewSet.ordering_fields
|
|
66
|
-
search_fields = TransactionRepresentationViewSet.search_fields
|
|
67
|
-
ordering = TransactionRepresentationViewSet.ordering
|
|
68
|
-
|
|
69
|
-
queryset = Transaction.objects.all()
|
|
70
|
-
display_config_class = TransactionDisplayConfig
|
|
71
|
-
endpoint_config_class = TransactionEndpointConfig
|
|
72
|
-
|
|
73
|
-
def get_queryset(self):
|
|
74
|
-
return (
|
|
75
|
-
super()
|
|
76
|
-
.get_queryset()
|
|
77
|
-
.annotate(
|
|
78
|
-
fx_rate=CurrencyFXRates.get_fx_rates_subquery(
|
|
79
|
-
"transaction_date", currency="currency", lookup_expr="exact"
|
|
80
|
-
),
|
|
81
|
-
total_value_usd=ExpressionWrapper(F("total_value"), output_field=DecimalField()),
|
|
82
|
-
total_value_gross_usd=ExpressionWrapper(F("total_value_gross"), output_field=DecimalField()),
|
|
83
|
-
transaction_underlying_type_trade=Subquery(
|
|
84
|
-
Trade.objects.filter(id=OuterRef("pk")).values("transaction_subtype")[:1]
|
|
85
|
-
),
|
|
86
|
-
transaction_underlying_type_fees=Subquery(
|
|
87
|
-
Fees.objects.filter(id=OuterRef("pk")).values("transaction_subtype")[:1]
|
|
88
|
-
),
|
|
89
|
-
transaction_underlying_type=Case(
|
|
90
|
-
When(
|
|
91
|
-
transaction_underlying_type_trade__isnull=False,
|
|
92
|
-
then=F("transaction_underlying_type_trade"),
|
|
93
|
-
),
|
|
94
|
-
When(transaction_underlying_type_fees__isnull=False, then=F("transaction_underlying_type_fees")),
|
|
95
|
-
),
|
|
96
|
-
)
|
|
97
|
-
.select_related("underlying_instrument")
|
|
98
|
-
.select_related("portfolio")
|
|
99
|
-
.select_related("currency")
|
|
100
|
-
)
|
|
101
|
-
|
|
102
|
-
def get_aggregates(self, queryset, paginated_queryset):
|
|
103
|
-
return {
|
|
104
|
-
"total_value_usd": {
|
|
105
|
-
"Σ": format_number(queryset.aggregate(s=Sum("total_value_usd"))["s"] or Decimal(0)),
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
class TransactionPortfolioModelViewSet(TransactionModelViewSet):
|
|
111
|
-
IDENTIFIER = "wbportfolio:transaction"
|
|
112
|
-
|
|
113
|
-
filterset_class = TransactionPortfolioFilterSet
|
|
114
|
-
display_config_class = TransactionPortfolioDisplayConfig
|
|
115
|
-
endpoint_config_class = TransactionPortfolioEndpointConfig
|
|
116
|
-
title_config_class = TransactionPortfolioTitleConfig
|
|
117
|
-
|
|
118
|
-
def get_queryset(self):
|
|
119
|
-
qs = super().get_queryset().filter(portfolio=self.portfolio)
|
|
120
|
-
if self.is_portfolio_manager:
|
|
121
|
-
return qs
|
|
122
|
-
return qs.exclude(transaction_type=Transaction.Type.FEES)
|
|
File without changes
|
|
File without changes
|