wbportfolio 1.47.1__tar.gz → 1.49.0__tar.gz

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 (528) hide show
  1. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/PKG-INFO +1 -1
  2. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/contrib/company_portfolio/tasks.py +8 -4
  3. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/dynamic_preferences_registry.py +9 -0
  4. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/factories/__init__.py +1 -3
  5. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/factories/portfolios.py +0 -12
  6. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/factories/product_groups.py +8 -1
  7. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/factories/products.py +18 -0
  8. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/factories/trades.py +5 -1
  9. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/handlers/trade.py +8 -0
  10. wbportfolio-1.49.0/wbportfolio/import_export/resources/trades.py +55 -0
  11. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/metric/backends/base.py +3 -15
  12. wbportfolio-1.49.0/wbportfolio/migrations/0075_portfolio_initial_position_date_and_more.py +28 -0
  13. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/models/__init__.py +1 -2
  14. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/models/asset.py +1 -1
  15. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/models/portfolio.py +20 -13
  16. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/models/products.py +50 -1
  17. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/models/transactions/rebalancing.py +7 -1
  18. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/models/transactions/trade_proposals.py +172 -67
  19. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/models/transactions/trades.py +34 -25
  20. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/pms/trading/handler.py +1 -1
  21. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/pms/typing.py +3 -0
  22. wbportfolio-1.49.0/wbportfolio/preferences.py +11 -0
  23. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/rebalancing/models/composite.py +14 -1
  24. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/risk_management/backends/accounts.py +14 -6
  25. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/risk_management/backends/exposure_portfolio.py +36 -5
  26. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/risk_management/tests/test_exposure_portfolio.py +47 -0
  27. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/serializers/portfolios.py +26 -0
  28. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/serializers/transactions/trade_proposals.py +2 -13
  29. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/serializers/transactions/trades.py +13 -0
  30. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/tasks.py +4 -1
  31. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/tests/conftest.py +1 -1
  32. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/tests/models/test_portfolios.py +1 -1
  33. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/tests/models/test_products.py +26 -0
  34. wbportfolio-1.49.0/wbportfolio/tests/models/transactions/test_trade_proposals.py +381 -0
  35. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/tests/models/transactions/test_trades.py +14 -0
  36. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/tests/signals.py +1 -1
  37. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/tests/viewsets/test_performances.py +2 -1
  38. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/display/portfolios.py +58 -14
  39. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/display/trades.py +23 -8
  40. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/endpoints/trades.py +9 -0
  41. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/portfolios.py +22 -7
  42. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/transactions/trade_proposals.py +21 -2
  43. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/transactions/trades.py +86 -12
  44. wbportfolio-1.47.1/wbportfolio/import_export/resources/trades.py +0 -66
  45. wbportfolio-1.47.1/wbportfolio/preferences.py +0 -6
  46. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/.gitignore +0 -0
  47. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/LICENSE +0 -0
  48. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/pyproject.toml +0 -0
  49. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/__init__.py +0 -0
  50. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/admin/__init__.py +0 -0
  51. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/admin/asset.py +0 -0
  52. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/admin/custodians.py +0 -0
  53. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/admin/indexes.py +0 -0
  54. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/admin/portfolio.py +0 -0
  55. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/admin/portfolio_relationships.py +0 -0
  56. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/admin/product_groups.py +0 -0
  57. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/admin/products.py +0 -0
  58. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/admin/reconciliations.py +0 -0
  59. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/admin/registers.py +0 -0
  60. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/admin/roles.py +0 -0
  61. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/admin/transactions/__init__.py +0 -0
  62. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/admin/transactions/claim.py +0 -0
  63. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/admin/transactions/dividends.py +0 -0
  64. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/admin/transactions/fees.py +0 -0
  65. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/admin/transactions/rebalancing.py +0 -0
  66. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/admin/transactions/trades.py +0 -0
  67. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/admin/transactions/transactions.py +0 -0
  68. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/analysis/__init__.py +0 -0
  69. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/analysis/claims.py +0 -0
  70. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/apps.py +0 -0
  71. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/contrib/__init__.py +0 -0
  72. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/contrib/company_portfolio/__init__.py +0 -0
  73. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/contrib/company_portfolio/admin.py +0 -0
  74. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/contrib/company_portfolio/apps.py +0 -0
  75. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/contrib/company_portfolio/configs/__init__.py +0 -0
  76. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/contrib/company_portfolio/configs/display.py +0 -0
  77. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/contrib/company_portfolio/configs/endpoints.py +0 -0
  78. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/contrib/company_portfolio/configs/previews.py +0 -0
  79. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/contrib/company_portfolio/constants.py +0 -0
  80. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/contrib/company_portfolio/dynamic_preferences_registry.py +0 -0
  81. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/contrib/company_portfolio/factories.py +0 -0
  82. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/contrib/company_portfolio/filters.py +0 -0
  83. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/contrib/company_portfolio/management.py +0 -0
  84. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/contrib/company_portfolio/migrations/0001_initial.py +0 -0
  85. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/contrib/company_portfolio/migrations/__init__.py +0 -0
  86. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/contrib/company_portfolio/models.py +0 -0
  87. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/contrib/company_portfolio/scripts.py +0 -0
  88. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/contrib/company_portfolio/serializers.py +0 -0
  89. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/contrib/company_portfolio/tests/__init__.py +0 -0
  90. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/contrib/company_portfolio/tests/conftest.py +0 -0
  91. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/contrib/company_portfolio/tests/test_models.py +0 -0
  92. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/contrib/company_portfolio/urls.py +0 -0
  93. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/contrib/company_portfolio/viewsets.py +0 -0
  94. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/defaults/__init__.py +0 -0
  95. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/defaults/fees/__init__.py +0 -0
  96. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/defaults/fees/default.py +0 -0
  97. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/factories/adjustments.py +0 -0
  98. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/factories/assets.py +0 -0
  99. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/factories/claim.py +0 -0
  100. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/factories/custodians.py +0 -0
  101. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/factories/dividends.py +0 -0
  102. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/factories/fees.py +0 -0
  103. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/factories/indexes.py +0 -0
  104. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/factories/portfolio_cash_flow.py +0 -0
  105. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/factories/portfolio_cash_targets.py +0 -0
  106. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/factories/portfolio_swing_pricings.py +0 -0
  107. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/factories/rebalancing.py +0 -0
  108. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/factories/reconciliations.py +0 -0
  109. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/factories/roles.py +0 -0
  110. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/factories/transactions.py +0 -0
  111. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/fdm/__init__.py +0 -0
  112. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/fdm/tasks.py +0 -0
  113. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/filters/__init__.py +0 -0
  114. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/filters/assets.py +0 -0
  115. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/filters/assets_and_net_new_money_progression.py +0 -0
  116. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/filters/custodians.py +0 -0
  117. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/filters/esg.py +0 -0
  118. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/filters/performances.py +0 -0
  119. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/filters/portfolios.py +0 -0
  120. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/filters/positions.py +0 -0
  121. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/filters/products.py +0 -0
  122. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/filters/roles.py +0 -0
  123. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/filters/signals.py +0 -0
  124. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/filters/transactions/__init__.py +0 -0
  125. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/filters/transactions/claim.py +0 -0
  126. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/filters/transactions/fees.py +0 -0
  127. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/filters/transactions/mixins.py +0 -0
  128. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/filters/transactions/trades.py +0 -0
  129. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/filters/transactions/transactions.py +0 -0
  130. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/fixtures/product_factsheets.yaml +0 -0
  131. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/fixtures/wbportfolio.yaml.gz +0 -0
  132. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/fixtures/wbrisk_management.yaml.gz +0 -0
  133. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/__init__.py +0 -0
  134. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/backends/__init__.py +0 -0
  135. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/backends/refinitiv/adjustment.py +0 -0
  136. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/backends/ubs/__init__.py +0 -0
  137. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/backends/ubs/asset_position.py +0 -0
  138. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/backends/ubs/fees.py +0 -0
  139. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/backends/ubs/instrument_price.py +0 -0
  140. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/backends/ubs/mixin.py +0 -0
  141. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/backends/utils.py +0 -0
  142. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/backends/wbfdm/__init__.py +0 -0
  143. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/backends/wbfdm/adjustment.py +0 -0
  144. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/backends/wbfdm/dividend.py +0 -0
  145. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/backends/wbfdm/mixin.py +0 -0
  146. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/handlers/__init__.py +0 -0
  147. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/handlers/adjustment.py +0 -0
  148. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/handlers/asset_position.py +0 -0
  149. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/handlers/dividend.py +0 -0
  150. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/handlers/fees.py +0 -0
  151. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/handlers/portfolio_cash_flow.py +0 -0
  152. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/handlers/register.py +0 -0
  153. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/__init__.py +0 -0
  154. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/default_mapping.py +0 -0
  155. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/jpmorgan/__init__.py +0 -0
  156. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/jpmorgan/customer_trade.py +0 -0
  157. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/jpmorgan/fees.py +0 -0
  158. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/jpmorgan/strategy.py +0 -0
  159. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/jpmorgan/valuation.py +0 -0
  160. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/leonteq/__init__.py +0 -0
  161. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/leonteq/customer_trade.py +0 -0
  162. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/leonteq/equity.py +0 -0
  163. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/leonteq/fees.py +0 -0
  164. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/leonteq/trade.py +0 -0
  165. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/leonteq/valuation.py +0 -0
  166. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/natixis/__init__.py +0 -0
  167. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/natixis/customer_trade.py +0 -0
  168. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/natixis/d1_customer_trade.py +0 -0
  169. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/natixis/d1_equity.py +0 -0
  170. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/natixis/d1_fees.py +0 -0
  171. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/natixis/d1_trade.py +0 -0
  172. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/natixis/d1_valuation.py +0 -0
  173. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/natixis/dividend.py +0 -0
  174. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/natixis/equity.py +0 -0
  175. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/natixis/fees.py +0 -0
  176. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/natixis/trade.py +0 -0
  177. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/natixis/utils.py +0 -0
  178. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/natixis/valuation.py +0 -0
  179. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/refinitiv/__init__.py +0 -0
  180. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/refinitiv/adjustment.py +0 -0
  181. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/sg_lux/__init__.py +0 -0
  182. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/sg_lux/custodian_positions.py +0 -0
  183. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/sg_lux/customer_trade.py +0 -0
  184. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/sg_lux/customer_trade_pending_slk.py +0 -0
  185. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/sg_lux/customer_trade_slk.py +0 -0
  186. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/sg_lux/customer_trade_without_pw.py +0 -0
  187. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/sg_lux/equity.py +0 -0
  188. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/sg_lux/fees.py +0 -0
  189. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/sg_lux/perf_fees.py +0 -0
  190. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/sg_lux/portfolio_cash_flow.py +0 -0
  191. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/sg_lux/portfolio_future_cash_flow.py +0 -0
  192. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/sg_lux/registers.py +0 -0
  193. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/sg_lux/sylk.py +0 -0
  194. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/sg_lux/utils.py +0 -0
  195. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/sg_lux/valuation.py +0 -0
  196. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/societe_generale/__init__.py +0 -0
  197. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/societe_generale/customer_trade.py +0 -0
  198. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/societe_generale/strategy.py +0 -0
  199. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/societe_generale/valuation.py +0 -0
  200. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/tellco/__init__.py +0 -0
  201. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/tellco/customer_trade.py +0 -0
  202. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/tellco/equity.py +0 -0
  203. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/tellco/valuation.py +0 -0
  204. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/ubs/__init__.py +0 -0
  205. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/ubs/api/__init__.py +0 -0
  206. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/ubs/api/asset_position.py +0 -0
  207. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/ubs/api/fees.py +0 -0
  208. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/ubs/api/instrument_price.py +0 -0
  209. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/ubs/api/utils.py +0 -0
  210. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/ubs/customer_trade.py +0 -0
  211. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/ubs/equity.py +0 -0
  212. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/ubs/historical_customer_trade.py +0 -0
  213. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/ubs/valuation.py +0 -0
  214. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/vontobel/__init__.py +0 -0
  215. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/vontobel/asset_position.py +0 -0
  216. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/vontobel/customer_trade.py +0 -0
  217. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/vontobel/historical_customer_trade.py +0 -0
  218. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/vontobel/instrument.py +0 -0
  219. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/vontobel/management_fees.py +0 -0
  220. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/vontobel/performance_fees.py +0 -0
  221. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/vontobel/trade.py +0 -0
  222. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/vontobel/utils.py +0 -0
  223. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/vontobel/valuation.py +0 -0
  224. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/parsers/vontobel/valuation_api.py +0 -0
  225. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/resources/__init__.py +0 -0
  226. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/resources/assets.py +0 -0
  227. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/import_export/utils.py +0 -0
  228. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/jinja2/wbportfolio/sql/aum_nnm.sql +0 -0
  229. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/kpi_handlers/nnm.py +0 -0
  230. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/metric/__init__.py +0 -0
  231. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/metric/backends/__init__.py +0 -0
  232. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/metric/backends/constants.py +0 -0
  233. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/metric/backends/portfolio_base.py +0 -0
  234. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/metric/backends/portfolio_esg.py +0 -0
  235. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/metric/tests/__init__.py +0 -0
  236. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/metric/tests/conftest.py +0 -0
  237. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/metric/tests/test_portfolio_base.py +0 -0
  238. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/metric/tests/test_portfolio_esg.py +0 -0
  239. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/migrations/0001_initial_squashed.py +0 -0
  240. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/migrations/0002_product_default_sub_account_squashed_0039_alter_assetallocation_company_and_more.py +0 -0
  241. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/migrations/0040_instrument_financial_instrument.py +0 -0
  242. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/migrations/0041_remove_listresearch_research_ptr_and_more.py +0 -0
  243. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/migrations/0042_instrumentlist_instrumentlistthroughmodel_and_more.py +0 -0
  244. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/migrations/0043_alter_instrumentlistthroughmodel_options_and_more.py +0 -0
  245. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/migrations/0044_alter_instrumentlist_identifier.py +0 -0
  246. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/migrations/0045_alter_instrument_financial_instrument.py +0 -0
  247. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/migrations/0046_add_product_default_account.py +0 -0
  248. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/migrations/0047_remove_product_default_sub_account.py +0 -0
  249. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/migrations/0048_alter_trade_status.py +0 -0
  250. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/migrations/0049_trade_claimed_shares.py +0 -0
  251. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/migrations/0050_fees_fee_date_fees_wbportfolio_transac_1f7a29_idx.py +0 -0
  252. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/migrations/0051_delete_macroreview.py +0 -0
  253. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/migrations/0052_remove_cash_instrument_ptr_and_more.py +0 -0
  254. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/migrations/0053_remove_product_group.py +0 -0
  255. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/migrations/0054_portfolioinstrumentpreferredclassificationthroughmodel_and_more.py +0 -0
  256. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/migrations/0055_remove_product__custom_management_rebates_and_more.py +0 -0
  257. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/migrations/0056_remove_companyportfoliodata_assets_under_management_currency_and_more.py +0 -0
  258. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/migrations/0057_alter_portfolio_preferred_instrument_classifications_and_more.py +0 -0
  259. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/migrations/0058_pmsinstrument.py +0 -0
  260. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/migrations/0059_fees_unique_fees.py +0 -0
  261. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/migrations/0060_alter_portfolioportfoliothroughmodel_type.py +0 -0
  262. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/migrations/0061_portfolio_bank_accounts_product_bank_account_and_more.py +0 -0
  263. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/migrations/0062_alter_dailyportfoliocashflow_options.py +0 -0
  264. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/migrations/0063_accountreconciliation_accountreconciliationline_and_more.py +0 -0
  265. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/migrations/0064_alter_portfolio_managers_portfolio_is_tracked_and_more.py +0 -0
  266. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/migrations/0065_alter_portfolio_managers_claim_as_shares_and_more.py +0 -0
  267. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/migrations/0066_assetposition_initial_shares_at_custodian_and_more.py +0 -0
  268. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/migrations/0067_assetposition_unique_asset_position.py +0 -0
  269. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/migrations/0068_trade_internal_trade_trade_marked_as_internal_and_more.py +0 -0
  270. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/migrations/0069_remove_portfolio_is_invested_and_more.py +0 -0
  271. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/migrations/0070_remove_assetposition_unique_asset_position_and_more.py +0 -0
  272. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/migrations/0071_alter_trade_options_alter_trade_order.py +0 -0
  273. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/migrations/0072_trade_diff_shares.py +0 -0
  274. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/migrations/0073_remove_product_price_computation_and_more.py +0 -0
  275. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/migrations/0074_alter_rebalancer_frequency_and_more.py +0 -0
  276. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/migrations/__init__.py +0 -0
  277. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/models/adjustments.py +0 -0
  278. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/models/custodians.py +0 -0
  279. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/models/exceptions.py +0 -0
  280. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/models/graphs/__init__.py +0 -0
  281. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/models/graphs/portfolio.py +0 -0
  282. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/models/graphs/utils.py +0 -0
  283. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/models/indexes.py +0 -0
  284. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/models/llm/wbcrm/analyze_relationship.py +0 -0
  285. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/models/mixins/__init__.py +0 -0
  286. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/models/mixins/instruments.py +0 -0
  287. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/models/mixins/liquidity_stress_test.py +0 -0
  288. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/models/portfolio_cash_flow.py +0 -0
  289. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/models/portfolio_cash_targets.py +0 -0
  290. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/models/portfolio_relationship.py +0 -0
  291. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/models/portfolio_swing_pricings.py +0 -0
  292. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/models/product_groups.py +0 -0
  293. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/models/reconciliations/__init__.py +0 -0
  294. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/models/reconciliations/account_reconciliation_lines.py +0 -0
  295. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/models/reconciliations/account_reconciliations.py +0 -0
  296. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/models/reconciliations/reconciliations.py +0 -0
  297. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/models/registers.py +0 -0
  298. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/models/roles.py +0 -0
  299. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/models/transactions/__init__.py +0 -0
  300. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/models/transactions/claim.py +0 -0
  301. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/models/transactions/dividends.py +0 -0
  302. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/models/transactions/expiry.py +0 -0
  303. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/models/transactions/fees.py +0 -0
  304. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/models/transactions/transactions.py +0 -0
  305. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/models/utils.py +0 -0
  306. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/permissions.py +0 -0
  307. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/pms/__init__.py +0 -0
  308. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/pms/analytics/__init__.py +0 -0
  309. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/pms/analytics/portfolio.py +0 -0
  310. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/pms/statistics/__init__.py +0 -0
  311. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/pms/trading/__init__.py +0 -0
  312. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/rebalancing/__init__.py +0 -0
  313. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/rebalancing/base.py +0 -0
  314. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/rebalancing/decorators.py +0 -0
  315. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/rebalancing/models/__init__.py +0 -0
  316. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/rebalancing/models/equally_weighted.py +0 -0
  317. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/rebalancing/models/market_capitalization_weighted.py +0 -0
  318. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/rebalancing/models/model_portfolio.py +0 -0
  319. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/reports/__init__.py +0 -0
  320. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/reports/monthly_position_report.py +0 -0
  321. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/risk_management/__init__.py +0 -0
  322. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/risk_management/backends/__init__.py +0 -0
  323. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/risk_management/backends/controversy_portfolio.py +0 -0
  324. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/risk_management/backends/instrument_list_portfolio.py +0 -0
  325. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/risk_management/backends/liquidity_risk.py +0 -0
  326. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/risk_management/backends/liquidity_stress_instrument.py +0 -0
  327. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/risk_management/backends/mixins.py +0 -0
  328. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/risk_management/backends/product_integrity.py +0 -0
  329. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/risk_management/backends/stop_loss_instrument.py +0 -0
  330. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/risk_management/backends/stop_loss_portfolio.py +0 -0
  331. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/risk_management/backends/ucits_portfolio.py +0 -0
  332. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/risk_management/tests/__init__.py +0 -0
  333. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/risk_management/tests/conftest.py +0 -0
  334. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/risk_management/tests/test_accounts.py +0 -0
  335. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/risk_management/tests/test_controversy_portfolio.py +0 -0
  336. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/risk_management/tests/test_instrument_list_portfolio.py +0 -0
  337. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/risk_management/tests/test_liquidity_risk.py +0 -0
  338. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/risk_management/tests/test_product_integrity.py +0 -0
  339. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/risk_management/tests/test_stop_loss_instrument.py +0 -0
  340. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/risk_management/tests/test_stop_loss_portfolio.py +0 -0
  341. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/risk_management/tests/test_ucits_portfolio.py +0 -0
  342. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/serializers/__init__.py +0 -0
  343. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/serializers/adjustments.py +0 -0
  344. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/serializers/assets.py +0 -0
  345. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/serializers/custodians.py +0 -0
  346. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/serializers/portfolio_cash_flow.py +0 -0
  347. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/serializers/portfolio_cash_targets.py +0 -0
  348. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/serializers/portfolio_relationship.py +0 -0
  349. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/serializers/portfolio_swing_pricing.py +0 -0
  350. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/serializers/positions.py +0 -0
  351. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/serializers/product_group.py +0 -0
  352. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/serializers/products.py +0 -0
  353. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/serializers/rebalancing.py +0 -0
  354. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/serializers/reconciliations.py +0 -0
  355. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/serializers/registers.py +0 -0
  356. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/serializers/roles.py +0 -0
  357. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/serializers/signals.py +0 -0
  358. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/serializers/transactions/__init__.py +0 -0
  359. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/serializers/transactions/claim.py +0 -0
  360. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/serializers/transactions/dividends.py +0 -0
  361. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/serializers/transactions/expiry.py +0 -0
  362. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/serializers/transactions/fees.py +0 -0
  363. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/serializers/transactions/transactions.py +0 -0
  364. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/static/wbportfolio/css/macro_review.css +0 -0
  365. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/static/wbportfolio/markdown/documentation/account_holding_reconciliation.md +0 -0
  366. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/static/wbportfolio/markdown/documentation/aggregate_asset_position_liquidity.md +0 -0
  367. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/static/wbportfolio/markdown/documentation/company.md +0 -0
  368. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/static/wbportfolio/markdown/documentation/earnings_instrument.md +0 -0
  369. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/static/wbportfolio/markdown/documentation/financial_analysis_instrument_ratios.md +0 -0
  370. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/static/wbportfolio/markdown/documentation/financial_statistics.md +0 -0
  371. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/static/wbportfolio/markdown/documentation/person.md +0 -0
  372. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/templates/portfolio/email/customer_report.html +0 -0
  373. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/templates/portfolio/email/customer_trade_notification.html +0 -0
  374. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/templates/portfolio/email/email_base_template.html +0 -0
  375. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/templates/portfolio/email/rebalancing_report.html +0 -0
  376. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/templates/portfolio/macro/macro_review.html +0 -0
  377. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/tests/__init__.py +0 -0
  378. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/tests/models/__init__.py +0 -0
  379. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/tests/models/test_account_reconciliation.py +0 -0
  380. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/tests/models/test_assets.py +0 -0
  381. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/tests/models/test_custodians.py +0 -0
  382. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/tests/models/test_customer_trades.py +0 -0
  383. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/tests/models/test_dividends.py +0 -0
  384. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/tests/models/test_imports.py +0 -0
  385. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/tests/models/test_instrument_mixins.py +0 -0
  386. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/tests/models/test_merge.py +0 -0
  387. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/tests/models/test_portfolio_cash_flow.py +0 -0
  388. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/tests/models/test_portfolio_cash_targets.py +0 -0
  389. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/tests/models/test_portfolio_swing_pricings.py +0 -0
  390. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/tests/models/test_product_groups.py +0 -0
  391. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/tests/models/test_roles.py +0 -0
  392. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/tests/models/test_splits.py +0 -0
  393. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/tests/models/transactions/__init__.py +0 -0
  394. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/tests/models/transactions/test_claim.py +0 -0
  395. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/tests/models/transactions/test_fees.py +0 -0
  396. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/tests/models/transactions/test_rebalancing.py +0 -0
  397. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/tests/models/utils.py +0 -0
  398. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/tests/pms/__init__.py +0 -0
  399. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/tests/pms/test_analytics.py +0 -0
  400. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/tests/rebalancing/__init__.py +0 -0
  401. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/tests/rebalancing/test_models.py +0 -0
  402. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/tests/serializers/__init__.py +0 -0
  403. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/tests/serializers/test_claims.py +0 -0
  404. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/tests/tests.py +0 -0
  405. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/tests/viewsets/__init__.py +0 -0
  406. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/tests/viewsets/test_assets.py +0 -0
  407. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/tests/viewsets/test_products.py +0 -0
  408. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/tests/viewsets/transactions/__init__.py +0 -0
  409. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/tests/viewsets/transactions/test_claims.py +0 -0
  410. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/urls.py +0 -0
  411. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/utils.py +0 -0
  412. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/__init__.py +0 -0
  413. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/adjustments.py +0 -0
  414. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/assets.py +0 -0
  415. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/assets_and_net_new_money_progression.py +0 -0
  416. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/charts/__init__.py +0 -0
  417. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/charts/assets.py +0 -0
  418. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/__init__.py +0 -0
  419. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/buttons/__init__.py +0 -0
  420. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/buttons/adjustments.py +0 -0
  421. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/buttons/assets.py +0 -0
  422. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/buttons/claims.py +0 -0
  423. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/buttons/custodians.py +0 -0
  424. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/buttons/fees.py +0 -0
  425. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/buttons/mixins.py +0 -0
  426. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/buttons/portfolios.py +0 -0
  427. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/buttons/products.py +0 -0
  428. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/buttons/reconciliations.py +0 -0
  429. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/buttons/registers.py +0 -0
  430. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/buttons/signals.py +0 -0
  431. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/buttons/trade_proposals.py +0 -0
  432. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/buttons/trades.py +0 -0
  433. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/display/__init__.py +0 -0
  434. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/display/adjustments.py +0 -0
  435. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/display/assets.py +0 -0
  436. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/display/claim.py +0 -0
  437. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/display/custodians.py +0 -0
  438. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/display/esg.py +0 -0
  439. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/display/fees.py +0 -0
  440. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/display/portfolio_cash_flow.py +0 -0
  441. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/display/portfolio_relationship.py +0 -0
  442. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/display/positions.py +0 -0
  443. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/display/product_groups.py +0 -0
  444. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/display/product_performance.py +0 -0
  445. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/display/products.py +0 -0
  446. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/display/rebalancing.py +0 -0
  447. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/display/reconciliations.py +0 -0
  448. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/display/registers.py +0 -0
  449. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/display/roles.py +0 -0
  450. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/display/trade_proposals.py +0 -0
  451. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/display/transactions.py +0 -0
  452. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/endpoints/__init__.py +0 -0
  453. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/endpoints/adjustments.py +0 -0
  454. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/endpoints/assets.py +0 -0
  455. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/endpoints/claim.py +0 -0
  456. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/endpoints/custodians.py +0 -0
  457. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/endpoints/esg.py +0 -0
  458. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/endpoints/fees.py +0 -0
  459. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/endpoints/portfolio_relationship.py +0 -0
  460. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/endpoints/portfolios.py +0 -0
  461. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/endpoints/positions.py +0 -0
  462. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/endpoints/product_groups.py +0 -0
  463. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/endpoints/product_performance.py +0 -0
  464. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/endpoints/products.py +0 -0
  465. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/endpoints/rebalancing.py +0 -0
  466. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/endpoints/reconciliations.py +0 -0
  467. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/endpoints/roles.py +0 -0
  468. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/endpoints/trade_proposals.py +0 -0
  469. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/endpoints/transactions.py +0 -0
  470. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/menu/__init__.py +0 -0
  471. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/menu/adjustments.py +0 -0
  472. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/menu/assets.py +0 -0
  473. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/menu/claim.py +0 -0
  474. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/menu/custodians.py +0 -0
  475. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/menu/fees.py +0 -0
  476. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/menu/instrument_prices.py +0 -0
  477. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/menu/portfolio_cash_flow.py +0 -0
  478. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/menu/portfolios.py +0 -0
  479. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/menu/positions.py +0 -0
  480. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/menu/product_groups.py +0 -0
  481. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/menu/product_performance.py +0 -0
  482. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/menu/products.py +0 -0
  483. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/menu/reconciliations.py +0 -0
  484. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/menu/registers.py +0 -0
  485. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/menu/roles.py +0 -0
  486. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/menu/trades.py +0 -0
  487. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/menu/transactions.py +0 -0
  488. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/previews/__init__.py +0 -0
  489. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/previews/portfolios.py +0 -0
  490. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/titles/__init__.py +0 -0
  491. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/titles/adjustments.py +0 -0
  492. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/titles/assets.py +0 -0
  493. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/titles/assets_and_net_new_money_progression.py +0 -0
  494. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/titles/claim.py +0 -0
  495. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/titles/custodians.py +0 -0
  496. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/titles/esg.py +0 -0
  497. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/titles/fees.py +0 -0
  498. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/titles/instrument_prices.py +0 -0
  499. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/titles/portfolios.py +0 -0
  500. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/titles/positions.py +0 -0
  501. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/titles/product_groups.py +0 -0
  502. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/titles/product_performance.py +0 -0
  503. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/titles/products.py +0 -0
  504. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/titles/registers.py +0 -0
  505. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/titles/roles.py +0 -0
  506. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/titles/trades.py +0 -0
  507. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/configs/titles/transactions.py +0 -0
  508. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/custodians.py +0 -0
  509. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/esg.py +0 -0
  510. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/mixins.py +0 -0
  511. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/portfolio_cash_flow.py +0 -0
  512. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/portfolio_cash_targets.py +0 -0
  513. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/portfolio_relationship.py +0 -0
  514. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/portfolio_swing_pricing.py +0 -0
  515. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/positions.py +0 -0
  516. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/product_groups.py +0 -0
  517. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/product_performance.py +0 -0
  518. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/products.py +0 -0
  519. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/reconciliations.py +0 -0
  520. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/registers.py +0 -0
  521. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/roles.py +0 -0
  522. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/signals.py +0 -0
  523. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/transactions/__init__.py +0 -0
  524. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/transactions/claim.py +0 -0
  525. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/transactions/fees.py +0 -0
  526. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/transactions/mixins.py +0 -0
  527. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/transactions/rebalancing.py +0 -0
  528. {wbportfolio-1.47.1 → wbportfolio-1.49.0}/wbportfolio/viewsets/transactions/transactions.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wbportfolio
3
- Version: 1.47.1
3
+ Version: 1.49.0
4
4
  Author-email: Christopher Wittlinger <c.wittlinger@stainly.com>
5
5
  License-File: LICENSE
6
6
  Requires-Dist: cryptography==3.4.*
@@ -1,11 +1,13 @@
1
1
  from datetime import date
2
2
 
3
3
  from celery import shared_task
4
+ from django.db.models import Exists, OuterRef
4
5
  from tqdm import tqdm
5
6
  from wbcore.contrib.currency.models import CurrencyFXRates
6
- from wbcore.contrib.directory.models import Company, Entry
7
+ from wbcore.contrib.directory.models import Company
8
+ from wbcrm.models import Account
7
9
 
8
- from .models import Updater
10
+ from .models import CompanyPortfolioData, Updater
9
11
 
10
12
 
11
13
  @shared_task(queue="portfolio")
@@ -13,7 +15,9 @@ def update_all_portfolio_data(val_date: date | None = None):
13
15
  if not val_date:
14
16
  val_date = CurrencyFXRates.objects.latest("date").date
15
17
  updater = Updater(val_date)
16
- account_owners = Entry.objects.filter(accounts__isnull=False)
17
- qs = Company.objects.filter(id__in=account_owners)
18
+ qs = Company.objects.annotate(
19
+ has_account=Exists(Account.objects.filter(owner=OuterRef("pk"))),
20
+ has_portfolio_data=Exists(CompanyPortfolioData.objects.filter(company=OuterRef("pk"))),
21
+ )
18
22
  for company in tqdm(qs, total=qs.count()):
19
23
  updater.update_company_data(company)
@@ -56,3 +56,12 @@ class AccountHoldingReconciliationNotificationBodyUpdate(LongStringPreference):
56
56
  section = portfolio
57
57
  name = "account_holding_reconciliation_notification_body_update"
58
58
  default = """A reconcilation has been updated and requires your review. Please review the reconciliation for the account {account} on {reconciliation_date}."""
59
+
60
+
61
+ @global_preferences_registry.register
62
+ class ProductTerminationNoticePeriod(IntegerPreference):
63
+ section = portfolio
64
+ name = "product_termination_notice_period"
65
+ default = 6 * 30 # approx 6 months
66
+
67
+ verbose_name = "Product Termination notice period"
@@ -9,18 +9,16 @@ from .claim import (
9
9
  from .custodians import CustodianFactory
10
10
  from .dividends import DividendTransactionsFactory
11
11
  from .fees import FeesFactory
12
- from wbfdm.factories.instrument_prices import InstrumentPriceFactory
13
12
  from .portfolios import (
14
13
  InstrumentPortfolioThroughModelFactory,
15
14
  ModelPortfolioFactory,
16
- ModelPortfolioWithBaseProductFactory,
17
15
  PortfolioFactory,
18
16
  )
19
17
  from .portfolio_swing_pricings import PortfolioSwingPricingFactory
20
18
  from .portfolio_cash_targets import PortfolioCashTargetFactory
21
19
  from .portfolio_cash_flow import DailyPortfolioCashFlowFactory
22
20
  from .product_groups import ProductGroupFactory, ProductGroupRepresentantFactory
23
- from .products import IndexProductFactory, ProductFactory, WhiteLabelProductFactory
21
+ from .products import IndexProductFactory, ProductFactory, WhiteLabelProductFactory, ModelPortfolioWithBaseProductFactory
24
22
  from .reconciliations import AccountReconciliationFactory, AccountReconciliationLineFactory
25
23
  from .roles import ManagerPortfolioRoleFactory, ProductPortfolioRoleFactory
26
24
  from .trades import CustomerTradeFactory, TradeFactory, TradeProposalFactory
@@ -9,8 +9,6 @@ from wbportfolio.models import (
9
9
  PortfolioPortfolioThroughModel,
10
10
  )
11
11
 
12
- from .products import ProductFactory
13
-
14
12
 
15
13
  class PortfolioFactory(factory.django.DjangoModelFactory):
16
14
  class Meta:
@@ -43,16 +41,6 @@ class ModelPortfolioFactory(PortfolioFactory):
43
41
  )
44
42
 
45
43
 
46
- class ModelPortfolioWithBaseProductFactory(ModelPortfolioFactory):
47
- @factory.post_generation
48
- def create_instrument(self, create, extracted, **kwargs):
49
- if create:
50
- instrument = ProductFactory.create()
51
- InstrumentPortfolioThroughModel.objects.update_or_create(
52
- instrument=instrument, defaults={"portfolio": self}
53
- )
54
-
55
-
56
44
  class InstrumentPortfolioThroughModelFactory(factory.django.DjangoModelFactory):
57
45
  instrument = factory.SubFactory("wbportfolio.factories.ProductFactory")
58
46
  portfolio = factory.SubFactory("wbportfolio.factories.PortfolioFactory")
@@ -1,7 +1,8 @@
1
1
  import factory
2
2
  from wbfdm.factories.instruments import InstrumentFactory
3
3
 
4
- from wbportfolio.models import ProductGroup, ProductGroupRepresentant
4
+ from wbportfolio.factories import PortfolioFactory
5
+ from wbportfolio.models import InstrumentPortfolioThroughModel, ProductGroup, ProductGroupRepresentant
5
6
 
6
7
 
7
8
  class ProductGroupFactory(InstrumentFactory):
@@ -19,6 +20,12 @@ class ProductGroupFactory(InstrumentFactory):
19
20
  auditor = factory.SubFactory("wbcore.contrib.directory.factories.entries.CompanyFactory")
20
21
  paying_agent = factory.SubFactory("wbcore.contrib.directory.factories.entries.CompanyFactory")
21
22
 
23
+ @factory.post_generation
24
+ def create_initial_portfolio(product_group, *args, **kwargs):
25
+ if product_group.id and not product_group.portfolios.exists():
26
+ portfolio = PortfolioFactory.create()
27
+ InstrumentPortfolioThroughModel.objects.create(instrument=product_group, portfolio=portfolio)
28
+
22
29
 
23
30
  class ProductGroupRepresentantFactory(factory.django.DjangoModelFactory):
24
31
  class Meta:
@@ -4,6 +4,8 @@ import factory
4
4
  from wbcore.contrib.directory.factories.entries import CompanyFactory
5
5
  from wbfdm.factories.instruments import InstrumentFactory, InstrumentTypeFactory
6
6
 
7
+ from wbportfolio.factories import ModelPortfolioFactory, PortfolioFactory
8
+ from wbportfolio.models import InstrumentPortfolioThroughModel
7
9
  from wbportfolio.models.products import (
8
10
  AssetClass,
9
11
  InvestmentIndex,
@@ -37,6 +39,12 @@ class ProductFactory(InstrumentFactory):
37
39
  external_webpage = factory.Faker("url")
38
40
  instrument_type = factory.LazyAttribute(lambda o: InstrumentTypeFactory.create(name="Product", key="product"))
39
41
 
42
+ @factory.post_generation
43
+ def create_initial_portfolio(product, *args, **kwargs):
44
+ if product.id and not product.portfolios.exists():
45
+ portfolio = PortfolioFactory.create()
46
+ InstrumentPortfolioThroughModel.objects.create(instrument=product, portfolio=portfolio)
47
+
40
48
  # wbportfolio = factory.SubFactory(PortfolioFactory)
41
49
  # portfolio_computed = factory.SubFactory(PortfolioFactory)
42
50
 
@@ -55,3 +63,13 @@ class WhiteLabelProductFactory(ProductFactory):
55
63
 
56
64
  class IndexProductFactory(ProductFactory):
57
65
  pass
66
+
67
+
68
+ class ModelPortfolioWithBaseProductFactory(ModelPortfolioFactory):
69
+ @factory.post_generation
70
+ def create_instrument(self, create, extracted, **kwargs):
71
+ if create:
72
+ instrument = ProductFactory.create()
73
+ InstrumentPortfolioThroughModel.objects.update_or_create(
74
+ instrument=instrument, defaults={"portfolio": self}
75
+ )
@@ -1,11 +1,15 @@
1
1
  import random
2
2
 
3
3
  import factory
4
+ from faker import Faker
5
+ from pandas._libs.tslibs.offsets import BDay
4
6
 
5
7
  from wbportfolio.models import Trade, TradeProposal
6
8
 
7
9
  from .transactions import TransactionFactory
8
10
 
11
+ fake = Faker()
12
+
9
13
 
10
14
  class TradeFactory(TransactionFactory):
11
15
  class Meta:
@@ -22,7 +26,7 @@ class TradeProposalFactory(factory.django.DjangoModelFactory):
22
26
  class Meta:
23
27
  model = TradeProposal
24
28
 
25
- trade_date = factory.Faker("date_object")
29
+ trade_date = factory.LazyAttribute(lambda o: (fake.date_object() + BDay(1)).date())
26
30
  comment = factory.Faker("paragraph")
27
31
  portfolio = factory.SubFactory("wbportfolio.factories.PortfolioFactory")
28
32
  creator = factory.SubFactory("wbcore.contrib.directory.factories.PersonFactory")
@@ -24,6 +24,7 @@ class TradeImportHandler(ImportExportHandler):
24
24
  self.instrument_handler = InstrumentImportHandler(self.import_source)
25
25
  self.register_handler = RegisterImportHandler(self.import_source)
26
26
  self.currency_handler = CurrencyImportHandler(self.import_source)
27
+ self.trade_proposals = set()
27
28
 
28
29
  def _data_changed(self, _object, change_data: Dict[str, Any], initial_data: Dict[str, Any], **kwargs):
29
30
  if (new_register := change_data.get("register")) and (current_register := _object.register):
@@ -42,6 +43,7 @@ class TradeImportHandler(ImportExportHandler):
42
43
 
43
44
  if trade_proposal_id := data.pop("trade_proposal_id", None):
44
45
  trade_proposal = TradeProposal.objects.get(id=trade_proposal_id)
46
+ self.trade_proposals.add(trade_proposal)
45
47
  data["value_date"] = trade_proposal.last_effective_date
46
48
  data["transaction_date"] = trade_proposal.trade_date
47
49
  data["trade_proposal"] = trade_proposal
@@ -180,6 +182,12 @@ class TradeImportHandler(ImportExportHandler):
180
182
  if instrument.instrument_type.key == "product":
181
183
  update_outstanding_shares_as_task.delay(instrument.id)
182
184
 
185
+ # if the trade import relates to a trade proposal, we reset the TP after the import to ensure it contains the deleted positions (often forgotten by user)
186
+ for changed_trade_proposal in self.trade_proposals:
187
+ changed_trade_proposal.reset_trades(
188
+ target_portfolio=changed_trade_proposal._build_dto().convert_to_portfolio()
189
+ )
190
+
183
191
  def _post_processing_updated_object(self, _object):
184
192
  if _object.marked_for_deletion:
185
193
  _object.marked_for_deletion = False
@@ -0,0 +1,55 @@
1
+ import rstr
2
+ from faker import Faker
3
+ from import_export import fields
4
+ from import_export.widgets import ForeignKeyWidget
5
+ from wbcore.contrib.io.resources import FilterModelResource
6
+ from wbfdm.models import Instrument
7
+
8
+ from wbportfolio.models import Trade
9
+
10
+ fake = Faker()
11
+
12
+
13
+ class TradeProposalTradeResource(FilterModelResource):
14
+ """
15
+ Trade Resource class to use to import trade from the trade proposal
16
+ """
17
+
18
+ DUMMY_FIELD_MAP = {
19
+ "underlying_instrument__isin": lambda: rstr.xeger("([A-Z]{2}[A-Z0-9]{9}[0-9]{1})"),
20
+ "underlying_instrument__ticker": "AAA",
21
+ "underlying_instrument__name": "stock name",
22
+ "weighting": 1.0,
23
+ "shares": 1000.2536,
24
+ "comment": lambda: fake.sentence(),
25
+ "order": 1,
26
+ }
27
+ underlying_instrument__isin = fields.Field(
28
+ column_name="underlying_instrument__isin",
29
+ attribute="underlying_instrument",
30
+ widget=ForeignKeyWidget(Instrument, field="isin"),
31
+ )
32
+ underlying_instrument__name = fields.Field(
33
+ column_name="underlying_instrument__name",
34
+ attribute="underlying_instrument",
35
+ widget=ForeignKeyWidget(Instrument, field="name"),
36
+ )
37
+ underlying_instrument__ticker = fields.Field(
38
+ column_name="underlying_instrument__ticker",
39
+ attribute="underlying_instrument",
40
+ widget=ForeignKeyWidget(Instrument, field="ticker"),
41
+ )
42
+
43
+ class Meta:
44
+ fields = (
45
+ "id",
46
+ "underlying_instrument__isin",
47
+ "underlying_instrument__name",
48
+ "underlying_instrument__ticker",
49
+ "weighting",
50
+ "shares",
51
+ "comment",
52
+ "order",
53
+ )
54
+ export_order = fields
55
+ model = Trade
@@ -2,12 +2,11 @@ from datetime import date
2
2
 
3
3
  import numpy as np
4
4
  import pandas as pd
5
- from django.db.models import Exists, OuterRef, QuerySet
5
+ from django.db.models import QuerySet
6
6
  from wbfdm.contrib.metric.backends.base import AbstractBackend, Metric
7
7
  from wbfdm.contrib.metric.exceptions import MetricInvalidParameterException
8
- from wbfdm.models import InstrumentType
9
8
 
10
- from wbportfolio.models import AssetPosition, InstrumentPortfolioThroughModel, Portfolio
9
+ from wbportfolio.models import AssetPosition, Portfolio
11
10
 
12
11
 
13
12
  class PortfolioMetricBaseBackend(AbstractBackend[Portfolio]):
@@ -66,18 +65,7 @@ class PortfolioMetricBaseBackend(AbstractBackend[Portfolio]):
66
65
  raise MetricInvalidParameterException()
67
66
 
68
67
  def get_queryset(self) -> QuerySet[Portfolio]:
69
- product_portfolios = (
70
- super()
71
- .get_queryset()
72
- .annotate(
73
- has_product=Exists(
74
- InstrumentPortfolioThroughModel.objects.filter(
75
- instrument__instrument_type=InstrumentType.PRODUCT, portfolio=OuterRef("pk")
76
- )
77
- )
78
- )
79
- .filter(has_product=True, is_active=True)
80
- )
68
+ product_portfolios = super().get_queryset().filter_active_and_tracked()
81
69
  try:
82
70
  last_position_date = (
83
71
  AssetPosition.objects.filter(portfolio__in=product_portfolios, is_estimated=False).latest("date").date
@@ -0,0 +1,28 @@
1
+ # Generated by Django 5.0.13 on 2025-03-20 08:19
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ('wbportfolio', '0074_alter_rebalancer_frequency_and_more'),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.AddField(
14
+ model_name='portfolio',
15
+ name='initial_position_date',
16
+ field=models.DateField(blank=True, null=True, verbose_name='Last Position Date'),
17
+ ),
18
+ migrations.AddField(
19
+ model_name='portfolio',
20
+ name='last_position_date',
21
+ field=models.DateField(blank=True, null=True, verbose_name='Last Position Date'),
22
+ ),
23
+ migrations.AlterField(
24
+ model_name='trade',
25
+ name='transaction_subtype',
26
+ field=models.CharField(choices=[('REBALANCE', 'Rebalance'), ('DECREASE', 'Decrease'), ('INCREASE', 'Increase'), ('SUBSCRIPTION', 'Subscription'), ('REDEMPTION', 'Redemption'), ('BUY', 'Buy'), ('SELL', 'Sell'), ('NO_CHANGE', 'No Change')], default='BUY', max_length=32, verbose_name='Trade Type'),
27
+ ),
28
+ ]
@@ -1,5 +1,5 @@
1
1
  # Import CRM relevant data
2
-
2
+ from .roles import PortfolioRole
3
3
  from .adjustments import Adjustment
4
4
  from .asset import AssetPosition, AssetPositionGroupBy
5
5
  from .custodians import Custodian
@@ -16,6 +16,5 @@ from .portfolio_cash_targets import PortfolioCashTarget
16
16
  from .portfolio_cash_flow import DailyPortfolioCashFlow
17
17
  from .portfolio_swing_pricings import PortfolioSwingPricing
18
18
  from .registers import Register
19
- from .roles import PortfolioRole
20
19
  from .transactions import *
21
20
  from .reconciliations import AccountReconciliation, AccountReconciliationLine
@@ -528,7 +528,7 @@ class AssetPosition(ImportMixin, models.Model):
528
528
  shares=self._shares,
529
529
  date=self.date,
530
530
  asset_valuation_date=self.asset_valuation_date,
531
- instrument_type=self.underlying_quote.instrument_type.id,
531
+ instrument_type=self.underlying_quote.security_instrument_type.id,
532
532
  currency=self.underlying_quote.currency.id,
533
533
  country=self.underlying_quote.country.id if self.underlying_quote.country else None,
534
534
  is_cash=self.underlying_quote.is_cash,
@@ -29,7 +29,6 @@ from django.dispatch import receiver
29
29
  from django.utils import timezone
30
30
  from django.utils.functional import cached_property
31
31
  from pandas._libs.tslibs.offsets import BDay
32
- from psycopg.types.range import DateRange
33
32
  from skfolio.preprocessing import prices_to_returns
34
33
  from wbcore.contrib.currency.models import Currency, CurrencyFXRates
35
34
  from wbcore.contrib.notifications.utils import create_notification_type
@@ -129,6 +128,15 @@ class DefaultPortfolioQueryset(QuerySet):
129
128
  & (Q(invested_timespan__endswith__gt=val_date) | Q(invested_timespan__endswith__isnull=True))
130
129
  )
131
130
 
131
+ def filter_active_and_tracked(self):
132
+ return self.annotate(
133
+ has_product=Exists(
134
+ InstrumentPortfolioThroughModel.objects.filter(
135
+ instrument__instrument_type=InstrumentType.PRODUCT, portfolio=OuterRef("pk")
136
+ )
137
+ )
138
+ ).filter((Q(has_product=True) | Q(is_manageable=True)) & Q(is_active=True) & Q(is_tracked=True))
139
+
132
140
  def to_dependency_iterator(self, val_date: date) -> Iterable["Portfolio"]:
133
141
  """
134
142
  A method to sort the given queryset to return undependable portfolio first. This is very useful if a routine needs to be applied sequentially on portfolios by order of dependence.
@@ -171,6 +179,9 @@ class DefaultPortfolioManager(ActiveObjectManager):
171
179
  def filter_invested_at_date(self, val_date: date):
172
180
  return self.get_queryset().filter_invested_at_date(val_date)
173
181
 
182
+ def filter_active_and_tracked(self):
183
+ return self.get_queryset().filter_active_and_tracked()
184
+
174
185
 
175
186
  class ActiveTrackedPortfolioManager(DefaultPortfolioManager):
176
187
  def get_queryset(self):
@@ -281,6 +292,9 @@ class Portfolio(DeleteToDisableMixin, WBModel):
281
292
  default=False, help_text="If true, this portfolio is a composition of other portfolio"
282
293
  )
283
294
  updated_at = models.DateTimeField(blank=True, null=True, verbose_name="Updated At")
295
+ last_position_date = models.DateField(blank=True, null=True, verbose_name="Last Position Date")
296
+ initial_position_date = models.DateField(blank=True, null=True, verbose_name="Last Position Date")
297
+
284
298
  bank_accounts = models.ManyToManyField(
285
299
  to="directory.BankingContact",
286
300
  related_name="wbportfolio_portfolios",
@@ -687,6 +701,11 @@ class Portfolio(DeleteToDisableMixin, WBModel):
687
701
  self.evaluate_rebalancing(val_date)
688
702
 
689
703
  self.updated_at = timezone.now()
704
+ if self.assets.filter(date=val_date).exists():
705
+ if not self.last_position_date or self.last_position_date < val_date:
706
+ self.last_position_date = val_date
707
+ if not self.initial_position_date or self.initial_position_date > val_date:
708
+ self.initial_position_date = val_date
690
709
  self.save()
691
710
 
692
711
  if compute_metrics:
@@ -1247,18 +1266,6 @@ def default_estimate_net_value(val_date: date, instrument: Instrument) -> float
1247
1266
  return analytic_portfolio.get_estimate_net_value(float(last_price.net_value))
1248
1267
 
1249
1268
 
1250
- @receiver(post_save, sender="wbportfolio.Product")
1251
- @receiver(post_save, sender="wbportfolio.ProductGroup")
1252
- def post_product_creation(sender, instance, created, raw, **kwargs):
1253
- if not raw and (created or not InstrumentPortfolioThroughModel.objects.filter(instrument=instance).exists()):
1254
- portfolio = Portfolio.objects.create(
1255
- name=f"Portfolio: {instance.name}",
1256
- currency=instance.currency,
1257
- invested_timespan=DateRange(instance.inception_date if instance.inception_date else date.min, date.max),
1258
- )
1259
- InstrumentPortfolioThroughModel.objects.get_or_create(instrument=instance, defaults={"portfolio": portfolio})
1260
-
1261
-
1262
1269
  @receiver(post_save, sender="wbportfolio.PortfolioPortfolioThroughModel")
1263
1270
  def post_portfolio_relationship_creation(sender, instance, created, raw, **kwargs):
1264
1271
  if (
@@ -1,5 +1,5 @@
1
1
  from contextlib import suppress
2
- from datetime import date, datetime, time
2
+ from datetime import date, datetime, time, timedelta
3
3
  from decimal import Decimal
4
4
 
5
5
  from celery import shared_task
@@ -25,6 +25,9 @@ from pandas.tseries.offsets import BDay
25
25
  from wbcore.contrib.ai.llm.config import add_llm_prompt
26
26
  from wbcore.contrib.currency.models import CurrencyFXRates
27
27
  from wbcore.contrib.directory.models import Entry
28
+ from wbcore.contrib.notifications.dispatch import send_notification
29
+ from wbcore.contrib.notifications.utils import create_notification_type
30
+ from wbcore.permissions.shortcuts import get_internal_users
28
31
  from wbcore.signals import pre_merge
29
32
  from wbcore.utils.enum import ChoiceEnum
30
33
  from wbcrm.models.accounts import Account
@@ -34,6 +37,8 @@ from wbfdm.models.instruments.instruments import InstrumentManager, InstrumentTy
34
37
  from wbportfolio.models.llm.wbcrm.analyze_relationship import get_holding_prompt
35
38
  from wbportfolio.models.portfolio_relationship import InstrumentPortfolioThroughModel
36
39
 
40
+ from ..preferences import get_product_termination_notice_period
41
+ from . import PortfolioRole
37
42
  from .mixins.instruments import PMSInstrument, PMSInstrumentAbstractModel
38
43
 
39
44
 
@@ -316,6 +321,17 @@ class Product(PMSInstrumentAbstractModel):
316
321
  class Meta:
317
322
  verbose_name = "Product"
318
323
  verbose_name_plural = "Products"
324
+ notification_types = [
325
+ create_notification_type(
326
+ "wbportfolio.product.termination_notice",
327
+ "Product Termination Notice",
328
+ "Sends a notification when a product is expected termination in the near future",
329
+ True,
330
+ True,
331
+ True,
332
+ is_lock=True,
333
+ ),
334
+ ]
319
335
 
320
336
  def pre_save(self):
321
337
  super().pre_save()
@@ -341,6 +357,39 @@ class Product(PMSInstrumentAbstractModel):
341
357
  computed_str += f" ({self.isin})"
342
358
  return computed_str
343
359
 
360
+ def check_and_notify_product_termination_on_date(self, today: date) -> bool:
361
+ """
362
+ Checks if today is the expected notice date for product termination and sends notifications if applicable.
363
+
364
+ The expected notice date is calculated by subtracting the product termination notice period from the product's delisted date. Notifications are sent to users associated with the product's portfolio roles.
365
+
366
+ Args:
367
+ today (date): The date to check against the expected notice date.
368
+
369
+ Returns:
370
+ bool: True if termination is due, False otherwise.
371
+ """
372
+ if self.delisted_date:
373
+ product_termination_expected_notice_date = self.delisted_date - timedelta(
374
+ days=get_product_termination_notice_period()
375
+ )
376
+ if today == product_termination_expected_notice_date:
377
+ roles = PortfolioRole.objects.filter(
378
+ (models.Q(instrument=self) | models.Q(instrument__isnull=True))
379
+ & (models.Q(start__isnull=True) | models.Q(start__gte=today))
380
+ & (models.Q(end__isnull=True) | models.Q(end__lte=today))
381
+ & models.Q(person__user_account__isnull=False)
382
+ )
383
+ for user in get_internal_users().filter(is_active=True, id__in=roles.values("person__user_account")):
384
+ send_notification(
385
+ code="wbportfolio.product.termination_notice",
386
+ title="Product Termination Notice",
387
+ body=f"The product {self} will be terminated on the {self.delisted_date:%Y-%m-%d}",
388
+ user=user,
389
+ )
390
+ return True
391
+ return False
392
+
344
393
  @property
345
394
  def white_label_product(self):
346
395
  return self.white_label_customers.all().count() > 0
@@ -133,7 +133,7 @@ class Rebalancer(ComplexToStringMixin, models.Model):
133
133
  trade_proposal.reset_trades(target_portfolio)
134
134
  trade_proposal.submit()
135
135
  if self.approve_trade_proposal_automatically and self.portfolio.can_be_rebalanced:
136
- trade_proposal.approve()
136
+ trade_proposal.approve(replay=False)
137
137
  except ValidationError:
138
138
  # If we encountered a validation error, we set the trade proposal as failed
139
139
  trade_proposal.status = TradeProposal.Status.FAILED
@@ -146,6 +146,12 @@ class Rebalancer(ComplexToStringMixin, models.Model):
146
146
  def rrule(self):
147
147
  return self.get_rrule()
148
148
 
149
+ def get_next_rebalancing_date(self, pivot_date: date) -> date | None:
150
+ for _dt in self.rrule:
151
+ _d = _dt.date()
152
+ if _d > pivot_date:
153
+ return _d
154
+
149
155
  @property
150
156
  def frequency_repr(self):
151
157
  return humanize_rrule(self.rrule)