wbportfolio 1.45.0__py2.py3-none-any.whl → 1.45.1__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/import_export/parsers/vontobel/valuation_api.py +11 -8
- wbportfolio/models/graphs/portfolio.py +43 -26
- wbportfolio/risk_management/backends/ucits_portfolio.py +11 -5
- wbportfolio/risk_management/tests/test_ucits_portfolio.py +1 -1
- wbportfolio/tests/models/test_portfolios.py +25 -0
- wbportfolio/viewsets/configs/endpoints/assets.py +12 -0
- wbportfolio/viewsets/portfolios.py +1 -1
- {wbportfolio-1.45.0.dist-info → wbportfolio-1.45.1.dist-info}/METADATA +1 -1
- {wbportfolio-1.45.0.dist-info → wbportfolio-1.45.1.dist-info}/RECORD +11 -11
- {wbportfolio-1.45.0.dist-info → wbportfolio-1.45.1.dist-info}/WHEEL +0 -0
- {wbportfolio-1.45.0.dist-info → wbportfolio-1.45.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -2,6 +2,8 @@ import json
|
|
|
2
2
|
from contextlib import suppress
|
|
3
3
|
from datetime import datetime
|
|
4
4
|
|
|
5
|
+
from wbportfolio.models import Product
|
|
6
|
+
|
|
5
7
|
|
|
6
8
|
def parse(import_source):
|
|
7
9
|
data = []
|
|
@@ -9,12 +11,13 @@ def parse(import_source):
|
|
|
9
11
|
series_data = json.loads(import_source.file.read())["payload"]["series"]
|
|
10
12
|
for series in series_data:
|
|
11
13
|
isin = series["item"]["priceIdentifier"]
|
|
12
|
-
for
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
14
|
+
if Product.objects.filter(isin=isin).exists(): # ensure the timeseries contain data for products we handle
|
|
15
|
+
for point in series["points"]:
|
|
16
|
+
data.append(
|
|
17
|
+
{
|
|
18
|
+
"instrument": {"isin": isin},
|
|
19
|
+
"date": datetime.fromtimestamp(int(point["timestamp"]) / 1000).strftime("%Y-%m-%d"),
|
|
20
|
+
"net_value": point["close"],
|
|
21
|
+
}
|
|
22
|
+
)
|
|
20
23
|
return {"data": data}
|
|
@@ -15,6 +15,7 @@ from .utils import networkx_graph_to_plotly
|
|
|
15
15
|
class PortfolioGraph:
|
|
16
16
|
def __init__(self, portfolio: Portfolio, val_date: date, **graph_kwargs):
|
|
17
17
|
self.graph = pydot.Dot("Portfolio Tree", strict=True, **graph_kwargs)
|
|
18
|
+
self.base_portfolio = portfolio
|
|
18
19
|
self.discovered_portfolios = set()
|
|
19
20
|
self.val_date = val_date
|
|
20
21
|
self._extend_portfolio_graph(portfolio)
|
|
@@ -31,13 +32,17 @@ class PortfolioGraph:
|
|
|
31
32
|
pydot.Node(
|
|
32
33
|
str(parent_portfolio.id),
|
|
33
34
|
label=self._convert_to_multilines(str(parent_portfolio)),
|
|
34
|
-
|
|
35
|
-
orientation="45",
|
|
36
|
-
style="solid",
|
|
35
|
+
**self._get_node_kwargs(parent_portfolio),
|
|
37
36
|
)
|
|
38
37
|
)
|
|
38
|
+
self.graph.del_edge((str(portfolio.id), str(parent_portfolio.id)))
|
|
39
39
|
self.graph.add_edge(
|
|
40
|
-
pydot.Edge(
|
|
40
|
+
pydot.Edge(
|
|
41
|
+
str(portfolio.id),
|
|
42
|
+
str(parent_portfolio.id),
|
|
43
|
+
label=f"Invest in ({weighting:.2%})",
|
|
44
|
+
style="dashed",
|
|
45
|
+
)
|
|
41
46
|
)
|
|
42
47
|
# composition_edges.append((str(portfolio.id), str(parent_portfolio.id)))
|
|
43
48
|
self._extend_parent_portfolios_to_graph(parent_portfolio)
|
|
@@ -49,28 +54,42 @@ class PortfolioGraph:
|
|
|
49
54
|
pydot.Node(
|
|
50
55
|
str(child_portfolio.id),
|
|
51
56
|
label=self._convert_to_multilines(str(child_portfolio)),
|
|
52
|
-
|
|
53
|
-
orientation="45",
|
|
54
|
-
style="solid",
|
|
57
|
+
**self._get_node_kwargs(child_portfolio),
|
|
55
58
|
)
|
|
56
59
|
)
|
|
57
|
-
#
|
|
60
|
+
# we add this edge only if the opposite relationship is not already added
|
|
61
|
+
graph_edge = pydot.Edge(str(child_portfolio.id), str(portfolio.id), label="implements", style="dashed")
|
|
62
|
+
if (graph_edge.get_source(), graph_edge.get_destination()) not in self.graph.obj_dict["edges"]:
|
|
63
|
+
self.graph.add_edge(graph_edge)
|
|
58
64
|
# composition_edges.append((str(child_portfolio.id), str(portfolio.id)))
|
|
59
65
|
self._extend_child_portfolios_to_graph(child_portfolio)
|
|
60
66
|
|
|
67
|
+
def _get_node_kwargs(self, portfolio):
|
|
68
|
+
node_args = {
|
|
69
|
+
"shape": "circle",
|
|
70
|
+
"orientation": "45",
|
|
71
|
+
}
|
|
72
|
+
if portfolio == self.base_portfolio:
|
|
73
|
+
node_args.update({"style": "filled", "fillcolor": "lightgrey"})
|
|
74
|
+
else:
|
|
75
|
+
node_args.update(
|
|
76
|
+
{
|
|
77
|
+
"style": "solid",
|
|
78
|
+
}
|
|
79
|
+
)
|
|
80
|
+
return node_args
|
|
81
|
+
|
|
61
82
|
def _extend_portfolio_graph(self, portfolio):
|
|
62
83
|
self.graph.add_node(
|
|
63
84
|
pydot.Node(
|
|
64
85
|
str(portfolio.id),
|
|
65
86
|
label=self._convert_to_multilines(str(portfolio)),
|
|
66
|
-
|
|
67
|
-
orientation="45",
|
|
68
|
-
style="solid",
|
|
87
|
+
**self._get_node_kwargs(portfolio),
|
|
69
88
|
)
|
|
70
89
|
)
|
|
71
90
|
|
|
72
|
-
self._extend_parent_portfolios_to_graph(portfolio)
|
|
73
91
|
self._extend_child_portfolios_to_graph(portfolio)
|
|
92
|
+
self._extend_parent_portfolios_to_graph(portfolio)
|
|
74
93
|
|
|
75
94
|
# composition_edges = []
|
|
76
95
|
# if composition_edges:
|
|
@@ -87,37 +106,35 @@ class PortfolioGraph:
|
|
|
87
106
|
pydot.Node(
|
|
88
107
|
str(rel.portfolio.id),
|
|
89
108
|
label=self._convert_to_multilines(str(rel.portfolio)),
|
|
90
|
-
|
|
91
|
-
orientation="45",
|
|
92
|
-
style="solid",
|
|
109
|
+
**self._get_node_kwargs(rel.portfolio),
|
|
93
110
|
)
|
|
94
111
|
)
|
|
95
112
|
self.graph.add_node(
|
|
96
113
|
pydot.Node(
|
|
97
114
|
str(rel.dependency_portfolio.id),
|
|
98
115
|
label=self._convert_to_multilines(str(rel.dependency_portfolio)),
|
|
99
|
-
|
|
100
|
-
orientation="45",
|
|
101
|
-
style="solid",
|
|
116
|
+
**self._get_node_kwargs(rel.dependency_portfolio),
|
|
102
117
|
)
|
|
103
118
|
)
|
|
104
119
|
label = PortfolioPortfolioThroughModel.Type[rel.type].label
|
|
105
120
|
if rel.dependency_portfolio.is_composition:
|
|
106
121
|
label += " (Composition)"
|
|
107
|
-
|
|
108
|
-
pydot.Edge(
|
|
109
|
-
str(rel.dependency_portfolio.id),
|
|
110
|
-
str(rel.portfolio.id),
|
|
111
|
-
label=label,
|
|
112
|
-
style="bold",
|
|
113
|
-
)
|
|
114
|
-
)
|
|
122
|
+
|
|
115
123
|
if rel.portfolio.is_lookthrough and rel.type == PortfolioPortfolioThroughModel.Type.PRIMARY:
|
|
116
124
|
self.graph.add_edge(
|
|
117
125
|
pydot.Edge(
|
|
118
126
|
str(rel.portfolio.id), str(rel.dependency_portfolio.id), label="Look-Through", style="dotted"
|
|
119
127
|
)
|
|
120
128
|
)
|
|
129
|
+
else:
|
|
130
|
+
self.graph.add_edge(
|
|
131
|
+
pydot.Edge(
|
|
132
|
+
str(rel.portfolio.id),
|
|
133
|
+
str(rel.dependency_portfolio.id),
|
|
134
|
+
label=label,
|
|
135
|
+
style="bold",
|
|
136
|
+
)
|
|
137
|
+
)
|
|
121
138
|
if rel.dependency_portfolio not in self.discovered_portfolios:
|
|
122
139
|
self._extend_portfolio_graph(rel.dependency_portfolio)
|
|
123
140
|
if rel.portfolio not in self.discovered_portfolios:
|
|
@@ -46,19 +46,25 @@ class RuleBackend(ActivePortfolioRelationshipMixin, backend.AbstractRuleBackend)
|
|
|
46
46
|
def _process_dto(self, portfolio: PortfolioDTO, **kwargs) -> Generator[backend.IncidentResult, None, None]:
|
|
47
47
|
if not (df := self._filter_df(pd.DataFrame(portfolio.to_df()).astype({"weighting": float}))).empty:
|
|
48
48
|
df = df[["underlying_instrument", "weighting"]].groupby("underlying_instrument").sum()
|
|
49
|
-
total_weight_threshold_1_2 = df
|
|
49
|
+
total_weight_threshold_1_2 = df["weighting"].sum()
|
|
50
50
|
highest_incident_type = RiskIncidentType.objects.order_by("-severity_order").first()
|
|
51
|
+
|
|
51
52
|
for id, row in df.to_dict("index").items():
|
|
52
53
|
if (row["weighting"] > self.threshold_2) or (total_weight_threshold_1_2 > self.threshold_3):
|
|
53
54
|
instrument = Instrument.objects.get(id=id)
|
|
55
|
+
breached_value = f"""
|
|
56
|
+
Sum >= {self.threshold_1:.2%}: {total_weight_threshold_1_2:+.2%}
|
|
57
|
+
"""
|
|
58
|
+
if row["weighting"] > self.threshold_2:
|
|
59
|
+
breached_value += f"<br>Instrument >= {self.threshold_2:.2%}: {instrument.name_repr}"
|
|
54
60
|
yield backend.IncidentResult(
|
|
55
61
|
breached_object=instrument,
|
|
56
62
|
breached_object_repr=str(instrument),
|
|
57
|
-
breached_value=
|
|
63
|
+
breached_value=breached_value,
|
|
58
64
|
report_details={
|
|
59
|
-
"Breach Thresholds": f"{self.threshold_1}|{self.threshold_2}|{self.threshold_3}",
|
|
60
|
-
"Weighting": f"{row['weighting']
|
|
61
|
-
f"Sum of positions
|
|
65
|
+
"Breach Thresholds": f"{self.threshold_1:.2%}|{self.threshold_2:.2%}|{self.threshold_3:.2%}",
|
|
66
|
+
"Weighting": f"{row['weighting']:+.2%}",
|
|
67
|
+
f"Sum of positions > {self.threshold_1:.2%}": f"{total_weight_threshold_1_2:+.2%}",
|
|
62
68
|
},
|
|
63
69
|
severity=highest_incident_type,
|
|
64
70
|
)
|
|
@@ -19,7 +19,7 @@ class TestUcitsRuleModel(PortfolioTestMixin):
|
|
|
19
19
|
# Check No single asset can represent more than 10% of the fund's assets;
|
|
20
20
|
asset_position_factory.create(date=weekday, weighting=0.05, portfolio=portfolio)
|
|
21
21
|
asset_position_factory.create(date=weekday, weighting=0.05, portfolio=portfolio)
|
|
22
|
-
a3 = asset_position_factory.create(date=weekday, weighting=0.
|
|
22
|
+
a3 = asset_position_factory.create(date=weekday, weighting=0.15, portfolio=portfolio)
|
|
23
23
|
|
|
24
24
|
res = list(ucits_backend.check_rule())
|
|
25
25
|
assert len(res) == 1
|
|
@@ -1114,3 +1114,28 @@ class TestPortfolioModel(PortfolioTestMixin):
|
|
|
1114
1114
|
undependant_portfolio = portfolio_factory.create(name="undependant portfolio", id=4)
|
|
1115
1115
|
res = list(Portfolio.objects.all().to_dependency_iterator(weekday))
|
|
1116
1116
|
assert res == [index_portfolio, dependency_portfolio, dependant_portfolio, undependant_portfolio]
|
|
1117
|
+
|
|
1118
|
+
def test_get_returns(self, instrument_factory, instrument_price_factory, portfolio):
|
|
1119
|
+
v1 = date(2025, 1, 1)
|
|
1120
|
+
v2 = date(2025, 1, 2)
|
|
1121
|
+
v3 = date(2025, 1, 3)
|
|
1122
|
+
|
|
1123
|
+
i1 = instrument_factory.create()
|
|
1124
|
+
i2 = instrument_factory.create()
|
|
1125
|
+
|
|
1126
|
+
i11 = instrument_price_factory.create(date=v1, instrument=i1)
|
|
1127
|
+
i12 = instrument_price_factory.create(date=v2, instrument=i1)
|
|
1128
|
+
i13 = instrument_price_factory.create(date=v3, instrument=i1)
|
|
1129
|
+
i11.refresh_from_db()
|
|
1130
|
+
i12.refresh_from_db()
|
|
1131
|
+
i13.refresh_from_db()
|
|
1132
|
+
returns, _ = portfolio.get_returns([i1.id, i2.id], from_date=v1, to_date=v3)
|
|
1133
|
+
|
|
1134
|
+
expected_returns = pd.DataFrame(
|
|
1135
|
+
[[i12.net_value / i11.net_value - 1], [i13.net_value / i12.net_value - 1]],
|
|
1136
|
+
index=[v2, v3],
|
|
1137
|
+
columns=[i1.id],
|
|
1138
|
+
dtype="float64",
|
|
1139
|
+
)
|
|
1140
|
+
expected_returns.index = pd.to_datetime(expected_returns.index)
|
|
1141
|
+
pd.testing.assert_frame_equal(returns, expected_returns, check_names=False, check_freq=False, atol=1e-6)
|
|
@@ -56,6 +56,8 @@ class AssetPositionProductGroupEndpointConfig(AssetPositionEndpointConfig):
|
|
|
56
56
|
|
|
57
57
|
|
|
58
58
|
class CashPositionPortfolioEndpointConfig(AssetPositionEndpointConfig):
|
|
59
|
+
PK_FIELD = "portfolio"
|
|
60
|
+
|
|
59
61
|
def get_list_endpoint(self, **kwargs):
|
|
60
62
|
return reverse(
|
|
61
63
|
"wbportfolio:productcashposition-list",
|
|
@@ -63,6 +65,16 @@ class CashPositionPortfolioEndpointConfig(AssetPositionEndpointConfig):
|
|
|
63
65
|
request=self.request,
|
|
64
66
|
)
|
|
65
67
|
|
|
68
|
+
def get_instance_endpoint(self, **kwargs):
|
|
69
|
+
return reverse(
|
|
70
|
+
"wbportfolio:portfolio-list",
|
|
71
|
+
args=[],
|
|
72
|
+
request=self.request,
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
def get_update_endpoint(self, **kwargs):
|
|
76
|
+
return None
|
|
77
|
+
|
|
66
78
|
|
|
67
79
|
class ContributorPortfolioChartEndpointConfig(AssetPositionEndpointConfig):
|
|
68
80
|
def get_list_endpoint(self, **kwargs):
|
|
@@ -181,7 +181,7 @@ class PortfolioTreeGraphChartViewSet(UserPortfolioRequestPermissionMixin, viewse
|
|
|
181
181
|
return parse_date(self.request.GET["date"])
|
|
182
182
|
|
|
183
183
|
def get_html(self, queryset) -> str:
|
|
184
|
-
portfolio_graph = PortfolioGraph(self.portfolio, self.val_date)
|
|
184
|
+
portfolio_graph = PortfolioGraph(self.portfolio, self.val_date, rankdir="LR", size="20,11")
|
|
185
185
|
return portfolio_graph.to_svg()
|
|
186
186
|
|
|
187
187
|
|
|
@@ -187,7 +187,7 @@ wbportfolio/import_export/parsers/vontobel/performance_fees.py,sha256=DlpP2Skih2
|
|
|
187
187
|
wbportfolio/import_export/parsers/vontobel/trade.py,sha256=Eu5qR-cjnkA_jwtrJ78xoi9ealysjHDLXIKSandqDe0,1570
|
|
188
188
|
wbportfolio/import_export/parsers/vontobel/utils.py,sha256=toleo4gRb4YFtiD8m2d7z1GGGdG-O3mpTMjOO9R_E1Q,516
|
|
189
189
|
wbportfolio/import_export/parsers/vontobel/valuation.py,sha256=iav8_xYpTJchmTa7KOPmFr1gi9xxLwq3e-VcZ9MDiRk,1220
|
|
190
|
-
wbportfolio/import_export/parsers/vontobel/valuation_api.py,sha256=
|
|
190
|
+
wbportfolio/import_export/parsers/vontobel/valuation_api.py,sha256=WLkZ5z-WqhFraNorWlOhIpSx1pQ2fnjdsLHwSTA7O2o,882
|
|
191
191
|
wbportfolio/import_export/resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
192
192
|
wbportfolio/import_export/resources/assets.py,sha256=zjgHlQWpud41jHrKdRyqGUt1KUJQm9Z7pt0uVh4qBWQ,2234
|
|
193
193
|
wbportfolio/import_export/resources/trades.py,sha256=5HC0YrE1fnc_dOMfkOEj7vsICv1JN_OEZiGryg2GboY,1125
|
|
@@ -256,7 +256,7 @@ wbportfolio/models/registers.py,sha256=qA6T33t4gxFYnabQFBMd90WGIr6wxxirDLKDFqjOf
|
|
|
256
256
|
wbportfolio/models/roles.py,sha256=34BwZleaPMHnUqDK1nHett45xaNNsUqSHY44844itW8,7387
|
|
257
257
|
wbportfolio/models/utils.py,sha256=iBdMjRCvr6aOL0nLgfSCWUKe0h39h3IGmUbYo6l9t6w,394
|
|
258
258
|
wbportfolio/models/graphs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
259
|
-
wbportfolio/models/graphs/portfolio.py,sha256=
|
|
259
|
+
wbportfolio/models/graphs/portfolio.py,sha256=NwkehWvTcyTYrKO5ku3eNNaYLuBwuLdSbTEuugGuSIU,6541
|
|
260
260
|
wbportfolio/models/graphs/utils.py,sha256=1AMpEE9mDuUZ82XgN2irxjCW1-LmziROhKevEBo0mJE,2347
|
|
261
261
|
wbportfolio/models/llm/wbcrm/analyze_relationship.py,sha256=_y2Myc-M2hXQDkRGXvzsM0ZNC31dmxSHHz5BKMtymww,2106
|
|
262
262
|
wbportfolio/models/mixins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -303,7 +303,7 @@ wbportfolio/risk_management/backends/mixins.py,sha256=anuOlop9gc9X8tywx7_wbH7fAJ
|
|
|
303
303
|
wbportfolio/risk_management/backends/product_integrity.py,sha256=3BbQBYYzLdj2iuQb9QOIgPjWMz1FaPkvEJoNgxWVfz0,4598
|
|
304
304
|
wbportfolio/risk_management/backends/stop_loss_instrument.py,sha256=qIzeV26TRdbgG8-Nsh5O0NPMrPmIXeaRdPR-EF_uaLo,1128
|
|
305
305
|
wbportfolio/risk_management/backends/stop_loss_portfolio.py,sha256=yiDa3FkZKdrmHSf8p1XmT8RhJW6KyiMuypYpY39SiO8,1674
|
|
306
|
-
wbportfolio/risk_management/backends/ucits_portfolio.py,sha256=
|
|
306
|
+
wbportfolio/risk_management/backends/ucits_portfolio.py,sha256=WAw2emAcwDBtYuYoieW0KqGST_CJ27UQuKY0B6jav_Q,3477
|
|
307
307
|
wbportfolio/risk_management/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
308
308
|
wbportfolio/risk_management/tests/conftest.py,sha256=ChVocx8SDmh13ixkRmnKe_MMudQAX0495o7nG4NDlsg,440
|
|
309
309
|
wbportfolio/risk_management/tests/test_accounts.py,sha256=q9Z3hDw0Yw86VealdmUfiJBkzRcqDwfybteGxS0hAJA,3990
|
|
@@ -314,7 +314,7 @@ wbportfolio/risk_management/tests/test_liquidity_risk.py,sha256=UtzBrW7LeY0Z0ARX
|
|
|
314
314
|
wbportfolio/risk_management/tests/test_product_integrity.py,sha256=wqJ4b5DO2BrEVQF4eVX2B9AvfrRMAyC_lppGrgKc_ug,1959
|
|
315
315
|
wbportfolio/risk_management/tests/test_stop_loss_instrument.py,sha256=ZueuA9qQOv6JdKuRiPLGV3auOLRnoUCZzfqcQzGJGig,4197
|
|
316
316
|
wbportfolio/risk_management/tests/test_stop_loss_portfolio.py,sha256=bFQqIUs1FZVn1SwiNkzt7hVrvT-qs3EcxOfI20xAjOM,4595
|
|
317
|
-
wbportfolio/risk_management/tests/test_ucits_portfolio.py,sha256=
|
|
317
|
+
wbportfolio/risk_management/tests/test_ucits_portfolio.py,sha256=UcZLhatl8iU9AhNNYv6OBs_cjILZKaws2nvUen6orkc,1807
|
|
318
318
|
wbportfolio/serializers/__init__.py,sha256=w1nPxkapcnGngYwiU7BGSLfyhJ67_PQWVjuya7YSxX0,1795
|
|
319
319
|
wbportfolio/serializers/adjustments.py,sha256=0yTPgDjGRyzSa-ecCklENKtLJXZhq1dryMI3nTRsQRo,783
|
|
320
320
|
wbportfolio/serializers/assets.py,sha256=EHTPwicRbdklLHvKS0_Y7pNtw7YC5iW_AuecPoTfJnc,6477
|
|
@@ -369,7 +369,7 @@ wbportfolio/tests/models/test_merge.py,sha256=sdsjiZsmR6vsUKwTa5kkvL6QTeAZqtd_EP
|
|
|
369
369
|
wbportfolio/tests/models/test_portfolio_cash_flow.py,sha256=X8dsXexsb1b0lBiuGzu40ps_Az_1UmmKT0eo1vbXH94,5792
|
|
370
370
|
wbportfolio/tests/models/test_portfolio_cash_targets.py,sha256=q8QWAwt-kKRkLC0E05GyRhF_TTQXIi8bdHjXVU0fCV0,965
|
|
371
371
|
wbportfolio/tests/models/test_portfolio_swing_pricings.py,sha256=kr2AOcQkyg2pX3ULjU-o9ye-NVpjMrrfoe-DVbYCbjs,1656
|
|
372
|
-
wbportfolio/tests/models/test_portfolios.py,sha256=
|
|
372
|
+
wbportfolio/tests/models/test_portfolios.py,sha256=YF1SRS-REJFQhbtxs1LfIUs91jmHpI7pXBE70pW4W7E,51735
|
|
373
373
|
wbportfolio/tests/models/test_product_groups.py,sha256=AcdxhurV-n_bBuUsfD1GqVtwLFcs7VI2CRrwzsIUWbU,3337
|
|
374
374
|
wbportfolio/tests/models/test_products.py,sha256=5YYmQreFnaKLbWmrSib103wgLalqn8u01Fnh3A0XMz8,8217
|
|
375
375
|
wbportfolio/tests/models/test_roles.py,sha256=4Cn7WyrA2ztJNeWLk5cy9kYo5XLWMbFSvo1O-9JYxeA,3323
|
|
@@ -403,7 +403,7 @@ wbportfolio/viewsets/portfolio_cash_flow.py,sha256=jkBfdZRQ3KsxGMJpltRjmdrZ2qEFJ
|
|
|
403
403
|
wbportfolio/viewsets/portfolio_cash_targets.py,sha256=CvHlrDE8qnnnfRpTYnFu-Uu15MDbF5d5gTmEKth2S24,322
|
|
404
404
|
wbportfolio/viewsets/portfolio_relationship.py,sha256=RGyvxd8NfFEs8YdqEvVD3VbrISvAO5UtCTlocSIuWQw,2109
|
|
405
405
|
wbportfolio/viewsets/portfolio_swing_pricing.py,sha256=-57l3WLQZRslIV67OT0ucHE5JXTtTtLvd3t7MppdVn8,357
|
|
406
|
-
wbportfolio/viewsets/portfolios.py,sha256=
|
|
406
|
+
wbportfolio/viewsets/portfolios.py,sha256=i4swoycpL3utZdTCgVAYSI2KE6bA2JyTetRh6taYUAc,13042
|
|
407
407
|
wbportfolio/viewsets/positions.py,sha256=MDf_0x9La2qE6qjaIqBtfV5VC0RfJ1chZIim45Emk10,13198
|
|
408
408
|
wbportfolio/viewsets/product_groups.py,sha256=YvmuXPPy98K1J_rz6YPsx9gNK-tCS2P-wc1uRYgfyo0,2399
|
|
409
409
|
wbportfolio/viewsets/product_performance.py,sha256=dRfRgifjGS1RgZSu9uJRM0SmB7eLnNUkPuqARMO4gyo,28371
|
|
@@ -452,7 +452,7 @@ wbportfolio/viewsets/configs/display/trades.py,sha256=e61wLzTEDwewgctpztDa4Exvie
|
|
|
452
452
|
wbportfolio/viewsets/configs/display/transactions.py,sha256=DOM3eV1DxBwX6Iiw3C2sJamWh6A_3ZSYC9447Jc3Wmo,2586
|
|
453
453
|
wbportfolio/viewsets/configs/endpoints/__init__.py,sha256=E13AYY3CIW4CZtmqwBVMPDYA5zNyKJeRZtiXKtad68Y,2871
|
|
454
454
|
wbportfolio/viewsets/configs/endpoints/adjustments.py,sha256=9CcnfNuFcxsZ8YvfUitSeyCvpLxY-jU-gIw3GG0mIp4,697
|
|
455
|
-
wbportfolio/viewsets/configs/endpoints/assets.py,sha256=
|
|
455
|
+
wbportfolio/viewsets/configs/endpoints/assets.py,sha256=fe_D-x3z4xzzAJ7ktvvvwGuoX51l8iTPdDNugagxHYc,3891
|
|
456
456
|
wbportfolio/viewsets/configs/endpoints/claim.py,sha256=H7oUbatjyq6HiSrMzgSMV8KqzH_PNQ5XcwHuL1yX1aA,3650
|
|
457
457
|
wbportfolio/viewsets/configs/endpoints/custodians.py,sha256=Ve7TxfvFnmvm9x0cx6taO502EVWJb23fdVT9yX3ME5o,194
|
|
458
458
|
wbportfolio/viewsets/configs/endpoints/esg.py,sha256=9wGxw1fW8UQJtGd-cT9XWl5gfKN68SSft3wqmkUK4MQ,467
|
|
@@ -515,7 +515,7 @@ wbportfolio/viewsets/transactions/rebalancing.py,sha256=6rIrdK0rtKL1afJ-tYfAGdQV
|
|
|
515
515
|
wbportfolio/viewsets/transactions/trade_proposals.py,sha256=fYTvvRk7k5xsBzbIgJvU4I4OrllF0VkhlrekD4GVgDk,4296
|
|
516
516
|
wbportfolio/viewsets/transactions/trades.py,sha256=6iTIM5g7TUlRtiCjIG4EdYvyfaoB6K3UC2WRX9BD9Jg,15850
|
|
517
517
|
wbportfolio/viewsets/transactions/transactions.py,sha256=ixDp-nsNA8t_A06rBCT19hOMJHy0iRmdz1XKdV1OwAs,4450
|
|
518
|
-
wbportfolio-1.45.
|
|
519
|
-
wbportfolio-1.45.
|
|
520
|
-
wbportfolio-1.45.
|
|
521
|
-
wbportfolio-1.45.
|
|
518
|
+
wbportfolio-1.45.1.dist-info/METADATA,sha256=A-LmtAIGxt9NHM9lduI0ajteCd-0BbzXyDcQu35Jpik,734
|
|
519
|
+
wbportfolio-1.45.1.dist-info/WHEEL,sha256=tkmg4JIqwd9H8mL30xA7crRmoStyCtGp0VWshokd1Jc,105
|
|
520
|
+
wbportfolio-1.45.1.dist-info/licenses/LICENSE,sha256=jvfVH0SY8_YMHlsJHKe_OajiscQDz4lpTlqT6x24sVw,172
|
|
521
|
+
wbportfolio-1.45.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|