wbportfolio 1.46.8__tar.gz → 1.46.10__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 (523) hide show
  1. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/PKG-INFO +1 -1
  2. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/models/asset.py +12 -7
  3. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/models/mixins/instruments.py +3 -1
  4. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/models/portfolio.py +143 -113
  5. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/models/transactions/rebalancing.py +9 -4
  6. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/models/transactions/trade_proposals.py +2 -3
  7. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/pms/analytics/portfolio.py +4 -8
  8. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/pms/trading/handler.py +1 -1
  9. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/rebalancing/models/market_capitalization_weighted.py +10 -9
  10. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/tests/models/test_portfolios.py +16 -13
  11. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/tests/pms/test_analytics.py +2 -2
  12. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/tests/rebalancing/test_models.py +4 -4
  13. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/.gitignore +0 -0
  14. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/LICENSE +0 -0
  15. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/pyproject.toml +0 -0
  16. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/__init__.py +0 -0
  17. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/admin/__init__.py +0 -0
  18. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/admin/asset.py +0 -0
  19. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/admin/custodians.py +0 -0
  20. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/admin/indexes.py +0 -0
  21. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/admin/portfolio.py +0 -0
  22. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/admin/portfolio_relationships.py +0 -0
  23. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/admin/product_groups.py +0 -0
  24. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/admin/products.py +0 -0
  25. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/admin/reconciliations.py +0 -0
  26. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/admin/registers.py +0 -0
  27. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/admin/roles.py +0 -0
  28. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/admin/transactions/__init__.py +0 -0
  29. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/admin/transactions/claim.py +0 -0
  30. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/admin/transactions/dividends.py +0 -0
  31. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/admin/transactions/fees.py +0 -0
  32. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/admin/transactions/rebalancing.py +0 -0
  33. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/admin/transactions/trades.py +0 -0
  34. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/admin/transactions/transactions.py +0 -0
  35. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/analysis/__init__.py +0 -0
  36. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/analysis/claims.py +0 -0
  37. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/apps.py +0 -0
  38. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/contrib/__init__.py +0 -0
  39. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/contrib/company_portfolio/__init__.py +0 -0
  40. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/contrib/company_portfolio/admin.py +0 -0
  41. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/contrib/company_portfolio/apps.py +0 -0
  42. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/contrib/company_portfolio/configs/__init__.py +0 -0
  43. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/contrib/company_portfolio/configs/display.py +0 -0
  44. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/contrib/company_portfolio/configs/endpoints.py +0 -0
  45. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/contrib/company_portfolio/configs/previews.py +0 -0
  46. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/contrib/company_portfolio/constants.py +0 -0
  47. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/contrib/company_portfolio/dynamic_preferences_registry.py +0 -0
  48. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/contrib/company_portfolio/factories.py +0 -0
  49. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/contrib/company_portfolio/filters.py +0 -0
  50. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/contrib/company_portfolio/management.py +0 -0
  51. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/contrib/company_portfolio/migrations/0001_initial.py +0 -0
  52. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/contrib/company_portfolio/migrations/__init__.py +0 -0
  53. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/contrib/company_portfolio/models.py +0 -0
  54. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/contrib/company_portfolio/scripts.py +0 -0
  55. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/contrib/company_portfolio/serializers.py +0 -0
  56. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/contrib/company_portfolio/tasks.py +0 -0
  57. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/contrib/company_portfolio/tests/__init__.py +0 -0
  58. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/contrib/company_portfolio/tests/conftest.py +0 -0
  59. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/contrib/company_portfolio/tests/test_models.py +0 -0
  60. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/contrib/company_portfolio/urls.py +0 -0
  61. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/contrib/company_portfolio/viewsets.py +0 -0
  62. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/defaults/__init__.py +0 -0
  63. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/defaults/fees/__init__.py +0 -0
  64. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/defaults/fees/default.py +0 -0
  65. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/dynamic_preferences_registry.py +0 -0
  66. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/factories/__init__.py +0 -0
  67. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/factories/adjustments.py +0 -0
  68. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/factories/assets.py +0 -0
  69. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/factories/claim.py +0 -0
  70. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/factories/custodians.py +0 -0
  71. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/factories/dividends.py +0 -0
  72. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/factories/fees.py +0 -0
  73. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/factories/indexes.py +0 -0
  74. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/factories/portfolio_cash_flow.py +0 -0
  75. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/factories/portfolio_cash_targets.py +0 -0
  76. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/factories/portfolio_swing_pricings.py +0 -0
  77. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/factories/portfolios.py +0 -0
  78. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/factories/product_groups.py +0 -0
  79. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/factories/products.py +0 -0
  80. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/factories/rebalancing.py +0 -0
  81. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/factories/reconciliations.py +0 -0
  82. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/factories/roles.py +0 -0
  83. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/factories/trades.py +0 -0
  84. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/factories/transactions.py +0 -0
  85. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/fdm/__init__.py +0 -0
  86. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/fdm/tasks.py +0 -0
  87. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/filters/__init__.py +0 -0
  88. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/filters/assets.py +0 -0
  89. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/filters/assets_and_net_new_money_progression.py +0 -0
  90. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/filters/custodians.py +0 -0
  91. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/filters/esg.py +0 -0
  92. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/filters/performances.py +0 -0
  93. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/filters/portfolios.py +0 -0
  94. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/filters/positions.py +0 -0
  95. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/filters/products.py +0 -0
  96. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/filters/roles.py +0 -0
  97. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/filters/signals.py +0 -0
  98. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/filters/transactions/__init__.py +0 -0
  99. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/filters/transactions/claim.py +0 -0
  100. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/filters/transactions/fees.py +0 -0
  101. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/filters/transactions/mixins.py +0 -0
  102. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/filters/transactions/trades.py +0 -0
  103. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/filters/transactions/transactions.py +0 -0
  104. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/fixtures/product_factsheets.yaml +0 -0
  105. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/fixtures/wbportfolio.yaml.gz +0 -0
  106. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/fixtures/wbrisk_management.yaml.gz +0 -0
  107. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/__init__.py +0 -0
  108. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/backends/__init__.py +0 -0
  109. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/backends/refinitiv/adjustment.py +0 -0
  110. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/backends/ubs/__init__.py +0 -0
  111. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/backends/ubs/asset_position.py +0 -0
  112. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/backends/ubs/fees.py +0 -0
  113. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/backends/ubs/instrument_price.py +0 -0
  114. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/backends/ubs/mixin.py +0 -0
  115. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/backends/utils.py +0 -0
  116. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/backends/wbfdm/__init__.py +0 -0
  117. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/backends/wbfdm/adjustment.py +0 -0
  118. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/backends/wbfdm/dividend.py +0 -0
  119. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/backends/wbfdm/mixin.py +0 -0
  120. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/handlers/__init__.py +0 -0
  121. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/handlers/adjustment.py +0 -0
  122. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/handlers/asset_position.py +0 -0
  123. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/handlers/dividend.py +0 -0
  124. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/handlers/fees.py +0 -0
  125. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/handlers/portfolio_cash_flow.py +0 -0
  126. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/handlers/register.py +0 -0
  127. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/handlers/trade.py +0 -0
  128. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/__init__.py +0 -0
  129. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/default_mapping.py +0 -0
  130. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/jpmorgan/__init__.py +0 -0
  131. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/jpmorgan/customer_trade.py +0 -0
  132. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/jpmorgan/fees.py +0 -0
  133. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/jpmorgan/strategy.py +0 -0
  134. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/jpmorgan/valuation.py +0 -0
  135. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/leonteq/__init__.py +0 -0
  136. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/leonteq/customer_trade.py +0 -0
  137. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/leonteq/equity.py +0 -0
  138. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/leonteq/fees.py +0 -0
  139. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/leonteq/trade.py +0 -0
  140. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/leonteq/valuation.py +0 -0
  141. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/natixis/__init__.py +0 -0
  142. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/natixis/customer_trade.py +0 -0
  143. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/natixis/d1_customer_trade.py +0 -0
  144. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/natixis/d1_equity.py +0 -0
  145. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/natixis/d1_fees.py +0 -0
  146. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/natixis/d1_trade.py +0 -0
  147. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/natixis/d1_valuation.py +0 -0
  148. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/natixis/dividend.py +0 -0
  149. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/natixis/equity.py +0 -0
  150. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/natixis/fees.py +0 -0
  151. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/natixis/trade.py +0 -0
  152. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/natixis/utils.py +0 -0
  153. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/natixis/valuation.py +0 -0
  154. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/refinitiv/__init__.py +0 -0
  155. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/refinitiv/adjustment.py +0 -0
  156. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/sg_lux/__init__.py +0 -0
  157. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/sg_lux/custodian_positions.py +0 -0
  158. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/sg_lux/customer_trade.py +0 -0
  159. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/sg_lux/customer_trade_pending_slk.py +0 -0
  160. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/sg_lux/customer_trade_slk.py +0 -0
  161. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/sg_lux/customer_trade_without_pw.py +0 -0
  162. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/sg_lux/equity.py +0 -0
  163. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/sg_lux/fees.py +0 -0
  164. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/sg_lux/perf_fees.py +0 -0
  165. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/sg_lux/portfolio_cash_flow.py +0 -0
  166. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/sg_lux/portfolio_future_cash_flow.py +0 -0
  167. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/sg_lux/registers.py +0 -0
  168. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/sg_lux/sylk.py +0 -0
  169. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/sg_lux/utils.py +0 -0
  170. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/sg_lux/valuation.py +0 -0
  171. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/societe_generale/__init__.py +0 -0
  172. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/societe_generale/customer_trade.py +0 -0
  173. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/societe_generale/strategy.py +0 -0
  174. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/societe_generale/valuation.py +0 -0
  175. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/tellco/__init__.py +0 -0
  176. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/tellco/customer_trade.py +0 -0
  177. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/tellco/equity.py +0 -0
  178. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/tellco/valuation.py +0 -0
  179. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/ubs/__init__.py +0 -0
  180. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/ubs/api/__init__.py +0 -0
  181. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/ubs/api/asset_position.py +0 -0
  182. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/ubs/api/fees.py +0 -0
  183. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/ubs/api/instrument_price.py +0 -0
  184. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/ubs/api/utils.py +0 -0
  185. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/ubs/customer_trade.py +0 -0
  186. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/ubs/equity.py +0 -0
  187. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/ubs/historical_customer_trade.py +0 -0
  188. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/ubs/valuation.py +0 -0
  189. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/vontobel/__init__.py +0 -0
  190. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/vontobel/asset_position.py +0 -0
  191. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/vontobel/customer_trade.py +0 -0
  192. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/vontobel/historical_customer_trade.py +0 -0
  193. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/vontobel/instrument.py +0 -0
  194. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/vontobel/management_fees.py +0 -0
  195. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/vontobel/performance_fees.py +0 -0
  196. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/vontobel/trade.py +0 -0
  197. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/vontobel/utils.py +0 -0
  198. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/vontobel/valuation.py +0 -0
  199. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/parsers/vontobel/valuation_api.py +0 -0
  200. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/resources/__init__.py +0 -0
  201. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/resources/assets.py +0 -0
  202. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/resources/trades.py +0 -0
  203. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/import_export/utils.py +0 -0
  204. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/jinja2/wbportfolio/sql/aum_nnm.sql +0 -0
  205. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/kpi_handlers/nnm.py +0 -0
  206. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/metric/__init__.py +0 -0
  207. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/metric/backends/__init__.py +0 -0
  208. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/metric/backends/base.py +0 -0
  209. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/metric/backends/constants.py +0 -0
  210. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/metric/backends/portfolio_base.py +0 -0
  211. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/metric/backends/portfolio_esg.py +0 -0
  212. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/metric/tests/__init__.py +0 -0
  213. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/metric/tests/conftest.py +0 -0
  214. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/metric/tests/test_portfolio_base.py +0 -0
  215. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/metric/tests/test_portfolio_esg.py +0 -0
  216. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/migrations/0001_initial_squashed.py +0 -0
  217. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/migrations/0002_product_default_sub_account_squashed_0039_alter_assetallocation_company_and_more.py +0 -0
  218. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/migrations/0040_instrument_financial_instrument.py +0 -0
  219. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/migrations/0041_remove_listresearch_research_ptr_and_more.py +0 -0
  220. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/migrations/0042_instrumentlist_instrumentlistthroughmodel_and_more.py +0 -0
  221. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/migrations/0043_alter_instrumentlistthroughmodel_options_and_more.py +0 -0
  222. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/migrations/0044_alter_instrumentlist_identifier.py +0 -0
  223. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/migrations/0045_alter_instrument_financial_instrument.py +0 -0
  224. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/migrations/0046_add_product_default_account.py +0 -0
  225. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/migrations/0047_remove_product_default_sub_account.py +0 -0
  226. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/migrations/0048_alter_trade_status.py +0 -0
  227. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/migrations/0049_trade_claimed_shares.py +0 -0
  228. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/migrations/0050_fees_fee_date_fees_wbportfolio_transac_1f7a29_idx.py +0 -0
  229. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/migrations/0051_delete_macroreview.py +0 -0
  230. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/migrations/0052_remove_cash_instrument_ptr_and_more.py +0 -0
  231. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/migrations/0053_remove_product_group.py +0 -0
  232. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/migrations/0054_portfolioinstrumentpreferredclassificationthroughmodel_and_more.py +0 -0
  233. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/migrations/0055_remove_product__custom_management_rebates_and_more.py +0 -0
  234. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/migrations/0056_remove_companyportfoliodata_assets_under_management_currency_and_more.py +0 -0
  235. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/migrations/0057_alter_portfolio_preferred_instrument_classifications_and_more.py +0 -0
  236. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/migrations/0058_pmsinstrument.py +0 -0
  237. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/migrations/0059_fees_unique_fees.py +0 -0
  238. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/migrations/0060_alter_portfolioportfoliothroughmodel_type.py +0 -0
  239. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/migrations/0061_portfolio_bank_accounts_product_bank_account_and_more.py +0 -0
  240. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/migrations/0062_alter_dailyportfoliocashflow_options.py +0 -0
  241. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/migrations/0063_accountreconciliation_accountreconciliationline_and_more.py +0 -0
  242. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/migrations/0064_alter_portfolio_managers_portfolio_is_tracked_and_more.py +0 -0
  243. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/migrations/0065_alter_portfolio_managers_claim_as_shares_and_more.py +0 -0
  244. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/migrations/0066_assetposition_initial_shares_at_custodian_and_more.py +0 -0
  245. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/migrations/0067_assetposition_unique_asset_position.py +0 -0
  246. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/migrations/0068_trade_internal_trade_trade_marked_as_internal_and_more.py +0 -0
  247. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/migrations/0069_remove_portfolio_is_invested_and_more.py +0 -0
  248. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/migrations/0070_remove_assetposition_unique_asset_position_and_more.py +0 -0
  249. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/migrations/0071_alter_trade_options_alter_trade_order.py +0 -0
  250. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/migrations/0072_trade_diff_shares.py +0 -0
  251. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/migrations/0073_remove_product_price_computation_and_more.py +0 -0
  252. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/migrations/0074_alter_rebalancer_frequency_and_more.py +0 -0
  253. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/migrations/__init__.py +0 -0
  254. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/models/__init__.py +0 -0
  255. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/models/adjustments.py +0 -0
  256. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/models/custodians.py +0 -0
  257. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/models/graphs/__init__.py +0 -0
  258. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/models/graphs/portfolio.py +0 -0
  259. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/models/graphs/utils.py +0 -0
  260. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/models/indexes.py +0 -0
  261. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/models/llm/wbcrm/analyze_relationship.py +0 -0
  262. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/models/mixins/__init__.py +0 -0
  263. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/models/mixins/liquidity_stress_test.py +0 -0
  264. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/models/portfolio_cash_flow.py +0 -0
  265. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/models/portfolio_cash_targets.py +0 -0
  266. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/models/portfolio_relationship.py +0 -0
  267. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/models/portfolio_swing_pricings.py +0 -0
  268. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/models/product_groups.py +0 -0
  269. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/models/products.py +0 -0
  270. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/models/reconciliations/__init__.py +0 -0
  271. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/models/reconciliations/account_reconciliation_lines.py +0 -0
  272. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/models/reconciliations/account_reconciliations.py +0 -0
  273. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/models/reconciliations/reconciliations.py +0 -0
  274. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/models/registers.py +0 -0
  275. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/models/roles.py +0 -0
  276. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/models/transactions/__init__.py +0 -0
  277. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/models/transactions/claim.py +0 -0
  278. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/models/transactions/dividends.py +0 -0
  279. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/models/transactions/expiry.py +0 -0
  280. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/models/transactions/fees.py +0 -0
  281. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/models/transactions/trades.py +0 -0
  282. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/models/transactions/transactions.py +0 -0
  283. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/models/utils.py +0 -0
  284. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/permissions.py +0 -0
  285. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/pms/__init__.py +0 -0
  286. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/pms/analytics/__init__.py +0 -0
  287. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/pms/statistics/__init__.py +0 -0
  288. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/pms/trading/__init__.py +0 -0
  289. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/pms/typing.py +0 -0
  290. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/preferences.py +0 -0
  291. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/rebalancing/__init__.py +0 -0
  292. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/rebalancing/base.py +0 -0
  293. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/rebalancing/decorators.py +0 -0
  294. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/rebalancing/models/__init__.py +0 -0
  295. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/rebalancing/models/composite.py +0 -0
  296. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/rebalancing/models/equally_weighted.py +0 -0
  297. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/rebalancing/models/model_portfolio.py +0 -0
  298. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/reports/__init__.py +0 -0
  299. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/reports/monthly_position_report.py +0 -0
  300. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/risk_management/__init__.py +0 -0
  301. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/risk_management/backends/__init__.py +0 -0
  302. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/risk_management/backends/accounts.py +0 -0
  303. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/risk_management/backends/controversy_portfolio.py +0 -0
  304. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/risk_management/backends/exposure_portfolio.py +0 -0
  305. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/risk_management/backends/instrument_list_portfolio.py +0 -0
  306. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/risk_management/backends/liquidity_risk.py +0 -0
  307. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/risk_management/backends/liquidity_stress_instrument.py +0 -0
  308. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/risk_management/backends/mixins.py +0 -0
  309. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/risk_management/backends/product_integrity.py +0 -0
  310. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/risk_management/backends/stop_loss_instrument.py +0 -0
  311. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/risk_management/backends/stop_loss_portfolio.py +0 -0
  312. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/risk_management/backends/ucits_portfolio.py +0 -0
  313. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/risk_management/tests/__init__.py +0 -0
  314. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/risk_management/tests/conftest.py +0 -0
  315. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/risk_management/tests/test_accounts.py +0 -0
  316. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/risk_management/tests/test_controversy_portfolio.py +0 -0
  317. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/risk_management/tests/test_exposure_portfolio.py +0 -0
  318. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/risk_management/tests/test_instrument_list_portfolio.py +0 -0
  319. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/risk_management/tests/test_liquidity_risk.py +0 -0
  320. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/risk_management/tests/test_product_integrity.py +0 -0
  321. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/risk_management/tests/test_stop_loss_instrument.py +0 -0
  322. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/risk_management/tests/test_stop_loss_portfolio.py +0 -0
  323. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/risk_management/tests/test_ucits_portfolio.py +0 -0
  324. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/serializers/__init__.py +0 -0
  325. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/serializers/adjustments.py +0 -0
  326. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/serializers/assets.py +0 -0
  327. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/serializers/custodians.py +0 -0
  328. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/serializers/portfolio_cash_flow.py +0 -0
  329. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/serializers/portfolio_cash_targets.py +0 -0
  330. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/serializers/portfolio_relationship.py +0 -0
  331. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/serializers/portfolio_swing_pricing.py +0 -0
  332. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/serializers/portfolios.py +0 -0
  333. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/serializers/positions.py +0 -0
  334. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/serializers/product_group.py +0 -0
  335. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/serializers/products.py +0 -0
  336. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/serializers/rebalancing.py +0 -0
  337. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/serializers/reconciliations.py +0 -0
  338. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/serializers/registers.py +0 -0
  339. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/serializers/roles.py +0 -0
  340. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/serializers/signals.py +0 -0
  341. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/serializers/transactions/__init__.py +0 -0
  342. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/serializers/transactions/claim.py +0 -0
  343. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/serializers/transactions/dividends.py +0 -0
  344. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/serializers/transactions/expiry.py +0 -0
  345. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/serializers/transactions/fees.py +0 -0
  346. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/serializers/transactions/trade_proposals.py +0 -0
  347. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/serializers/transactions/trades.py +0 -0
  348. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/serializers/transactions/transactions.py +0 -0
  349. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/static/wbportfolio/css/macro_review.css +0 -0
  350. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/static/wbportfolio/markdown/documentation/account_holding_reconciliation.md +0 -0
  351. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/static/wbportfolio/markdown/documentation/aggregate_asset_position_liquidity.md +0 -0
  352. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/static/wbportfolio/markdown/documentation/company.md +0 -0
  353. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/static/wbportfolio/markdown/documentation/earnings_instrument.md +0 -0
  354. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/static/wbportfolio/markdown/documentation/financial_analysis_instrument_ratios.md +0 -0
  355. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/static/wbportfolio/markdown/documentation/financial_statistics.md +0 -0
  356. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/static/wbportfolio/markdown/documentation/person.md +0 -0
  357. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/tasks.py +0 -0
  358. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/templates/portfolio/email/customer_report.html +0 -0
  359. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/templates/portfolio/email/customer_trade_notification.html +0 -0
  360. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/templates/portfolio/email/email_base_template.html +0 -0
  361. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/templates/portfolio/email/rebalancing_report.html +0 -0
  362. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/templates/portfolio/macro/macro_review.html +0 -0
  363. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/tests/__init__.py +0 -0
  364. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/tests/conftest.py +0 -0
  365. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/tests/models/__init__.py +0 -0
  366. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/tests/models/test_account_reconciliation.py +0 -0
  367. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/tests/models/test_assets.py +0 -0
  368. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/tests/models/test_custodians.py +0 -0
  369. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/tests/models/test_customer_trades.py +0 -0
  370. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/tests/models/test_dividends.py +0 -0
  371. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/tests/models/test_imports.py +0 -0
  372. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/tests/models/test_instrument_mixins.py +0 -0
  373. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/tests/models/test_merge.py +0 -0
  374. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/tests/models/test_portfolio_cash_flow.py +0 -0
  375. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/tests/models/test_portfolio_cash_targets.py +0 -0
  376. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/tests/models/test_portfolio_swing_pricings.py +0 -0
  377. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/tests/models/test_product_groups.py +0 -0
  378. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/tests/models/test_products.py +0 -0
  379. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/tests/models/test_roles.py +0 -0
  380. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/tests/models/test_splits.py +0 -0
  381. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/tests/models/transactions/__init__.py +0 -0
  382. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/tests/models/transactions/test_claim.py +0 -0
  383. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/tests/models/transactions/test_fees.py +0 -0
  384. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/tests/models/transactions/test_rebalancing.py +0 -0
  385. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/tests/models/transactions/test_trades.py +0 -0
  386. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/tests/models/utils.py +0 -0
  387. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/tests/pms/__init__.py +0 -0
  388. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/tests/rebalancing/__init__.py +0 -0
  389. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/tests/serializers/__init__.py +0 -0
  390. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/tests/serializers/test_claims.py +0 -0
  391. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/tests/signals.py +0 -0
  392. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/tests/tests.py +0 -0
  393. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/tests/viewsets/__init__.py +0 -0
  394. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/tests/viewsets/test_assets.py +0 -0
  395. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/tests/viewsets/test_performances.py +0 -0
  396. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/tests/viewsets/test_products.py +0 -0
  397. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/tests/viewsets/transactions/__init__.py +0 -0
  398. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/tests/viewsets/transactions/test_claims.py +0 -0
  399. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/urls.py +0 -0
  400. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/utils.py +0 -0
  401. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/__init__.py +0 -0
  402. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/adjustments.py +0 -0
  403. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/assets.py +0 -0
  404. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/assets_and_net_new_money_progression.py +0 -0
  405. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/charts/__init__.py +0 -0
  406. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/charts/assets.py +0 -0
  407. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/__init__.py +0 -0
  408. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/buttons/__init__.py +0 -0
  409. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/buttons/adjustments.py +0 -0
  410. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/buttons/assets.py +0 -0
  411. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/buttons/claims.py +0 -0
  412. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/buttons/custodians.py +0 -0
  413. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/buttons/fees.py +0 -0
  414. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/buttons/mixins.py +0 -0
  415. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/buttons/portfolios.py +0 -0
  416. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/buttons/products.py +0 -0
  417. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/buttons/reconciliations.py +0 -0
  418. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/buttons/registers.py +0 -0
  419. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/buttons/signals.py +0 -0
  420. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/buttons/trade_proposals.py +0 -0
  421. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/buttons/trades.py +0 -0
  422. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/display/__init__.py +0 -0
  423. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/display/adjustments.py +0 -0
  424. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/display/assets.py +0 -0
  425. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/display/claim.py +0 -0
  426. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/display/custodians.py +0 -0
  427. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/display/esg.py +0 -0
  428. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/display/fees.py +0 -0
  429. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/display/portfolio_cash_flow.py +0 -0
  430. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/display/portfolio_relationship.py +0 -0
  431. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/display/portfolios.py +0 -0
  432. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/display/positions.py +0 -0
  433. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/display/product_groups.py +0 -0
  434. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/display/product_performance.py +0 -0
  435. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/display/products.py +0 -0
  436. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/display/rebalancing.py +0 -0
  437. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/display/reconciliations.py +0 -0
  438. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/display/registers.py +0 -0
  439. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/display/roles.py +0 -0
  440. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/display/trade_proposals.py +0 -0
  441. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/display/trades.py +0 -0
  442. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/display/transactions.py +0 -0
  443. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/endpoints/__init__.py +0 -0
  444. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/endpoints/adjustments.py +0 -0
  445. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/endpoints/assets.py +0 -0
  446. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/endpoints/claim.py +0 -0
  447. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/endpoints/custodians.py +0 -0
  448. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/endpoints/esg.py +0 -0
  449. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/endpoints/fees.py +0 -0
  450. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/endpoints/portfolio_relationship.py +0 -0
  451. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/endpoints/portfolios.py +0 -0
  452. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/endpoints/positions.py +0 -0
  453. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/endpoints/product_groups.py +0 -0
  454. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/endpoints/product_performance.py +0 -0
  455. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/endpoints/products.py +0 -0
  456. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/endpoints/rebalancing.py +0 -0
  457. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/endpoints/reconciliations.py +0 -0
  458. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/endpoints/roles.py +0 -0
  459. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/endpoints/trade_proposals.py +0 -0
  460. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/endpoints/trades.py +0 -0
  461. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/endpoints/transactions.py +0 -0
  462. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/menu/__init__.py +0 -0
  463. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/menu/adjustments.py +0 -0
  464. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/menu/assets.py +0 -0
  465. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/menu/claim.py +0 -0
  466. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/menu/custodians.py +0 -0
  467. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/menu/fees.py +0 -0
  468. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/menu/instrument_prices.py +0 -0
  469. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/menu/portfolio_cash_flow.py +0 -0
  470. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/menu/portfolios.py +0 -0
  471. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/menu/positions.py +0 -0
  472. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/menu/product_groups.py +0 -0
  473. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/menu/product_performance.py +0 -0
  474. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/menu/products.py +0 -0
  475. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/menu/reconciliations.py +0 -0
  476. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/menu/registers.py +0 -0
  477. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/menu/roles.py +0 -0
  478. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/menu/trades.py +0 -0
  479. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/menu/transactions.py +0 -0
  480. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/previews/__init__.py +0 -0
  481. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/previews/portfolios.py +0 -0
  482. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/titles/__init__.py +0 -0
  483. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/titles/adjustments.py +0 -0
  484. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/titles/assets.py +0 -0
  485. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/titles/assets_and_net_new_money_progression.py +0 -0
  486. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/titles/claim.py +0 -0
  487. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/titles/custodians.py +0 -0
  488. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/titles/esg.py +0 -0
  489. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/titles/fees.py +0 -0
  490. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/titles/instrument_prices.py +0 -0
  491. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/titles/portfolios.py +0 -0
  492. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/titles/positions.py +0 -0
  493. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/titles/product_groups.py +0 -0
  494. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/titles/product_performance.py +0 -0
  495. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/titles/products.py +0 -0
  496. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/titles/registers.py +0 -0
  497. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/titles/roles.py +0 -0
  498. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/titles/trades.py +0 -0
  499. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/configs/titles/transactions.py +0 -0
  500. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/custodians.py +0 -0
  501. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/esg.py +0 -0
  502. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/mixins.py +0 -0
  503. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/portfolio_cash_flow.py +0 -0
  504. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/portfolio_cash_targets.py +0 -0
  505. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/portfolio_relationship.py +0 -0
  506. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/portfolio_swing_pricing.py +0 -0
  507. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/portfolios.py +0 -0
  508. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/positions.py +0 -0
  509. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/product_groups.py +0 -0
  510. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/product_performance.py +0 -0
  511. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/products.py +0 -0
  512. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/reconciliations.py +0 -0
  513. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/registers.py +0 -0
  514. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/roles.py +0 -0
  515. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/signals.py +0 -0
  516. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/transactions/__init__.py +0 -0
  517. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/transactions/claim.py +0 -0
  518. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/transactions/fees.py +0 -0
  519. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/transactions/mixins.py +0 -0
  520. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/transactions/rebalancing.py +0 -0
  521. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/transactions/trade_proposals.py +0 -0
  522. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/transactions/trades.py +0 -0
  523. {wbportfolio-1.46.8 → wbportfolio-1.46.10}/wbportfolio/viewsets/transactions/transactions.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wbportfolio
3
- Version: 1.46.8
3
+ Version: 1.46.10
4
4
  Author-email: Christopher Wittlinger <c.wittlinger@stainly.com>
5
5
  License-File: LICENSE
6
6
  Requires-Dist: cryptography==3.4.*
@@ -1,6 +1,6 @@
1
1
  from contextlib import suppress
2
2
  from datetime import date
3
- from decimal import Decimal
3
+ from decimal import Decimal, InvalidOperation
4
4
 
5
5
  from django.contrib import admin
6
6
  from django.db import models
@@ -393,7 +393,9 @@ class AssetPosition(ImportMixin, models.Model):
393
393
  analytical_objects = AnalyticalAssetPositionManager()
394
394
  unannotated_objects = models.Manager()
395
395
 
396
- def pre_save(self, create_underlying_quote_price_if_missing: bool = False):
396
+ def pre_save(
397
+ self, create_underlying_quote_price_if_missing: bool = False, infer_underlying_quote_price: bool = True
398
+ ):
397
399
  if not self.asset_valuation_date:
398
400
  self.asset_valuation_date = self.date
399
401
 
@@ -417,10 +419,10 @@ class AssetPosition(ImportMixin, models.Model):
417
419
 
418
420
  if not getattr(self, "currency", None):
419
421
  self.currency = self.underlying_quote.currency
420
- if not self.underlying_quote_price:
422
+ if not self.underlying_quote_price and infer_underlying_quote_price:
421
423
  try:
422
424
  # We get only the instrument price (and don't create it) because we don't want to create product instrument price on asset position propagation
423
- # Instead, we deciced to opt for a post_save based system that will assign the missing position price when a price is created
425
+ # Instead, we decided to opt for a post_save based system that will assign the missing position price when a price is created
424
426
  self.underlying_quote_price = InstrumentPrice.objects.get(
425
427
  calculated=False, instrument=self.underlying_quote, date=self.asset_valuation_date
426
428
  )
@@ -468,9 +470,12 @@ class AssetPosition(ImportMixin, models.Model):
468
470
  if self.initial_currency_fx_rate is None:
469
471
  self.initial_currency_fx_rate = Decimal(1.0)
470
472
  if self.currency_fx_rate_portfolio_to_usd and self.currency_fx_rate_instrument_to_usd:
471
- self.initial_currency_fx_rate = (
472
- self.currency_fx_rate_portfolio_to_usd.value / self.currency_fx_rate_instrument_to_usd.value
473
- )
473
+ try:
474
+ self.initial_currency_fx_rate = (
475
+ self.currency_fx_rate_portfolio_to_usd.value / self.currency_fx_rate_instrument_to_usd.value
476
+ )
477
+ except InvalidOperation:
478
+ self.initial_currency_fx_rate = Decimal(0.0)
474
479
 
475
480
  def save(self, *args, create_underlying_quote_price_if_missing: bool = False, **kwargs):
476
481
  self.pre_save(create_underlying_quote_price_if_missing=create_underlying_quote_price_if_missing)
@@ -65,7 +65,9 @@ class PMSInstrument(Instrument):
65
65
  try:
66
66
  return InstrumentPrice.objects.filter_only_valid_prices().get(instrument=self, date=val_date)
67
67
  except InstrumentPrice.DoesNotExist:
68
- if not self.inception_date or not self.prices.filter(date__lte=val_date).exists():
68
+ if (not self.inception_date or self.inception_date == val_date) and not self.prices.filter(
69
+ date__lte=val_date
70
+ ).exists():
69
71
  return InstrumentPrice.objects.get_or_create(
70
72
  instrument=self, date=val_date, defaults={"calculated": False, "net_value": self.issue_price}
71
73
  )[0]
@@ -1,4 +1,5 @@
1
1
  import logging
2
+ from collections import defaultdict
2
3
  from contextlib import suppress
3
4
  from datetime import date, timedelta
4
5
  from decimal import Decimal
@@ -26,6 +27,7 @@ from django.db.models import (
26
27
  from django.db.models.signals import post_save
27
28
  from django.dispatch import receiver
28
29
  from django.utils import timezone
30
+ from django.utils.functional import cached_property
29
31
  from pandas._libs.tslibs.offsets import BDay
30
32
  from psycopg.types.range import DateRange
31
33
  from skfolio.preprocessing import prices_to_returns
@@ -54,6 +56,63 @@ from . import ProductGroup
54
56
  logger = logging.getLogger("pms")
55
57
 
56
58
 
59
+ class PositionDictConverter:
60
+ """Utility class to load a dictionary of dictionary (dictionary of instrument_id and float per date) into a iterable of assetposition"""
61
+
62
+ def __init__(self, portfolio, prices: pd.DataFrame, infer_underlying_quote_price=False):
63
+ self.portfolio = portfolio
64
+ self.instruments = {}
65
+ self.fx_rates = defaultdict(dict)
66
+ self.prices = prices
67
+ self.infer_underlying_quote_price = infer_underlying_quote_price
68
+
69
+ def _get_instrument(self, instrument_id: int) -> Instrument:
70
+ try:
71
+ return self.instruments[instrument_id]
72
+ except KeyError:
73
+ instrument = Instrument.objects.get(id=instrument_id)
74
+ self.instruments[instrument_id] = instrument
75
+ return instrument
76
+
77
+ def _get_fx_rate(self, val_date: date, currency) -> CurrencyFXRates:
78
+ try:
79
+ return self.fx_rates[currency][val_date]
80
+ except KeyError:
81
+ fx_rate = CurrencyFXRates.objects.get_or_create(
82
+ currency=currency, date=val_date, defaults={"value": Decimal(0)}
83
+ )[0] # we create a fx rate anyway to not fail the position. The fx rate expect to be there later on
84
+ self.fx_rates[currency][val_date] = fx_rate
85
+ return fx_rate
86
+
87
+ def dict_to_model(self, val_date: date, instrument_id: int, weighting: float) -> AssetPosition:
88
+ underlying_quote = self._get_instrument(instrument_id)
89
+ currency_fx_rate_portfolio_to_usd = self._get_fx_rate(val_date, self.portfolio.currency)
90
+ currency_fx_rate_instrument_to_usd = self._get_fx_rate(val_date, underlying_quote.currency)
91
+ position = AssetPosition(
92
+ underlying_quote=underlying_quote,
93
+ weighting=weighting,
94
+ date=val_date,
95
+ asset_valuation_date=val_date,
96
+ is_estimated=True,
97
+ portfolio=self.portfolio,
98
+ currency=underlying_quote.currency,
99
+ initial_price=self.prices.loc[pd.Timestamp(val_date), instrument_id],
100
+ currency_fx_rate_portfolio_to_usd=currency_fx_rate_portfolio_to_usd,
101
+ currency_fx_rate_instrument_to_usd=currency_fx_rate_instrument_to_usd,
102
+ initial_currency_fx_rate=None,
103
+ underlying_quote_price=None,
104
+ underlying_instrument=None,
105
+ )
106
+ position.pre_save(
107
+ infer_underlying_quote_price=self.infer_underlying_quote_price
108
+ ) # inferring underlying quote price is potentially very slow for big dataset of positions, it's not very needed for model portfolio so we disable it
109
+ return position
110
+
111
+ def convert(self, positions: dict[date, dict[int, float]]) -> Iterable[AssetPosition]:
112
+ for val_date, weights in positions.items():
113
+ yield from map(lambda row: self.dict_to_model(val_date, row[0], row[1]), weights.items())
114
+
115
+
57
116
  class DefaultPortfolioQueryset(QuerySet):
58
117
  def filter_invested_at_date(self, val_date: date) -> QuerySet:
59
118
  """
@@ -253,11 +312,12 @@ class Portfolio(DeleteToDisableMixin, WBModel):
253
312
  def imported_assets(self):
254
313
  return self.assets.filter(is_estimated=False)
255
314
 
256
- @property
315
+ @cached_property
257
316
  def pms_instruments(self):
258
- yield from Product.objects.filter(portfolios=self)
259
- yield from ProductGroup.objects.filter(portfolios=self)
260
- yield from Index.objects.filter(portfolios=self)
317
+ instruments = [i for i in Product.objects.filter(portfolios=self)]
318
+ instruments.extend([i for i in ProductGroup.objects.filter(portfolios=self)])
319
+ instruments.extend([i for i in Index.objects.filter(portfolios=self)])
320
+ return instruments
261
321
 
262
322
  @property
263
323
  def can_be_rebalanced(self):
@@ -298,31 +358,28 @@ class Portfolio(DeleteToDisableMixin, WBModel):
298
358
  )
299
359
  )
300
360
 
301
- def get_analytic_portfolio(self, val_date: date, with_previous_weights: bool = False) -> AnalyticPortfolio:
361
+ def get_analytic_portfolio(self, val_date: date, **kwargs) -> tuple[AnalyticPortfolio, pd.DataFrame]:
302
362
  """
303
363
  Return the analytic portfolio associated with this portfolio at the given date
304
364
 
305
365
  the analytic portfolio inherit from SKFolio Portfolio and can be used to access all this library methods
306
366
  Args:
307
367
  val_date: the date to calculate the portfolio for
308
- with_previous_weights: If true, excludes the previous weights into the analytic portfolio (might be necessary for some metrics)
309
368
 
310
369
  Returns:
311
370
  The instantiated analytic portfolio
312
371
  """
313
372
  weights = self.get_weights(val_date)
314
373
  instrument_ids = weights.keys()
315
- previous_weights = None
316
- if with_previous_weights:
317
- if previous_date := self.get_latest_asset_position_date(val_date - timedelta(days=1)):
318
- previous_weights = self.get_weights(previous_date)
319
- instrument_ids = previous_weights.keys()
320
- returns = self.get_returns(instrument_ids, (val_date - BDay(3)).date(), val_date)[0]
374
+ return_date = (val_date + BDay(1)).date()
375
+ returns, prices = self.get_returns(instrument_ids, (val_date - BDay(2)).date(), return_date, **kwargs)
321
376
  returns = returns.fillna(0) # not sure this is what we want
322
- return AnalyticPortfolio(
323
- X=returns,
324
- weights=weights,
325
- previous_weights=previous_weights,
377
+ return (
378
+ AnalyticPortfolio(
379
+ X=returns,
380
+ weights=weights,
381
+ ),
382
+ prices,
326
383
  )
327
384
 
328
385
  def is_invested_at_date(self, val_date: date) -> bool:
@@ -567,10 +624,11 @@ class Portfolio(DeleteToDisableMixin, WBModel):
567
624
 
568
625
  def get_child_portfolios(self, val_date: date) -> set["Portfolio"]:
569
626
  child_portfolios = set()
570
- if pms_instruments := list(self.pms_instruments):
627
+ instrument_rel = InstrumentPortfolioThroughModel.objects.filter(portfolio=self)
628
+ if instrument_rel.exists():
571
629
  for parent_portfolio in Portfolio.objects.filter(
572
630
  id__in=AssetPosition.unannotated_objects.filter(
573
- date=val_date, underlying_quote__in=pms_instruments
631
+ date=val_date, underlying_quote__in=instrument_rel.values("instrument")
574
632
  ).values("portfolio")
575
633
  ):
576
634
  child_portfolios.add(parent_portfolio)
@@ -592,24 +650,29 @@ class Portfolio(DeleteToDisableMixin, WBModel):
592
650
  evaluate_rebalancer: bool = True,
593
651
  ):
594
652
  logger.info(f"change at date for {self} at {val_date}")
595
- qs = self.assets.filter(date=val_date).filter(
596
- Q(total_value_fx_portfolio__isnull=False) | Q(weighting__isnull=False)
597
- )
598
653
 
599
- # We normalize weight across the portfolio for a given date
600
- if (self.is_lookthrough or self.is_manageable or force_recompute_weighting) and qs.exists():
601
- total_weighting = qs.aggregate(s=Sum("weighting"))["s"]
602
- # We check if this actually necessary
603
- # (i.e. if the weight is already summed to 100%, it is already normalized)
604
- if not total_weighting or not isclose(total_weighting, Decimal(1.0), abs_tol=0.001) or recompute_weighting:
605
- total_value = qs.aggregate(s=Sum("total_value_fx_portfolio"))["s"]
606
- # TODO we change this because postgres doesn't support join statement in update (and total_value_fx_portfolio is a joined annoted field)
607
- for asset in qs:
608
- if total_value:
609
- asset.weighting = asset._total_value_fx_portfolio / total_value
610
- elif total_weighting:
611
- asset.weighting = asset.weighting / total_weighting
612
- asset.save()
654
+ if recompute_weighting:
655
+ # We normalize weight across the portfolio for a given date
656
+ qs = self.assets.filter(date=val_date).filter(
657
+ Q(total_value_fx_portfolio__isnull=False) | Q(weighting__isnull=False)
658
+ )
659
+ if (self.is_lookthrough or self.is_manageable or force_recompute_weighting) and qs.exists():
660
+ total_weighting = qs.aggregate(s=Sum("weighting"))["s"]
661
+ # We check if this actually necessary
662
+ # (i.e. if the weight is already summed to 100%, it is already normalized)
663
+ if (
664
+ not total_weighting
665
+ or not isclose(total_weighting, Decimal(1.0), abs_tol=0.001)
666
+ or force_recompute_weighting
667
+ ):
668
+ total_value = qs.aggregate(s=Sum("total_value_fx_portfolio"))["s"]
669
+ # TODO we change this because postgres doesn't support join statement in update (and total_value_fx_portfolio is a joined annoted field)
670
+ for asset in qs:
671
+ if total_value:
672
+ asset.weighting = asset._total_value_fx_portfolio / total_value
673
+ elif total_weighting:
674
+ asset.weighting = asset.weighting / total_weighting
675
+ asset.save()
613
676
 
614
677
  # We check if there is an instrument attached to the portfolio with calculated NAV and price computation method
615
678
  self.estimate_net_asset_values(val_date)
@@ -641,17 +704,21 @@ class Portfolio(DeleteToDisableMixin, WBModel):
641
704
  dependent_portfolio.handle_controlling_portfolio_change_at_date(val_date)
642
705
 
643
706
  def evaluate_rebalancing(self, val_date: date):
644
- # if the portfolio has an automatic rebalancer and the next business day is suitable with the rebalancer, we create a trade proposal automatically
645
- next_business_date = (val_date + BDay(1)).date()
646
-
647
707
  if hasattr(self, "automatic_rebalancer"):
648
- logger.info(f"Evaluate Rebalancing for {self} at {next_business_date}")
708
+ # if the portfolio has an automatic rebalancer and the next business day is suitable with the rebalancer, we create a trade proposal automatically
709
+ next_business_date = (val_date + BDay(1)).date()
710
+ if self.automatic_rebalancer.is_valid(val_date): # we evaluate the rebalancer in t0 and t+1
711
+ logger.info(f"Evaluate Rebalancing for {self} at {val_date}")
712
+ self.automatic_rebalancer.evaluate_rebalancing(val_date)
649
713
  if self.automatic_rebalancer.is_valid(next_business_date):
714
+ logger.info(f"Evaluate Rebalancing for {self} at {next_business_date}")
650
715
  self.automatic_rebalancer.evaluate_rebalancing(next_business_date)
651
716
 
652
717
  def estimate_net_asset_values(self, val_date: date):
653
718
  for instrument in self.pms_instruments:
654
- if net_asset_value_computation_method_path := instrument.net_asset_value_computation_method_path:
719
+ if instrument.is_active_at_date(val_date) and (
720
+ net_asset_value_computation_method_path := instrument.net_asset_value_computation_method_path
721
+ ):
655
722
  logger.info(f"Estimate NAV of {val_date:%Y-%m-%d} for instrument {instrument}")
656
723
  net_asset_value_computation_method = import_from_dotted_path(net_asset_value_computation_method_path)
657
724
  estimated_net_asset_value = net_asset_value_computation_method(val_date, instrument)
@@ -671,76 +738,32 @@ class Portfolio(DeleteToDisableMixin, WBModel):
671
738
  instrument.update_last_valuation_date()
672
739
  instrument.update_last_valuation_date()
673
740
 
674
- def get_estimated_portfolio_from_weights(
675
- self, val_date: date, weights: dict[int, float], prices: dict[int, Decimal] | None = None
676
- ) -> Iterable[AssetPosition]:
677
- """
678
- Given weights and the corresponding instrument price, instantiate asset positions (as AssetPosition object)
679
-
680
- Args:
681
- val_date: The positions valuation date
682
- weights: The positions weights as dictionary (Instrument IDS as key and weights as values)
683
- prices: The prices associated with each position
684
-
685
- Returns:
686
- Yield AssetPosition objects.
687
- """
688
- if prices is None:
689
- prices = dict()
690
- try:
691
- currency_fx_rate_portfolio_to_usd = CurrencyFXRates.objects.get(date=val_date, currency=self.currency)
692
- except CurrencyFXRates.DoesNotExist:
693
- currency_fx_rate_portfolio_to_usd = None
694
- for underlying_quote_id, next_weight in weights.items():
695
- underlying_quote = Instrument.objects.get(id=underlying_quote_id)
696
- position = AssetPosition(
697
- underlying_quote=underlying_quote,
698
- weighting=next_weight,
699
- date=val_date,
700
- asset_valuation_date=val_date,
701
- is_estimated=True,
702
- portfolio=self,
703
- currency=underlying_quote.currency,
704
- currency_fx_rate_portfolio_to_usd=currency_fx_rate_portfolio_to_usd,
705
- initial_price=prices.get(underlying_quote_id, None),
706
- initial_currency_fx_rate=None,
707
- currency_fx_rate_instrument_to_usd=None,
708
- underlying_quote_price=None,
709
- underlying_instrument=None,
710
- )
711
- position.pre_save()
712
- yield position
713
-
714
741
  def batch_portfolio(self, start_date: date, end_date: date):
715
742
  """
716
743
  Create the cumulative portfolios between the two given dates and stop at the first rebalancing (if any)
717
744
 
718
745
  Returns: The trade proposal generated by the rebalancing, if any (otherwise None)
719
746
  """
720
- analytic_portfolio = self.get_analytic_portfolio(start_date)
721
747
  rebalancer = getattr(self, "automatic_rebalancer", None)
722
- initial_assets = analytic_portfolio.assets
723
- positions = []
748
+
749
+ weights = self.get_weights(start_date) # initial weights
750
+ positions = dict()
724
751
  next_trade_proposal = None
725
752
  rebalancing_date = None
726
753
  logger.info(f"compute next weights in batch for {self} from {start_date:%Y-%m-%d} to {end_date:%Y-%m-%d}")
727
- returns, prices = self.get_returns(initial_assets, (start_date - BDay(3)).date(), end_date, ffill_returns=True)
754
+ returns, prices = self.get_returns(weights.keys(), (start_date - BDay(3)).date(), end_date, ffill_returns=True)
728
755
  for to_date_ts in pd.date_range(start_date + timedelta(days=1), end_date, freq="B"):
729
756
  to_date = to_date_ts.date()
730
757
  logger.info(f"Processing {to_date:%Y-%m-%d}")
731
758
  if rebalancer and rebalancer.is_valid(to_date):
732
759
  rebalancing_date = to_date
733
760
  break
734
- # with suppress(IndexError):
735
761
  last_returns = returns.loc[[to_date_ts], :]
736
- next_weights = analytic_portfolio.get_next_weights(last_returns.iloc[-1, :].T)
737
- positions.extend(
738
- self.get_estimated_portfolio_from_weights(
739
- to_date, next_weights, prices.loc[to_date_ts, :].dropna().to_dict()
740
- )
741
- )
742
- analytic_portfolio = AnalyticPortfolio(X=last_returns, weights=next_weights)
762
+ analytic_portfolio = AnalyticPortfolio(weights=weights, X=last_returns)
763
+ positions[to_date] = analytic_portfolio.get_next_weights()
743
764
 
765
+ positions_generator = PositionDictConverter(self, prices)
766
+ positions = list(positions_generator.convert(positions))
744
767
  self.bulk_create_positions(positions, delete_leftovers=True, compute_metrics=False, evaluate_rebalancer=False)
745
768
  if rebalancing_date:
746
769
  next_trade_proposal = rebalancer.evaluate_rebalancing(rebalancing_date)
@@ -774,18 +797,13 @@ class Portfolio(DeleteToDisableMixin, WBModel):
774
797
  self.is_tracked and not self.is_lookthrough and not is_target_portfolio_imported and from_is_active
775
798
  ): # we cannot propagate a new portfolio for untracked, or look-through or already imported or inactive portfolios
776
799
  logger.info(f"computing next weight for {self} from {from_date:%Y-%m-%d} to {to_date:%Y-%m-%d}")
777
- analytic_portfolio = self.get_analytic_portfolio(from_date)
778
- returns, prices = self.get_returns(analytic_portfolio.assets, (from_date - BDay(3)).date(), to_date)
779
- if not returns.empty:
780
- weights = analytic_portfolio.get_next_weights(returns.iloc[-1, :].T)
781
- positions = list(
782
- map(
783
- lambda a: _parse_position(a),
784
- self.get_estimated_portfolio_from_weights(
785
- to_date, weights, prices.iloc[-1, :].T.dropna().to_dict()
786
- ),
787
- )
788
- )
800
+ analytic_portfolio, to_prices = self.get_analytic_portfolio(from_date)
801
+ if not to_prices.empty:
802
+ weights = analytic_portfolio.get_next_weights()
803
+ positions_generator = PositionDictConverter(
804
+ self, to_prices, infer_underlying_quote_price=True
805
+ ).convert({to_date: weights})
806
+ positions = list(map(lambda a: _parse_position(a), positions_generator))
789
807
  self.bulk_create_positions(positions, delete_leftovers=True, compute_metrics=True)
790
808
 
791
809
  def get_lookthrough_positions(
@@ -932,8 +950,11 @@ class Portfolio(DeleteToDisableMixin, WBModel):
932
950
  for position in positions:
933
951
  position.portfolio = self
934
952
  update_dates.add(position.date)
935
- self.assets.filter(date__in=update_dates, is_estimated=True).delete()
936
- leftover_positions = self.assets.filter(date__in=update_dates).all()
953
+ # self.assets.filter(date__in=update_dates, is_estimated=True).delete()
954
+ leftover_positions_ids = list(
955
+ self.assets.filter(date__in=update_dates).values_list("id", flat=True)
956
+ ) # we need to get the ids otherwise the queryset is reevaluated later
957
+ logger.info(f"bulk saving {len(positions)} positions ({len(leftover_positions_ids)} leftovers) ...")
937
958
  objs = AssetPosition.unannotated_objects.bulk_create(
938
959
  positions,
939
960
  update_fields=[
@@ -951,11 +972,13 @@ class Portfolio(DeleteToDisableMixin, WBModel):
951
972
  ],
952
973
  unique_fields=["portfolio", "date", "underlying_quote", "portfolio_created"],
953
974
  update_conflicts=True,
975
+ batch_size=10000,
954
976
  )
955
977
  if delete_leftovers:
956
- for leftover_position in leftover_positions:
957
- if leftover_position not in objs: # this works because __eq__ of a django model use the id field
958
- leftover_position.delete()
978
+ objs_ids = list(map(lambda x: x.id, objs))
979
+ leftover_positions_ids = list(filter(lambda i: i not in objs_ids, leftover_positions_ids))
980
+ logger.info(f"deleting {len(leftover_positions_ids)} leftover positions..")
981
+ AssetPosition.objects.filter(id__in=leftover_positions_ids).delete()
959
982
  for update_date in sorted(update_dates):
960
983
  self.change_at_date(update_date, **kwargs)
961
984
 
@@ -972,7 +995,12 @@ class Portfolio(DeleteToDisableMixin, WBModel):
972
995
  return self.assets.filter(Q(date=val_date) & ~Q(initial_shares=F("initial_shares_at_custodian"))).exists()
973
996
 
974
997
  def get_returns(
975
- self, instruments: Iterable, from_date: date, to_date: date, ffill_returns: bool = True
998
+ self,
999
+ instruments: Iterable,
1000
+ from_date: date,
1001
+ to_date: date,
1002
+ ffill_returns: bool = True,
1003
+ convert_to_portfolio_currency: bool = True,
976
1004
  ) -> tuple[pd.DataFrame, pd.DataFrame]:
977
1005
  """
978
1006
  Utility methods to get instrument returns for a given date range
@@ -988,8 +1016,10 @@ class Portfolio(DeleteToDisableMixin, WBModel):
988
1016
  prices = InstrumentPrice.objects.filter(
989
1017
  instrument__in=instruments, date__gte=from_date, date__lte=to_date
990
1018
  ).annotate(
991
- # fx_rate=CurrencyFXRates.get_fx_rates_subquery_for_two_currencies("date", "instrument__currency", self.currency),
992
- price_fx_portfolio=F("net_value") # * F("net_value")
1019
+ fx_rate=CurrencyFXRates.get_fx_rates_subquery_for_two_currencies(
1020
+ "date", "instrument__currency", self.currency
1021
+ ),
1022
+ price_fx_portfolio=F("net_value") * F("fx_rate") if convert_to_portfolio_currency else F("net_value"),
993
1023
  )
994
1024
  prices_df = (
995
1025
  pd.DataFrame(
@@ -1190,9 +1220,9 @@ def default_estimate_net_value(val_date: date, instrument: Instrument) -> float
1190
1220
  if (
1191
1221
  previous_date := portfolio.get_latest_asset_position_date(val_date - BDay(1), with_estimated=True)
1192
1222
  ) and portfolio.assets.filter(date=val_date).exists():
1193
- analytic_portfolio = portfolio.get_analytic_portfolio(val_date, with_previous_weights=True)
1194
1223
  with suppress(IndexError):
1195
1224
  if last_price := instrument.get_latest_price(previous_date):
1225
+ analytic_portfolio, _ = portfolio.get_analytic_portfolio(previous_date)
1196
1226
  return analytic_portfolio.get_estimate_net_value(float(last_price.net_value))
1197
1227
 
1198
1228
 
@@ -99,11 +99,16 @@ class Rebalancer(ComplexToStringMixin, models.Model):
99
99
  return pivot_date
100
100
 
101
101
  def is_valid(self, trade_date: date) -> bool:
102
- for valid_datetime in self.get_rrule(trade_date):
103
- valid_date = self._get_next_valid_date(valid_datetime.date())
104
- if valid_date == trade_date:
102
+ if TradeProposal.objects.filter(
103
+ portfolio=self.portfolio, status=TradeProposal.Status.APPROVED, trade_date=trade_date
104
+ ).exists(): # if a already approved trade proposal exists, we do not allow a re-evaluatioon of the rebalancing (only possible if "replayed")
105
+ return False
106
+ for initial_valid_datetime in self.get_rrule(trade_date):
107
+ initial_valid_date = initial_valid_datetime.date()
108
+ alternative_valid_date = self._get_next_valid_date(initial_valid_date)
109
+ if trade_date in [alternative_valid_date, initial_valid_date]:
105
110
  return True
106
- if valid_date > trade_date:
111
+ if alternative_valid_date > trade_date:
107
112
  break
108
113
  return False
109
114
 
@@ -79,6 +79,8 @@ class TradeProposal(RiskCheckMixin, WBModel):
79
79
  if not self.rebalancing_model and (rebalancer := getattr(self.portfolio, "automatic_rebalancer", None)):
80
80
  self.rebalancing_model = rebalancer.rebalancing_model
81
81
  super().save(*args, **kwargs)
82
+ if self.status == TradeProposal.Status.APPROVED:
83
+ self.portfolio.change_at_date(self.trade_date)
82
84
 
83
85
  def _get_checked_object_field_name(self) -> str:
84
86
  """
@@ -234,7 +236,6 @@ class TradeProposal(RiskCheckMixin, WBModel):
234
236
  )
235
237
  service.normalize()
236
238
  service.is_valid()
237
-
238
239
  for trade_dto in service.validated_trades:
239
240
  instrument = Instrument.objects.get(id=trade_dto.underlying_instrument)
240
241
  currency_fx_rate = instrument.currency.convert(
@@ -378,8 +379,6 @@ class TradeProposal(RiskCheckMixin, WBModel):
378
379
  for trade in self.trades.all():
379
380
  trade.execute()
380
381
  trade.save()
381
- self.portfolio.change_at_date(self.trade_date)
382
- # replay_as_task.delay(self.id)
383
382
 
384
383
  def can_approve(self):
385
384
  errors = dict()
@@ -16,16 +16,14 @@ class Portfolio(BasePortfolio):
16
16
  )
17
17
  return df
18
18
 
19
- def get_next_weights(self, returns: pd.Series) -> dict[int, float]:
19
+ def get_next_weights(self) -> dict[int, float]:
20
20
  """
21
- Given the next returns, compute the next weights of this portfolio
22
-
23
- Args:
24
- returns: The returns for the next day as a pandas series
21
+ Given the next returns, compute the drifted weights of this portfolio
25
22
 
26
23
  Returns:
27
24
  A dictionary of weights (instrument ids as keys and weights as values)
28
25
  """
26
+ returns = self.X.iloc[-1, :].T
29
27
  weights = self.all_weights_per_observation.iloc[-1, :].T
30
28
  if weights.sum() != 0:
31
29
  weights /= weights.sum()
@@ -35,7 +33,5 @@ class Portfolio(BasePortfolio):
35
33
  return contribution.dropna().to_dict()
36
34
 
37
35
  def get_estimate_net_value(self, previous_net_asset_value: float) -> float:
38
- if self.previous_weights is None:
39
- raise ValueError("No previous weights available")
40
- expected_returns = self.previous_weights @ self.X.iloc[-1, :].T
36
+ expected_returns = self.weights @ self.X.iloc[-1, :].T
41
37
  return previous_net_asset_value * (1.0 + expected_returns)
@@ -97,7 +97,7 @@ class TradingService:
97
97
  effective_shares = 0
98
98
  instrument_type = currency = None
99
99
  if effective_pos := effective_portfolio.positions_map.get(instrument, None):
100
- effective_weight = target_weight = effective_pos.weighting
100
+ effective_weight = effective_pos.weighting
101
101
  effective_shares = effective_pos.shares
102
102
  instrument_type, currency = effective_pos.instrument_type, effective_pos.currency
103
103
  if target_pos := target_portfolio.positions_map.get(instrument, None):
@@ -1,5 +1,6 @@
1
1
  from decimal import Decimal
2
2
 
3
+ import numpy as np
3
4
  import pandas as pd
4
5
  from django.db.models import Q, QuerySet
5
6
  from wbfdm.enums import MarketData
@@ -26,7 +27,7 @@ class MarketCapitalizationRebalancing(AbstractRebalancingModel):
26
27
  self.market_cap_df = pd.DataFrame(
27
28
  instruments.dl.market_data(
28
29
  values=[MarketData.MARKET_CAPITALIZATION],
29
- exact_date=self.last_effective_date,
30
+ exact_date=self.trade_date,
30
31
  target_currency=self.TARGET_CURRENCY,
31
32
  )
32
33
  )
@@ -80,9 +81,7 @@ class MarketCapitalizationRebalancing(AbstractRebalancingModel):
80
81
 
81
82
  if not instrument_ids:
82
83
  instrument_ids = list(
83
- self.portfolio.assets.filter(date=self.last_effective_date).values_list(
84
- "underlying_instrument", flat=True
85
- )
84
+ self.portfolio.assets.filter(date=self.trade_date).values_list("underlying_instrument", flat=True)
86
85
  )
87
86
 
88
87
  return Instrument.objects.filter(id__in=instrument_ids).filter(
@@ -107,14 +106,16 @@ class MarketCapitalizationRebalancing(AbstractRebalancingModel):
107
106
 
108
107
  def get_target_portfolio(self) -> Portfolio:
109
108
  positions = []
110
- market_cap_df = self.market_cap_df.dropna()
111
- total_market_cap = market_cap_df.sum()
112
-
113
- for underlying_instrument, market_cap in total_market_cap.to_dict().items():
109
+ total_market_cap = self.market_cap_df.dropna().sum()
110
+ for underlying_instrument, market_cap in self.market_cap_df.to_dict().items():
111
+ if np.isnan(market_cap):
112
+ weighting = Decimal(0)
113
+ else:
114
+ weighting = Decimal(market_cap / total_market_cap)
114
115
  positions.append(
115
116
  Position(
116
117
  underlying_instrument=underlying_instrument,
117
- weighting=Decimal(market_cap / total_market_cap),
118
+ weighting=weighting,
118
119
  date=self.trade_date,
119
120
  )
120
121
  )