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,171 @@
1
+ from django.db.models import Q, TextChoices
2
+ from django.utils.timezone import localdate
3
+ from wbcore import filters as wb_filters
4
+ from wbcore.pandas.filterset import PandasFilterSetMixin
5
+ from wbcore.utils.date import current_financial_month
6
+ from wbfdm.filters.utils import last_period_date_range
7
+ from wbfdm.models import Instrument
8
+ from wbportfolio.models import Product
9
+
10
+ from .products import BaseProductFilterSet
11
+
12
+
13
+ def current_date(*args, **kwargs):
14
+ return localdate()
15
+
16
+
17
+ class PerformancePandasFilter(PandasFilterSetMixin, BaseProductFilterSet):
18
+ class PerformanceBy(TextChoices):
19
+ NNM = "NNM", "NNM"
20
+ AUM = "AUM", "AUM"
21
+ PRICE = "PRICE", "Price"
22
+
23
+ is_forex_fix = wb_filters.BooleanFilter(label="Fix Forex rate", method="fake_filter", default=False)
24
+
25
+ date = wb_filters.FinancialPerformanceDateRangeFilter(
26
+ label="Date Range",
27
+ method=lambda queryset, label, value: queryset,
28
+ required=True,
29
+ clearable=False,
30
+ default=current_financial_month,
31
+ )
32
+
33
+ performance_by = wb_filters.ChoiceFilter(
34
+ label="Performance By",
35
+ choices=PerformanceBy.choices,
36
+ default=PerformanceBy.PRICE.name,
37
+ method="fake_filter",
38
+ clearable=False,
39
+ required=True,
40
+ )
41
+ white_label_customers = (
42
+ classifications
43
+ ) = classifications_neq = unclassified = invested = portfolio = content_type = tags = None
44
+
45
+ class Meta:
46
+ model = Product
47
+ fields = {}
48
+ df_fields = {
49
+ "diff__gte": wb_filters.NumberFilter(
50
+ precision=2, label="Difference", lookup_expr="gte", field_name="diff"
51
+ ),
52
+ "perf__gte": wb_filters.NumberFilter(
53
+ precision=2, label="Performance", lookup_expr="gte", field_name="perf"
54
+ ),
55
+ "n1__gte": wb_filters.NumberFilter(precision=2, label="N1", lookup_expr="gte", field_name="n1"),
56
+ "n2__gte": wb_filters.NumberFilter(precision=2, label="N2", lookup_expr="gte", field_name="n2"),
57
+ "n1_usd__gte": wb_filters.NumberFilter(
58
+ precision=2, label="N1 (USD)", lookup_expr="gte", field_name="n1_usd"
59
+ ),
60
+ "n2_usd__gte": wb_filters.NumberFilter(
61
+ precision=2, label="N2 (USD)", lookup_expr="gte", field_name="n2_usd"
62
+ ),
63
+ "diff_usd__gte": wb_filters.NumberFilter(
64
+ precision=2, label="Difference (USD)", lookup_expr="gte", field_name="diff_usd"
65
+ ),
66
+ "perf_usd__gte": wb_filters.NumberFilter(
67
+ precision=2, label="Performance (USD)", lookup_expr="gte", field_name="perf_usd"
68
+ ),
69
+ "diff__lte": wb_filters.NumberFilter(
70
+ precision=2, label="Difference", lookup_expr="lte", field_name="diff"
71
+ ),
72
+ "perf__lte": wb_filters.NumberFilter(
73
+ precision=2, label="Performance", lookup_expr="lte", field_name="perf"
74
+ ),
75
+ "n1__lte": wb_filters.NumberFilter(precision=2, label="N1", lookup_expr="lte", field_name="n1"),
76
+ "n2__lte": wb_filters.NumberFilter(precision=2, label="N2", lookup_expr="lte", field_name="n2"),
77
+ "n1_usd__lte": wb_filters.NumberFilter(
78
+ precision=2, label="N1 (USD)", lookup_expr="lte", field_name="n1_usd"
79
+ ),
80
+ "n2_usd__lte": wb_filters.NumberFilter(
81
+ precision=2, label="N2 (USD)", lookup_expr="lte", field_name="n2_usd"
82
+ ),
83
+ "diff_usd__lte": wb_filters.NumberFilter(
84
+ precision=2, label="Difference (USD)", lookup_expr="lte", field_name="diff_usd"
85
+ ),
86
+ "perf_usd__lte": wb_filters.NumberFilter(
87
+ precision=2, label="Performance (USD)", lookup_expr="lte", field_name="perf_usd"
88
+ ),
89
+ }
90
+
91
+
92
+ class ProductPerformanceNetNewMoneyFilter(PandasFilterSetMixin, BaseProductFilterSet):
93
+ is_active = wb_filters.BooleanFilter(label="Is Active", method="filter_active_products", default=True)
94
+ net_negative_money__gte = wb_filters.NumberFilter(
95
+ label="Net Negative money", lookup_expr="gte", field_name="net_negative_money"
96
+ )
97
+ net_negative_money__lte = wb_filters.NumberFilter(
98
+ label="Net Negative money", lookup_expr="lte", field_name="net_negative_money"
99
+ )
100
+ net_positive_money__gte = wb_filters.NumberFilter(
101
+ label="Net Positive money", lookup_expr="gte", field_name="net_positive_money"
102
+ )
103
+ net_positive_money__lte = wb_filters.NumberFilter(
104
+ label="Net Positive money", lookup_expr="lte", field_name="net_positive_money"
105
+ )
106
+ net_positive_money_usd__gte = wb_filters.NumberFilter(
107
+ label="Net Positive money ($)", lookup_expr="gte", field_name="net_positive_money_usd"
108
+ )
109
+ net_positive_money_usd__lte = wb_filters.NumberFilter(
110
+ label="Net Positive money ($)", lookup_expr="lte", field_name="net_positive_money_usd"
111
+ )
112
+ net_negative_money_usd__gte = wb_filters.NumberFilter(
113
+ label="Net Negative money ($)", lookup_expr="gte", field_name="net_negative_money_usd"
114
+ )
115
+ net_negative_money_usd__lte = wb_filters.NumberFilter(
116
+ label="Net Negative money ($)", lookup_expr="lte", field_name="net_negative_money_usd"
117
+ )
118
+ net_money__gte = wb_filters.NumberFilter(label="Net Money", lookup_expr="gte", field_name="net_money")
119
+ net_money__lte = wb_filters.NumberFilter(label="Net Money", lookup_expr="lte", field_name="net_money")
120
+ net_money_usd__gte = wb_filters.NumberFilter(label="Net Money ($)", lookup_expr="gte", field_name="net_money_usd")
121
+ net_money_usd__lte = wb_filters.NumberFilter(label="Net Money ($)", lookup_expr="lte", field_name="net_money_usd")
122
+
123
+ date = wb_filters.DateRangeFilter(
124
+ label="Date Range",
125
+ method=lambda queryset, label, value: queryset,
126
+ required=True,
127
+ clearable=False,
128
+ default=last_period_date_range,
129
+ )
130
+
131
+ def filter_active_products(self, queryset, name, value):
132
+ if value is True:
133
+ return queryset.filter(~Q(net_money=0.0))
134
+ elif value is False:
135
+ return queryset.filter(Q(net_money=0.0))
136
+
137
+ return queryset
138
+
139
+ white_label_customers = (
140
+ classifications
141
+ ) = classifications_neq = unclassified = invested = portfolio = content_type = tags = None
142
+
143
+ class Meta:
144
+ model = Product
145
+ fields = {
146
+ "computed_str": ["exact", "icontains"],
147
+ }
148
+
149
+
150
+ class PerformanceComparisonFilter(PandasFilterSetMixin, BaseProductFilterSet):
151
+ classifications = unclassified = invested = None
152
+ dates = wb_filters.FinancialPerformanceDateRangeFilter(
153
+ method=lambda q, n, v: q, label="Compute Performance between these dates"
154
+ )
155
+
156
+ comparison_instrument = wb_filters.ModelChoiceFilter(
157
+ label="Compare with...",
158
+ queryset=Instrument.objects.all(),
159
+ endpoint=Instrument.get_representation_endpoint(),
160
+ value_key=Instrument.get_representation_value_key(),
161
+ label_key=Instrument.get_representation_label_key(),
162
+ filter_params={"level": 0},
163
+ method="fake_filter",
164
+ )
165
+ compare_primary_benchmark = wb_filters.BooleanFilter(
166
+ default=False, label="Compare against primary benchmark", method="fake_filter"
167
+ )
168
+
169
+ class Meta:
170
+ model = Product
171
+ fields = {}
@@ -0,0 +1,24 @@
1
+ from wbcore import filters as wb_filters
2
+ from wbfdm.models import Instrument
3
+ from wbportfolio.models import Portfolio
4
+
5
+
6
+ class PortfolioFilterSet(wb_filters.FilterSet):
7
+ instrument = wb_filters.ModelChoiceFilter(
8
+ label="Instrument",
9
+ queryset=Instrument.objects.all(),
10
+ endpoint=Instrument.get_representation_endpoint(),
11
+ value_key=Instrument.get_representation_value_key(),
12
+ label_key=Instrument.get_representation_label_key(),
13
+ filter_params={"is_managed": True},
14
+ method="filter_instrument",
15
+ )
16
+
17
+ def filter_instrument(self, queryset, name, value):
18
+ if value:
19
+ return queryset.filter(instruments=value)
20
+ return queryset
21
+
22
+ class Meta:
23
+ model = Portfolio
24
+ fields = {"currency": ["exact"], "is_manageable": ["exact"]}
@@ -0,0 +1,178 @@
1
+ import datetime as dt
2
+
3
+ from django.db.models import TextChoices
4
+ from pandas.tseries.offsets import BDay
5
+ from wbcore import filters as wb_filters
6
+ from wbcore.contrib.currency.models import CurrencyFXRates
7
+ from wbcore.pandas.filterset import PandasFilterSetMixin
8
+ from wbcore.utils.date import current_financial_month
9
+ from wbportfolio.filters.assets import (
10
+ DateFilterMixin,
11
+ get_latest_end_quarter_date_asset_position,
12
+ )
13
+ from wbportfolio.models import AssetPosition
14
+
15
+
16
+ class GroupbyChoice(TextChoices):
17
+ UNDERLYING_INSTRUMENT = "UNDERLYING_INSTRUMENT", "Underlying Instrument"
18
+ CURRENCY = "CURRENCY", "Currency"
19
+ COUNTRY = "COUNTRY", "Country"
20
+ PORTFOLIO = "PORTFOLIO", "Portfolio"
21
+ PRIMARY_CLASSIFICATION = "PRIMARY_CLASSIFICATION", "Primary Classification (Specified Height)"
22
+ PREFERRED_CLASSIFICATION = "PREFERRED_CLASSIFICATION", "Preferred Classification (Specified Height)"
23
+
24
+ @classmethod
25
+ def get_id(cls, name: str) -> str:
26
+ return {
27
+ "UNDERLYING_INSTRUMENT": "underlying_instrument",
28
+ "CURRENCY": "underlying_instrument__currency",
29
+ "COUNTRY": "underlying_instrument__country",
30
+ "PORTFOLIO": "portfolio",
31
+ "PRIMARY_CLASSIFICATION": "classification_id",
32
+ "PREFERRED_CLASSIFICATION": "classification_id",
33
+ }[name]
34
+
35
+ @classmethod
36
+ def get_repr(cls, name: str) -> str:
37
+ return {
38
+ "UNDERLYING_INSTRUMENT": "underlying_instrument__name_repr",
39
+ "CURRENCY": "underlying_instrument__currency__key",
40
+ "COUNTRY": "underlying_instrument__country__name",
41
+ "PORTFOLIO": "portfolio__name",
42
+ "PRIMARY_CLASSIFICATION": "classification_title",
43
+ "PREFERRED_CLASSIFICATION": "classification_title",
44
+ }[name]
45
+
46
+
47
+ def get_latest_date_based_on_multiple_models(field, request, view):
48
+ models = [AssetPosition.objects, CurrencyFXRates.objects]
49
+ default_date = (dt.date.today() - BDay(1)).date() # default latest date
50
+ if not any(model.exists() for model in models): # if at least one model is empty, it return the default date.
51
+ return default_date
52
+
53
+ def get_most_recent_common_date(date):
54
+ for model in models:
55
+ latest_model_date = model.filter(date__lte=date).latest("date").date
56
+ if latest_model_date != date:
57
+ return get_most_recent_common_date(latest_model_date)
58
+ return date
59
+
60
+ latest_date = get_most_recent_common_date(default_date)
61
+ return latest_date
62
+
63
+
64
+ class AssetPositionPandasFilter(DateFilterMixin, PandasFilterSetMixin, wb_filters.FilterSet):
65
+ # price_start = wb_filters.NumberFilter(label="Price Start")
66
+ # price_end = wb_filters.NumberFilter(label="Price End")
67
+
68
+ date = total_value_fx_usd = total_value_fx_usd__gte = total_value_fx_usd__lte = None
69
+
70
+ date = wb_filters.FinancialPerformanceDateRangeFilter(
71
+ method=wb_filters.DateRangeFilter.base_date_range_filter_method,
72
+ label="Date Range",
73
+ required=True,
74
+ clearable=False,
75
+ default=current_financial_month,
76
+ )
77
+
78
+ group_by = wb_filters.ChoiceFilter(
79
+ label="Group By",
80
+ choices=GroupbyChoice.choices,
81
+ default=GroupbyChoice.UNDERLYING_INSTRUMENT,
82
+ method="fake_filter",
83
+ clearable=False,
84
+ required=True,
85
+ )
86
+
87
+ groupby_classification_height = wb_filters.NumberFilter(
88
+ method="fake_filter", label="Classification Height (groupby)", default=0, clearable=False, required=True
89
+ )
90
+
91
+ class Meta:
92
+ model = AssetPosition
93
+ fields = {
94
+ # "price_start" : ["gte", "exact", "lte"],
95
+ # "price_end" : ["gte", "exact", "lte"],
96
+ "underlying_instrument": ["exact"],
97
+ "portfolio": ["exact"],
98
+ "currency": ["exact"],
99
+ "exchange": ["exact"],
100
+ }
101
+ df_fields = {
102
+ "total_value_start__gte": wb_filters.NumberFilter(
103
+ precision=1, label="Total Value Start", lookup_expr="gte", field_name="total_value_start"
104
+ ),
105
+ "total_value_end__gte": wb_filters.NumberFilter(
106
+ precision=1, label="Total Value End", lookup_expr="gte", field_name="total_value_end"
107
+ ),
108
+ "allocation_start__gte": wb_filters.NumberFilter(
109
+ precision=2, label="Weighting Start", lookup_expr="gte", field_name="allocation_start"
110
+ ),
111
+ "allocation_end__gte": wb_filters.NumberFilter(
112
+ precision=2, label="Weighting End", lookup_expr="gte", field_name="allocation_end"
113
+ ),
114
+ "performance_total__gte": wb_filters.NumberFilter(
115
+ precision=2, label="Total Performance", lookup_expr="gte", field_name="performance_total"
116
+ ),
117
+ "contribution_total__gte": wb_filters.NumberFilter(
118
+ precision=2, label="Total Contribution", lookup_expr="gte", field_name="contribution_total"
119
+ ),
120
+ "performance_forex__gte": wb_filters.NumberFilter(
121
+ precision=2, label="Forex Performance", lookup_expr="gte", field_name="performance_forex"
122
+ ),
123
+ "contribution_forex__gte": wb_filters.NumberFilter(
124
+ precision=2, label="Forex Contribution", lookup_expr="gte", field_name="contribution_forex"
125
+ ),
126
+ "market_share__gte": wb_filters.NumberFilter(
127
+ precision=2, label="Market Shares", lookup_expr="gte", field_name="market_share"
128
+ ),
129
+ "total_value_start__lte": wb_filters.NumberFilter(
130
+ lookup_expr="lte", field_name="total_value_start", precision=1, label="Total Value Start"
131
+ ),
132
+ "total_value_end__lte": wb_filters.NumberFilter(
133
+ lookup_expr="lte", field_name="total_value_end", precision=1, label="Total Value End"
134
+ ),
135
+ "allocation_start__lte": wb_filters.NumberFilter(
136
+ lookup_expr="lte", field_name="allocation_start", precision=2, label="Weighting Start"
137
+ ),
138
+ "allocation_end__lte": wb_filters.NumberFilter(
139
+ lookup_expr="lte", field_name="allocation_end", precision=2, label="Weighting End"
140
+ ),
141
+ "performance_total__lte": wb_filters.NumberFilter(
142
+ lookup_expr="lte", field_name="performance_total", precision=2, label="Total Performance"
143
+ ),
144
+ "contribution_total__lte": wb_filters.NumberFilter(
145
+ lookup_expr="lte", field_name="contribution_total", precision=2, label="Total Contribution"
146
+ ),
147
+ "performance_forex__lte": wb_filters.NumberFilter(
148
+ lookup_expr="lte", field_name="performance_forex", precision=2, label="Forex Performance"
149
+ ),
150
+ "contribution_forex__lte": wb_filters.NumberFilter(
151
+ lookup_expr="lte", field_name="contribution_forex", precision=2, label="Forex Contribution"
152
+ ),
153
+ "market_share__lte": wb_filters.NumberFilter(
154
+ lookup_expr="lte", field_name="market_share", precision=2, label="Market Shares"
155
+ ),
156
+ }
157
+
158
+
159
+ class AggregatedAssetPositionLiquidityFilter(PandasFilterSetMixin, wb_filters.FilterSet):
160
+ historic_date = wb_filters.DateFilter(
161
+ label="Historic Date",
162
+ method=lambda queryset, label, value: queryset,
163
+ default=get_latest_date_based_on_multiple_models,
164
+ required=True,
165
+ )
166
+ compared_date = wb_filters.DateFilter(
167
+ label="Compared Date",
168
+ method=lambda queryset, label, value: queryset,
169
+ default=get_latest_end_quarter_date_asset_position,
170
+ required=True,
171
+ )
172
+ bigger_than_x = wb_filters.NumberFilter(
173
+ label="Bigger Than..", method=lambda queryset, label, value: queryset, default=1.00, required=True, precision=2
174
+ )
175
+
176
+ class Meta:
177
+ model = AssetPosition
178
+ fields = {}
@@ -0,0 +1,157 @@
1
+ from django.db.models import Q
2
+ from wbcore import filters as wb_filters
3
+ from wbcore.contrib.directory.models import Company, Entry
4
+ from wbfdm.filters.instruments import InstrumentFilterSet
5
+ from wbfdm.filters.utils import last_period_date_range
6
+ from wbfdm.models import Classification
7
+ from wbportfolio.models import Product, ProductGroup
8
+
9
+
10
+ class BaseProductFilterSet(InstrumentFilterSet):
11
+ classifications = wb_filters.ModelChoiceFilter(
12
+ label="Classification",
13
+ queryset=Classification.objects.all(),
14
+ endpoint=Classification.get_representation_endpoint(),
15
+ value_key=Classification.get_representation_value_key(),
16
+ label_key=Classification.get_representation_label_key(),
17
+ filter_params={"instrument_type_key": "product"},
18
+ method="filter_classification",
19
+ )
20
+
21
+ bank = wb_filters.ModelMultipleChoiceFilter(
22
+ label="Bank",
23
+ queryset=Company.bank_objects.all(),
24
+ endpoint=Company.get_representation_endpoint(),
25
+ filter_params={"bank_product": True},
26
+ value_key=Company.get_representation_value_key(),
27
+ label_key=Company.get_representation_label_key(),
28
+ )
29
+ white_label_customers = wb_filters.ModelMultipleChoiceFilter(
30
+ label="White Label Customers",
31
+ queryset=Entry.objects.all(),
32
+ endpoint=Entry.get_representation_endpoint(),
33
+ value_key=Entry.get_representation_value_key(),
34
+ label_key=Entry.get_representation_label_key(),
35
+ )
36
+ parent = wb_filters.ModelChoiceFilter(
37
+ label="Group",
38
+ queryset=ProductGroup.objects.all(),
39
+ endpoint=ProductGroup.get_representation_endpoint(),
40
+ value_key=ProductGroup.get_representation_value_key(),
41
+ label_key=ProductGroup.get_representation_label_key(),
42
+ )
43
+ is_invested = wb_filters.BooleanFilter(label="Invested")
44
+ is_active = wb_filters.BooleanFilter(label="Only Active", method="filter_is_active", default=True)
45
+
46
+ class Meta:
47
+ model = Product
48
+ fields = {"currency": ["exact"]}
49
+
50
+
51
+ class ProductFilter(BaseProductFilterSet):
52
+ is_white_label = wb_filters.BooleanFilter(label="Is White Label", method="filter_is_white_label")
53
+
54
+ net_value = wb_filters.NumberFilter(label="Last NAV")
55
+ net_value__gte = wb_filters.NumberFilter(field_name="net_value", label="Last NAV", lookup_expr="gte")
56
+ net_value__lte = wb_filters.NumberFilter(field_name="net_value", label="Last NAV", lookup_expr="lte")
57
+
58
+ assets_under_management__gte = wb_filters.NumberFilter(
59
+ lookup_expr="gte", field_name="assets_under_management", label="Asset under management"
60
+ )
61
+ assets_under_management__lte = wb_filters.NumberFilter(
62
+ lookup_expr="lte", field_name="assets_under_management", label="Asset under management"
63
+ )
64
+
65
+ assets_under_management_usd__gte = wb_filters.NumberFilter(
66
+ lookup_expr="gte", field_name="assets_under_management_usd", label="Asset under management ($)"
67
+ )
68
+ assets_under_management_usd__lte = wb_filters.NumberFilter(
69
+ lookup_expr="lte", field_name="assets_under_management_usd", label="Asset under management ($)"
70
+ )
71
+
72
+ last_valuation_date = wb_filters.DateFilter(
73
+ field_name="last_valuation_date", lookup_expr="exact", label="Last Valuation Date"
74
+ )
75
+
76
+ def filter_is_white_label(self, queryset, name, value):
77
+ if value:
78
+ return queryset.filter(is_white_label=True)
79
+ return queryset
80
+
81
+ class Meta(BaseProductFilterSet.Meta):
82
+ fields = {
83
+ "isin": ["exact", "icontains"],
84
+ "ticker": ["exact", "icontains"],
85
+ "currency": ["exact"],
86
+ }
87
+
88
+
89
+ class ProductCustomerFilter(wb_filters.FilterSet):
90
+ net_value = wb_filters.NumberFilter(label="Net Value")
91
+ net_value__gte = wb_filters.NumberFilter(field_name="net_value", label="Last NAV", lookup_expr="gte")
92
+ net_value__lte = wb_filters.NumberFilter(field_name="net_value", label="Last NAV", lookup_expr="lte")
93
+
94
+ class Meta:
95
+ model = Product
96
+ fields = {}
97
+
98
+
99
+ class ProductFeeFilter(BaseProductFilterSet):
100
+ sum_management_fees = wb_filters.NumberFilter(label="Sum Management Fees")
101
+ sum_management_fees__gte = wb_filters.NumberFilter(
102
+ lookup_expr="gte", field_name="sum_management_fees", label="Sum Management Fees"
103
+ )
104
+ sum_management_fees__lte = wb_filters.NumberFilter(
105
+ lookup_expr="lte", field_name="sum_management_fees", label="Sum Management Fees"
106
+ )
107
+
108
+ sum_management_fees_usd__gte = wb_filters.NumberFilter(
109
+ lookup_expr="gte", field_name="sum_management_fees_usd", label="Sum Management Fees (USD)"
110
+ )
111
+ sum_performance_fees_net__gte = wb_filters.NumberFilter(
112
+ lookup_expr="gte", field_name="sum_performance_fees_net", label="Sum Performance Fees"
113
+ )
114
+ sum_performance_fees_net_usd__gte = wb_filters.NumberFilter(
115
+ lookup_expr="gte", field_name="sum_performance_fees_net_usd", label="Sum Performance Fees (USD)"
116
+ )
117
+ sum_total_usd__gte = wb_filters.NumberFilter(
118
+ lookup_expr="gte", field_name="sum_total_usd", label="Total Fees (USD)"
119
+ )
120
+
121
+ sum_management_fees_usd__lte = wb_filters.NumberFilter(
122
+ lookup_expr="lte", field_name="sum_management_fees_usd", label="Sum Management Fees (USD)"
123
+ )
124
+ sum_performance_fees_net__lte = wb_filters.NumberFilter(
125
+ lookup_expr="lte", field_name="sum_performance_fees_net", label="Sum Performance Fees"
126
+ )
127
+ sum_performance_fees_net_usd__lte = wb_filters.NumberFilter(
128
+ lookup_expr="lte", field_name="sum_performance_fees_net_usd", label="Sum Performance Fees (USD)"
129
+ )
130
+ sum_total_usd__lte = wb_filters.NumberFilter(
131
+ lookup_expr="lte", field_name="sum_total_usd", label="Total Fees (USD)"
132
+ )
133
+
134
+ assets_under_management__gte = (
135
+ assets_under_management__lte
136
+ ) = (
137
+ assets_under_management_usd__gte
138
+ ) = (
139
+ assets_under_management_usd__lte
140
+ ) = date = net_value = net_value__lte = net_value__gte = assets_under_management_usd = name = ticker = None
141
+
142
+ date = wb_filters.DateRangeFilter(
143
+ label="Date Range",
144
+ method=lambda queryset, label, value: queryset,
145
+ required=True,
146
+ clearable=False,
147
+ default=last_period_date_range(),
148
+ )
149
+
150
+ def filter_active_products(self, queryset, name, value):
151
+ if value:
152
+ return queryset.filter(~(Q(sum_management_fees=0.0) & Q(sum_performance_fees_net=0.0)))
153
+ return queryset
154
+
155
+ class Meta:
156
+ model = Product
157
+ fields = {"currency": ["exact"]}
@@ -0,0 +1,26 @@
1
+ from django.db.models import Q
2
+ from django.utils import timezone
3
+ from wbcore import filters as wb_filters
4
+ from wbportfolio.models import PortfolioRole
5
+
6
+
7
+ class PortfolioRoleFilterSet(wb_filters.FilterSet):
8
+ is_active = wb_filters.BooleanFilter(method="filter_is_active", default=True, label="Is Active")
9
+
10
+ def filter_is_active(self, queryset, name, value):
11
+ if value is True:
12
+ return queryset.filter(Q(end__isnull=True) | Q(end__gte=timezone.now())).distinct()
13
+ elif value is False:
14
+ return queryset.filter(end__lte=timezone.now())
15
+ return queryset
16
+
17
+ class Meta:
18
+ model = PortfolioRole
19
+ fields = {
20
+ "role_type": ["exact"],
21
+ "person": ["exact"],
22
+ "start": ["gte", "exact", "lte"],
23
+ "end": ["gte", "exact", "lte"],
24
+ "weighting": ["gte", "exact", "lte"],
25
+ "instrument": ["exact"],
26
+ }
@@ -0,0 +1,92 @@
1
+ from datetime import date
2
+
3
+ from django.db.models import Exists, OuterRef
4
+ from django.dispatch import receiver
5
+ from wbcore import filters as wb_filters
6
+ from wbcore.contrib.directory.filters import CompanyFilter
7
+ from wbcore.signals.filters import add_filters
8
+ from wbfdm.filters import BaseClassifiedInstrumentFilterSet, ClassificationFilter
9
+ from wbfdm.models import InstrumentClassificationThroughModel
10
+ from wbportfolio.models import AssetPosition, Portfolio
11
+
12
+
13
+ @receiver(add_filters, sender=CompanyFilter)
14
+ def add_bank_product_filter(sender, request=None, *args, **kwargs):
15
+ def method_bank(queryset, name, value):
16
+ if value is True:
17
+ return queryset.filter(issues_products__isnull=False).distinct()
18
+ elif value is False:
19
+ return queryset.filter(issues_products__isnull=True).distinct()
20
+ return queryset
21
+
22
+ return {
23
+ "bank_product": wb_filters.BooleanFilter(
24
+ field_name="bank_product",
25
+ label="Is a Bank",
26
+ help_text="Filter for companies that are a bank and serve as the custodian of a product in the PMS",
27
+ method=method_bank,
28
+ )
29
+ }
30
+
31
+
32
+ @receiver(add_filters, sender=ClassificationFilter)
33
+ def add_portfolio_filter(sender, request=None, *args, **kwargs):
34
+ def _filter_portfolio(queryset, name, value):
35
+ if value:
36
+ try:
37
+ last_position_date = value.assets.latest("date").date
38
+ except AssetPosition.DoesNotExist:
39
+ last_position_date = (
40
+ AssetPosition.objects.latest("date").date if AssetPosition.objects.exists() else date.today()
41
+ )
42
+ invested_instruments = AssetPosition.get_invested_instruments(last_position_date, portfolio=value)
43
+ rels = InstrumentClassificationThroughModel.objects.filter(
44
+ instrument__in=invested_instruments.values("root")
45
+ )
46
+ return queryset.filter(id__in=rels.values("classification"))
47
+ return queryset
48
+
49
+ def _filter_invested(queryset, name, value):
50
+ if value:
51
+ last_position_date = (
52
+ AssetPosition.objects.latest("date").date if AssetPosition.objects.exists() else date.today()
53
+ )
54
+ invested_instruments = AssetPosition.get_invested_instruments(last_position_date)
55
+ rels = InstrumentClassificationThroughModel.objects.filter(
56
+ instrument__in=invested_instruments.values("root")
57
+ )
58
+ return queryset.filter(id__in=rels.values("classification"))
59
+ return queryset
60
+
61
+ return {
62
+ "portfolio": wb_filters.ModelChoiceFilter(
63
+ label="Associated Portfolio",
64
+ queryset=Portfolio.objects.all(),
65
+ endpoint=Portfolio.get_representation_endpoint(),
66
+ value_key=Portfolio.get_representation_value_key(),
67
+ label_key=Portfolio.get_representation_label_key(),
68
+ method=_filter_portfolio,
69
+ ),
70
+ "only_invested": wb_filters.BooleanFilter(
71
+ label="Only invested instruments (anytime)",
72
+ method=_filter_invested,
73
+ ),
74
+ }
75
+
76
+
77
+ @receiver(add_filters, sender=BaseClassifiedInstrumentFilterSet)
78
+ def add_classification_instrument_filter(sender, request=None, *args, **kwargs):
79
+ def _filter_invested(queryset, name, value):
80
+ if value:
81
+ last_invested_date = (
82
+ AssetPosition.objects.latest("date").date if AssetPosition.objects.exists() else date.today()
83
+ )
84
+ invested_instruments = AssetPosition.get_invested_instruments(last_invested_date)
85
+ return queryset.filter(Exists(invested_instruments.filter(root=OuterRef("instrument"))))
86
+ return queryset
87
+
88
+ return {
89
+ "only_invested": wb_filters.BooleanFilter(
90
+ method=_filter_invested, label="Invested Instruments (last date)", default=False
91
+ )
92
+ }
@@ -0,0 +1,20 @@
1
+ from .claim import (
2
+ ClaimFilter,
3
+ ClaimGroupByFilter,
4
+ ConsolidatedTradeSummaryTableFilterSet,
5
+ CumulativeNNMChartFilter,
6
+ CustomerAPIFilter,
7
+ CustomerClaimFilter,
8
+ CustomerClaimGroupByFilter,
9
+ NegativeTermimalAccountPerProductFilterSet,
10
+ ProfitAndLossPandasFilter,
11
+ )
12
+ from .fees import FeesAggregatedFilter, FeesFilter, FeesPortfolioFilterSet
13
+ from .trades import (
14
+ SubscriptionRedemptionFilterSet,
15
+ SubscriptionRedemptionPortfolioFilterSet,
16
+ TradeFilter,
17
+ TradeInstrumentFilterSet,
18
+ TradePortfolioFilter,
19
+ )
20
+ from .transactions import TransactionFilterSet, TransactionPortfolioFilterSet