wbportfolio 1.44.4__py2.py3-none-any.whl → 1.45.0__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/asset.py +2 -1
- wbportfolio/admin/custodians.py +1 -0
- wbportfolio/admin/indexes.py +15 -0
- wbportfolio/admin/portfolio.py +12 -7
- wbportfolio/admin/portfolio_relationships.py +1 -0
- wbportfolio/admin/product_groups.py +2 -0
- wbportfolio/admin/products.py +2 -1
- wbportfolio/admin/reconciliations.py +1 -0
- wbportfolio/admin/registers.py +1 -0
- wbportfolio/admin/roles.py +1 -0
- wbportfolio/admin/transactions/__init__.py +1 -0
- wbportfolio/admin/transactions/claim.py +1 -0
- wbportfolio/admin/transactions/dividends.py +1 -0
- wbportfolio/admin/transactions/fees.py +1 -0
- wbportfolio/admin/transactions/rebalancing.py +26 -0
- wbportfolio/admin/transactions/trades.py +4 -3
- wbportfolio/admin/transactions/transactions.py +1 -0
- wbportfolio/analysis/claims.py +2 -1
- wbportfolio/contrib/company_portfolio/models.py +3 -6
- wbportfolio/contrib/company_portfolio/tests/conftest.py +0 -12
- wbportfolio/contrib/company_portfolio/tests/test_models.py +1 -0
- wbportfolio/defaults/fees/default.py +1 -0
- wbportfolio/factories/__init__.py +1 -7
- wbportfolio/factories/adjustments.py +1 -0
- wbportfolio/factories/assets.py +13 -7
- wbportfolio/factories/claim.py +1 -0
- wbportfolio/factories/custodians.py +1 -0
- wbportfolio/factories/dividends.py +1 -0
- wbportfolio/factories/fees.py +1 -0
- wbportfolio/factories/indexes.py +1 -0
- wbportfolio/factories/portfolio_cash_flow.py +1 -0
- wbportfolio/factories/portfolio_cash_targets.py +1 -0
- wbportfolio/factories/portfolio_swing_pricings.py +1 -0
- wbportfolio/factories/portfolios.py +3 -0
- wbportfolio/factories/product_groups.py +1 -0
- wbportfolio/factories/products.py +1 -0
- wbportfolio/factories/rebalancing.py +23 -0
- wbportfolio/factories/reconciliations.py +1 -0
- wbportfolio/factories/roles.py +1 -0
- wbportfolio/factories/trades.py +1 -0
- wbportfolio/factories/transactions.py +1 -0
- wbportfolio/fdm/tasks.py +1 -0
- wbportfolio/filters/__init__.py +1 -1
- wbportfolio/filters/assets.py +8 -9
- wbportfolio/filters/assets_and_net_new_money_progression.py +1 -0
- wbportfolio/filters/custodians.py +1 -0
- wbportfolio/filters/esg.py +1 -0
- wbportfolio/filters/performances.py +7 -6
- wbportfolio/filters/portfolios.py +21 -1
- wbportfolio/filters/positions.py +1 -0
- wbportfolio/filters/products.py +1 -0
- wbportfolio/filters/roles.py +1 -0
- wbportfolio/filters/signals.py +1 -0
- wbportfolio/filters/transactions/claim.py +1 -0
- wbportfolio/filters/transactions/fees.py +1 -0
- wbportfolio/filters/transactions/trades.py +2 -1
- wbportfolio/filters/transactions/transactions.py +1 -0
- wbportfolio/import_export/backends/ubs/mixin.py +1 -0
- wbportfolio/import_export/backends/wbfdm/adjustment.py +1 -0
- wbportfolio/import_export/handlers/asset_position.py +11 -13
- wbportfolio/import_export/handlers/fees.py +1 -0
- wbportfolio/import_export/handlers/portfolio_cash_flow.py +1 -0
- wbportfolio/import_export/handlers/trade.py +1 -0
- wbportfolio/import_export/parsers/jpmorgan/customer_trade.py +1 -0
- wbportfolio/import_export/parsers/jpmorgan/fees.py +1 -0
- wbportfolio/import_export/parsers/jpmorgan/strategy.py +5 -4
- wbportfolio/import_export/parsers/jpmorgan/valuation.py +1 -0
- wbportfolio/import_export/parsers/leonteq/customer_trade.py +1 -0
- wbportfolio/import_export/parsers/leonteq/equity.py +13 -12
- wbportfolio/import_export/parsers/leonteq/fees.py +1 -0
- wbportfolio/import_export/parsers/leonteq/trade.py +1 -0
- wbportfolio/import_export/parsers/leonteq/valuation.py +1 -0
- wbportfolio/import_export/parsers/natixis/customer_trade.py +1 -0
- wbportfolio/import_export/parsers/natixis/d1_customer_trade.py +1 -0
- wbportfolio/import_export/parsers/natixis/d1_equity.py +3 -2
- wbportfolio/import_export/parsers/natixis/d1_fees.py +1 -0
- wbportfolio/import_export/parsers/natixis/d1_trade.py +1 -0
- wbportfolio/import_export/parsers/natixis/d1_valuation.py +1 -0
- wbportfolio/import_export/parsers/natixis/equity.py +5 -5
- wbportfolio/import_export/parsers/natixis/trade.py +1 -0
- wbportfolio/import_export/parsers/natixis/utils.py +8 -7
- wbportfolio/import_export/parsers/sg_lux/custodian_positions.py +1 -0
- wbportfolio/import_export/parsers/sg_lux/customer_trade.py +1 -0
- wbportfolio/import_export/parsers/sg_lux/customer_trade_pending_slk.py +2 -1
- wbportfolio/import_export/parsers/sg_lux/customer_trade_slk.py +2 -1
- wbportfolio/import_export/parsers/sg_lux/customer_trade_without_pw.py +1 -0
- wbportfolio/import_export/parsers/sg_lux/equity.py +7 -8
- wbportfolio/import_export/parsers/sg_lux/portfolio_cash_flow.py +1 -0
- wbportfolio/import_export/parsers/sg_lux/portfolio_future_cash_flow.py +1 -0
- wbportfolio/import_export/parsers/sg_lux/registers.py +2 -1
- wbportfolio/import_export/parsers/societe_generale/customer_trade.py +1 -0
- wbportfolio/import_export/parsers/societe_generale/strategy.py +8 -9
- wbportfolio/import_export/parsers/societe_generale/valuation.py +1 -0
- wbportfolio/import_export/parsers/tellco/equity.py +5 -4
- wbportfolio/import_export/parsers/ubs/api/asset_position.py +15 -14
- wbportfolio/import_export/parsers/ubs/api/fees.py +1 -0
- wbportfolio/import_export/parsers/ubs/customer_trade.py +1 -0
- wbportfolio/import_export/parsers/ubs/equity.py +3 -2
- wbportfolio/import_export/parsers/ubs/historical_customer_trade.py +1 -0
- wbportfolio/import_export/parsers/ubs/valuation.py +1 -0
- wbportfolio/import_export/parsers/vontobel/asset_position.py +19 -19
- wbportfolio/import_export/parsers/vontobel/customer_trade.py +1 -0
- wbportfolio/import_export/parsers/vontobel/historical_customer_trade.py +1 -0
- wbportfolio/import_export/parsers/vontobel/management_fees.py +1 -0
- wbportfolio/import_export/parsers/vontobel/performance_fees.py +1 -0
- wbportfolio/import_export/parsers/vontobel/trade.py +1 -0
- wbportfolio/import_export/parsers/vontobel/valuation_api.py +20 -0
- wbportfolio/import_export/resources/assets.py +4 -3
- wbportfolio/import_export/resources/trades.py +1 -0
- wbportfolio/metric/backends/base.py +1 -0
- wbportfolio/metric/backends/portfolio_base.py +1 -0
- wbportfolio/metric/backends/portfolio_esg.py +1 -0
- wbportfolio/metric/tests/test_portfolio_base.py +1 -0
- wbportfolio/migrations/0052_remove_cash_instrument_ptr_and_more.py +1 -131
- wbportfolio/migrations/0067_assetposition_unique_asset_position.py +1 -1
- wbportfolio/migrations/0070_remove_assetposition_unique_asset_position_and_more.py +1 -1
- wbportfolio/migrations/0073_remove_product_price_computation_and_more.py +407 -0
- wbportfolio/models/__init__.py +0 -5
- wbportfolio/models/adjustments.py +8 -2
- wbportfolio/models/asset.py +117 -98
- wbportfolio/models/graphs/portfolio.py +144 -0
- wbportfolio/models/graphs/utils.py +83 -0
- wbportfolio/models/indexes.py +2 -13
- wbportfolio/models/mixins/instruments.py +30 -8
- wbportfolio/models/portfolio.py +538 -332
- wbportfolio/models/portfolio_cash_flow.py +1 -0
- wbportfolio/models/portfolio_relationship.py +6 -2
- wbportfolio/models/product_groups.py +3 -2
- wbportfolio/models/products.py +3 -17
- wbportfolio/models/reconciliations/account_reconciliation_lines.py +1 -0
- wbportfolio/models/reconciliations/account_reconciliations.py +1 -0
- wbportfolio/models/registers.py +1 -0
- wbportfolio/models/transactions/__init__.py +1 -0
- wbportfolio/models/transactions/claim.py +8 -8
- wbportfolio/models/transactions/dividends.py +1 -0
- wbportfolio/models/transactions/fees.py +1 -0
- wbportfolio/models/transactions/rebalancing.py +153 -0
- wbportfolio/models/transactions/trade_proposals.py +153 -155
- wbportfolio/models/transactions/trades.py +48 -40
- wbportfolio/models/transactions/transactions.py +6 -12
- wbportfolio/models/utils.py +1 -0
- wbportfolio/pms/analytics/__init__.py +0 -0
- wbportfolio/pms/analytics/portfolio.py +28 -0
- wbportfolio/pms/trading/handler.py +13 -16
- wbportfolio/pms/typing.py +13 -29
- wbportfolio/rebalancing/__init__.py +0 -0
- wbportfolio/rebalancing/base.py +16 -0
- wbportfolio/rebalancing/decorators.py +17 -0
- wbportfolio/rebalancing/models/__init__.py +3 -0
- wbportfolio/rebalancing/models/composite.py +31 -0
- wbportfolio/rebalancing/models/equally_weighted.py +21 -0
- wbportfolio/rebalancing/models/model_portfolio.py +35 -0
- wbportfolio/reports/monthly_position_report.py +1 -1
- wbportfolio/risk_management/backends/accounts.py +7 -6
- wbportfolio/risk_management/backends/controversy_portfolio.py +1 -0
- wbportfolio/risk_management/backends/exposure_portfolio.py +1 -0
- wbportfolio/risk_management/backends/instrument_list_portfolio.py +1 -0
- wbportfolio/risk_management/backends/liquidity_risk.py +1 -0
- wbportfolio/risk_management/backends/liquidity_stress_instrument.py +1 -0
- wbportfolio/risk_management/backends/mixins.py +1 -0
- wbportfolio/risk_management/backends/product_integrity.py +6 -1
- wbportfolio/risk_management/backends/stop_loss_instrument.py +1 -0
- wbportfolio/risk_management/backends/stop_loss_portfolio.py +1 -0
- wbportfolio/risk_management/backends/ucits_portfolio.py +1 -0
- wbportfolio/risk_management/tests/test_accounts.py +1 -0
- wbportfolio/risk_management/tests/test_controversy_portfolio.py +1 -0
- wbportfolio/risk_management/tests/test_exposure_portfolio.py +1 -0
- wbportfolio/risk_management/tests/test_instrument_list_portfolio.py +1 -0
- wbportfolio/risk_management/tests/test_liquidity_risk.py +1 -0
- wbportfolio/risk_management/tests/test_product_integrity.py +1 -0
- wbportfolio/risk_management/tests/test_stop_loss_instrument.py +1 -0
- wbportfolio/risk_management/tests/test_stop_loss_portfolio.py +1 -0
- wbportfolio/risk_management/tests/test_ucits_portfolio.py +1 -0
- wbportfolio/serializers/__init__.py +5 -5
- wbportfolio/serializers/adjustments.py +1 -0
- wbportfolio/serializers/assets.py +18 -19
- wbportfolio/serializers/custodians.py +1 -0
- wbportfolio/serializers/portfolio_cash_flow.py +1 -0
- wbportfolio/serializers/portfolio_cash_targets.py +1 -0
- wbportfolio/serializers/portfolio_relationship.py +1 -0
- wbportfolio/serializers/portfolio_swing_pricing.py +1 -0
- wbportfolio/serializers/portfolios.py +61 -40
- wbportfolio/serializers/positions.py +1 -0
- wbportfolio/serializers/product_group.py +1 -0
- wbportfolio/serializers/products.py +4 -7
- wbportfolio/serializers/rebalancing.py +57 -0
- wbportfolio/serializers/reconciliations.py +2 -1
- wbportfolio/serializers/registers.py +1 -0
- wbportfolio/serializers/roles.py +1 -0
- wbportfolio/serializers/signals.py +10 -15
- wbportfolio/serializers/transactions/__init__.py +1 -1
- wbportfolio/serializers/transactions/claim.py +1 -0
- wbportfolio/serializers/transactions/fees.py +1 -0
- wbportfolio/serializers/transactions/trade_proposals.py +85 -0
- wbportfolio/serializers/transactions/trades.py +9 -51
- wbportfolio/serializers/transactions/transactions.py +4 -3
- wbportfolio/tasks.py +1 -78
- wbportfolio/tests/conftest.py +6 -13
- wbportfolio/tests/models/test_account_reconciliation.py +2 -0
- wbportfolio/tests/models/test_assets.py +27 -19
- wbportfolio/tests/models/test_customer_trades.py +1 -0
- wbportfolio/tests/models/test_imports.py +5 -1
- wbportfolio/tests/models/test_merge.py +5 -4
- wbportfolio/tests/models/test_portfolio_cash_flow.py +8 -6
- wbportfolio/tests/models/test_portfolios.py +594 -154
- wbportfolio/tests/models/test_product_groups.py +1 -0
- wbportfolio/tests/models/test_products.py +6 -3
- wbportfolio/tests/models/test_roles.py +1 -0
- wbportfolio/tests/models/test_splits.py +1 -0
- wbportfolio/tests/models/transactions/test_claim.py +1 -0
- wbportfolio/tests/models/transactions/test_fees.py +1 -0
- wbportfolio/tests/models/transactions/test_rebalancing.py +81 -0
- wbportfolio/tests/models/transactions/test_trades.py +1 -0
- wbportfolio/tests/models/utils.py +1 -0
- wbportfolio/tests/pms/__init__.py +0 -0
- wbportfolio/tests/pms/test_analytics.py +35 -0
- wbportfolio/tests/rebalancing/__init__.py +0 -0
- wbportfolio/tests/rebalancing/test_models.py +127 -0
- wbportfolio/tests/serializers/test_claims.py +1 -0
- wbportfolio/tests/signals.py +1 -7
- wbportfolio/tests/tests.py +2 -0
- wbportfolio/tests/viewsets/test_assets.py +1 -0
- wbportfolio/tests/viewsets/test_performances.py +1 -0
- wbportfolio/tests/viewsets/test_products.py +1 -0
- wbportfolio/tests/viewsets/transactions/test_claims.py +1 -0
- wbportfolio/urls.py +26 -12
- wbportfolio/viewsets/__init__.py +2 -5
- wbportfolio/viewsets/adjustments.py +1 -0
- wbportfolio/viewsets/assets.py +62 -51
- wbportfolio/viewsets/assets_and_net_new_money_progression.py +1 -0
- wbportfolio/viewsets/charts/assets.py +3 -1
- wbportfolio/viewsets/configs/buttons/__init__.py +1 -1
- wbportfolio/viewsets/configs/buttons/assets.py +1 -0
- wbportfolio/viewsets/configs/buttons/custodians.py +1 -0
- wbportfolio/viewsets/configs/buttons/mixins.py +1 -20
- wbportfolio/viewsets/configs/buttons/portfolios.py +90 -76
- wbportfolio/viewsets/configs/buttons/signals.py +1 -0
- wbportfolio/viewsets/configs/buttons/trades.py +1 -0
- wbportfolio/viewsets/configs/display/__init__.py +2 -1
- wbportfolio/viewsets/configs/display/adjustments.py +1 -0
- wbportfolio/viewsets/configs/display/assets.py +7 -6
- wbportfolio/viewsets/configs/display/claim.py +1 -0
- wbportfolio/viewsets/configs/display/portfolios.py +127 -79
- wbportfolio/viewsets/configs/display/product_performance.py +1 -0
- wbportfolio/viewsets/configs/display/rebalancing.py +27 -0
- wbportfolio/viewsets/configs/display/trade_proposals.py +7 -4
- wbportfolio/viewsets/configs/display/trades.py +75 -42
- wbportfolio/viewsets/configs/endpoints/__init__.py +3 -1
- wbportfolio/viewsets/configs/endpoints/claim.py +1 -0
- wbportfolio/viewsets/configs/endpoints/portfolios.py +23 -7
- wbportfolio/viewsets/configs/endpoints/rebalancing.py +6 -0
- wbportfolio/viewsets/configs/endpoints/reconciliations.py +1 -0
- wbportfolio/viewsets/configs/endpoints/trade_proposals.py +1 -0
- wbportfolio/viewsets/configs/endpoints/trades.py +1 -0
- wbportfolio/viewsets/configs/menu/adjustments.py +1 -0
- wbportfolio/viewsets/configs/menu/assets.py +1 -0
- wbportfolio/viewsets/configs/menu/fees.py +1 -0
- wbportfolio/viewsets/configs/menu/portfolio_cash_flow.py +1 -0
- wbportfolio/viewsets/configs/menu/portfolios.py +4 -2
- wbportfolio/viewsets/configs/menu/positions.py +1 -0
- wbportfolio/viewsets/configs/menu/roles.py +1 -0
- wbportfolio/viewsets/configs/menu/transactions.py +1 -0
- wbportfolio/viewsets/configs/previews/portfolios.py +1 -6
- wbportfolio/viewsets/configs/titles/__init__.py +1 -1
- wbportfolio/viewsets/configs/titles/assets.py +1 -0
- wbportfolio/viewsets/configs/titles/fees.py +1 -0
- wbportfolio/viewsets/configs/titles/instrument_prices.py +1 -0
- wbportfolio/viewsets/configs/titles/portfolios.py +13 -11
- wbportfolio/viewsets/configs/titles/roles.py +1 -0
- wbportfolio/viewsets/configs/titles/trades.py +1 -0
- wbportfolio/viewsets/configs/titles/transactions.py +1 -0
- wbportfolio/viewsets/custodians.py +1 -0
- wbportfolio/viewsets/esg.py +1 -0
- wbportfolio/viewsets/mixins.py +1 -0
- wbportfolio/viewsets/portfolio_cash_flow.py +1 -0
- wbportfolio/viewsets/portfolio_cash_targets.py +1 -0
- wbportfolio/viewsets/portfolio_relationship.py +1 -0
- wbportfolio/viewsets/portfolio_swing_pricing.py +1 -0
- wbportfolio/viewsets/portfolios.py +228 -61
- wbportfolio/viewsets/positions.py +3 -2
- wbportfolio/viewsets/product_groups.py +1 -0
- wbportfolio/viewsets/product_performance.py +1 -0
- wbportfolio/viewsets/products.py +1 -0
- wbportfolio/viewsets/reconciliations.py +1 -0
- wbportfolio/viewsets/registers.py +1 -0
- wbportfolio/viewsets/roles.py +1 -0
- wbportfolio/viewsets/signals.py +1 -0
- wbportfolio/viewsets/transactions/__init__.py +1 -0
- wbportfolio/viewsets/transactions/claim.py +2 -1
- wbportfolio/viewsets/transactions/fees.py +1 -0
- wbportfolio/viewsets/transactions/mixins.py +1 -0
- wbportfolio/viewsets/transactions/rebalancing.py +31 -0
- wbportfolio/viewsets/transactions/trade_proposals.py +25 -5
- wbportfolio/viewsets/transactions/trades.py +16 -9
- wbportfolio/viewsets/transactions/transactions.py +1 -0
- {wbportfolio-1.44.4.dist-info → wbportfolio-1.45.0.dist-info}/METADATA +4 -1
- {wbportfolio-1.44.4.dist-info → wbportfolio-1.45.0.dist-info}/RECORD +301 -288
- wbportfolio/admin/synchronization/__init__.py +0 -2
- wbportfolio/admin/synchronization/admin.py +0 -114
- wbportfolio/admin/synchronization/portfolio_synchronization.py +0 -18
- wbportfolio/admin/synchronization/price_computation.py +0 -21
- wbportfolio/defaults/portfolio/default_rebalancing.py +0 -45
- wbportfolio/factories/pytest_utils.py +0 -121
- wbportfolio/factories/synchronization.py +0 -40
- wbportfolio/models/synchronization/__init__.py +0 -3
- wbportfolio/models/synchronization/portfolio_synchronization.py +0 -292
- wbportfolio/models/synchronization/price_computation.py +0 -200
- wbportfolio/models/synchronization/synchronization.py +0 -188
- wbportfolio/serializers/synchronization.py +0 -18
- wbportfolio/tests/models/test_synchronization.py +0 -617
- wbportfolio/viewsets/synchronization.py +0 -25
- /wbportfolio/{defaults/portfolio → models/graphs}/__init__.py +0 -0
- {wbportfolio-1.44.4.dist-info → wbportfolio-1.45.0.dist-info}/WHEEL +0 -0
- {wbportfolio-1.44.4.dist-info → wbportfolio-1.45.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -4,6 +4,7 @@ from decimal import Decimal
|
|
|
4
4
|
import pytest
|
|
5
5
|
from faker import Faker
|
|
6
6
|
from wbfdm.models import Instrument
|
|
7
|
+
|
|
7
8
|
from wbportfolio.models import Product, Trade
|
|
8
9
|
|
|
9
10
|
from .utils import PortfolioTestMixin
|
|
@@ -48,9 +49,11 @@ class TestProductModel(PortfolioTestMixin):
|
|
|
48
49
|
p3 = instrument_price_factory.create(
|
|
49
50
|
instrument=Instrument.objects.get(id=product.id), date=t3.transaction_date
|
|
50
51
|
)
|
|
51
|
-
assert product.
|
|
52
|
-
assert product.
|
|
53
|
-
|
|
52
|
+
assert product.get_total_aum_usd(p1.date) == pytest.approx(Decimal(0), rel=Decimal("1e-4"))
|
|
53
|
+
assert product.get_total_aum_usd(p2.date) == pytest.approx(
|
|
54
|
+
Decimal(p2.net_value * (t1.shares)), rel=Decimal("1e-4")
|
|
55
|
+
)
|
|
56
|
+
assert product.get_total_aum_usd(p3.date) == pytest.approx(
|
|
54
57
|
Decimal(p3.net_value * (t1.shares + t2.shares)), rel=Decimal("1e-4")
|
|
55
58
|
)
|
|
56
59
|
|
|
@@ -4,6 +4,7 @@ from unittest.mock import patch
|
|
|
4
4
|
import pytest
|
|
5
5
|
from faker import Faker
|
|
6
6
|
from pandas.tseries.offsets import BDay
|
|
7
|
+
|
|
7
8
|
from wbportfolio.factories import AdjustmentFactory
|
|
8
9
|
from wbportfolio.models import Adjustment, PortfolioRole
|
|
9
10
|
from wbportfolio.models.adjustments import post_adjustment_on_prices
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
from datetime import date
|
|
2
|
+
from decimal import Decimal
|
|
3
|
+
|
|
4
|
+
import pandas as pd
|
|
5
|
+
import pytest
|
|
6
|
+
from django.core.exceptions import ValidationError
|
|
7
|
+
from pandas._libs.tslibs.offsets import BDay
|
|
8
|
+
|
|
9
|
+
from wbportfolio.models import AssetPosition, TradeProposal
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@pytest.mark.django_db
|
|
13
|
+
class TestRebalancingModel:
|
|
14
|
+
def test_get_target_portfolio(self, rebalancing_model, portfolio, weekday, asset_position_factory):
|
|
15
|
+
with pytest.raises(ValidationError): # trigger value error because rebalancing not valid (no position yet)
|
|
16
|
+
rebalancing_model.get_target_portfolio(portfolio, (weekday + BDay(1)).date(), weekday)
|
|
17
|
+
a1 = asset_position_factory(weighting=0.7, portfolio=portfolio, date=weekday)
|
|
18
|
+
a2 = asset_position_factory(weighting=0.3, portfolio=portfolio, date=weekday)
|
|
19
|
+
target_portfolio = rebalancing_model.get_target_portfolio(portfolio, (weekday + BDay(1)).date(), weekday)
|
|
20
|
+
target_positions = target_portfolio.positions_map
|
|
21
|
+
assert target_positions[a1.underlying_instrument.id].weighting == 0.5
|
|
22
|
+
assert target_positions[a2.underlying_instrument.id].weighting == 0.5
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@pytest.mark.django_db
|
|
26
|
+
class TestRebalancer:
|
|
27
|
+
def test_activation_date(self, rebalancer_factory, asset_position):
|
|
28
|
+
r1 = rebalancer_factory.create(portfolio=asset_position.portfolio)
|
|
29
|
+
assert r1.activation_date == asset_position.date
|
|
30
|
+
|
|
31
|
+
r2 = rebalancer_factory.create()
|
|
32
|
+
r2.activation_date = date.today()
|
|
33
|
+
|
|
34
|
+
def test_is_valid(self, weekday, rebalancer_factory):
|
|
35
|
+
# default frequency is monthly
|
|
36
|
+
|
|
37
|
+
first_of_the_month = weekday.replace(day=1)
|
|
38
|
+
rebalancer = rebalancer_factory.create(frequency="RRULE:FREQ=MONTHLY;", activation_date=first_of_the_month)
|
|
39
|
+
assert rebalancer.is_valid(first_of_the_month)
|
|
40
|
+
if weekday.day != 1:
|
|
41
|
+
assert not rebalancer.is_valid(weekday)
|
|
42
|
+
|
|
43
|
+
def test_evaluate_rebalancing(
|
|
44
|
+
self, weekday, rebalancer_factory, asset_position_factory, instrument_factory, instrument_price_factory
|
|
45
|
+
):
|
|
46
|
+
rebalancer = rebalancer_factory.create(approve_trade_proposal_automatically=True)
|
|
47
|
+
trade_date = (weekday + BDay(1)).date()
|
|
48
|
+
|
|
49
|
+
i1 = instrument_factory.create()
|
|
50
|
+
i2 = instrument_factory.create()
|
|
51
|
+
instrument_price_factory.create(instrument=i1, date=weekday)
|
|
52
|
+
instrument_price_factory.create(instrument=i1, date=trade_date)
|
|
53
|
+
instrument_price_factory.create(instrument=i2, date=weekday)
|
|
54
|
+
instrument_price_factory.create(instrument=i2, date=trade_date)
|
|
55
|
+
|
|
56
|
+
a1 = asset_position_factory.create(
|
|
57
|
+
portfolio=rebalancer.portfolio, date=weekday, weighting=0.7, underlying_instrument=i1
|
|
58
|
+
)
|
|
59
|
+
a2 = asset_position_factory.create(
|
|
60
|
+
portfolio=rebalancer.portfolio, date=weekday, weighting=0.3, underlying_instrument=i2
|
|
61
|
+
)
|
|
62
|
+
trade_proposal = rebalancer.evaluate_rebalancing(trade_date)
|
|
63
|
+
assert trade_proposal.trades.count() == 2
|
|
64
|
+
assert trade_proposal.status == TradeProposal.Status.APPROVED
|
|
65
|
+
assert AssetPosition.objects.get(
|
|
66
|
+
portfolio=rebalancer.portfolio, date=trade_date, underlying_quote=a1.underlying_instrument
|
|
67
|
+
).weighting == Decimal(0.5)
|
|
68
|
+
assert AssetPosition.objects.get(
|
|
69
|
+
portfolio=rebalancer.portfolio, date=trade_date, underlying_quote=a2.underlying_instrument
|
|
70
|
+
).weighting == Decimal(0.5)
|
|
71
|
+
|
|
72
|
+
def test_get_rrule(self, weekday, rebalancer_factory):
|
|
73
|
+
# default frequency is monthly
|
|
74
|
+
|
|
75
|
+
first_of_the_month = weekday.replace(day=1)
|
|
76
|
+
until = first_of_the_month.replace(year=first_of_the_month.year + 1)
|
|
77
|
+
rebalancer = rebalancer_factory.create(frequency="RRULE:FREQ=MONTHLY;", activation_date=first_of_the_month)
|
|
78
|
+
|
|
79
|
+
valid_dates = set(rebalancer.get_rrule(until))
|
|
80
|
+
assert valid_dates
|
|
81
|
+
assert set(valid_dates) == set(pd.date_range(start=first_of_the_month, end=until, freq="MS"))
|
|
File without changes
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
|
|
3
|
+
from wbportfolio.pms.analytics.portfolio import Portfolio
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def test_get_next_weights():
|
|
7
|
+
w0 = 0.3
|
|
8
|
+
w1 = 0.5
|
|
9
|
+
w2 = 0.2
|
|
10
|
+
r0 = 0.1
|
|
11
|
+
r1 = 0.05
|
|
12
|
+
r2 = -0.23
|
|
13
|
+
weights = [w0, w1, w2]
|
|
14
|
+
returns = [r0, r1, r2]
|
|
15
|
+
portfolio = Portfolio(X=pd.DataFrame([returns]), weights=pd.Series(weights))
|
|
16
|
+
next_weights = portfolio.get_next_weights(pd.Series(returns))
|
|
17
|
+
|
|
18
|
+
assert next_weights[0] == w0 * (r0 + 1) / (w0 * (r0 + 1) + w1 * (r1 + 1) + w2 * (r2 + 1))
|
|
19
|
+
assert next_weights[1] == w1 * (r1 + 1) / (w0 * (r0 + 1) + w1 * (r1 + 1) + w2 * (r2 + 1))
|
|
20
|
+
assert next_weights[2] == w2 * (r2 + 1) / (w0 * (r0 + 1) + w1 * (r1 + 1) + w2 * (r2 + 1))
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def test_get_estimate_net_value():
|
|
24
|
+
w0 = 0.3
|
|
25
|
+
w1 = 0.5
|
|
26
|
+
w2 = 0.2
|
|
27
|
+
r0 = 0.1
|
|
28
|
+
r1 = 0.05
|
|
29
|
+
r2 = -0.23
|
|
30
|
+
weights = [w0, w1, w2]
|
|
31
|
+
returns = [r0, r1, r2]
|
|
32
|
+
portfolio = Portfolio(X=pd.DataFrame([returns]), weights=pd.Series(weights), previous_weights=pd.Series(weights))
|
|
33
|
+
current_price = 100
|
|
34
|
+
net_asset_value = portfolio.get_estimate_net_value(current_price)
|
|
35
|
+
return net_asset_value == current_price * (1.0 + w0 * r0 + w1 * r1 + w2 * r2)
|
|
File without changes
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
from decimal import Decimal
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
from pandas._libs.tslibs.offsets import BDay
|
|
5
|
+
|
|
6
|
+
from wbportfolio.factories import PortfolioFactory, TradeFactory, TradeProposalFactory
|
|
7
|
+
from wbportfolio.models import PortfolioPortfolioThroughModel, Trade, TradeProposal
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@pytest.mark.django_db
|
|
11
|
+
class TestEquallyWeightedRebalancing:
|
|
12
|
+
@pytest.fixture()
|
|
13
|
+
def model(self, portfolio, weekday):
|
|
14
|
+
from wbportfolio.rebalancing.models import EquallyWeightedRebalancing
|
|
15
|
+
|
|
16
|
+
return EquallyWeightedRebalancing(portfolio, (weekday + BDay(1)).date(), weekday)
|
|
17
|
+
|
|
18
|
+
def test_is_valid(self, portfolio, weekday, model, asset_position_factory):
|
|
19
|
+
assert not model.is_valid()
|
|
20
|
+
asset_position_factory.create(portfolio=model.portfolio, date=model.last_effective_date)
|
|
21
|
+
assert model.is_valid()
|
|
22
|
+
|
|
23
|
+
def test_get_target_portfolio(self, portfolio, weekday, model, asset_position_factory):
|
|
24
|
+
a1 = asset_position_factory(weighting=0.7, portfolio=portfolio, date=model.last_effective_date)
|
|
25
|
+
a2 = asset_position_factory(weighting=0.3, portfolio=portfolio, date=model.last_effective_date)
|
|
26
|
+
target_portfolio = model.get_target_portfolio()
|
|
27
|
+
target_positions = target_portfolio.positions_map
|
|
28
|
+
assert target_positions[a1.underlying_instrument.id].weighting == Decimal(0.5)
|
|
29
|
+
assert target_positions[a2.underlying_instrument.id].weighting == Decimal(0.5)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@pytest.mark.django_db
|
|
33
|
+
class TestModelPortfolioRebalancing:
|
|
34
|
+
@pytest.fixture()
|
|
35
|
+
def model(self, portfolio, weekday):
|
|
36
|
+
from wbportfolio.rebalancing.models import ModelPortfolioRebalancing
|
|
37
|
+
|
|
38
|
+
return ModelPortfolioRebalancing(portfolio, (weekday + BDay(1)).date(), weekday)
|
|
39
|
+
|
|
40
|
+
def test_is_valid(self, portfolio, weekday, model, asset_position_factory):
|
|
41
|
+
assert not model.is_valid()
|
|
42
|
+
asset_position_factory.create(portfolio=model.portfolio, date=model.last_effective_date)
|
|
43
|
+
assert not model.is_valid()
|
|
44
|
+
model_portfolio = PortfolioFactory.create()
|
|
45
|
+
PortfolioPortfolioThroughModel.objects.create(
|
|
46
|
+
portfolio=model.portfolio,
|
|
47
|
+
dependency_portfolio=model_portfolio,
|
|
48
|
+
type=PortfolioPortfolioThroughModel.Type.MODEL,
|
|
49
|
+
)
|
|
50
|
+
asset_position_factory.create(portfolio=model.model_portfolio, date=model.last_effective_date)
|
|
51
|
+
assert model.is_valid()
|
|
52
|
+
|
|
53
|
+
def test_get_target_portfolio(self, portfolio, weekday, model, asset_position_factory):
|
|
54
|
+
model_portfolio = PortfolioFactory.create()
|
|
55
|
+
PortfolioPortfolioThroughModel.objects.create(
|
|
56
|
+
portfolio=model.portfolio,
|
|
57
|
+
dependency_portfolio=model_portfolio,
|
|
58
|
+
type=PortfolioPortfolioThroughModel.Type.MODEL,
|
|
59
|
+
)
|
|
60
|
+
asset_position_factory(portfolio=portfolio, date=model.last_effective_date) # noise
|
|
61
|
+
asset_position_factory(portfolio=portfolio, date=model.last_effective_date) # noise
|
|
62
|
+
a1 = asset_position_factory(weighting=0.8, portfolio=portfolio.model_portfolio, date=model.last_effective_date)
|
|
63
|
+
a2 = asset_position_factory(weighting=0.2, portfolio=portfolio.model_portfolio, date=model.last_effective_date)
|
|
64
|
+
target_portfolio = model.get_target_portfolio()
|
|
65
|
+
target_positions = target_portfolio.positions_map
|
|
66
|
+
assert target_positions[a1.underlying_instrument.id].weighting == Decimal("0.800000")
|
|
67
|
+
assert target_positions[a2.underlying_instrument.id].weighting == Decimal("0.200000")
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
@pytest.mark.django_db
|
|
71
|
+
class TestCompositeRebalancing:
|
|
72
|
+
@pytest.fixture()
|
|
73
|
+
def model(self, portfolio, weekday):
|
|
74
|
+
from wbportfolio.rebalancing.models import CompositeRebalancing
|
|
75
|
+
|
|
76
|
+
return CompositeRebalancing(portfolio, (weekday + BDay(1)).date(), weekday)
|
|
77
|
+
|
|
78
|
+
def test_is_valid(self, portfolio, weekday, model, asset_position_factory):
|
|
79
|
+
assert not model.is_valid()
|
|
80
|
+
|
|
81
|
+
trade_proposal = TradeProposalFactory.create(
|
|
82
|
+
portfolio=model.portfolio, trade_date=model.trade_date, status=TradeProposal.Status.APPROVED
|
|
83
|
+
)
|
|
84
|
+
TradeFactory.create(
|
|
85
|
+
portfolio=model.portfolio,
|
|
86
|
+
transaction_date=model.trade_date,
|
|
87
|
+
transaction_subtype=Trade.Type.BUY,
|
|
88
|
+
trade_proposal=trade_proposal,
|
|
89
|
+
weighting=0.7,
|
|
90
|
+
status=Trade.Status.EXECUTED,
|
|
91
|
+
)
|
|
92
|
+
TradeFactory.create(
|
|
93
|
+
portfolio=model.portfolio,
|
|
94
|
+
transaction_date=model.trade_date,
|
|
95
|
+
transaction_subtype=Trade.Type.BUY,
|
|
96
|
+
trade_proposal=trade_proposal,
|
|
97
|
+
weighting=0.3,
|
|
98
|
+
status=Trade.Status.EXECUTED,
|
|
99
|
+
)
|
|
100
|
+
assert model.is_valid()
|
|
101
|
+
|
|
102
|
+
def test_get_target_portfolio(self, portfolio, weekday, model, asset_position_factory):
|
|
103
|
+
trade_proposal = TradeProposalFactory.create(
|
|
104
|
+
portfolio=model.portfolio, trade_date=model.trade_date, status=TradeProposal.Status.APPROVED
|
|
105
|
+
)
|
|
106
|
+
asset_position_factory(portfolio=portfolio, date=model.last_effective_date) # noise
|
|
107
|
+
asset_position_factory(portfolio=portfolio, date=model.last_effective_date) # noise
|
|
108
|
+
t1 = TradeFactory.create(
|
|
109
|
+
portfolio=model.portfolio,
|
|
110
|
+
transaction_date=model.trade_date,
|
|
111
|
+
transaction_subtype=Trade.Type.BUY,
|
|
112
|
+
trade_proposal=trade_proposal,
|
|
113
|
+
weighting=0.8,
|
|
114
|
+
status=Trade.Status.EXECUTED,
|
|
115
|
+
)
|
|
116
|
+
t2 = TradeFactory.create(
|
|
117
|
+
portfolio=model.portfolio,
|
|
118
|
+
transaction_date=model.trade_date,
|
|
119
|
+
transaction_subtype=Trade.Type.BUY,
|
|
120
|
+
trade_proposal=trade_proposal,
|
|
121
|
+
weighting=0.2,
|
|
122
|
+
status=Trade.Status.EXECUTED,
|
|
123
|
+
)
|
|
124
|
+
target_portfolio = model.get_target_portfolio()
|
|
125
|
+
target_positions = target_portfolio.positions_map
|
|
126
|
+
assert target_positions[t1.underlying_instrument.id].weighting == Decimal("0.800000")
|
|
127
|
+
assert target_positions[t2.underlying_instrument.id].weighting == Decimal("0.200000")
|
wbportfolio/tests/signals.py
CHANGED
|
@@ -2,10 +2,10 @@ from django.dispatch import receiver
|
|
|
2
2
|
from wbcore.contrib.currency.factories import CurrencyFXRatesFactory
|
|
3
3
|
from wbcore.contrib.directory.factories import CompanyFactory
|
|
4
4
|
from wbcore.test.signals import custom_update_kwargs, get_custom_factory
|
|
5
|
+
|
|
5
6
|
from wbportfolio.factories import (
|
|
6
7
|
CustomerTradeFactory,
|
|
7
8
|
InstrumentPriceFactory,
|
|
8
|
-
ModelPortfolioFactory,
|
|
9
9
|
ProductFactory,
|
|
10
10
|
ProductPortfolioRoleFactory,
|
|
11
11
|
TradeProposalFactory,
|
|
@@ -19,7 +19,6 @@ from wbportfolio.viewsets import (
|
|
|
19
19
|
CustomerDistributionInstrumentChartViewSet,
|
|
20
20
|
DistributionChartViewSet,
|
|
21
21
|
DistributionTableViewSet,
|
|
22
|
-
ModelPortfolioModelViewSet,
|
|
23
22
|
NominalProductChartView,
|
|
24
23
|
PortfolioRoleInstrumentModelViewSet,
|
|
25
24
|
ProductCustomerModelViewSet,
|
|
@@ -42,11 +41,6 @@ def receive_factory_subscription_redemption_instrument(sender, *args, **kwargs):
|
|
|
42
41
|
return CustomerTradeFactory
|
|
43
42
|
|
|
44
43
|
|
|
45
|
-
@receiver(get_custom_factory, sender=ModelPortfolioModelViewSet)
|
|
46
|
-
def receive_factory_model_portfolio(sender, *args, **kwargs):
|
|
47
|
-
return ModelPortfolioFactory
|
|
48
|
-
|
|
49
|
-
|
|
50
44
|
@receiver(get_custom_factory, sender=PortfolioRoleInstrumentModelViewSet)
|
|
51
45
|
def receive_factory_product_portfolio_role(sender, *args, **kwargs):
|
|
52
46
|
return ProductPortfolioRoleFactory
|
wbportfolio/tests/tests.py
CHANGED
|
@@ -17,6 +17,8 @@ for key, value in default_config.items():
|
|
|
17
17
|
"AccountReconciliationLineModelViewSet",
|
|
18
18
|
"AccountReconciliation",
|
|
19
19
|
"AccountReconciliationLine",
|
|
20
|
+
"TopDownPortfolioCompositionPandasAPIView",
|
|
21
|
+
"CompositionModelPortfolioPandasView",
|
|
20
22
|
# "ClaimModelViewSet",
|
|
21
23
|
# "ClaimModelSerializer",
|
|
22
24
|
],
|
|
@@ -6,6 +6,7 @@ from faker import Faker
|
|
|
6
6
|
from pandas.tseries.offsets import BDay, BMonthEnd, BYearEnd
|
|
7
7
|
from rest_framework.reverse import reverse
|
|
8
8
|
from rest_framework.test import force_authenticate
|
|
9
|
+
|
|
9
10
|
from wbportfolio.factories import InstrumentPriceFactory, ProductFactory
|
|
10
11
|
from wbportfolio.viewsets.product_performance import PerformanceComparisonPandasView
|
|
11
12
|
|
|
@@ -9,6 +9,7 @@ from psycopg.types.range import DateRange
|
|
|
9
9
|
from rest_framework.reverse import reverse
|
|
10
10
|
from rest_framework.test import force_authenticate
|
|
11
11
|
from wbfdm.models import InstrumentPrice
|
|
12
|
+
|
|
12
13
|
from wbportfolio.models import InstrumentPortfolioThroughModel, Product
|
|
13
14
|
from wbportfolio.viewsets import ProductModelViewSet
|
|
14
15
|
|
|
@@ -8,6 +8,7 @@ from wbcore.contrib.directory.models import Entry
|
|
|
8
8
|
from wbcore.utils.strings import format_number
|
|
9
9
|
from wbcrm.factories.accounts import AccountFactory, AccountRoleFactory
|
|
10
10
|
from wbcrm.models import Account
|
|
11
|
+
|
|
11
12
|
from wbportfolio.factories.claim import ClaimFactory
|
|
12
13
|
from wbportfolio.models.transactions.claim import Claim
|
|
13
14
|
from wbportfolio.viewsets.transactions.claim import (
|
wbportfolio/urls.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from django.urls import include, path
|
|
2
2
|
from wbcore.routers import WBCoreRouter
|
|
3
|
+
|
|
3
4
|
from wbportfolio import viewsets
|
|
4
5
|
|
|
5
6
|
router = WBCoreRouter()
|
|
@@ -21,22 +22,10 @@ router.register(r"portfolio", viewsets.PortfolioModelViewSet, basename="portfoli
|
|
|
21
22
|
router.register(r"portfoliocashflow", viewsets.DailyPortfolioCashFlowModelViewSet, basename="portfoliocashflow")
|
|
22
23
|
router.register(r"portfolioswingpricing", viewsets.PortfolioSwingPricingModelViewSet, basename="portfolioswingpricing")
|
|
23
24
|
router.register(r"portfoliocashtarget", viewsets.PortfolioCashTargetModelViewSet, basename="portfoliocashtarget")
|
|
24
|
-
router.register(r"modelportfolio", viewsets.ModelPortfolioModelViewSet, basename="modelportfolio")
|
|
25
25
|
|
|
26
26
|
router.register(
|
|
27
27
|
r"portfoliorepresentation", viewsets.PortfolioRepresentationViewSet, basename="portfoliorepresentation"
|
|
28
28
|
)
|
|
29
|
-
router.register(
|
|
30
|
-
r"portfoliosynchronizationrepresentation",
|
|
31
|
-
viewsets.PortfolioSynchronizationRepresentationViewSet,
|
|
32
|
-
basename="portfoliosynchronizationrepresentation",
|
|
33
|
-
)
|
|
34
|
-
router.register(
|
|
35
|
-
r"pricecomputationrepresentation",
|
|
36
|
-
viewsets.PriceComputationRepresentationViewSet,
|
|
37
|
-
basename="pricecomputationrepresentation",
|
|
38
|
-
)
|
|
39
|
-
|
|
40
29
|
|
|
41
30
|
router.register(r"portfoliorole", viewsets.PortfolioRoleModelViewSet, basename="portfoliorole")
|
|
42
31
|
|
|
@@ -52,6 +41,21 @@ router.register(r"traderepresentation", viewsets.TradeRepresentationViewSet, bas
|
|
|
52
41
|
router.register(
|
|
53
42
|
r"tradeproposalrepresentation", viewsets.TradeProposalRepresentationViewSet, basename="tradeproposalrepresentation"
|
|
54
43
|
)
|
|
44
|
+
router.register(
|
|
45
|
+
r"rebalancingmodelrepresentation",
|
|
46
|
+
viewsets.RebalancingModelRepresentationViewSet,
|
|
47
|
+
basename="rebalancingmodelrepresentation",
|
|
48
|
+
)
|
|
49
|
+
router.register(
|
|
50
|
+
r"rebalancerrepresentation",
|
|
51
|
+
viewsets.RebalancerRepresentationViewSet,
|
|
52
|
+
basename="rebalancerrepresentation",
|
|
53
|
+
)
|
|
54
|
+
router.register(
|
|
55
|
+
r"rebalancer",
|
|
56
|
+
viewsets.RebalancerModelViewSet,
|
|
57
|
+
basename="rebalancer",
|
|
58
|
+
)
|
|
55
59
|
router.register(
|
|
56
60
|
r"feesproductperformance", viewsets.ProductPerformanceFeesModelViewSet, basename="feesproductperformance"
|
|
57
61
|
)
|
|
@@ -115,6 +119,16 @@ portfolio_router.register(
|
|
|
115
119
|
viewsets.ESGMetricAggregationPortfolioPandasViewSet,
|
|
116
120
|
basename="portfolio-esgaggregation",
|
|
117
121
|
)
|
|
122
|
+
portfolio_router.register(
|
|
123
|
+
r"treegraphchart",
|
|
124
|
+
viewsets.PortfolioTreeGraphChartViewSet,
|
|
125
|
+
basename="portfolio-treegraphchart",
|
|
126
|
+
)
|
|
127
|
+
portfolio_router.register(
|
|
128
|
+
r"topdowncomposition",
|
|
129
|
+
viewsets.TopDownPortfolioCompositionPandasAPIView,
|
|
130
|
+
basename="portfolio-topdowncomposition",
|
|
131
|
+
)
|
|
118
132
|
|
|
119
133
|
router.register(r"register", viewsets.RegisterModelViewSet, basename="register")
|
|
120
134
|
router.register(r"registerrepresentation", viewsets.RegisterRepresentationViewSet, basename="registerrepresentation")
|
wbportfolio/viewsets/__init__.py
CHANGED
|
@@ -11,10 +11,11 @@ from .charts import *
|
|
|
11
11
|
from .custodians import CustodianModelViewSet, CustodianRepresentationViewSet
|
|
12
12
|
from .portfolio_relationship import InstrumentPreferedClassificationThroughProductModelViewSet
|
|
13
13
|
from .portfolios import (
|
|
14
|
-
ModelPortfolioModelViewSet,
|
|
15
14
|
PortfolioModelViewSet,
|
|
16
15
|
PortfolioPortfolioThroughModelViewSet,
|
|
17
16
|
PortfolioRepresentationViewSet,
|
|
17
|
+
PortfolioTreeGraphChartViewSet,
|
|
18
|
+
TopDownPortfolioCompositionPandasAPIView
|
|
18
19
|
)
|
|
19
20
|
from .positions import (
|
|
20
21
|
AggregatedAssetPositionLiquidityPandasView,
|
|
@@ -23,10 +24,6 @@ from .positions import (
|
|
|
23
24
|
from .registers import RegisterModelViewSet, RegisterRepresentationViewSet
|
|
24
25
|
from .roles import PortfolioRoleInstrumentModelViewSet, PortfolioRoleModelViewSet
|
|
25
26
|
from .signals import *
|
|
26
|
-
from .synchronization import (
|
|
27
|
-
PortfolioSynchronizationRepresentationViewSet,
|
|
28
|
-
PriceComputationRepresentationViewSet,
|
|
29
|
-
)
|
|
30
27
|
from .transactions import *
|
|
31
28
|
from .adjustments import AdjustmentEquityModelViewSet, AdjustmentModelViewSet
|
|
32
29
|
from .product_groups import ProductGroupModelViewSet, ProductGroupRepresentationViewSet
|