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
|
@@ -3,9 +3,10 @@ from io import StringIO
|
|
|
3
3
|
|
|
4
4
|
import numpy as np
|
|
5
5
|
import pandas as pd
|
|
6
|
-
from wbportfolio.models import Product, Trade
|
|
7
6
|
from xlrd import xldate_as_datetime
|
|
8
7
|
|
|
8
|
+
from wbportfolio.models import Product, Trade
|
|
9
|
+
|
|
9
10
|
from .sylk import SYLK
|
|
10
11
|
from .utils import get_portfolio_id
|
|
11
12
|
|
|
@@ -4,6 +4,7 @@ from contextlib import suppress
|
|
|
4
4
|
|
|
5
5
|
import numpy as np
|
|
6
6
|
import pandas as pd
|
|
7
|
+
|
|
7
8
|
from wbportfolio.models import ProductGroup
|
|
8
9
|
|
|
9
10
|
|
|
@@ -29,7 +30,7 @@ def get_exchange(row):
|
|
|
29
30
|
return None
|
|
30
31
|
|
|
31
32
|
|
|
32
|
-
def
|
|
33
|
+
def get_underlying_quote(row):
|
|
33
34
|
if str(row["Asset type code"]) == "VMOB":
|
|
34
35
|
data = {
|
|
35
36
|
"instrument_type": "equity",
|
|
@@ -58,7 +59,7 @@ def parse(import_source):
|
|
|
58
59
|
df = df.replace([np.inf, -np.inf, np.nan], None)
|
|
59
60
|
columns_map = {
|
|
60
61
|
"Code": "portfolio",
|
|
61
|
-
"
|
|
62
|
+
"underlying_quote": "underlying_quote",
|
|
62
63
|
"exchange__bbg_exchange_codes": "exchange__bbg_exchange_codes",
|
|
63
64
|
"NAV Date": "date",
|
|
64
65
|
"Quantity / Amount": "initial_shares",
|
|
@@ -99,9 +100,7 @@ def parse(import_source):
|
|
|
99
100
|
)
|
|
100
101
|
.reset_index()
|
|
101
102
|
).copy()
|
|
102
|
-
cash["
|
|
103
|
-
lambda x: {"currency__key": x, "instrument_type": "cash"}
|
|
104
|
-
)
|
|
103
|
+
cash["underlying_quote"] = cash["currency__key"].apply(lambda x: {"currency__key": x, "instrument_type": "cash"})
|
|
105
104
|
|
|
106
105
|
# cash_equivalents_mask, all asset type code that match TRES and which don't have accounting category T111
|
|
107
106
|
cash_equivalents_mask = df["Asset type code"].str.match("TRES") & ~df["Accounting category"].str.match("T111")
|
|
@@ -127,14 +126,14 @@ def parse(import_source):
|
|
|
127
126
|
)
|
|
128
127
|
.reset_index()
|
|
129
128
|
).copy()
|
|
130
|
-
cash_equivalents["
|
|
129
|
+
cash_equivalents["underlying_quote"] = cash_equivalents["currency__key"].apply(
|
|
131
130
|
lambda x: {"currency__key": x, "instrument_type": "cash_equivalent"}
|
|
132
131
|
)
|
|
133
132
|
|
|
134
133
|
# equities = df.loc[df["Accounting category"].str.match("010"), :].copy() # Historically, we filter out equity base on the "accounting category" that matches "010", we had issue with equity having the code "020". We decided to use the column "Asset type code" and filter out with the code "VCOM"
|
|
135
134
|
equities = df.loc[df["Asset type code"].str.match("VMOB"), :].copy()
|
|
136
135
|
if not equities.empty:
|
|
137
|
-
equities["
|
|
136
|
+
equities["underlying_quote"] = equities.apply(lambda x: get_underlying_quote(x), axis=1)
|
|
138
137
|
equities["exchange"] = equities.apply(lambda x: get_exchange(x), axis=1)
|
|
139
138
|
del equities["Accounting category"]
|
|
140
139
|
del equities["Asset type code"]
|
|
@@ -149,7 +148,7 @@ def parse(import_source):
|
|
|
149
148
|
|
|
150
149
|
df["is_estimated"] = False
|
|
151
150
|
df = df.replace([np.inf, -np.inf, np.nan], None)
|
|
152
|
-
df = df[df["
|
|
151
|
+
df = df[df["underlying_quote"].notnull()]
|
|
153
152
|
|
|
154
153
|
df["weighting"] = df.initial_currency_fx_rate * df.initial_price * df.initial_shares
|
|
155
154
|
portfolio_weights = df.groupby("portfolio")["weighting"].sum()
|
|
@@ -4,9 +4,10 @@ from io import StringIO
|
|
|
4
4
|
import numpy as np
|
|
5
5
|
import pandas as pd
|
|
6
6
|
from wbcore.contrib.geography.models import Geography
|
|
7
|
-
from wbportfolio.models import Register
|
|
8
7
|
from xlrd import xldate_as_datetime
|
|
9
8
|
|
|
9
|
+
from wbportfolio.models import Register
|
|
10
|
+
|
|
10
11
|
from .sylk import SYLK
|
|
11
12
|
|
|
12
13
|
|
|
@@ -5,6 +5,7 @@ from io import BytesIO
|
|
|
5
5
|
|
|
6
6
|
import numpy as np
|
|
7
7
|
import pandas as pd
|
|
8
|
+
|
|
8
9
|
from wbportfolio.import_export.utils import extract_exchange_ticker
|
|
9
10
|
|
|
10
11
|
logger = logging.getLogger("importers.parsers.jp_morgan.strategy")
|
|
@@ -44,24 +45,22 @@ def parse(import_source):
|
|
|
44
45
|
df_positions.columns[df_positions.columns.str.contains("Currency")][0]: "currency__key",
|
|
45
46
|
df_positions.columns[df_positions.columns.str.contains("Weight")][0]: "weighting",
|
|
46
47
|
df_positions.columns[df_positions.columns.str.contains("Level")][0]: "initial_price",
|
|
47
|
-
df_positions.columns[df_positions.columns.str.contains("Ticker")][
|
|
48
|
-
|
|
49
|
-
]: "
|
|
50
|
-
df_positions.columns[df_positions.columns.str.contains("ISIN")][0]: "underlying_instrument__isin",
|
|
51
|
-
df_positions.columns[df_positions.columns.str.contains("Name")][0]: "underlying_instrument__name",
|
|
48
|
+
df_positions.columns[df_positions.columns.str.contains("Ticker")][0]: "underlying_quote__ticker",
|
|
49
|
+
df_positions.columns[df_positions.columns.str.contains("ISIN")][0]: "underlying_quote__isin",
|
|
50
|
+
df_positions.columns[df_positions.columns.str.contains("Name")][0]: "underlying_quote__name",
|
|
52
51
|
}
|
|
53
52
|
)
|
|
54
53
|
for position in df_positions.to_dict("records"):
|
|
55
|
-
ticker, exchange = extract_exchange_ticker(position["
|
|
54
|
+
ticker, exchange = extract_exchange_ticker(position["underlying_quote__ticker"])
|
|
56
55
|
if exchange:
|
|
57
56
|
exchange = {"bbg_exchange_codes": exchange}
|
|
58
57
|
data.append(
|
|
59
58
|
{
|
|
60
|
-
"
|
|
59
|
+
"underlying_quote": {
|
|
61
60
|
"instrument_type": "equity",
|
|
62
61
|
"ticker": ticker,
|
|
63
|
-
"isin": position["
|
|
64
|
-
"name": position["
|
|
62
|
+
"isin": position["underlying_quote__isin"],
|
|
63
|
+
"name": position["underlying_quote__name"],
|
|
65
64
|
"currency__key": position["currency__key"],
|
|
66
65
|
"exchange": exchange,
|
|
67
66
|
},
|
|
@@ -4,6 +4,7 @@ import datetime
|
|
|
4
4
|
|
|
5
5
|
import pandas as pd
|
|
6
6
|
from wbcore.contrib.currency.models import Currency
|
|
7
|
+
|
|
7
8
|
from wbportfolio.import_export.utils import convert_string_to_number
|
|
8
9
|
from wbportfolio.models import ProductGroup
|
|
9
10
|
|
|
@@ -36,7 +37,7 @@ def parse(import_source):
|
|
|
36
37
|
ticker = "CASH"
|
|
37
38
|
title = currency.title
|
|
38
39
|
initial_price = 1
|
|
39
|
-
|
|
40
|
+
underlying_quote = {
|
|
40
41
|
"instrument_type": "cash",
|
|
41
42
|
"ticker": ticker,
|
|
42
43
|
"name": title,
|
|
@@ -50,7 +51,7 @@ def parse(import_source):
|
|
|
50
51
|
initial_price = basket["Wertpapierkurs"]
|
|
51
52
|
|
|
52
53
|
exchange = f'X{basket["Bloomberg Code"]}' if basket["Bloomberg Code"] else None
|
|
53
|
-
|
|
54
|
+
underlying_quote = {
|
|
54
55
|
"instrument_type": instrument_type,
|
|
55
56
|
"isin": basket["ISIN"],
|
|
56
57
|
"exchange": {"mic_code": exchange},
|
|
@@ -62,8 +63,8 @@ def parse(import_source):
|
|
|
62
63
|
|
|
63
64
|
data.append(
|
|
64
65
|
{
|
|
65
|
-
"
|
|
66
|
-
"exchange":
|
|
66
|
+
"underlying_quote": underlying_quote,
|
|
67
|
+
"exchange": underlying_quote.get("exchange", None),
|
|
67
68
|
"portfolio": {
|
|
68
69
|
"instrument_type": "product_group",
|
|
69
70
|
"id": product_group.id,
|
|
@@ -3,16 +3,17 @@ import json
|
|
|
3
3
|
import numpy as np
|
|
4
4
|
import pandas as pd
|
|
5
5
|
from wbcore.contrib.currency.models import CurrencyFXRates
|
|
6
|
+
|
|
6
7
|
from wbportfolio.import_export.utils import extract_exchange_ticker
|
|
7
8
|
|
|
8
9
|
BASE_MAPPING = {
|
|
9
|
-
"instrument": "
|
|
10
|
-
"ric": "
|
|
11
|
-
"bbTicker": "
|
|
12
|
-
"isin": "
|
|
13
|
-
"sedol": "
|
|
14
|
-
"valoren": "
|
|
15
|
-
"assetClass": "
|
|
10
|
+
"instrument": "underlying_quote__name",
|
|
11
|
+
"ric": "underlying_quote__refinitiv_identifier_code",
|
|
12
|
+
"bbTicker": "underlying_quote__ticker",
|
|
13
|
+
"isin": "underlying_quote__isin",
|
|
14
|
+
"sedol": "underlying_quote__sedol",
|
|
15
|
+
"valoren": "underlying_quote__valoren",
|
|
16
|
+
"assetClass": "underlying_quote__instrument_type",
|
|
16
17
|
"percentageWeight": "weighting",
|
|
17
18
|
"shares": "initial_shares",
|
|
18
19
|
"localClose": "initial_price",
|
|
@@ -77,8 +78,8 @@ def parse(import_source):
|
|
|
77
78
|
df["date"] = val_date
|
|
78
79
|
df["portfolio__instrument_type"] = "product"
|
|
79
80
|
df["portfolio__isin"] = amc["isin"]
|
|
80
|
-
df["
|
|
81
|
-
df["
|
|
81
|
+
df["underlying_quote__currency__key"] = df["currency__key"]
|
|
82
|
+
df["underlying_quote__instrument_type"] = df.underlying_quote__instrument_type.apply(
|
|
82
83
|
lambda x: INSTRUMENT_TYPE_MAP[x]
|
|
83
84
|
)
|
|
84
85
|
if asset_class == "CASH":
|
|
@@ -93,14 +94,14 @@ def parse(import_source):
|
|
|
93
94
|
.astype(float)
|
|
94
95
|
)
|
|
95
96
|
df["is_estimated"] = False
|
|
96
|
-
if "
|
|
97
|
-
df["
|
|
97
|
+
if "underlying_quote__ticker" in df.columns:
|
|
98
|
+
df["underlying_quote__exchange"] = df["underlying_quote__ticker"].apply(
|
|
98
99
|
lambda x: {"bbg_exchange_codes": extract_exchange_ticker(x)[1]}
|
|
99
100
|
)
|
|
100
|
-
df["
|
|
101
|
+
df["underlying_quote__ticker"] = df["underlying_quote__ticker"].apply(
|
|
101
102
|
lambda x: extract_exchange_ticker(x)[0]
|
|
102
103
|
)
|
|
103
|
-
if "
|
|
104
|
-
df["exchange"] = df["
|
|
104
|
+
if "underlying_quote__exchange" in df.columns:
|
|
105
|
+
df["exchange"] = df["underlying_quote__exchange"]
|
|
105
106
|
data.extend(df.to_dict("records"))
|
|
106
107
|
return {"data": data}
|
|
@@ -2,6 +2,7 @@ import datetime
|
|
|
2
2
|
import re
|
|
3
3
|
|
|
4
4
|
import xlrd
|
|
5
|
+
|
|
5
6
|
from wbportfolio.models import Product
|
|
6
7
|
|
|
7
8
|
|
|
@@ -53,7 +54,7 @@ def parse(import_source):
|
|
|
53
54
|
exchange_data = {"bbg_exchange_codes": exchange}
|
|
54
55
|
data.append(
|
|
55
56
|
{
|
|
56
|
-
"
|
|
57
|
+
"underlying_quote": {
|
|
57
58
|
"instrument_type": "equity",
|
|
58
59
|
"ticker": ticker,
|
|
59
60
|
"exchange": exchange_data,
|
|
@@ -77,7 +78,7 @@ def parse(import_source):
|
|
|
77
78
|
if "Currency" == row[1].value:
|
|
78
79
|
data.append(
|
|
79
80
|
{
|
|
80
|
-
"
|
|
81
|
+
"underlying_quote": {
|
|
81
82
|
"instrument_type": "cash",
|
|
82
83
|
"currency__key": cash_sheet.cell_value(row_index + 1, 1),
|
|
83
84
|
},
|
|
@@ -10,14 +10,14 @@ FIELD_MAP = {
|
|
|
10
10
|
"Quantity": "initial_shares",
|
|
11
11
|
"TradingCurrency": "currency__key",
|
|
12
12
|
"FxRate": "initial_currency_fx_rate",
|
|
13
|
-
"ISIN": "
|
|
14
|
-
"InstrumentName": "
|
|
13
|
+
"ISIN": "underlying_quote__isin",
|
|
14
|
+
"InstrumentName": "underlying_quote__name",
|
|
15
15
|
"BuCurrency": "portfolio__currency__key",
|
|
16
|
-
"Ticker": "
|
|
16
|
+
"Ticker": "underlying_quote__ticker",
|
|
17
17
|
# "TradingPlace": "exchange",
|
|
18
18
|
"Booking_comment": "comment",
|
|
19
|
-
"AssetGroup": "
|
|
20
|
-
"InstrumentIdentifier": "
|
|
19
|
+
"AssetGroup": "underlying_quote__instrument_type",
|
|
20
|
+
"InstrumentIdentifier": "underlying_quote__identifier",
|
|
21
21
|
"#ClientName": "portfolio__identifier",
|
|
22
22
|
}
|
|
23
23
|
|
|
@@ -46,25 +46,25 @@ def parse(import_source):
|
|
|
46
46
|
df = df.rename(columns=FIELD_MAP).replace([np.inf, -np.inf, np.nan], None)
|
|
47
47
|
df = df.drop(columns=df.columns.difference(FIELD_MAP.values()))
|
|
48
48
|
if import_source.source.import_parameters.get("import_perf_fees_as_cash", False):
|
|
49
|
-
fees_idx = df["
|
|
50
|
-
df.loc[fees_idx, "
|
|
51
|
-
df.loc[fees_idx, "
|
|
49
|
+
fees_idx = df["underlying_quote__isin"] == perf_fee_isin
|
|
50
|
+
df.loc[fees_idx, "underlying_quote__isin"] = None
|
|
51
|
+
df.loc[fees_idx, "underlying_quote__instrument_type"] = "cash_equivalent"
|
|
52
52
|
df.loc[fees_idx, "initial_shares"] = df.loc[fees_idx, "initial_price"] # inverse price and share
|
|
53
53
|
else:
|
|
54
|
-
df = df.loc[df["
|
|
54
|
+
df = df.loc[df["underlying_quote__isin"] != perf_fee_isin, :]
|
|
55
55
|
|
|
56
|
-
df["
|
|
56
|
+
df["underlying_quote__instrument_type"] = df["underlying_quote__instrument_type"].apply(
|
|
57
57
|
lambda x: ASSET_GROUP_MAP[x] if x else None
|
|
58
58
|
)
|
|
59
59
|
# we remove instrument without isin or not of type cash because we don't support these (e.g, Dividend)
|
|
60
60
|
df = df[
|
|
61
|
-
~df["
|
|
62
|
-
| df["
|
|
61
|
+
~df["underlying_quote__isin"].isnull()
|
|
62
|
+
| df["underlying_quote__instrument_type"].isin(["cash", "cash_equivalent"])
|
|
63
63
|
]
|
|
64
64
|
|
|
65
65
|
# we group by instrument identifier to be sure we don't introduce duplicated position
|
|
66
66
|
df = (
|
|
67
|
-
df.groupby("
|
|
67
|
+
df.groupby("underlying_quote__identifier", dropna=False)
|
|
68
68
|
.agg(
|
|
69
69
|
{
|
|
70
70
|
"initial_currency_fx_rate": "first",
|
|
@@ -73,21 +73,21 @@ def parse(import_source):
|
|
|
73
73
|
"date": "first",
|
|
74
74
|
"asset_valuation_date": "first",
|
|
75
75
|
"currency__key": "first",
|
|
76
|
-
"
|
|
77
|
-
"
|
|
76
|
+
"underlying_quote__isin": "first",
|
|
77
|
+
"underlying_quote__name": "first",
|
|
78
78
|
"portfolio__currency__key": "first",
|
|
79
|
-
"
|
|
80
|
-
"
|
|
79
|
+
"underlying_quote__ticker": "first",
|
|
80
|
+
"underlying_quote__instrument_type": "first",
|
|
81
81
|
"portfolio__identifier": "first",
|
|
82
82
|
}
|
|
83
83
|
)
|
|
84
84
|
.reset_index(drop=True)
|
|
85
85
|
)
|
|
86
|
-
df.loc[df["
|
|
86
|
+
df.loc[df["underlying_quote__instrument_type"].isin(["cash", "cash_equivalent"]), "initial_price"] = 1.0
|
|
87
87
|
df["date"] = pd.to_datetime(df["date"], dayfirst=True).dt.strftime("%Y-%m-%d")
|
|
88
88
|
df["asset_valuation_date"] = pd.to_datetime(df["asset_valuation_date"], dayfirst=True).dt.strftime("%Y-%m-%d")
|
|
89
89
|
df["is_estimated"] = False
|
|
90
|
-
df["
|
|
90
|
+
df["underlying_quote__currency__key"] = df["currency__key"]
|
|
91
91
|
df["weighting"] = df.initial_currency_fx_rate * df.initial_price * df.initial_shares
|
|
92
92
|
df["weighting"] = df.weighting / df.weighting.sum()
|
|
93
93
|
df["portfolio__currency__key"] = (
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from contextlib import suppress
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def parse(import_source):
|
|
7
|
+
data = []
|
|
8
|
+
with suppress(KeyError):
|
|
9
|
+
series_data = json.loads(import_source.file.read())["payload"]["series"]
|
|
10
|
+
for series in series_data:
|
|
11
|
+
isin = series["item"]["priceIdentifier"]
|
|
12
|
+
for point in series["points"]:
|
|
13
|
+
data.append(
|
|
14
|
+
{
|
|
15
|
+
"instrument": {"isin": isin},
|
|
16
|
+
"date": datetime.fromtimestamp(int(point["timestamp"]) / 1000).strftime("%Y-%m-%d"),
|
|
17
|
+
"net_value": point["close"],
|
|
18
|
+
}
|
|
19
|
+
)
|
|
20
|
+
return {"data": data}
|
|
@@ -3,6 +3,7 @@ from import_export.widgets import DecimalWidget, ForeignKeyWidget
|
|
|
3
3
|
from wbcore.contrib.currency.models import Currency
|
|
4
4
|
from wbcore.contrib.io.resources import ViewResource
|
|
5
5
|
from wbfdm.models import Exchange
|
|
6
|
+
|
|
6
7
|
from wbportfolio.models import AssetPosition
|
|
7
8
|
|
|
8
9
|
|
|
@@ -52,9 +53,9 @@ class AssetPositionResource(ViewResource):
|
|
|
52
53
|
)
|
|
53
54
|
export_order = (
|
|
54
55
|
"date",
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"
|
|
56
|
+
"underlying_quote_name",
|
|
57
|
+
"underlying_quote_ticker",
|
|
58
|
+
"underlying_quote_isin",
|
|
58
59
|
"exchange",
|
|
59
60
|
"price",
|
|
60
61
|
"shares",
|
|
@@ -6,6 +6,7 @@ from django.db.models import Exists, OuterRef, QuerySet
|
|
|
6
6
|
from wbfdm.contrib.metric.backends.base import AbstractBackend, Metric
|
|
7
7
|
from wbfdm.contrib.metric.exceptions import MetricInvalidParameterException
|
|
8
8
|
from wbfdm.models import InstrumentType
|
|
9
|
+
|
|
9
10
|
from wbportfolio.models import AssetPosition, InstrumentPortfolioThroughModel, Portfolio
|
|
10
11
|
|
|
11
12
|
|
|
@@ -9,6 +9,7 @@ from wbfdm.contrib.metric.backends.base import Metric
|
|
|
9
9
|
from wbfdm.contrib.metric.decorators import register
|
|
10
10
|
from wbfdm.enums import Financial, MarketData
|
|
11
11
|
from wbfdm.models import Instrument
|
|
12
|
+
|
|
12
13
|
from wbportfolio.models import Portfolio
|
|
13
14
|
|
|
14
15
|
from .base import PortfolioMetricBaseBackend
|
|
@@ -5,6 +5,7 @@ from wbfdm.analysis.esg.enums import ESGAggregation
|
|
|
5
5
|
from wbfdm.analysis.esg.esg_analysis import DataLoader, get_esg_df
|
|
6
6
|
from wbfdm.contrib.metric.decorators import register
|
|
7
7
|
from wbfdm.contrib.metric.dto import Metric, MetricField, MetricKey
|
|
8
|
+
|
|
8
9
|
from wbportfolio.models import Portfolio
|
|
9
10
|
|
|
10
11
|
from .base import PortfolioMetricBaseBackend
|
|
@@ -7,6 +7,7 @@ from django.db.models import Sum
|
|
|
7
7
|
from faker import Faker
|
|
8
8
|
from wbfdm.dataloaders.proxies import InstrumentDataloaderProxy
|
|
9
9
|
from wbfdm.enums import Financial
|
|
10
|
+
|
|
10
11
|
from wbportfolio.factories import AssetPositionFactory, PortfolioFactory
|
|
11
12
|
from wbportfolio.models import AssetPosition
|
|
12
13
|
|