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.

Files changed (486) hide show
  1. wbportfolio/__init__.py +1 -0
  2. wbportfolio/admin/__init__.py +12 -0
  3. wbportfolio/admin/asset.py +47 -0
  4. wbportfolio/admin/custodians.py +9 -0
  5. wbportfolio/admin/portfolio.py +127 -0
  6. wbportfolio/admin/portfolio_relationships.py +22 -0
  7. wbportfolio/admin/product_groups.py +42 -0
  8. wbportfolio/admin/products.py +80 -0
  9. wbportfolio/admin/reconciliations.py +14 -0
  10. wbportfolio/admin/registers.py +17 -0
  11. wbportfolio/admin/roles.py +19 -0
  12. wbportfolio/admin/synchronization/__init__.py +2 -0
  13. wbportfolio/admin/synchronization/admin.py +114 -0
  14. wbportfolio/admin/synchronization/portfolio_synchronization.py +18 -0
  15. wbportfolio/admin/synchronization/price_computation.py +21 -0
  16. wbportfolio/admin/transactions/__init__.py +5 -0
  17. wbportfolio/admin/transactions/claim.py +16 -0
  18. wbportfolio/admin/transactions/dividends.py +14 -0
  19. wbportfolio/admin/transactions/fees.py +35 -0
  20. wbportfolio/admin/transactions/trades.py +49 -0
  21. wbportfolio/admin/transactions/transactions.py +37 -0
  22. wbportfolio/analysis/__init__.py +0 -0
  23. wbportfolio/analysis/claims.py +235 -0
  24. wbportfolio/apps.py +5 -0
  25. wbportfolio/contrib/__init__.py +0 -0
  26. wbportfolio/contrib/company_portfolio/__init__.py +0 -0
  27. wbportfolio/contrib/company_portfolio/admin.py +28 -0
  28. wbportfolio/contrib/company_portfolio/apps.py +29 -0
  29. wbportfolio/contrib/company_portfolio/configs/__init__.py +3 -0
  30. wbportfolio/contrib/company_portfolio/configs/display.py +182 -0
  31. wbportfolio/contrib/company_portfolio/configs/endpoints.py +34 -0
  32. wbportfolio/contrib/company_portfolio/configs/previews.py +37 -0
  33. wbportfolio/contrib/company_portfolio/constants.py +1 -0
  34. wbportfolio/contrib/company_portfolio/dynamic_preferences_registry.py +87 -0
  35. wbportfolio/contrib/company_portfolio/factories.py +32 -0
  36. wbportfolio/contrib/company_portfolio/filters.py +127 -0
  37. wbportfolio/contrib/company_portfolio/management.py +19 -0
  38. wbportfolio/contrib/company_portfolio/migrations/0001_initial.py +214 -0
  39. wbportfolio/contrib/company_portfolio/migrations/__init__.py +0 -0
  40. wbportfolio/contrib/company_portfolio/models.py +334 -0
  41. wbportfolio/contrib/company_portfolio/scripts.py +76 -0
  42. wbportfolio/contrib/company_portfolio/serializers.py +303 -0
  43. wbportfolio/contrib/company_portfolio/tasks.py +19 -0
  44. wbportfolio/contrib/company_portfolio/tests/__init__.py +0 -0
  45. wbportfolio/contrib/company_portfolio/tests/conftest.py +161 -0
  46. wbportfolio/contrib/company_portfolio/tests/test_models.py +161 -0
  47. wbportfolio/contrib/company_portfolio/urls.py +29 -0
  48. wbportfolio/contrib/company_portfolio/viewsets.py +195 -0
  49. wbportfolio/defaults/__init__.py +0 -0
  50. wbportfolio/defaults/fees/__init__.py +0 -0
  51. wbportfolio/defaults/fees/default.py +92 -0
  52. wbportfolio/defaults/portfolio/__init__.py +0 -0
  53. wbportfolio/defaults/portfolio/default_rebalancing.py +45 -0
  54. wbportfolio/dynamic_preferences_registry.py +58 -0
  55. wbportfolio/factories/__init__.py +35 -0
  56. wbportfolio/factories/adjustments.py +17 -0
  57. wbportfolio/factories/assets.py +75 -0
  58. wbportfolio/factories/claim.py +39 -0
  59. wbportfolio/factories/custodians.py +11 -0
  60. wbportfolio/factories/dividends.py +14 -0
  61. wbportfolio/factories/fees.py +15 -0
  62. wbportfolio/factories/indexes.py +17 -0
  63. wbportfolio/factories/portfolio_cash_flow.py +20 -0
  64. wbportfolio/factories/portfolio_cash_targets.py +15 -0
  65. wbportfolio/factories/portfolio_swing_pricings.py +15 -0
  66. wbportfolio/factories/portfolios.py +59 -0
  67. wbportfolio/factories/product_groups.py +28 -0
  68. wbportfolio/factories/products.py +56 -0
  69. wbportfolio/factories/pytest_utils.py +121 -0
  70. wbportfolio/factories/reconciliations.py +23 -0
  71. wbportfolio/factories/roles.py +20 -0
  72. wbportfolio/factories/synchronization.py +40 -0
  73. wbportfolio/factories/trades.py +35 -0
  74. wbportfolio/factories/transactions.py +21 -0
  75. wbportfolio/fdm/__init__.py +0 -0
  76. wbportfolio/fdm/tasks.py +12 -0
  77. wbportfolio/filters/__init__.py +32 -0
  78. wbportfolio/filters/assets.py +485 -0
  79. wbportfolio/filters/assets_and_net_new_money_progression.py +42 -0
  80. wbportfolio/filters/custodians.py +10 -0
  81. wbportfolio/filters/esg.py +22 -0
  82. wbportfolio/filters/performances.py +171 -0
  83. wbportfolio/filters/portfolios.py +24 -0
  84. wbportfolio/filters/positions.py +178 -0
  85. wbportfolio/filters/products.py +157 -0
  86. wbportfolio/filters/roles.py +26 -0
  87. wbportfolio/filters/signals.py +92 -0
  88. wbportfolio/filters/transactions/__init__.py +20 -0
  89. wbportfolio/filters/transactions/claim.py +394 -0
  90. wbportfolio/filters/transactions/fees.py +66 -0
  91. wbportfolio/filters/transactions/trades.py +224 -0
  92. wbportfolio/filters/transactions/transactions.py +98 -0
  93. wbportfolio/import_export/__init__.py +0 -0
  94. wbportfolio/import_export/backends/__init__.py +2 -0
  95. wbportfolio/import_export/backends/ubs/__init__.py +3 -0
  96. wbportfolio/import_export/backends/ubs/asset_position.py +45 -0
  97. wbportfolio/import_export/backends/ubs/fees.py +63 -0
  98. wbportfolio/import_export/backends/ubs/instrument_price.py +44 -0
  99. wbportfolio/import_export/backends/ubs/mixin.py +15 -0
  100. wbportfolio/import_export/backends/utils.py +58 -0
  101. wbportfolio/import_export/backends/wbfdm/__init__.py +2 -0
  102. wbportfolio/import_export/backends/wbfdm/adjustment.py +50 -0
  103. wbportfolio/import_export/backends/wbfdm/dividend.py +16 -0
  104. wbportfolio/import_export/backends/wbfdm/mixin.py +15 -0
  105. wbportfolio/import_export/handlers/__init__.py +0 -0
  106. wbportfolio/import_export/handlers/adjustment.py +39 -0
  107. wbportfolio/import_export/handlers/asset_position.py +167 -0
  108. wbportfolio/import_export/handlers/dividend.py +80 -0
  109. wbportfolio/import_export/handlers/fees.py +58 -0
  110. wbportfolio/import_export/handlers/portfolio_cash_flow.py +57 -0
  111. wbportfolio/import_export/handlers/register.py +43 -0
  112. wbportfolio/import_export/handlers/trade.py +191 -0
  113. wbportfolio/import_export/parsers/__init__.py +0 -0
  114. wbportfolio/import_export/parsers/default_mapping.py +30 -0
  115. wbportfolio/import_export/parsers/jpmorgan/__init__.py +0 -0
  116. wbportfolio/import_export/parsers/jpmorgan/customer_trade.py +63 -0
  117. wbportfolio/import_export/parsers/jpmorgan/fees.py +64 -0
  118. wbportfolio/import_export/parsers/jpmorgan/strategy.py +116 -0
  119. wbportfolio/import_export/parsers/jpmorgan/valuation.py +41 -0
  120. wbportfolio/import_export/parsers/leonteq/__init__.py +0 -0
  121. wbportfolio/import_export/parsers/leonteq/customer_trade.py +47 -0
  122. wbportfolio/import_export/parsers/leonteq/equity.py +81 -0
  123. wbportfolio/import_export/parsers/leonteq/fees.py +70 -0
  124. wbportfolio/import_export/parsers/leonteq/trade.py +94 -0
  125. wbportfolio/import_export/parsers/leonteq/valuation.py +39 -0
  126. wbportfolio/import_export/parsers/natixis/__init__.py +0 -0
  127. wbportfolio/import_export/parsers/natixis/customer_trade.py +62 -0
  128. wbportfolio/import_export/parsers/natixis/d1_customer_trade.py +66 -0
  129. wbportfolio/import_export/parsers/natixis/d1_equity.py +80 -0
  130. wbportfolio/import_export/parsers/natixis/d1_fees.py +58 -0
  131. wbportfolio/import_export/parsers/natixis/d1_trade.py +70 -0
  132. wbportfolio/import_export/parsers/natixis/d1_valuation.py +41 -0
  133. wbportfolio/import_export/parsers/natixis/dividend.py +53 -0
  134. wbportfolio/import_export/parsers/natixis/equity.py +60 -0
  135. wbportfolio/import_export/parsers/natixis/fees.py +53 -0
  136. wbportfolio/import_export/parsers/natixis/trade.py +63 -0
  137. wbportfolio/import_export/parsers/natixis/utils.py +76 -0
  138. wbportfolio/import_export/parsers/natixis/valuation.py +46 -0
  139. wbportfolio/import_export/parsers/refinitiv/__init__.py +0 -0
  140. wbportfolio/import_export/parsers/refinitiv/adjustment.py +24 -0
  141. wbportfolio/import_export/parsers/sg_lux/__init__.py +0 -0
  142. wbportfolio/import_export/parsers/sg_lux/custodian_positions.py +70 -0
  143. wbportfolio/import_export/parsers/sg_lux/customer_trade.py +75 -0
  144. wbportfolio/import_export/parsers/sg_lux/customer_trade_pending_slk.py +140 -0
  145. wbportfolio/import_export/parsers/sg_lux/customer_trade_slk.py +80 -0
  146. wbportfolio/import_export/parsers/sg_lux/customer_trade_without_pw.py +57 -0
  147. wbportfolio/import_export/parsers/sg_lux/equity.py +137 -0
  148. wbportfolio/import_export/parsers/sg_lux/fees.py +56 -0
  149. wbportfolio/import_export/parsers/sg_lux/perf_fees.py +51 -0
  150. wbportfolio/import_export/parsers/sg_lux/portfolio_cash_flow.py +29 -0
  151. wbportfolio/import_export/parsers/sg_lux/portfolio_future_cash_flow.py +36 -0
  152. wbportfolio/import_export/parsers/sg_lux/registers.py +210 -0
  153. wbportfolio/import_export/parsers/sg_lux/sylk.py +248 -0
  154. wbportfolio/import_export/parsers/sg_lux/utils.py +36 -0
  155. wbportfolio/import_export/parsers/sg_lux/valuation.py +53 -0
  156. wbportfolio/import_export/parsers/societe_generale/__init__.py +0 -0
  157. wbportfolio/import_export/parsers/societe_generale/customer_trade.py +54 -0
  158. wbportfolio/import_export/parsers/societe_generale/strategy.py +94 -0
  159. wbportfolio/import_export/parsers/societe_generale/valuation.py +37 -0
  160. wbportfolio/import_export/parsers/tellco/__init__.py +0 -0
  161. wbportfolio/import_export/parsers/tellco/customer_trade.py +64 -0
  162. wbportfolio/import_export/parsers/tellco/equity.py +86 -0
  163. wbportfolio/import_export/parsers/tellco/valuation.py +52 -0
  164. wbportfolio/import_export/parsers/ubs/__init__.py +0 -0
  165. wbportfolio/import_export/parsers/ubs/api/__init__.py +0 -0
  166. wbportfolio/import_export/parsers/ubs/api/asset_position.py +106 -0
  167. wbportfolio/import_export/parsers/ubs/api/fees.py +31 -0
  168. wbportfolio/import_export/parsers/ubs/api/instrument_price.py +20 -0
  169. wbportfolio/import_export/parsers/ubs/api/utils.py +0 -0
  170. wbportfolio/import_export/parsers/ubs/customer_trade.py +60 -0
  171. wbportfolio/import_export/parsers/ubs/equity.py +97 -0
  172. wbportfolio/import_export/parsers/ubs/historical_customer_trade.py +67 -0
  173. wbportfolio/import_export/parsers/ubs/valuation.py +52 -0
  174. wbportfolio/import_export/parsers/vontobel/__init__.py +0 -0
  175. wbportfolio/import_export/parsers/vontobel/asset_position.py +97 -0
  176. wbportfolio/import_export/parsers/vontobel/customer_trade.py +54 -0
  177. wbportfolio/import_export/parsers/vontobel/historical_customer_trade.py +40 -0
  178. wbportfolio/import_export/parsers/vontobel/instrument.py +34 -0
  179. wbportfolio/import_export/parsers/vontobel/management_fees.py +86 -0
  180. wbportfolio/import_export/parsers/vontobel/performance_fees.py +35 -0
  181. wbportfolio/import_export/parsers/vontobel/trade.py +38 -0
  182. wbportfolio/import_export/parsers/vontobel/utils.py +17 -0
  183. wbportfolio/import_export/parsers/vontobel/valuation.py +29 -0
  184. wbportfolio/import_export/resources/__init__.py +0 -0
  185. wbportfolio/import_export/resources/assets.py +68 -0
  186. wbportfolio/import_export/resources/trades.py +41 -0
  187. wbportfolio/import_export/utils.py +42 -0
  188. wbportfolio/metric/__init__.py +0 -0
  189. wbportfolio/metric/backends/__init__.py +2 -0
  190. wbportfolio/metric/backends/base.py +86 -0
  191. wbportfolio/metric/backends/constants.py +222 -0
  192. wbportfolio/metric/backends/portfolio_base.py +255 -0
  193. wbportfolio/metric/backends/portfolio_esg.py +66 -0
  194. wbportfolio/metric/tests/__init__.py +0 -0
  195. wbportfolio/metric/tests/conftest.py +4 -0
  196. wbportfolio/metric/tests/test_portfolio_base.py +135 -0
  197. wbportfolio/metric/tests/test_portfolio_esg.py +69 -0
  198. wbportfolio/migrations/0001_initial_squashed.py +13848 -0
  199. wbportfolio/migrations/0002_product_default_sub_account_squashed_0039_alter_assetallocation_company_and_more.py +3836 -0
  200. wbportfolio/migrations/0040_instrument_financial_instrument.py +26 -0
  201. wbportfolio/migrations/0041_remove_listresearch_research_ptr_and_more.py +129 -0
  202. wbportfolio/migrations/0042_instrumentlist_instrumentlistthroughmodel_and_more.py +71 -0
  203. wbportfolio/migrations/0043_alter_instrumentlistthroughmodel_options_and_more.py +238 -0
  204. wbportfolio/migrations/0044_alter_instrumentlist_identifier.py +35 -0
  205. wbportfolio/migrations/0045_alter_instrument_financial_instrument.py +26 -0
  206. wbportfolio/migrations/0046_add_product_default_account.py +166 -0
  207. wbportfolio/migrations/0047_remove_product_default_sub_account.py +14 -0
  208. wbportfolio/migrations/0048_alter_trade_status.py +29 -0
  209. wbportfolio/migrations/0049_trade_claimed_shares.py +25 -0
  210. wbportfolio/migrations/0050_fees_fee_date_fees_wbportfolio_transac_1f7a29_idx.py +44 -0
  211. wbportfolio/migrations/0051_delete_macroreview.py +11 -0
  212. wbportfolio/migrations/0052_remove_cash_instrument_ptr_and_more.py +888 -0
  213. wbportfolio/migrations/0053_remove_product_group.py +132 -0
  214. wbportfolio/migrations/0054_portfolioinstrumentpreferredclassificationthroughmodel_and_more.py +270 -0
  215. wbportfolio/migrations/0055_remove_product__custom_management_rebates_and_more.py +139 -0
  216. wbportfolio/migrations/0056_remove_companyportfoliodata_assets_under_management_currency_and_more.py +56 -0
  217. wbportfolio/migrations/0057_alter_portfolio_preferred_instrument_classifications_and_more.py +36 -0
  218. wbportfolio/migrations/0058_pmsinstrument.py +23 -0
  219. wbportfolio/migrations/0059_fees_unique_fees.py +51 -0
  220. wbportfolio/migrations/0060_alter_portfolioportfoliothroughmodel_type.py +21 -0
  221. wbportfolio/migrations/0061_portfolio_bank_accounts_product_bank_account_and_more.py +175 -0
  222. wbportfolio/migrations/0062_alter_dailyportfoliocashflow_options.py +20 -0
  223. wbportfolio/migrations/0063_accountreconciliation_accountreconciliationline_and_more.py +133 -0
  224. wbportfolio/migrations/0064_alter_portfolio_managers_portfolio_is_tracked_and_more.py +40 -0
  225. wbportfolio/migrations/0065_alter_portfolio_managers_claim_as_shares_and_more.py +73 -0
  226. wbportfolio/migrations/0066_assetposition_initial_shares_at_custodian_and_more.py +108 -0
  227. wbportfolio/migrations/0067_assetposition_unique_asset_position.py +77 -0
  228. wbportfolio/migrations/0068_trade_internal_trade_trade_marked_as_internal_and_more.py +59 -0
  229. wbportfolio/migrations/0069_remove_portfolio_is_invested_and_more.py +56 -0
  230. wbportfolio/migrations/0070_remove_assetposition_unique_asset_position_and_more.py +82 -0
  231. wbportfolio/migrations/0071_alter_trade_options_alter_trade_order.py +22 -0
  232. wbportfolio/migrations/__init__.py +0 -0
  233. wbportfolio/models/__init__.py +26 -0
  234. wbportfolio/models/adjustments.py +246 -0
  235. wbportfolio/models/asset.py +869 -0
  236. wbportfolio/models/custodians.py +101 -0
  237. wbportfolio/models/indexes.py +33 -0
  238. wbportfolio/models/mixins/__init__.py +0 -0
  239. wbportfolio/models/mixins/instruments.py +127 -0
  240. wbportfolio/models/mixins/liquidity_stress_test.py +1307 -0
  241. wbportfolio/models/portfolio.py +1039 -0
  242. wbportfolio/models/portfolio_cash_flow.py +167 -0
  243. wbportfolio/models/portfolio_cash_targets.py +46 -0
  244. wbportfolio/models/portfolio_relationship.py +135 -0
  245. wbportfolio/models/portfolio_swing_pricings.py +51 -0
  246. wbportfolio/models/product_groups.py +230 -0
  247. wbportfolio/models/products.py +569 -0
  248. wbportfolio/models/reconciliations/__init__.py +2 -0
  249. wbportfolio/models/reconciliations/account_reconciliation_lines.py +192 -0
  250. wbportfolio/models/reconciliations/account_reconciliations.py +102 -0
  251. wbportfolio/models/reconciliations/reconciliations.py +25 -0
  252. wbportfolio/models/registers.py +132 -0
  253. wbportfolio/models/roles.py +208 -0
  254. wbportfolio/models/synchronization/__init__.py +3 -0
  255. wbportfolio/models/synchronization/portfolio_synchronization.py +292 -0
  256. wbportfolio/models/synchronization/price_computation.py +200 -0
  257. wbportfolio/models/synchronization/synchronization.py +188 -0
  258. wbportfolio/models/transactions/__init__.py +7 -0
  259. wbportfolio/models/transactions/claim.py +634 -0
  260. wbportfolio/models/transactions/dividends.py +31 -0
  261. wbportfolio/models/transactions/expiry.py +7 -0
  262. wbportfolio/models/transactions/fees.py +153 -0
  263. wbportfolio/models/transactions/trade_proposals.py +502 -0
  264. wbportfolio/models/transactions/trades.py +704 -0
  265. wbportfolio/models/transactions/transactions.py +211 -0
  266. wbportfolio/models/utils.py +12 -0
  267. wbportfolio/permissions.py +13 -0
  268. wbportfolio/pms/__init__.py +0 -0
  269. wbportfolio/pms/statistics/__init__.py +0 -0
  270. wbportfolio/pms/trading/__init__.py +1 -0
  271. wbportfolio/pms/trading/handler.py +164 -0
  272. wbportfolio/pms/typing.py +194 -0
  273. wbportfolio/preferences.py +6 -0
  274. wbportfolio/reports/__init__.py +0 -0
  275. wbportfolio/reports/monthly_position_report.py +74 -0
  276. wbportfolio/risk_management/__init__.py +0 -0
  277. wbportfolio/risk_management/backends/__init__.py +11 -0
  278. wbportfolio/risk_management/backends/accounts.py +166 -0
  279. wbportfolio/risk_management/backends/controversy_portfolio.py +63 -0
  280. wbportfolio/risk_management/backends/exposure_portfolio.py +203 -0
  281. wbportfolio/risk_management/backends/instrument_list_portfolio.py +89 -0
  282. wbportfolio/risk_management/backends/liquidity_risk.py +86 -0
  283. wbportfolio/risk_management/backends/liquidity_stress_instrument.py +86 -0
  284. wbportfolio/risk_management/backends/mixins.py +220 -0
  285. wbportfolio/risk_management/backends/product_integrity.py +111 -0
  286. wbportfolio/risk_management/backends/stop_loss_instrument.py +24 -0
  287. wbportfolio/risk_management/backends/stop_loss_portfolio.py +36 -0
  288. wbportfolio/risk_management/backends/ucits_portfolio.py +63 -0
  289. wbportfolio/risk_management/tests/__init__.py +0 -0
  290. wbportfolio/risk_management/tests/conftest.py +15 -0
  291. wbportfolio/risk_management/tests/test_accounts.py +98 -0
  292. wbportfolio/risk_management/tests/test_controversy_portfolio.py +33 -0
  293. wbportfolio/risk_management/tests/test_exposure_portfolio.py +94 -0
  294. wbportfolio/risk_management/tests/test_instrument_list_portfolio.py +60 -0
  295. wbportfolio/risk_management/tests/test_liquidity_risk.py +47 -0
  296. wbportfolio/risk_management/tests/test_product_integrity.py +55 -0
  297. wbportfolio/risk_management/tests/test_stop_loss_instrument.py +110 -0
  298. wbportfolio/risk_management/tests/test_stop_loss_portfolio.py +119 -0
  299. wbportfolio/risk_management/tests/test_ucits_portfolio.py +39 -0
  300. wbportfolio/serializers/__init__.py +42 -0
  301. wbportfolio/serializers/adjustments.py +24 -0
  302. wbportfolio/serializers/assets.py +166 -0
  303. wbportfolio/serializers/custodians.py +26 -0
  304. wbportfolio/serializers/portfolio_cash_flow.py +48 -0
  305. wbportfolio/serializers/portfolio_cash_targets.py +20 -0
  306. wbportfolio/serializers/portfolio_relationship.py +53 -0
  307. wbportfolio/serializers/portfolio_swing_pricing.py +20 -0
  308. wbportfolio/serializers/portfolios.py +143 -0
  309. wbportfolio/serializers/positions.py +76 -0
  310. wbportfolio/serializers/product_group.py +88 -0
  311. wbportfolio/serializers/products.py +331 -0
  312. wbportfolio/serializers/reconciliations.py +171 -0
  313. wbportfolio/serializers/registers.py +72 -0
  314. wbportfolio/serializers/roles.py +60 -0
  315. wbportfolio/serializers/signals.py +157 -0
  316. wbportfolio/serializers/synchronization.py +18 -0
  317. wbportfolio/serializers/transactions/__init__.py +24 -0
  318. wbportfolio/serializers/transactions/claim.py +310 -0
  319. wbportfolio/serializers/transactions/dividends.py +18 -0
  320. wbportfolio/serializers/transactions/expiry.py +18 -0
  321. wbportfolio/serializers/transactions/fees.py +32 -0
  322. wbportfolio/serializers/transactions/trades.py +315 -0
  323. wbportfolio/serializers/transactions/transactions.py +84 -0
  324. wbportfolio/tasks.py +125 -0
  325. wbportfolio/tests/__init__.py +0 -0
  326. wbportfolio/tests/conftest.py +164 -0
  327. wbportfolio/tests/models/__init__.py +0 -0
  328. wbportfolio/tests/models/test_account_reconciliation.py +191 -0
  329. wbportfolio/tests/models/test_assets.py +193 -0
  330. wbportfolio/tests/models/test_custodians.py +12 -0
  331. wbportfolio/tests/models/test_customer_trades.py +113 -0
  332. wbportfolio/tests/models/test_dividends.py +7 -0
  333. wbportfolio/tests/models/test_imports.py +192 -0
  334. wbportfolio/tests/models/test_instrument_mixins.py +48 -0
  335. wbportfolio/tests/models/test_merge.py +133 -0
  336. wbportfolio/tests/models/test_portfolio_cash_flow.py +112 -0
  337. wbportfolio/tests/models/test_portfolio_cash_targets.py +27 -0
  338. wbportfolio/tests/models/test_portfolio_swing_pricings.py +42 -0
  339. wbportfolio/tests/models/test_portfolios.py +676 -0
  340. wbportfolio/tests/models/test_product_groups.py +80 -0
  341. wbportfolio/tests/models/test_products.py +187 -0
  342. wbportfolio/tests/models/test_roles.py +82 -0
  343. wbportfolio/tests/models/test_splits.py +233 -0
  344. wbportfolio/tests/models/test_synchronization.py +617 -0
  345. wbportfolio/tests/models/transactions/__init__.py +0 -0
  346. wbportfolio/tests/models/transactions/test_claim.py +129 -0
  347. wbportfolio/tests/models/transactions/test_fees.py +65 -0
  348. wbportfolio/tests/models/transactions/test_trades.py +204 -0
  349. wbportfolio/tests/models/utils.py +13 -0
  350. wbportfolio/tests/serializers/__init__.py +0 -0
  351. wbportfolio/tests/serializers/test_claims.py +21 -0
  352. wbportfolio/tests/signals.py +151 -0
  353. wbportfolio/tests/tests.py +31 -0
  354. wbportfolio/tests/viewsets/__init__.py +0 -0
  355. wbportfolio/tests/viewsets/test_assets.py +67 -0
  356. wbportfolio/tests/viewsets/test_performances.py +72 -0
  357. wbportfolio/tests/viewsets/test_products.py +92 -0
  358. wbportfolio/tests/viewsets/transactions/__init__.py +0 -0
  359. wbportfolio/tests/viewsets/transactions/test_claims.py +146 -0
  360. wbportfolio/urls.py +247 -0
  361. wbportfolio/utils.py +30 -0
  362. wbportfolio/viewsets/__init__.py +57 -0
  363. wbportfolio/viewsets/adjustments.py +46 -0
  364. wbportfolio/viewsets/assets.py +562 -0
  365. wbportfolio/viewsets/assets_and_net_new_money_progression.py +117 -0
  366. wbportfolio/viewsets/charts/__init__.py +1 -0
  367. wbportfolio/viewsets/charts/assets.py +247 -0
  368. wbportfolio/viewsets/configs/__init__.py +6 -0
  369. wbportfolio/viewsets/configs/buttons/__init__.py +23 -0
  370. wbportfolio/viewsets/configs/buttons/adjustments.py +13 -0
  371. wbportfolio/viewsets/configs/buttons/assets.py +145 -0
  372. wbportfolio/viewsets/configs/buttons/claims.py +83 -0
  373. wbportfolio/viewsets/configs/buttons/custodians.py +76 -0
  374. wbportfolio/viewsets/configs/buttons/fees.py +14 -0
  375. wbportfolio/viewsets/configs/buttons/mixins.py +88 -0
  376. wbportfolio/viewsets/configs/buttons/portfolios.py +115 -0
  377. wbportfolio/viewsets/configs/buttons/products.py +41 -0
  378. wbportfolio/viewsets/configs/buttons/reconciliations.py +65 -0
  379. wbportfolio/viewsets/configs/buttons/registers.py +11 -0
  380. wbportfolio/viewsets/configs/buttons/signals.py +68 -0
  381. wbportfolio/viewsets/configs/buttons/trade_proposals.py +25 -0
  382. wbportfolio/viewsets/configs/buttons/trades.py +144 -0
  383. wbportfolio/viewsets/configs/display/__init__.py +61 -0
  384. wbportfolio/viewsets/configs/display/adjustments.py +81 -0
  385. wbportfolio/viewsets/configs/display/assets.py +265 -0
  386. wbportfolio/viewsets/configs/display/claim.py +299 -0
  387. wbportfolio/viewsets/configs/display/custodians.py +24 -0
  388. wbportfolio/viewsets/configs/display/esg.py +88 -0
  389. wbportfolio/viewsets/configs/display/fees.py +133 -0
  390. wbportfolio/viewsets/configs/display/portfolio_cash_flow.py +103 -0
  391. wbportfolio/viewsets/configs/display/portfolio_relationship.py +38 -0
  392. wbportfolio/viewsets/configs/display/portfolios.py +125 -0
  393. wbportfolio/viewsets/configs/display/positions.py +75 -0
  394. wbportfolio/viewsets/configs/display/product_groups.py +54 -0
  395. wbportfolio/viewsets/configs/display/product_performance.py +241 -0
  396. wbportfolio/viewsets/configs/display/products.py +249 -0
  397. wbportfolio/viewsets/configs/display/reconciliations.py +151 -0
  398. wbportfolio/viewsets/configs/display/registers.py +71 -0
  399. wbportfolio/viewsets/configs/display/roles.py +49 -0
  400. wbportfolio/viewsets/configs/display/trade_proposals.py +97 -0
  401. wbportfolio/viewsets/configs/display/trades.py +359 -0
  402. wbportfolio/viewsets/configs/display/transactions.py +55 -0
  403. wbportfolio/viewsets/configs/endpoints/__init__.py +75 -0
  404. wbportfolio/viewsets/configs/endpoints/adjustments.py +17 -0
  405. wbportfolio/viewsets/configs/endpoints/assets.py +115 -0
  406. wbportfolio/viewsets/configs/endpoints/claim.py +106 -0
  407. wbportfolio/viewsets/configs/endpoints/custodians.py +6 -0
  408. wbportfolio/viewsets/configs/endpoints/esg.py +14 -0
  409. wbportfolio/viewsets/configs/endpoints/fees.py +26 -0
  410. wbportfolio/viewsets/configs/endpoints/portfolio_relationship.py +23 -0
  411. wbportfolio/viewsets/configs/endpoints/portfolios.py +43 -0
  412. wbportfolio/viewsets/configs/endpoints/positions.py +18 -0
  413. wbportfolio/viewsets/configs/endpoints/product_groups.py +11 -0
  414. wbportfolio/viewsets/configs/endpoints/product_performance.py +29 -0
  415. wbportfolio/viewsets/configs/endpoints/products.py +37 -0
  416. wbportfolio/viewsets/configs/endpoints/reconciliations.py +31 -0
  417. wbportfolio/viewsets/configs/endpoints/roles.py +9 -0
  418. wbportfolio/viewsets/configs/endpoints/trade_proposals.py +17 -0
  419. wbportfolio/viewsets/configs/endpoints/trades.py +82 -0
  420. wbportfolio/viewsets/configs/endpoints/transactions.py +17 -0
  421. wbportfolio/viewsets/configs/menu/__init__.py +30 -0
  422. wbportfolio/viewsets/configs/menu/adjustments.py +8 -0
  423. wbportfolio/viewsets/configs/menu/assets.py +8 -0
  424. wbportfolio/viewsets/configs/menu/claim.py +41 -0
  425. wbportfolio/viewsets/configs/menu/custodians.py +11 -0
  426. wbportfolio/viewsets/configs/menu/fees.py +13 -0
  427. wbportfolio/viewsets/configs/menu/instrument_prices.py +10 -0
  428. wbportfolio/viewsets/configs/menu/portfolio_cash_flow.py +8 -0
  429. wbportfolio/viewsets/configs/menu/portfolios.py +15 -0
  430. wbportfolio/viewsets/configs/menu/positions.py +14 -0
  431. wbportfolio/viewsets/configs/menu/product_groups.py +10 -0
  432. wbportfolio/viewsets/configs/menu/product_performance.py +25 -0
  433. wbportfolio/viewsets/configs/menu/products.py +15 -0
  434. wbportfolio/viewsets/configs/menu/reconciliations.py +7 -0
  435. wbportfolio/viewsets/configs/menu/registers.py +10 -0
  436. wbportfolio/viewsets/configs/menu/roles.py +16 -0
  437. wbportfolio/viewsets/configs/menu/trades.py +18 -0
  438. wbportfolio/viewsets/configs/menu/transactions.py +8 -0
  439. wbportfolio/viewsets/configs/previews/__init__.py +1 -0
  440. wbportfolio/viewsets/configs/previews/portfolios.py +21 -0
  441. wbportfolio/viewsets/configs/titles/__init__.py +65 -0
  442. wbportfolio/viewsets/configs/titles/adjustments.py +19 -0
  443. wbportfolio/viewsets/configs/titles/assets.py +57 -0
  444. wbportfolio/viewsets/configs/titles/assets_and_net_new_money_progression.py +6 -0
  445. wbportfolio/viewsets/configs/titles/claim.py +81 -0
  446. wbportfolio/viewsets/configs/titles/custodians.py +12 -0
  447. wbportfolio/viewsets/configs/titles/esg.py +10 -0
  448. wbportfolio/viewsets/configs/titles/fees.py +25 -0
  449. wbportfolio/viewsets/configs/titles/instrument_prices.py +20 -0
  450. wbportfolio/viewsets/configs/titles/portfolios.py +32 -0
  451. wbportfolio/viewsets/configs/titles/positions.py +11 -0
  452. wbportfolio/viewsets/configs/titles/product_groups.py +12 -0
  453. wbportfolio/viewsets/configs/titles/product_performance.py +16 -0
  454. wbportfolio/viewsets/configs/titles/products.py +6 -0
  455. wbportfolio/viewsets/configs/titles/registers.py +12 -0
  456. wbportfolio/viewsets/configs/titles/roles.py +23 -0
  457. wbportfolio/viewsets/configs/titles/trades.py +51 -0
  458. wbportfolio/viewsets/configs/titles/transactions.py +8 -0
  459. wbportfolio/viewsets/custodians.py +66 -0
  460. wbportfolio/viewsets/esg.py +165 -0
  461. wbportfolio/viewsets/mixins.py +48 -0
  462. wbportfolio/viewsets/portfolio_cash_flow.py +31 -0
  463. wbportfolio/viewsets/portfolio_cash_targets.py +8 -0
  464. wbportfolio/viewsets/portfolio_relationship.py +46 -0
  465. wbportfolio/viewsets/portfolio_swing_pricing.py +8 -0
  466. wbportfolio/viewsets/portfolios.py +154 -0
  467. wbportfolio/viewsets/positions.py +292 -0
  468. wbportfolio/viewsets/product_groups.py +84 -0
  469. wbportfolio/viewsets/product_performance.py +646 -0
  470. wbportfolio/viewsets/products.py +529 -0
  471. wbportfolio/viewsets/reconciliations.py +160 -0
  472. wbportfolio/viewsets/registers.py +75 -0
  473. wbportfolio/viewsets/roles.py +44 -0
  474. wbportfolio/viewsets/signals.py +42 -0
  475. wbportfolio/viewsets/synchronization.py +25 -0
  476. wbportfolio/viewsets/transactions/__init__.py +40 -0
  477. wbportfolio/viewsets/transactions/claim.py +933 -0
  478. wbportfolio/viewsets/transactions/fees.py +190 -0
  479. wbportfolio/viewsets/transactions/mixins.py +19 -0
  480. wbportfolio/viewsets/transactions/trade_proposals.py +93 -0
  481. wbportfolio/viewsets/transactions/trades.py +395 -0
  482. wbportfolio/viewsets/transactions/transactions.py +123 -0
  483. wbportfolio-2.2.1.dist-info/METADATA +21 -0
  484. wbportfolio-2.2.1.dist-info/RECORD +486 -0
  485. wbportfolio-2.2.1.dist-info/WHEEL +5 -0
  486. 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()