wbportfolio 2.2.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/__init__.py +1 -0
- wbportfolio/admin/__init__.py +12 -0
- wbportfolio/admin/asset.py +47 -0
- wbportfolio/admin/custodians.py +9 -0
- wbportfolio/admin/portfolio.py +127 -0
- wbportfolio/admin/portfolio_relationships.py +22 -0
- wbportfolio/admin/product_groups.py +42 -0
- wbportfolio/admin/products.py +80 -0
- wbportfolio/admin/reconciliations.py +14 -0
- wbportfolio/admin/registers.py +17 -0
- wbportfolio/admin/roles.py +19 -0
- wbportfolio/admin/synchronization/__init__.py +2 -0
- wbportfolio/admin/synchronization/admin.py +114 -0
- wbportfolio/admin/synchronization/portfolio_synchronization.py +18 -0
- wbportfolio/admin/synchronization/price_computation.py +21 -0
- wbportfolio/admin/transactions/__init__.py +5 -0
- wbportfolio/admin/transactions/claim.py +16 -0
- wbportfolio/admin/transactions/dividends.py +14 -0
- wbportfolio/admin/transactions/fees.py +35 -0
- wbportfolio/admin/transactions/trades.py +49 -0
- wbportfolio/admin/transactions/transactions.py +37 -0
- wbportfolio/analysis/__init__.py +0 -0
- wbportfolio/analysis/claims.py +235 -0
- wbportfolio/apps.py +5 -0
- wbportfolio/contrib/__init__.py +0 -0
- wbportfolio/contrib/company_portfolio/__init__.py +0 -0
- wbportfolio/contrib/company_portfolio/admin.py +28 -0
- wbportfolio/contrib/company_portfolio/apps.py +29 -0
- wbportfolio/contrib/company_portfolio/configs/__init__.py +3 -0
- wbportfolio/contrib/company_portfolio/configs/display.py +182 -0
- wbportfolio/contrib/company_portfolio/configs/endpoints.py +34 -0
- wbportfolio/contrib/company_portfolio/configs/previews.py +37 -0
- wbportfolio/contrib/company_portfolio/constants.py +1 -0
- wbportfolio/contrib/company_portfolio/dynamic_preferences_registry.py +87 -0
- wbportfolio/contrib/company_portfolio/factories.py +32 -0
- wbportfolio/contrib/company_portfolio/filters.py +127 -0
- wbportfolio/contrib/company_portfolio/management.py +19 -0
- wbportfolio/contrib/company_portfolio/migrations/0001_initial.py +214 -0
- wbportfolio/contrib/company_portfolio/migrations/__init__.py +0 -0
- wbportfolio/contrib/company_portfolio/models.py +334 -0
- wbportfolio/contrib/company_portfolio/scripts.py +76 -0
- wbportfolio/contrib/company_portfolio/serializers.py +303 -0
- wbportfolio/contrib/company_portfolio/tasks.py +19 -0
- wbportfolio/contrib/company_portfolio/tests/__init__.py +0 -0
- wbportfolio/contrib/company_portfolio/tests/conftest.py +161 -0
- wbportfolio/contrib/company_portfolio/tests/test_models.py +161 -0
- wbportfolio/contrib/company_portfolio/urls.py +29 -0
- wbportfolio/contrib/company_portfolio/viewsets.py +195 -0
- wbportfolio/defaults/__init__.py +0 -0
- wbportfolio/defaults/fees/__init__.py +0 -0
- wbportfolio/defaults/fees/default.py +92 -0
- wbportfolio/defaults/portfolio/__init__.py +0 -0
- wbportfolio/defaults/portfolio/default_rebalancing.py +45 -0
- wbportfolio/dynamic_preferences_registry.py +58 -0
- wbportfolio/factories/__init__.py +35 -0
- wbportfolio/factories/adjustments.py +17 -0
- wbportfolio/factories/assets.py +75 -0
- wbportfolio/factories/claim.py +39 -0
- wbportfolio/factories/custodians.py +11 -0
- wbportfolio/factories/dividends.py +14 -0
- wbportfolio/factories/fees.py +15 -0
- wbportfolio/factories/indexes.py +17 -0
- wbportfolio/factories/portfolio_cash_flow.py +20 -0
- wbportfolio/factories/portfolio_cash_targets.py +15 -0
- wbportfolio/factories/portfolio_swing_pricings.py +15 -0
- wbportfolio/factories/portfolios.py +59 -0
- wbportfolio/factories/product_groups.py +28 -0
- wbportfolio/factories/products.py +56 -0
- wbportfolio/factories/pytest_utils.py +121 -0
- wbportfolio/factories/reconciliations.py +23 -0
- wbportfolio/factories/roles.py +20 -0
- wbportfolio/factories/synchronization.py +40 -0
- wbportfolio/factories/trades.py +35 -0
- wbportfolio/factories/transactions.py +21 -0
- wbportfolio/fdm/__init__.py +0 -0
- wbportfolio/fdm/tasks.py +12 -0
- wbportfolio/filters/__init__.py +32 -0
- wbportfolio/filters/assets.py +485 -0
- wbportfolio/filters/assets_and_net_new_money_progression.py +42 -0
- wbportfolio/filters/custodians.py +10 -0
- wbportfolio/filters/esg.py +22 -0
- wbportfolio/filters/performances.py +171 -0
- wbportfolio/filters/portfolios.py +24 -0
- wbportfolio/filters/positions.py +178 -0
- wbportfolio/filters/products.py +157 -0
- wbportfolio/filters/roles.py +26 -0
- wbportfolio/filters/signals.py +92 -0
- wbportfolio/filters/transactions/__init__.py +20 -0
- wbportfolio/filters/transactions/claim.py +394 -0
- wbportfolio/filters/transactions/fees.py +66 -0
- wbportfolio/filters/transactions/trades.py +224 -0
- wbportfolio/filters/transactions/transactions.py +98 -0
- wbportfolio/import_export/__init__.py +0 -0
- wbportfolio/import_export/backends/__init__.py +2 -0
- wbportfolio/import_export/backends/ubs/__init__.py +3 -0
- wbportfolio/import_export/backends/ubs/asset_position.py +45 -0
- wbportfolio/import_export/backends/ubs/fees.py +63 -0
- wbportfolio/import_export/backends/ubs/instrument_price.py +44 -0
- wbportfolio/import_export/backends/ubs/mixin.py +15 -0
- wbportfolio/import_export/backends/utils.py +58 -0
- wbportfolio/import_export/backends/wbfdm/__init__.py +2 -0
- wbportfolio/import_export/backends/wbfdm/adjustment.py +50 -0
- wbportfolio/import_export/backends/wbfdm/dividend.py +16 -0
- wbportfolio/import_export/backends/wbfdm/mixin.py +15 -0
- wbportfolio/import_export/handlers/__init__.py +0 -0
- wbportfolio/import_export/handlers/adjustment.py +39 -0
- wbportfolio/import_export/handlers/asset_position.py +167 -0
- wbportfolio/import_export/handlers/dividend.py +80 -0
- wbportfolio/import_export/handlers/fees.py +58 -0
- wbportfolio/import_export/handlers/portfolio_cash_flow.py +57 -0
- wbportfolio/import_export/handlers/register.py +43 -0
- wbportfolio/import_export/handlers/trade.py +191 -0
- wbportfolio/import_export/parsers/__init__.py +0 -0
- wbportfolio/import_export/parsers/default_mapping.py +30 -0
- wbportfolio/import_export/parsers/jpmorgan/__init__.py +0 -0
- wbportfolio/import_export/parsers/jpmorgan/customer_trade.py +63 -0
- wbportfolio/import_export/parsers/jpmorgan/fees.py +64 -0
- wbportfolio/import_export/parsers/jpmorgan/strategy.py +116 -0
- wbportfolio/import_export/parsers/jpmorgan/valuation.py +41 -0
- wbportfolio/import_export/parsers/leonteq/__init__.py +0 -0
- wbportfolio/import_export/parsers/leonteq/customer_trade.py +47 -0
- wbportfolio/import_export/parsers/leonteq/equity.py +81 -0
- wbportfolio/import_export/parsers/leonteq/fees.py +70 -0
- wbportfolio/import_export/parsers/leonteq/trade.py +94 -0
- wbportfolio/import_export/parsers/leonteq/valuation.py +39 -0
- wbportfolio/import_export/parsers/natixis/__init__.py +0 -0
- wbportfolio/import_export/parsers/natixis/customer_trade.py +62 -0
- wbportfolio/import_export/parsers/natixis/d1_customer_trade.py +66 -0
- wbportfolio/import_export/parsers/natixis/d1_equity.py +80 -0
- wbportfolio/import_export/parsers/natixis/d1_fees.py +58 -0
- wbportfolio/import_export/parsers/natixis/d1_trade.py +70 -0
- wbportfolio/import_export/parsers/natixis/d1_valuation.py +41 -0
- wbportfolio/import_export/parsers/natixis/dividend.py +53 -0
- wbportfolio/import_export/parsers/natixis/equity.py +60 -0
- wbportfolio/import_export/parsers/natixis/fees.py +53 -0
- wbportfolio/import_export/parsers/natixis/trade.py +63 -0
- wbportfolio/import_export/parsers/natixis/utils.py +76 -0
- wbportfolio/import_export/parsers/natixis/valuation.py +46 -0
- wbportfolio/import_export/parsers/refinitiv/__init__.py +0 -0
- wbportfolio/import_export/parsers/refinitiv/adjustment.py +24 -0
- wbportfolio/import_export/parsers/sg_lux/__init__.py +0 -0
- wbportfolio/import_export/parsers/sg_lux/custodian_positions.py +70 -0
- wbportfolio/import_export/parsers/sg_lux/customer_trade.py +75 -0
- wbportfolio/import_export/parsers/sg_lux/customer_trade_pending_slk.py +140 -0
- wbportfolio/import_export/parsers/sg_lux/customer_trade_slk.py +80 -0
- wbportfolio/import_export/parsers/sg_lux/customer_trade_without_pw.py +57 -0
- wbportfolio/import_export/parsers/sg_lux/equity.py +137 -0
- wbportfolio/import_export/parsers/sg_lux/fees.py +56 -0
- wbportfolio/import_export/parsers/sg_lux/perf_fees.py +51 -0
- wbportfolio/import_export/parsers/sg_lux/portfolio_cash_flow.py +29 -0
- wbportfolio/import_export/parsers/sg_lux/portfolio_future_cash_flow.py +36 -0
- wbportfolio/import_export/parsers/sg_lux/registers.py +210 -0
- wbportfolio/import_export/parsers/sg_lux/sylk.py +248 -0
- wbportfolio/import_export/parsers/sg_lux/utils.py +36 -0
- wbportfolio/import_export/parsers/sg_lux/valuation.py +53 -0
- wbportfolio/import_export/parsers/societe_generale/__init__.py +0 -0
- wbportfolio/import_export/parsers/societe_generale/customer_trade.py +54 -0
- wbportfolio/import_export/parsers/societe_generale/strategy.py +94 -0
- wbportfolio/import_export/parsers/societe_generale/valuation.py +37 -0
- wbportfolio/import_export/parsers/tellco/__init__.py +0 -0
- wbportfolio/import_export/parsers/tellco/customer_trade.py +64 -0
- wbportfolio/import_export/parsers/tellco/equity.py +86 -0
- wbportfolio/import_export/parsers/tellco/valuation.py +52 -0
- wbportfolio/import_export/parsers/ubs/__init__.py +0 -0
- wbportfolio/import_export/parsers/ubs/api/__init__.py +0 -0
- wbportfolio/import_export/parsers/ubs/api/asset_position.py +106 -0
- wbportfolio/import_export/parsers/ubs/api/fees.py +31 -0
- wbportfolio/import_export/parsers/ubs/api/instrument_price.py +20 -0
- wbportfolio/import_export/parsers/ubs/api/utils.py +0 -0
- wbportfolio/import_export/parsers/ubs/customer_trade.py +60 -0
- wbportfolio/import_export/parsers/ubs/equity.py +97 -0
- wbportfolio/import_export/parsers/ubs/historical_customer_trade.py +67 -0
- wbportfolio/import_export/parsers/ubs/valuation.py +52 -0
- wbportfolio/import_export/parsers/vontobel/__init__.py +0 -0
- wbportfolio/import_export/parsers/vontobel/asset_position.py +97 -0
- wbportfolio/import_export/parsers/vontobel/customer_trade.py +54 -0
- wbportfolio/import_export/parsers/vontobel/historical_customer_trade.py +40 -0
- wbportfolio/import_export/parsers/vontobel/instrument.py +34 -0
- wbportfolio/import_export/parsers/vontobel/management_fees.py +86 -0
- wbportfolio/import_export/parsers/vontobel/performance_fees.py +35 -0
- wbportfolio/import_export/parsers/vontobel/trade.py +38 -0
- wbportfolio/import_export/parsers/vontobel/utils.py +17 -0
- wbportfolio/import_export/parsers/vontobel/valuation.py +29 -0
- wbportfolio/import_export/resources/__init__.py +0 -0
- wbportfolio/import_export/resources/assets.py +68 -0
- wbportfolio/import_export/resources/trades.py +41 -0
- wbportfolio/import_export/utils.py +42 -0
- wbportfolio/metric/__init__.py +0 -0
- wbportfolio/metric/backends/__init__.py +2 -0
- wbportfolio/metric/backends/base.py +86 -0
- wbportfolio/metric/backends/constants.py +222 -0
- wbportfolio/metric/backends/portfolio_base.py +255 -0
- wbportfolio/metric/backends/portfolio_esg.py +66 -0
- wbportfolio/metric/tests/__init__.py +0 -0
- wbportfolio/metric/tests/conftest.py +4 -0
- wbportfolio/metric/tests/test_portfolio_base.py +135 -0
- wbportfolio/metric/tests/test_portfolio_esg.py +69 -0
- wbportfolio/migrations/0001_initial_squashed.py +13848 -0
- wbportfolio/migrations/0002_product_default_sub_account_squashed_0039_alter_assetallocation_company_and_more.py +3836 -0
- wbportfolio/migrations/0040_instrument_financial_instrument.py +26 -0
- wbportfolio/migrations/0041_remove_listresearch_research_ptr_and_more.py +129 -0
- wbportfolio/migrations/0042_instrumentlist_instrumentlistthroughmodel_and_more.py +71 -0
- wbportfolio/migrations/0043_alter_instrumentlistthroughmodel_options_and_more.py +238 -0
- wbportfolio/migrations/0044_alter_instrumentlist_identifier.py +35 -0
- wbportfolio/migrations/0045_alter_instrument_financial_instrument.py +26 -0
- wbportfolio/migrations/0046_add_product_default_account.py +166 -0
- wbportfolio/migrations/0047_remove_product_default_sub_account.py +14 -0
- wbportfolio/migrations/0048_alter_trade_status.py +29 -0
- wbportfolio/migrations/0049_trade_claimed_shares.py +25 -0
- wbportfolio/migrations/0050_fees_fee_date_fees_wbportfolio_transac_1f7a29_idx.py +44 -0
- wbportfolio/migrations/0051_delete_macroreview.py +11 -0
- wbportfolio/migrations/0052_remove_cash_instrument_ptr_and_more.py +888 -0
- wbportfolio/migrations/0053_remove_product_group.py +132 -0
- wbportfolio/migrations/0054_portfolioinstrumentpreferredclassificationthroughmodel_and_more.py +270 -0
- wbportfolio/migrations/0055_remove_product__custom_management_rebates_and_more.py +139 -0
- wbportfolio/migrations/0056_remove_companyportfoliodata_assets_under_management_currency_and_more.py +56 -0
- wbportfolio/migrations/0057_alter_portfolio_preferred_instrument_classifications_and_more.py +36 -0
- wbportfolio/migrations/0058_pmsinstrument.py +23 -0
- wbportfolio/migrations/0059_fees_unique_fees.py +51 -0
- wbportfolio/migrations/0060_alter_portfolioportfoliothroughmodel_type.py +21 -0
- wbportfolio/migrations/0061_portfolio_bank_accounts_product_bank_account_and_more.py +175 -0
- wbportfolio/migrations/0062_alter_dailyportfoliocashflow_options.py +20 -0
- wbportfolio/migrations/0063_accountreconciliation_accountreconciliationline_and_more.py +133 -0
- wbportfolio/migrations/0064_alter_portfolio_managers_portfolio_is_tracked_and_more.py +40 -0
- wbportfolio/migrations/0065_alter_portfolio_managers_claim_as_shares_and_more.py +73 -0
- wbportfolio/migrations/0066_assetposition_initial_shares_at_custodian_and_more.py +108 -0
- wbportfolio/migrations/0067_assetposition_unique_asset_position.py +77 -0
- wbportfolio/migrations/0068_trade_internal_trade_trade_marked_as_internal_and_more.py +59 -0
- wbportfolio/migrations/0069_remove_portfolio_is_invested_and_more.py +56 -0
- wbportfolio/migrations/0070_remove_assetposition_unique_asset_position_and_more.py +82 -0
- wbportfolio/migrations/0071_alter_trade_options_alter_trade_order.py +22 -0
- wbportfolio/migrations/__init__.py +0 -0
- wbportfolio/models/__init__.py +26 -0
- wbportfolio/models/adjustments.py +246 -0
- wbportfolio/models/asset.py +869 -0
- wbportfolio/models/custodians.py +101 -0
- wbportfolio/models/indexes.py +33 -0
- wbportfolio/models/mixins/__init__.py +0 -0
- wbportfolio/models/mixins/instruments.py +127 -0
- wbportfolio/models/mixins/liquidity_stress_test.py +1307 -0
- wbportfolio/models/portfolio.py +1039 -0
- wbportfolio/models/portfolio_cash_flow.py +167 -0
- wbportfolio/models/portfolio_cash_targets.py +46 -0
- wbportfolio/models/portfolio_relationship.py +135 -0
- wbportfolio/models/portfolio_swing_pricings.py +51 -0
- wbportfolio/models/product_groups.py +230 -0
- wbportfolio/models/products.py +569 -0
- wbportfolio/models/reconciliations/__init__.py +2 -0
- wbportfolio/models/reconciliations/account_reconciliation_lines.py +192 -0
- wbportfolio/models/reconciliations/account_reconciliations.py +102 -0
- wbportfolio/models/reconciliations/reconciliations.py +25 -0
- wbportfolio/models/registers.py +132 -0
- wbportfolio/models/roles.py +208 -0
- wbportfolio/models/synchronization/__init__.py +3 -0
- wbportfolio/models/synchronization/portfolio_synchronization.py +292 -0
- wbportfolio/models/synchronization/price_computation.py +200 -0
- wbportfolio/models/synchronization/synchronization.py +188 -0
- wbportfolio/models/transactions/__init__.py +7 -0
- wbportfolio/models/transactions/claim.py +634 -0
- wbportfolio/models/transactions/dividends.py +31 -0
- wbportfolio/models/transactions/expiry.py +7 -0
- wbportfolio/models/transactions/fees.py +153 -0
- wbportfolio/models/transactions/trade_proposals.py +502 -0
- wbportfolio/models/transactions/trades.py +704 -0
- wbportfolio/models/transactions/transactions.py +211 -0
- wbportfolio/models/utils.py +12 -0
- wbportfolio/permissions.py +13 -0
- wbportfolio/pms/__init__.py +0 -0
- wbportfolio/pms/statistics/__init__.py +0 -0
- wbportfolio/pms/trading/__init__.py +1 -0
- wbportfolio/pms/trading/handler.py +164 -0
- wbportfolio/pms/typing.py +194 -0
- wbportfolio/preferences.py +6 -0
- wbportfolio/reports/__init__.py +0 -0
- wbportfolio/reports/monthly_position_report.py +74 -0
- wbportfolio/risk_management/__init__.py +0 -0
- wbportfolio/risk_management/backends/__init__.py +11 -0
- wbportfolio/risk_management/backends/accounts.py +166 -0
- wbportfolio/risk_management/backends/controversy_portfolio.py +63 -0
- wbportfolio/risk_management/backends/exposure_portfolio.py +203 -0
- wbportfolio/risk_management/backends/instrument_list_portfolio.py +89 -0
- wbportfolio/risk_management/backends/liquidity_risk.py +86 -0
- wbportfolio/risk_management/backends/liquidity_stress_instrument.py +86 -0
- wbportfolio/risk_management/backends/mixins.py +220 -0
- wbportfolio/risk_management/backends/product_integrity.py +111 -0
- wbportfolio/risk_management/backends/stop_loss_instrument.py +24 -0
- wbportfolio/risk_management/backends/stop_loss_portfolio.py +36 -0
- wbportfolio/risk_management/backends/ucits_portfolio.py +63 -0
- wbportfolio/risk_management/tests/__init__.py +0 -0
- wbportfolio/risk_management/tests/conftest.py +15 -0
- wbportfolio/risk_management/tests/test_accounts.py +98 -0
- wbportfolio/risk_management/tests/test_controversy_portfolio.py +33 -0
- wbportfolio/risk_management/tests/test_exposure_portfolio.py +94 -0
- wbportfolio/risk_management/tests/test_instrument_list_portfolio.py +60 -0
- wbportfolio/risk_management/tests/test_liquidity_risk.py +47 -0
- wbportfolio/risk_management/tests/test_product_integrity.py +55 -0
- wbportfolio/risk_management/tests/test_stop_loss_instrument.py +110 -0
- wbportfolio/risk_management/tests/test_stop_loss_portfolio.py +119 -0
- wbportfolio/risk_management/tests/test_ucits_portfolio.py +39 -0
- wbportfolio/serializers/__init__.py +42 -0
- wbportfolio/serializers/adjustments.py +24 -0
- wbportfolio/serializers/assets.py +166 -0
- wbportfolio/serializers/custodians.py +26 -0
- wbportfolio/serializers/portfolio_cash_flow.py +48 -0
- wbportfolio/serializers/portfolio_cash_targets.py +20 -0
- wbportfolio/serializers/portfolio_relationship.py +53 -0
- wbportfolio/serializers/portfolio_swing_pricing.py +20 -0
- wbportfolio/serializers/portfolios.py +143 -0
- wbportfolio/serializers/positions.py +76 -0
- wbportfolio/serializers/product_group.py +88 -0
- wbportfolio/serializers/products.py +331 -0
- wbportfolio/serializers/reconciliations.py +171 -0
- wbportfolio/serializers/registers.py +72 -0
- wbportfolio/serializers/roles.py +60 -0
- wbportfolio/serializers/signals.py +157 -0
- wbportfolio/serializers/synchronization.py +18 -0
- wbportfolio/serializers/transactions/__init__.py +24 -0
- wbportfolio/serializers/transactions/claim.py +310 -0
- wbportfolio/serializers/transactions/dividends.py +18 -0
- wbportfolio/serializers/transactions/expiry.py +18 -0
- wbportfolio/serializers/transactions/fees.py +32 -0
- wbportfolio/serializers/transactions/trades.py +315 -0
- wbportfolio/serializers/transactions/transactions.py +84 -0
- wbportfolio/tasks.py +125 -0
- wbportfolio/tests/__init__.py +0 -0
- wbportfolio/tests/conftest.py +164 -0
- wbportfolio/tests/models/__init__.py +0 -0
- wbportfolio/tests/models/test_account_reconciliation.py +191 -0
- wbportfolio/tests/models/test_assets.py +193 -0
- wbportfolio/tests/models/test_custodians.py +12 -0
- wbportfolio/tests/models/test_customer_trades.py +113 -0
- wbportfolio/tests/models/test_dividends.py +7 -0
- wbportfolio/tests/models/test_imports.py +192 -0
- wbportfolio/tests/models/test_instrument_mixins.py +48 -0
- wbportfolio/tests/models/test_merge.py +133 -0
- wbportfolio/tests/models/test_portfolio_cash_flow.py +112 -0
- wbportfolio/tests/models/test_portfolio_cash_targets.py +27 -0
- wbportfolio/tests/models/test_portfolio_swing_pricings.py +42 -0
- wbportfolio/tests/models/test_portfolios.py +676 -0
- wbportfolio/tests/models/test_product_groups.py +80 -0
- wbportfolio/tests/models/test_products.py +187 -0
- wbportfolio/tests/models/test_roles.py +82 -0
- wbportfolio/tests/models/test_splits.py +233 -0
- wbportfolio/tests/models/test_synchronization.py +617 -0
- wbportfolio/tests/models/transactions/__init__.py +0 -0
- wbportfolio/tests/models/transactions/test_claim.py +129 -0
- wbportfolio/tests/models/transactions/test_fees.py +65 -0
- wbportfolio/tests/models/transactions/test_trades.py +204 -0
- wbportfolio/tests/models/utils.py +13 -0
- wbportfolio/tests/serializers/__init__.py +0 -0
- wbportfolio/tests/serializers/test_claims.py +21 -0
- wbportfolio/tests/signals.py +151 -0
- wbportfolio/tests/tests.py +31 -0
- wbportfolio/tests/viewsets/__init__.py +0 -0
- wbportfolio/tests/viewsets/test_assets.py +67 -0
- wbportfolio/tests/viewsets/test_performances.py +72 -0
- wbportfolio/tests/viewsets/test_products.py +92 -0
- wbportfolio/tests/viewsets/transactions/__init__.py +0 -0
- wbportfolio/tests/viewsets/transactions/test_claims.py +146 -0
- wbportfolio/urls.py +247 -0
- wbportfolio/utils.py +30 -0
- wbportfolio/viewsets/__init__.py +57 -0
- wbportfolio/viewsets/adjustments.py +46 -0
- wbportfolio/viewsets/assets.py +562 -0
- wbportfolio/viewsets/assets_and_net_new_money_progression.py +117 -0
- wbportfolio/viewsets/charts/__init__.py +1 -0
- wbportfolio/viewsets/charts/assets.py +247 -0
- wbportfolio/viewsets/configs/__init__.py +6 -0
- wbportfolio/viewsets/configs/buttons/__init__.py +23 -0
- wbportfolio/viewsets/configs/buttons/adjustments.py +13 -0
- wbportfolio/viewsets/configs/buttons/assets.py +145 -0
- wbportfolio/viewsets/configs/buttons/claims.py +83 -0
- wbportfolio/viewsets/configs/buttons/custodians.py +76 -0
- wbportfolio/viewsets/configs/buttons/fees.py +14 -0
- wbportfolio/viewsets/configs/buttons/mixins.py +88 -0
- wbportfolio/viewsets/configs/buttons/portfolios.py +115 -0
- wbportfolio/viewsets/configs/buttons/products.py +41 -0
- wbportfolio/viewsets/configs/buttons/reconciliations.py +65 -0
- wbportfolio/viewsets/configs/buttons/registers.py +11 -0
- wbportfolio/viewsets/configs/buttons/signals.py +68 -0
- wbportfolio/viewsets/configs/buttons/trade_proposals.py +25 -0
- wbportfolio/viewsets/configs/buttons/trades.py +144 -0
- wbportfolio/viewsets/configs/display/__init__.py +61 -0
- wbportfolio/viewsets/configs/display/adjustments.py +81 -0
- wbportfolio/viewsets/configs/display/assets.py +265 -0
- wbportfolio/viewsets/configs/display/claim.py +299 -0
- wbportfolio/viewsets/configs/display/custodians.py +24 -0
- wbportfolio/viewsets/configs/display/esg.py +88 -0
- wbportfolio/viewsets/configs/display/fees.py +133 -0
- wbportfolio/viewsets/configs/display/portfolio_cash_flow.py +103 -0
- wbportfolio/viewsets/configs/display/portfolio_relationship.py +38 -0
- wbportfolio/viewsets/configs/display/portfolios.py +125 -0
- wbportfolio/viewsets/configs/display/positions.py +75 -0
- wbportfolio/viewsets/configs/display/product_groups.py +54 -0
- wbportfolio/viewsets/configs/display/product_performance.py +241 -0
- wbportfolio/viewsets/configs/display/products.py +249 -0
- wbportfolio/viewsets/configs/display/reconciliations.py +151 -0
- wbportfolio/viewsets/configs/display/registers.py +71 -0
- wbportfolio/viewsets/configs/display/roles.py +49 -0
- wbportfolio/viewsets/configs/display/trade_proposals.py +97 -0
- wbportfolio/viewsets/configs/display/trades.py +359 -0
- wbportfolio/viewsets/configs/display/transactions.py +55 -0
- wbportfolio/viewsets/configs/endpoints/__init__.py +75 -0
- wbportfolio/viewsets/configs/endpoints/adjustments.py +17 -0
- wbportfolio/viewsets/configs/endpoints/assets.py +115 -0
- wbportfolio/viewsets/configs/endpoints/claim.py +106 -0
- wbportfolio/viewsets/configs/endpoints/custodians.py +6 -0
- wbportfolio/viewsets/configs/endpoints/esg.py +14 -0
- wbportfolio/viewsets/configs/endpoints/fees.py +26 -0
- wbportfolio/viewsets/configs/endpoints/portfolio_relationship.py +23 -0
- wbportfolio/viewsets/configs/endpoints/portfolios.py +43 -0
- wbportfolio/viewsets/configs/endpoints/positions.py +18 -0
- wbportfolio/viewsets/configs/endpoints/product_groups.py +11 -0
- wbportfolio/viewsets/configs/endpoints/product_performance.py +29 -0
- wbportfolio/viewsets/configs/endpoints/products.py +37 -0
- wbportfolio/viewsets/configs/endpoints/reconciliations.py +31 -0
- wbportfolio/viewsets/configs/endpoints/roles.py +9 -0
- wbportfolio/viewsets/configs/endpoints/trade_proposals.py +17 -0
- wbportfolio/viewsets/configs/endpoints/trades.py +82 -0
- wbportfolio/viewsets/configs/endpoints/transactions.py +17 -0
- wbportfolio/viewsets/configs/menu/__init__.py +30 -0
- wbportfolio/viewsets/configs/menu/adjustments.py +8 -0
- wbportfolio/viewsets/configs/menu/assets.py +8 -0
- wbportfolio/viewsets/configs/menu/claim.py +41 -0
- wbportfolio/viewsets/configs/menu/custodians.py +11 -0
- wbportfolio/viewsets/configs/menu/fees.py +13 -0
- wbportfolio/viewsets/configs/menu/instrument_prices.py +10 -0
- wbportfolio/viewsets/configs/menu/portfolio_cash_flow.py +8 -0
- wbportfolio/viewsets/configs/menu/portfolios.py +15 -0
- wbportfolio/viewsets/configs/menu/positions.py +14 -0
- wbportfolio/viewsets/configs/menu/product_groups.py +10 -0
- wbportfolio/viewsets/configs/menu/product_performance.py +25 -0
- wbportfolio/viewsets/configs/menu/products.py +15 -0
- wbportfolio/viewsets/configs/menu/reconciliations.py +7 -0
- wbportfolio/viewsets/configs/menu/registers.py +10 -0
- wbportfolio/viewsets/configs/menu/roles.py +16 -0
- wbportfolio/viewsets/configs/menu/trades.py +18 -0
- wbportfolio/viewsets/configs/menu/transactions.py +8 -0
- wbportfolio/viewsets/configs/previews/__init__.py +1 -0
- wbportfolio/viewsets/configs/previews/portfolios.py +21 -0
- wbportfolio/viewsets/configs/titles/__init__.py +65 -0
- wbportfolio/viewsets/configs/titles/adjustments.py +19 -0
- wbportfolio/viewsets/configs/titles/assets.py +57 -0
- wbportfolio/viewsets/configs/titles/assets_and_net_new_money_progression.py +6 -0
- wbportfolio/viewsets/configs/titles/claim.py +81 -0
- wbportfolio/viewsets/configs/titles/custodians.py +12 -0
- wbportfolio/viewsets/configs/titles/esg.py +10 -0
- wbportfolio/viewsets/configs/titles/fees.py +25 -0
- wbportfolio/viewsets/configs/titles/instrument_prices.py +20 -0
- wbportfolio/viewsets/configs/titles/portfolios.py +32 -0
- wbportfolio/viewsets/configs/titles/positions.py +11 -0
- wbportfolio/viewsets/configs/titles/product_groups.py +12 -0
- wbportfolio/viewsets/configs/titles/product_performance.py +16 -0
- wbportfolio/viewsets/configs/titles/products.py +6 -0
- wbportfolio/viewsets/configs/titles/registers.py +12 -0
- wbportfolio/viewsets/configs/titles/roles.py +23 -0
- wbportfolio/viewsets/configs/titles/trades.py +51 -0
- wbportfolio/viewsets/configs/titles/transactions.py +8 -0
- wbportfolio/viewsets/custodians.py +66 -0
- wbportfolio/viewsets/esg.py +165 -0
- wbportfolio/viewsets/mixins.py +48 -0
- wbportfolio/viewsets/portfolio_cash_flow.py +31 -0
- wbportfolio/viewsets/portfolio_cash_targets.py +8 -0
- wbportfolio/viewsets/portfolio_relationship.py +46 -0
- wbportfolio/viewsets/portfolio_swing_pricing.py +8 -0
- wbportfolio/viewsets/portfolios.py +154 -0
- wbportfolio/viewsets/positions.py +292 -0
- wbportfolio/viewsets/product_groups.py +84 -0
- wbportfolio/viewsets/product_performance.py +646 -0
- wbportfolio/viewsets/products.py +529 -0
- wbportfolio/viewsets/reconciliations.py +160 -0
- wbportfolio/viewsets/registers.py +75 -0
- wbportfolio/viewsets/roles.py +44 -0
- wbportfolio/viewsets/signals.py +42 -0
- wbportfolio/viewsets/synchronization.py +25 -0
- wbportfolio/viewsets/transactions/__init__.py +40 -0
- wbportfolio/viewsets/transactions/claim.py +933 -0
- wbportfolio/viewsets/transactions/fees.py +190 -0
- wbportfolio/viewsets/transactions/mixins.py +19 -0
- wbportfolio/viewsets/transactions/trade_proposals.py +93 -0
- wbportfolio/viewsets/transactions/trades.py +395 -0
- wbportfolio/viewsets/transactions/transactions.py +123 -0
- wbportfolio-2.2.1.dist-info/METADATA +21 -0
- wbportfolio-2.2.1.dist-info/RECORD +486 -0
- wbportfolio-2.2.1.dist-info/WHEEL +5 -0
- wbportfolio-2.2.1.dist-info/licenses/LICENSE +4 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
from wbcore import serializers as wb_serializers
|
|
2
|
+
from wbcore.contrib.icons import WBIcon
|
|
3
|
+
from wbcore.enums import RequestType
|
|
4
|
+
from wbcore.metadata.configs import buttons as bt
|
|
5
|
+
from wbcore.metadata.configs.buttons.view_config import ButtonViewConfig
|
|
6
|
+
from wbcore.metadata.configs.display.instance_display.shortcuts import (
|
|
7
|
+
create_simple_display,
|
|
8
|
+
)
|
|
9
|
+
from wbportfolio.models import Custodian
|
|
10
|
+
from wbportfolio.serializers import CustodianRepresentationSerializer
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class CustodianButtonConfig(ButtonViewConfig):
|
|
14
|
+
def get_custom_list_instance_buttons(self):
|
|
15
|
+
custodians_qs = Custodian.objects.all()
|
|
16
|
+
if self.view.kwargs.get("pk", None):
|
|
17
|
+
custodians_qs = custodians_qs.exclude(id=self.view.kwargs["pk"])
|
|
18
|
+
|
|
19
|
+
class CustodianMergeModelSerializer(wb_serializers.ModelSerializer):
|
|
20
|
+
merged_custodian = wb_serializers.PrimaryKeyRelatedField(
|
|
21
|
+
required=True, queryset=custodians_qs, label="Custodian to be merged"
|
|
22
|
+
)
|
|
23
|
+
_merged_custodian = CustodianRepresentationSerializer(source="merged_custodian")
|
|
24
|
+
|
|
25
|
+
class Meta:
|
|
26
|
+
model = Custodian
|
|
27
|
+
fields = ("id", "merged_custodian", "_merged_custodian")
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
bt.ActionButton(
|
|
31
|
+
method=RequestType.PATCH,
|
|
32
|
+
identifiers=("wbportfolio:custodian",),
|
|
33
|
+
key="merge",
|
|
34
|
+
icon=WBIcon.TRADE.icon,
|
|
35
|
+
label="Merge custodians",
|
|
36
|
+
description_fields="""
|
|
37
|
+
<p>Merge the custodian <strong>{{name}}</strong> with another custodian in the list bellow</p>
|
|
38
|
+
""",
|
|
39
|
+
serializer=CustodianMergeModelSerializer,
|
|
40
|
+
action_label="Merge",
|
|
41
|
+
title="Merge custodians",
|
|
42
|
+
instance_display=create_simple_display([["merged_custodian"]]),
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
def get_custom_instance_buttons(self):
|
|
47
|
+
if custodian_id := self.view.kwargs.get("pk", None):
|
|
48
|
+
custodian = Custodian.objects.get(id=custodian_id)
|
|
49
|
+
|
|
50
|
+
class AdjustmentModelSerializer(wb_serializers.ModelSerializer):
|
|
51
|
+
mapping_choice = wb_serializers.ChoiceField(
|
|
52
|
+
required=True, choices={m: m for m in custodian.mapping}, label="Mapping to split off"
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
class Meta:
|
|
56
|
+
model = Custodian
|
|
57
|
+
fields = ("id", "mapping_choice", "name")
|
|
58
|
+
|
|
59
|
+
merge_button = {
|
|
60
|
+
bt.ActionButton(
|
|
61
|
+
method=RequestType.PATCH,
|
|
62
|
+
identifiers=("wbportfolio:custodian",),
|
|
63
|
+
key="split",
|
|
64
|
+
icon=WBIcon.TRADE.icon,
|
|
65
|
+
label="Adjustment custodians",
|
|
66
|
+
description_fields="""
|
|
67
|
+
<p>Adjustment the custodian <strong>{{name}}</strong> with another custodian in the list bellow</p>
|
|
68
|
+
""",
|
|
69
|
+
serializer=AdjustmentModelSerializer,
|
|
70
|
+
action_label="Adjustment",
|
|
71
|
+
title="Adjustment custodians",
|
|
72
|
+
instance_display=create_simple_display([["mapping_choice"]]),
|
|
73
|
+
)
|
|
74
|
+
}
|
|
75
|
+
return self.get_custom_list_instance_buttons() | merge_button
|
|
76
|
+
return self.get_custom_list_instance_buttons()
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from wbcore.contrib.icons import WBIcon
|
|
2
|
+
from wbcore.metadata.configs import buttons as bt
|
|
3
|
+
from wbcore.metadata.configs.buttons.view_config import ButtonViewConfig
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class FeesButtonConfig(ButtonViewConfig):
|
|
7
|
+
def get_custom_list_instance_buttons(self):
|
|
8
|
+
return {
|
|
9
|
+
bt.HyperlinkButton(
|
|
10
|
+
key="import_source",
|
|
11
|
+
label="Import Source",
|
|
12
|
+
icon=WBIcon.SAVE.icon,
|
|
13
|
+
)
|
|
14
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
from contextlib import suppress
|
|
2
|
+
|
|
3
|
+
from wbcore.contrib.icons import WBIcon
|
|
4
|
+
from wbcore.enums import RequestType
|
|
5
|
+
from wbcore.metadata.configs import buttons as bt
|
|
6
|
+
from wbcore.metadata.configs.display.instance_display.shortcuts import (
|
|
7
|
+
create_simple_display,
|
|
8
|
+
)
|
|
9
|
+
from wbfdm.models.instruments import Instrument
|
|
10
|
+
|
|
11
|
+
from .portfolios import get_portfolio_start_end_serializer_class
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class InstrumentButtonMixin:
|
|
15
|
+
@classmethod
|
|
16
|
+
def add_instrument_request_button(self, request=None, view=None, pk=None, **kwargs):
|
|
17
|
+
buttons = [
|
|
18
|
+
bt.WidgetButton(key="assets", label="Implemented Portfolios (Assets)"),
|
|
19
|
+
# bt.WidgetButton(
|
|
20
|
+
# key="adjustments",
|
|
21
|
+
# label="Adjustments",
|
|
22
|
+
# icon=WBIcon.DATA_LIST.icon,
|
|
23
|
+
# ),
|
|
24
|
+
]
|
|
25
|
+
with suppress(Instrument.DoesNotExist):
|
|
26
|
+
instrument = Instrument.objects.get(id=pk)
|
|
27
|
+
asset_instrument_btn_label = "Asset Portfolio"
|
|
28
|
+
if portfolio := instrument.portfolio:
|
|
29
|
+
buttons.extend(
|
|
30
|
+
[
|
|
31
|
+
bt.ActionButton(
|
|
32
|
+
method=RequestType.PATCH,
|
|
33
|
+
identifiers=("wbportfolio:portfolio",),
|
|
34
|
+
key="resynchronize",
|
|
35
|
+
label="Resynchronize/Rebalance",
|
|
36
|
+
description_fields="""
|
|
37
|
+
<p>Resynchronize portfolio from {{start}} to {{end}}</p>
|
|
38
|
+
""",
|
|
39
|
+
serializer=get_portfolio_start_end_serializer_class(portfolio),
|
|
40
|
+
action_label="resynchronize",
|
|
41
|
+
title="Resynchronize/Rebalance",
|
|
42
|
+
instance_display=create_simple_display([["start"], ["end"]]),
|
|
43
|
+
),
|
|
44
|
+
bt.WidgetButton(key="portfolio_positions", label=asset_instrument_btn_label),
|
|
45
|
+
bt.DropDownButton(
|
|
46
|
+
label="Charts",
|
|
47
|
+
icon=WBIcon.UNFOLD.icon,
|
|
48
|
+
buttons=(
|
|
49
|
+
bt.WidgetButton(
|
|
50
|
+
key="portfolio_positions_contributors", label="Contributors (Computed)"
|
|
51
|
+
),
|
|
52
|
+
bt.WidgetButton(key="distribution_chart", label="Distribution Chart"),
|
|
53
|
+
bt.WidgetButton(key="distribution_table", label="Distribution Table"),
|
|
54
|
+
bt.WidgetButton(key="assetschart", label="Portfolio Allocation"),
|
|
55
|
+
),
|
|
56
|
+
),
|
|
57
|
+
]
|
|
58
|
+
)
|
|
59
|
+
return bt.DropDownButton(
|
|
60
|
+
label="Portfolio",
|
|
61
|
+
icon=WBIcon.UNFOLD.icon,
|
|
62
|
+
buttons=buttons,
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
@classmethod
|
|
66
|
+
def add_transactions_request_button(self, request=None, view=None, pk=None, **kwargs):
|
|
67
|
+
return bt.DropDownButton(
|
|
68
|
+
label="Transactions",
|
|
69
|
+
icon=WBIcon.UNFOLD.icon,
|
|
70
|
+
buttons=(
|
|
71
|
+
bt.WidgetButton(key="portfolio_transactions", label="Transactions"),
|
|
72
|
+
bt.WidgetButton(key="portfolio_trades", label="Trades"),
|
|
73
|
+
bt.WidgetButton(key="instrument_subscriptionsredemptions", label="Subscriptions/Redemptions"),
|
|
74
|
+
bt.WidgetButton(key="instrument_trades", label="Trades (Implemented)"),
|
|
75
|
+
bt.WidgetButton(key="portfolio_fees", label="Fees"),
|
|
76
|
+
bt.WidgetButton(key="portfolio_aggregatedfees", label="Aggregated Fees"),
|
|
77
|
+
bt.DropDownButton(
|
|
78
|
+
label="Charts",
|
|
79
|
+
icon=WBIcon.UNFOLD.icon,
|
|
80
|
+
buttons=(
|
|
81
|
+
bt.WidgetButton(key="tradechart", label="Nominal"),
|
|
82
|
+
bt.WidgetButton(key="aumchart", label="AUM"),
|
|
83
|
+
bt.WidgetButton(key="custodiandistribution", label="Custodian Distribution"),
|
|
84
|
+
bt.WidgetButton(key="customerdistribution", label="Customer Distribution"),
|
|
85
|
+
),
|
|
86
|
+
),
|
|
87
|
+
),
|
|
88
|
+
)
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
from datetime import date
|
|
2
|
+
|
|
3
|
+
from django.shortcuts import get_object_or_404
|
|
4
|
+
from rest_framework.reverse import reverse
|
|
5
|
+
from wbcore import serializers as wb_serializers
|
|
6
|
+
from wbcore.contrib.currency.serializers import CurrencyRepresentationSerializer
|
|
7
|
+
from wbcore.contrib.icons import WBIcon
|
|
8
|
+
from wbcore.enums import RequestType
|
|
9
|
+
from wbcore.metadata.configs import buttons as bt
|
|
10
|
+
from wbcore.metadata.configs.buttons.view_config import ButtonViewConfig
|
|
11
|
+
from wbcore.metadata.configs.display.instance_display.shortcuts import (
|
|
12
|
+
create_simple_display,
|
|
13
|
+
)
|
|
14
|
+
from wbportfolio.models import Portfolio, PriceComputation
|
|
15
|
+
from wbportfolio.serializers import (
|
|
16
|
+
PortfolioSynchronizationRepresentationSerializer,
|
|
17
|
+
PriceComputationRepresentationSerializer,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def get_portfolio_start_end_serializer_class(portfolio):
|
|
22
|
+
today = date.today()
|
|
23
|
+
|
|
24
|
+
class StartEndDateSerializer(wb_serializers.Serializer):
|
|
25
|
+
start = wb_serializers.DateField(
|
|
26
|
+
label="Start",
|
|
27
|
+
default=portfolio.assets.earliest("date").date if portfolio.assets.exists() else today,
|
|
28
|
+
)
|
|
29
|
+
end = wb_serializers.DateField(
|
|
30
|
+
label="End", default=portfolio.assets.latest("date").date if portfolio.assets.exists() else today
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
return StartEndDateSerializer
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class PortfolioButtonConfig(ButtonViewConfig):
|
|
37
|
+
def get_custom_instance_buttons(self):
|
|
38
|
+
portfolio_buttons = [
|
|
39
|
+
bt.WidgetButton(key="assets", label="Assets"),
|
|
40
|
+
bt.WidgetButton(key="contributor", label="Contributor"),
|
|
41
|
+
bt.WidgetButton(key="distribution_chart", label="Distribution Chart"),
|
|
42
|
+
bt.WidgetButton(key="distribution_table", label="Distribution Table"),
|
|
43
|
+
bt.WidgetButton(key="modelcomposition", label="Portfolio Composition vs. Dependant Portfolios"),
|
|
44
|
+
]
|
|
45
|
+
if pk := self.view.kwargs.get("pk", None):
|
|
46
|
+
portfolio = get_object_or_404(Portfolio, pk=pk)
|
|
47
|
+
|
|
48
|
+
portfolio_buttons.append(
|
|
49
|
+
bt.ActionButton(
|
|
50
|
+
method=RequestType.PATCH,
|
|
51
|
+
identifiers=("wbportfolio:portfolio",),
|
|
52
|
+
key="resynchronize",
|
|
53
|
+
label="Resynchronize/Rebalance",
|
|
54
|
+
description_fields="""
|
|
55
|
+
<p>Resynchronize portfolio from {{start}} to {{end}}</p>
|
|
56
|
+
""",
|
|
57
|
+
serializer=get_portfolio_start_end_serializer_class(portfolio),
|
|
58
|
+
action_label="resynchronize",
|
|
59
|
+
title="Resynchronize/Rebalance",
|
|
60
|
+
instance_display=create_simple_display([["start"], ["end"]]),
|
|
61
|
+
)
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
bt.DropDownButton(label="Portfolio", icon=WBIcon.UNFOLD.icon, buttons=tuple(portfolio_buttons)),
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
def get_custom_list_instance_buttons(self):
|
|
69
|
+
return self.get_custom_instance_buttons()
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class CreateModelPortfolioSerializer(wb_serializers.ModelSerializer):
|
|
73
|
+
create_index = wb_serializers.BooleanField(default=False, label="Create Underlying Index")
|
|
74
|
+
name = wb_serializers.CharField(required=True)
|
|
75
|
+
_currency = CurrencyRepresentationSerializer(source="currency")
|
|
76
|
+
_portfolio_synchronization = PortfolioSynchronizationRepresentationSerializer(source="portfolio_synchronization")
|
|
77
|
+
price_computation = wb_serializers.PrimaryKeyRelatedField(queryset=PriceComputation.objects.all(), required=False)
|
|
78
|
+
_price_computation = PriceComputationRepresentationSerializer(source="price_computation")
|
|
79
|
+
|
|
80
|
+
class Meta:
|
|
81
|
+
model = Portfolio
|
|
82
|
+
dependency_map = {
|
|
83
|
+
"price_computation": ["create_index"],
|
|
84
|
+
}
|
|
85
|
+
fields = (
|
|
86
|
+
"name",
|
|
87
|
+
"currency",
|
|
88
|
+
"portfolio_synchronization",
|
|
89
|
+
"create_index",
|
|
90
|
+
"price_computation",
|
|
91
|
+
"_price_computation",
|
|
92
|
+
"_currency",
|
|
93
|
+
"_portfolio_synchronization",
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
class ModelPortfolioButtonConfig(PortfolioButtonConfig):
|
|
98
|
+
# pass
|
|
99
|
+
def get_custom_buttons(self):
|
|
100
|
+
if not self.view.kwargs.get("pk", None):
|
|
101
|
+
return {
|
|
102
|
+
bt.ActionButton(
|
|
103
|
+
method=RequestType.POST,
|
|
104
|
+
identifiers=("wbportfolio:portfolio",),
|
|
105
|
+
endpoint=reverse("wbportfolio:modelportfolio-createmodelportfolio", request=self.request),
|
|
106
|
+
label="Create New Model Portfolio",
|
|
107
|
+
serializer=CreateModelPortfolioSerializer,
|
|
108
|
+
action_label="create",
|
|
109
|
+
title="Create Model Portfolio",
|
|
110
|
+
instance_display=create_simple_display(
|
|
111
|
+
[["name", "currency", "portfolio_synchronization"], ["create_index", "price_computation", "."]]
|
|
112
|
+
),
|
|
113
|
+
)
|
|
114
|
+
}
|
|
115
|
+
return set()
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
from wbcore.contrib.icons import WBIcon
|
|
2
|
+
from wbcore.metadata.configs import buttons as bt
|
|
3
|
+
from wbcore.metadata.configs.buttons.view_config import ButtonViewConfig
|
|
4
|
+
from wbfdm.viewsets.configs.buttons.instruments import InstrumentButtonViewConfig
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class ProductButtonConfig(ButtonViewConfig):
|
|
8
|
+
def get_custom_list_instance_buttons(self):
|
|
9
|
+
return self.get_custom_instance_buttons()
|
|
10
|
+
|
|
11
|
+
def get_custom_instance_buttons(self):
|
|
12
|
+
return {
|
|
13
|
+
bt.DropDownButton(
|
|
14
|
+
label="Commission",
|
|
15
|
+
icon=WBIcon.UNFOLD.icon,
|
|
16
|
+
buttons=(
|
|
17
|
+
bt.WidgetButton(key="claims", label="Claims"),
|
|
18
|
+
bt.WidgetButton(key="aum", label="AUM per account"),
|
|
19
|
+
),
|
|
20
|
+
),
|
|
21
|
+
*InstrumentButtonViewConfig(self.view, self.request, self.instance).get_custom_instance_buttons(),
|
|
22
|
+
bt.WidgetButton(
|
|
23
|
+
key="risk_incidents",
|
|
24
|
+
label="Risk Incidents",
|
|
25
|
+
icon=WBIcon.VIEW.icon,
|
|
26
|
+
),
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class ProductCustomerButtonConfig(ButtonViewConfig):
|
|
31
|
+
def get_custom_list_instance_buttons(self):
|
|
32
|
+
return {
|
|
33
|
+
bt.WidgetButton(
|
|
34
|
+
key="historical-chart",
|
|
35
|
+
label="Historical Chart",
|
|
36
|
+
icon=WBIcon.STATS.icon,
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
def get_custom_instance_buttons(self):
|
|
41
|
+
return self.get_custom_list_instance_buttons()
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
from wbcore.contrib.icons import WBIcon
|
|
2
|
+
from wbcore.enums import RequestType
|
|
3
|
+
from wbcore.metadata.configs import buttons as bt
|
|
4
|
+
from wbcore.metadata.configs.buttons.enums import ButtonDefaultColor
|
|
5
|
+
from wbcore.metadata.configs.buttons.view_config import ButtonViewConfig
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class AccountReconciliationButtonViewConfig(ButtonViewConfig):
|
|
9
|
+
def get_custom_instance_buttons(self):
|
|
10
|
+
return {
|
|
11
|
+
bt.ActionButton(
|
|
12
|
+
method=RequestType.PATCH,
|
|
13
|
+
color=ButtonDefaultColor.SUCCESS,
|
|
14
|
+
identifiers=("wbportfolio:accountreconciliation",),
|
|
15
|
+
icon=WBIcon.APPROVE.icon,
|
|
16
|
+
key="agree_customer",
|
|
17
|
+
label="Agree",
|
|
18
|
+
action_label="Agreeing",
|
|
19
|
+
description_fields="<p>After agreening to this holdings, you cannot change this reconcilation anymore!</p>",
|
|
20
|
+
),
|
|
21
|
+
bt.ActionButton(
|
|
22
|
+
method=RequestType.PATCH,
|
|
23
|
+
color=ButtonDefaultColor.ERROR,
|
|
24
|
+
identifiers=("wbportfolio:accountreconciliation",),
|
|
25
|
+
icon=WBIcon.DENY.icon,
|
|
26
|
+
key="disagree_customer",
|
|
27
|
+
label="Communicate Differences",
|
|
28
|
+
action_label="Communicating Differences",
|
|
29
|
+
description_fields="<p>After disagreeing with this holdings, someone will reach out to you do discuss the differences.</p>",
|
|
30
|
+
),
|
|
31
|
+
bt.ActionButton(
|
|
32
|
+
method=RequestType.PATCH,
|
|
33
|
+
color=ButtonDefaultColor.ERROR,
|
|
34
|
+
identifiers=("wbportfolio:accountreconciliationline", "wbportfolio:accountreconciliation"),
|
|
35
|
+
icon=WBIcon.REFRESH.icon,
|
|
36
|
+
key="recalculate",
|
|
37
|
+
label="Recalculate",
|
|
38
|
+
action_label="Recalculating",
|
|
39
|
+
description_fields="<p>After confirming, the Reconciliation will recompute 'Our Calculations'</p>",
|
|
40
|
+
),
|
|
41
|
+
bt.ActionButton(
|
|
42
|
+
method=RequestType.PATCH,
|
|
43
|
+
color=ButtonDefaultColor.WARNING,
|
|
44
|
+
identifiers=("wbportfolio:accountreconciliationline",),
|
|
45
|
+
icon=WBIcon.MAIL.icon,
|
|
46
|
+
key="notify",
|
|
47
|
+
label="Notify Reconciliation Managers",
|
|
48
|
+
action_label="Notifying",
|
|
49
|
+
description_fields="<p>After confirming the reconciliation managers of this account reconciliation will be notified.</p>",
|
|
50
|
+
),
|
|
51
|
+
bt.WidgetButton(key="claims", label="Show Subscriptions/Redemptions", icon=WBIcon.TRADE.icon, weight=200),
|
|
52
|
+
bt.WidgetButton(
|
|
53
|
+
key="add-claim", label="Add Subscription/Redemption", icon=WBIcon.ADD.icon, new_mode=True, weight=300
|
|
54
|
+
),
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class AccountReconciliationLineButtonViewConfig(ButtonViewConfig):
|
|
59
|
+
def get_custom_list_instance_buttons(self):
|
|
60
|
+
return {
|
|
61
|
+
bt.WidgetButton(key="product-claims", label="Show Subscriptions/Redemptions", icon=WBIcon.TRADE.icon),
|
|
62
|
+
bt.WidgetButton(
|
|
63
|
+
key="add-product-claim", label="Add Subscription/Redemption", icon=WBIcon.ADD.icon, new_mode=True
|
|
64
|
+
),
|
|
65
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from wbcore.contrib.icons import WBIcon
|
|
2
|
+
from wbcore.metadata.configs import buttons as bt
|
|
3
|
+
from wbcore.metadata.configs.buttons.view_config import ButtonViewConfig
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class RegisterButtonConfig(ButtonViewConfig):
|
|
7
|
+
def get_custom_list_instance_buttons(self):
|
|
8
|
+
return {bt.WidgetButton(key="trades", label="Trades", icon=WBIcon.TRADE.icon)}
|
|
9
|
+
|
|
10
|
+
def get_custom_instance_buttons(self):
|
|
11
|
+
return self.get_custom_list_instance_buttons()
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
from django.dispatch import receiver
|
|
2
|
+
from wbcore.contrib.directory.viewsets import (
|
|
3
|
+
CompanyModelViewSet,
|
|
4
|
+
EntryModelViewSet,
|
|
5
|
+
PersonModelViewSet,
|
|
6
|
+
)
|
|
7
|
+
from wbcore.contrib.icons import WBIcon
|
|
8
|
+
from wbcore.enums import RequestType
|
|
9
|
+
from wbcore.metadata.configs import buttons as bt
|
|
10
|
+
from wbcore.metadata.configs.display import create_simple_display
|
|
11
|
+
from wbcore.signals.instance_buttons import add_instance_button
|
|
12
|
+
from wbcrm.viewsets import AccountModelViewSet
|
|
13
|
+
from wbfdm.viewsets.instruments import InstrumentModelViewSet
|
|
14
|
+
from wbportfolio.serializers.reconciliations import AccountReconciliationModelSerializer
|
|
15
|
+
|
|
16
|
+
from .mixins import InstrumentButtonMixin
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@receiver(add_instance_button, sender=InstrumentModelViewSet)
|
|
20
|
+
def add_instrument_request_button(sender, many, *args, request=None, view=None, pk=None, **kwargs):
|
|
21
|
+
return InstrumentButtonMixin.add_instrument_request_button(request=request, view=view, pk=pk)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@receiver(add_instance_button, sender=InstrumentModelViewSet)
|
|
25
|
+
def add_transactions_request_button(sender, many, *args, request=None, view=None, pk=None, **kwargs):
|
|
26
|
+
return InstrumentButtonMixin.add_transactions_request_button(request=request, view=view, pk=pk)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@receiver(add_instance_button, sender=PersonModelViewSet)
|
|
30
|
+
@receiver(add_instance_button, sender=EntryModelViewSet)
|
|
31
|
+
@receiver(add_instance_button, sender=CompanyModelViewSet)
|
|
32
|
+
def crm_claim_buttons(sender, many, *args, **kwargs):
|
|
33
|
+
if many:
|
|
34
|
+
return
|
|
35
|
+
return bt.DropDownButton(
|
|
36
|
+
label="Claims",
|
|
37
|
+
icon=WBIcon.UNFOLD.icon,
|
|
38
|
+
buttons=(
|
|
39
|
+
bt.WidgetButton(key="claims", label="Claims", icon=WBIcon.TRADE.icon),
|
|
40
|
+
bt.WidgetButton(key="aum", label="AUM", icon=WBIcon.DOLLAR.icon),
|
|
41
|
+
),
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@receiver(add_instance_button, sender=AccountModelViewSet)
|
|
46
|
+
def add_account_holdings_reconciliation_button(sender, many, *args, **kwargs):
|
|
47
|
+
if many:
|
|
48
|
+
return
|
|
49
|
+
return bt.DropDownButton(
|
|
50
|
+
label="Reconciliations",
|
|
51
|
+
icon=WBIcon.UNFOLD.icon,
|
|
52
|
+
buttons=[
|
|
53
|
+
bt.WidgetButton(
|
|
54
|
+
label="Reconciliations",
|
|
55
|
+
key="wbportfolio-accountreconciliation",
|
|
56
|
+
),
|
|
57
|
+
bt.ActionButton(
|
|
58
|
+
label="Reconcile",
|
|
59
|
+
icon=WBIcon.APPROVE.icon,
|
|
60
|
+
key="wbportfolio-reconcile-account",
|
|
61
|
+
method=RequestType.POST,
|
|
62
|
+
identifiers=("wbportfolio:accountreconciliation", "wbportfolio:accountreconciliationline"),
|
|
63
|
+
action_label="Reconcile this account. A notification will be send to the customer",
|
|
64
|
+
serializer=AccountReconciliationModelSerializer,
|
|
65
|
+
instance_display=create_simple_display([["reconciliation_date"]]),
|
|
66
|
+
),
|
|
67
|
+
],
|
|
68
|
+
)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from wbcore.contrib.icons import WBIcon
|
|
2
|
+
from wbcore.enums import RequestType
|
|
3
|
+
from wbcore.metadata.configs import buttons as bt
|
|
4
|
+
from wbcore.metadata.configs.buttons.view_config import ButtonViewConfig
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class TradeProposalButtonConfig(ButtonViewConfig):
|
|
8
|
+
def get_custom_list_instance_buttons(self):
|
|
9
|
+
return {
|
|
10
|
+
bt.ActionButton(
|
|
11
|
+
method=RequestType.PATCH,
|
|
12
|
+
identifiers=("wbportfolio:tradeproposal",),
|
|
13
|
+
key="replay",
|
|
14
|
+
icon=WBIcon.SYNCHRONIZE.icon,
|
|
15
|
+
label="Replay Trades",
|
|
16
|
+
description_fields="""
|
|
17
|
+
<p>Replay Trades. It will recompute all assets positions until next trade proposal day (or today otherwise) </p>
|
|
18
|
+
""",
|
|
19
|
+
action_label="Replay Trade",
|
|
20
|
+
title="Replay Trade",
|
|
21
|
+
)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
def get_custom_instance_buttons(self):
|
|
25
|
+
return self.get_custom_list_instance_buttons()
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
from rest_framework.reverse import reverse
|
|
2
|
+
from wbcore.contrib.icons import WBIcon
|
|
3
|
+
from wbcore.enums import RequestType
|
|
4
|
+
from wbcore.metadata.configs import buttons as bt
|
|
5
|
+
from wbcore.metadata.configs.buttons.view_config import ButtonViewConfig
|
|
6
|
+
from wbfdm.models import Instrument
|
|
7
|
+
from wbportfolio.models import TradeProposal
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class TradeButtonConfig(ButtonViewConfig):
|
|
11
|
+
def get_custom_list_instance_buttons(self):
|
|
12
|
+
return {bt.WidgetButton(key="claims", label="Claims", icon=WBIcon.TRADE.icon)}
|
|
13
|
+
|
|
14
|
+
def get_custom_instance_buttons(self):
|
|
15
|
+
btn = self.get_custom_list_instance_buttons()
|
|
16
|
+
btn.add(
|
|
17
|
+
bt.HyperlinkButton(
|
|
18
|
+
key="import_source",
|
|
19
|
+
label="Import Source",
|
|
20
|
+
icon=WBIcon.SAVE.icon,
|
|
21
|
+
)
|
|
22
|
+
)
|
|
23
|
+
return btn
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class TradeInstrumentButtonConfig(TradeButtonConfig):
|
|
27
|
+
def get_custom_buttons(self):
|
|
28
|
+
res = set()
|
|
29
|
+
if instrument_id := self.view.kwargs.get("instrument_id", None):
|
|
30
|
+
instrument = Instrument.objects.get(id=instrument_id)
|
|
31
|
+
res = {
|
|
32
|
+
bt.WidgetButton(
|
|
33
|
+
endpoint=reverse(
|
|
34
|
+
"wbportfolio:instrument-custodiandistribution-list", args=[instrument_id], request=self.request
|
|
35
|
+
),
|
|
36
|
+
label="Custodian Distribution",
|
|
37
|
+
),
|
|
38
|
+
bt.WidgetButton(
|
|
39
|
+
endpoint=reverse(
|
|
40
|
+
"wbportfolio:instrument-customerdistribution-list", args=[instrument_id], request=self.request
|
|
41
|
+
),
|
|
42
|
+
label="Customer Distribution",
|
|
43
|
+
),
|
|
44
|
+
}
|
|
45
|
+
if instrument.security_instrument_type.key == "product":
|
|
46
|
+
res.add(
|
|
47
|
+
bt.WidgetButton(
|
|
48
|
+
endpoint=reverse(
|
|
49
|
+
"wbportfolio:product-nominalchart-list", args=[instrument_id], request=self.request
|
|
50
|
+
),
|
|
51
|
+
label="Nominal Chart",
|
|
52
|
+
)
|
|
53
|
+
)
|
|
54
|
+
res.add(
|
|
55
|
+
bt.WidgetButton(
|
|
56
|
+
endpoint=reverse(
|
|
57
|
+
"wbportfolio:product-aumchart-list", args=[instrument_id], request=self.request
|
|
58
|
+
),
|
|
59
|
+
label="AUM Chart",
|
|
60
|
+
)
|
|
61
|
+
)
|
|
62
|
+
return res
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class TradeTradeProposalButtonConfig(ButtonViewConfig):
|
|
66
|
+
def get_custom_buttons(self):
|
|
67
|
+
if trade_proposal_id := self.view.kwargs.get("trade_proposal_id", None):
|
|
68
|
+
trade_proposal = TradeProposal.objects.get(id=trade_proposal_id)
|
|
69
|
+
if trade_proposal.status == TradeProposal.Status.DRAFT:
|
|
70
|
+
return {
|
|
71
|
+
bt.DropDownButton(
|
|
72
|
+
label="Tools",
|
|
73
|
+
buttons=(
|
|
74
|
+
bt.ActionButton(
|
|
75
|
+
method=RequestType.PATCH,
|
|
76
|
+
identifiers=("wbportfolio:tradeproposal",),
|
|
77
|
+
endpoint=reverse(
|
|
78
|
+
"wbportfolio:tradeproposal-reset", args=[trade_proposal_id], request=self.request
|
|
79
|
+
),
|
|
80
|
+
icon=WBIcon.REGENERATE.icon,
|
|
81
|
+
label="Reset Trade",
|
|
82
|
+
description_fields="""
|
|
83
|
+
<p>Delete and recreate initial trades to from its associated model portfolio</p>
|
|
84
|
+
""",
|
|
85
|
+
action_label="Reset Trade",
|
|
86
|
+
title="Reset Trade",
|
|
87
|
+
),
|
|
88
|
+
bt.ActionButton(
|
|
89
|
+
method=RequestType.PATCH,
|
|
90
|
+
identifiers=("wbportfolio:tradeproposal",),
|
|
91
|
+
endpoint=reverse(
|
|
92
|
+
"wbportfolio:tradeproposal-normalize",
|
|
93
|
+
args=[trade_proposal_id],
|
|
94
|
+
request=self.request,
|
|
95
|
+
),
|
|
96
|
+
icon=WBIcon.EDIT.icon,
|
|
97
|
+
label="Normalize Trades",
|
|
98
|
+
description_fields="""
|
|
99
|
+
<p>Make sure all trades normalize to a total target weight of 100%</p>
|
|
100
|
+
""",
|
|
101
|
+
action_label="Normalize Trades",
|
|
102
|
+
title="Normalize Trades",
|
|
103
|
+
),
|
|
104
|
+
bt.ActionButton(
|
|
105
|
+
method=RequestType.PATCH,
|
|
106
|
+
identifiers=("wbportfolio:tradeproposal",),
|
|
107
|
+
endpoint=reverse(
|
|
108
|
+
"wbportfolio:tradeproposal-deleteall",
|
|
109
|
+
args=[trade_proposal_id],
|
|
110
|
+
request=self.request,
|
|
111
|
+
),
|
|
112
|
+
icon=WBIcon.DELETE.icon,
|
|
113
|
+
label="Delete All Trades",
|
|
114
|
+
description_fields="""
|
|
115
|
+
<p>Delete all trades from this trade proposal?</p>
|
|
116
|
+
""",
|
|
117
|
+
action_label="Delete All Trades",
|
|
118
|
+
title="Delete All Trades",
|
|
119
|
+
),
|
|
120
|
+
),
|
|
121
|
+
)
|
|
122
|
+
}
|
|
123
|
+
return {}
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
class TradeProposalButtonConfig(ButtonViewConfig):
|
|
127
|
+
def get_custom_list_instance_buttons(self):
|
|
128
|
+
return {
|
|
129
|
+
bt.ActionButton(
|
|
130
|
+
method=RequestType.PATCH,
|
|
131
|
+
identifiers=("wbportfolio:tradeproposal",),
|
|
132
|
+
key="replay",
|
|
133
|
+
icon=WBIcon.SYNCHRONIZE.icon,
|
|
134
|
+
label="Replay Trades",
|
|
135
|
+
description_fields="""
|
|
136
|
+
<p>Replay Trades. It will recompute all assets positions until next trade proposal day (or today otherwise) </p>
|
|
137
|
+
""",
|
|
138
|
+
action_label="Replay Trade",
|
|
139
|
+
title="Replay Trade",
|
|
140
|
+
)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
def get_custom_instance_buttons(self):
|
|
144
|
+
return self.get_custom_list_instance_buttons()
|