wbportfolio 1.54.20__tar.gz → 1.54.21__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 (560) hide show
  1. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/PKG-INFO +1 -1
  2. wbportfolio-1.54.21/wbportfolio/migrations/0084_orderproposal_min_order_value.py +25 -0
  3. wbportfolio-1.54.21/wbportfolio/migrations/0085_order_desired_target_weight.py +26 -0
  4. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/models/asset.py +4 -141
  5. wbportfolio-1.54.21/wbportfolio/models/builder.py +258 -0
  6. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/models/orders/order_proposals.py +39 -33
  7. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/models/orders/orders.py +18 -21
  8. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/models/portfolio.py +108 -232
  9. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/serializers/orders/order_proposals.py +1 -0
  10. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/tests/models/orders/test_order_proposals.py +16 -1
  11. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/tests/models/test_portfolios.py +34 -121
  12. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/orders/configs/displays/order_proposals.py +6 -5
  13. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/orders/orders.py +1 -1
  14. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/.gitignore +0 -0
  15. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/LICENSE +0 -0
  16. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/pyproject.toml +0 -0
  17. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/__init__.py +0 -0
  18. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/admin/__init__.py +0 -0
  19. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/admin/asset.py +0 -0
  20. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/admin/custodians.py +0 -0
  21. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/admin/indexes.py +0 -0
  22. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/admin/orders/__init__.py +0 -0
  23. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/admin/orders/order_proposals.py +0 -0
  24. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/admin/orders/orders.py +0 -0
  25. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/admin/portfolio.py +0 -0
  26. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/admin/portfolio_relationships.py +0 -0
  27. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/admin/product_groups.py +0 -0
  28. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/admin/products.py +0 -0
  29. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/admin/rebalancing.py +0 -0
  30. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/admin/reconciliations.py +0 -0
  31. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/admin/registers.py +0 -0
  32. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/admin/roles.py +0 -0
  33. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/admin/transactions/__init__.py +0 -0
  34. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/admin/transactions/claim.py +0 -0
  35. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/admin/transactions/dividends.py +0 -0
  36. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/admin/transactions/fees.py +0 -0
  37. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/admin/transactions/trades.py +0 -0
  38. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/analysis/__init__.py +0 -0
  39. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/analysis/claims.py +0 -0
  40. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/apps.py +0 -0
  41. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/contrib/__init__.py +0 -0
  42. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/contrib/company_portfolio/__init__.py +0 -0
  43. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/contrib/company_portfolio/admin.py +0 -0
  44. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/contrib/company_portfolio/apps.py +0 -0
  45. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/contrib/company_portfolio/configs/__init__.py +0 -0
  46. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/contrib/company_portfolio/configs/display.py +0 -0
  47. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/contrib/company_portfolio/configs/endpoints.py +0 -0
  48. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/contrib/company_portfolio/configs/previews.py +0 -0
  49. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/contrib/company_portfolio/constants.py +0 -0
  50. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/contrib/company_portfolio/dynamic_preferences_registry.py +0 -0
  51. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/contrib/company_portfolio/factories.py +0 -0
  52. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/contrib/company_portfolio/filters.py +0 -0
  53. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/contrib/company_portfolio/management.py +0 -0
  54. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/contrib/company_portfolio/migrations/0001_initial.py +0 -0
  55. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/contrib/company_portfolio/migrations/__init__.py +0 -0
  56. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/contrib/company_portfolio/models.py +0 -0
  57. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/contrib/company_portfolio/scripts.py +0 -0
  58. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/contrib/company_portfolio/serializers.py +0 -0
  59. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/contrib/company_portfolio/tasks.py +0 -0
  60. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/contrib/company_portfolio/tests/__init__.py +0 -0
  61. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/contrib/company_portfolio/tests/conftest.py +0 -0
  62. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/contrib/company_portfolio/tests/test_models.py +0 -0
  63. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/contrib/company_portfolio/urls.py +0 -0
  64. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/contrib/company_portfolio/viewsets.py +0 -0
  65. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/defaults/__init__.py +0 -0
  66. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/defaults/fees/__init__.py +0 -0
  67. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/defaults/fees/default.py +0 -0
  68. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/dynamic_preferences_registry.py +0 -0
  69. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/factories/__init__.py +0 -0
  70. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/factories/adjustments.py +0 -0
  71. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/factories/assets.py +0 -0
  72. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/factories/claim.py +0 -0
  73. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/factories/custodians.py +0 -0
  74. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/factories/dividends.py +0 -0
  75. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/factories/fees.py +0 -0
  76. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/factories/indexes.py +0 -0
  77. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/factories/orders/__init__.py +0 -0
  78. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/factories/orders/order_proposals.py +0 -0
  79. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/factories/orders/orders.py +0 -0
  80. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/factories/portfolio_cash_flow.py +0 -0
  81. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/factories/portfolio_cash_targets.py +0 -0
  82. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/factories/portfolio_swing_pricings.py +0 -0
  83. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/factories/portfolios.py +0 -0
  84. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/factories/product_groups.py +0 -0
  85. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/factories/products.py +0 -0
  86. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/factories/rebalancing.py +0 -0
  87. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/factories/reconciliations.py +0 -0
  88. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/factories/roles.py +0 -0
  89. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/factories/trades.py +0 -0
  90. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/fdm/__init__.py +0 -0
  91. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/fdm/tasks.py +0 -0
  92. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/filters/__init__.py +0 -0
  93. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/filters/assets.py +0 -0
  94. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/filters/assets_and_net_new_money_progression.py +0 -0
  95. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/filters/custodians.py +0 -0
  96. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/filters/esg.py +0 -0
  97. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/filters/orders/__init__.py +0 -0
  98. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/filters/orders/orders.py +0 -0
  99. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/filters/performances.py +0 -0
  100. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/filters/portfolios.py +0 -0
  101. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/filters/positions.py +0 -0
  102. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/filters/products.py +0 -0
  103. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/filters/roles.py +0 -0
  104. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/filters/signals.py +0 -0
  105. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/filters/transactions/__init__.py +0 -0
  106. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/filters/transactions/claim.py +0 -0
  107. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/filters/transactions/fees.py +0 -0
  108. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/filters/transactions/mixins.py +0 -0
  109. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/filters/transactions/trades.py +0 -0
  110. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/filters/transactions/utils.py +0 -0
  111. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/fixtures/product_factsheets.yaml +0 -0
  112. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/fixtures/wbportfolio.yaml.gz +0 -0
  113. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/fixtures/wbrisk_management.yaml.gz +0 -0
  114. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/__init__.py +0 -0
  115. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/backends/__init__.py +0 -0
  116. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/backends/refinitiv/adjustment.py +0 -0
  117. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/backends/ubs/__init__.py +0 -0
  118. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/backends/ubs/asset_position.py +0 -0
  119. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/backends/ubs/fees.py +0 -0
  120. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/backends/ubs/instrument_price.py +0 -0
  121. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/backends/ubs/mixin.py +0 -0
  122. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/backends/utils.py +0 -0
  123. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/backends/wbfdm/__init__.py +0 -0
  124. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/backends/wbfdm/adjustment.py +0 -0
  125. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/backends/wbfdm/dividend.py +0 -0
  126. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/backends/wbfdm/mixin.py +0 -0
  127. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/handlers/__init__.py +0 -0
  128. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/handlers/adjustment.py +0 -0
  129. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/handlers/asset_position.py +0 -0
  130. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/handlers/dividend.py +0 -0
  131. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/handlers/fees.py +0 -0
  132. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/handlers/orders.py +0 -0
  133. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/handlers/portfolio_cash_flow.py +0 -0
  134. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/handlers/register.py +0 -0
  135. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/handlers/trade.py +0 -0
  136. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/__init__.py +0 -0
  137. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/default_mapping.py +0 -0
  138. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/jpmorgan/__init__.py +0 -0
  139. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/jpmorgan/customer_trade.py +0 -0
  140. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/jpmorgan/fees.py +0 -0
  141. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/jpmorgan/strategy.py +0 -0
  142. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/jpmorgan/valuation.py +0 -0
  143. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/leonteq/__init__.py +0 -0
  144. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/leonteq/customer_trade.py +0 -0
  145. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/leonteq/equity.py +0 -0
  146. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/leonteq/fees.py +0 -0
  147. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/leonteq/trade.py +0 -0
  148. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/leonteq/valuation.py +0 -0
  149. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/natixis/__init__.py +0 -0
  150. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/natixis/customer_trade.py +0 -0
  151. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/natixis/d1_customer_trade.py +0 -0
  152. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/natixis/d1_equity.py +0 -0
  153. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/natixis/d1_fees.py +0 -0
  154. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/natixis/d1_trade.py +0 -0
  155. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/natixis/d1_valuation.py +0 -0
  156. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/natixis/dividend.py +0 -0
  157. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/natixis/equity.py +0 -0
  158. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/natixis/fees.py +0 -0
  159. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/natixis/trade.py +0 -0
  160. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/natixis/utils.py +0 -0
  161. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/natixis/valuation.py +0 -0
  162. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/refinitiv/__init__.py +0 -0
  163. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/refinitiv/adjustment.py +0 -0
  164. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/sg_lux/__init__.py +0 -0
  165. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/sg_lux/custodian_positions.py +0 -0
  166. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/sg_lux/customer_trade.py +0 -0
  167. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/sg_lux/customer_trade_pending_slk.py +0 -0
  168. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/sg_lux/customer_trade_slk.py +0 -0
  169. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/sg_lux/customer_trade_without_pw.py +0 -0
  170. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/sg_lux/equity.py +0 -0
  171. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/sg_lux/fees.py +0 -0
  172. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/sg_lux/perf_fees.py +0 -0
  173. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/sg_lux/portfolio_cash_flow.py +0 -0
  174. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/sg_lux/portfolio_future_cash_flow.py +0 -0
  175. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/sg_lux/registers.py +0 -0
  176. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/sg_lux/sylk.py +0 -0
  177. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/sg_lux/utils.py +0 -0
  178. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/sg_lux/valuation.py +0 -0
  179. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/societe_generale/__init__.py +0 -0
  180. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/societe_generale/customer_trade.py +0 -0
  181. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/societe_generale/strategy.py +0 -0
  182. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/societe_generale/valuation.py +0 -0
  183. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/tellco/__init__.py +0 -0
  184. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/tellco/customer_trade.py +0 -0
  185. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/tellco/equity.py +0 -0
  186. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/tellco/valuation.py +0 -0
  187. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/ubs/__init__.py +0 -0
  188. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/ubs/api/__init__.py +0 -0
  189. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/ubs/api/asset_position.py +0 -0
  190. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/ubs/api/fees.py +0 -0
  191. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/ubs/api/instrument_price.py +0 -0
  192. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/ubs/api/utils.py +0 -0
  193. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/ubs/customer_trade.py +0 -0
  194. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/ubs/equity.py +0 -0
  195. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/ubs/historical_customer_trade.py +0 -0
  196. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/ubs/valuation.py +0 -0
  197. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/vontobel/__init__.py +0 -0
  198. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/vontobel/asset_position.py +0 -0
  199. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/vontobel/customer_trade.py +0 -0
  200. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/vontobel/historical_customer_trade.py +0 -0
  201. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/vontobel/instrument.py +0 -0
  202. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/vontobel/management_fees.py +0 -0
  203. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/vontobel/performance_fees.py +0 -0
  204. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/vontobel/trade.py +0 -0
  205. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/vontobel/utils.py +0 -0
  206. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/vontobel/valuation.py +0 -0
  207. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/parsers/vontobel/valuation_api.py +0 -0
  208. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/resources/__init__.py +0 -0
  209. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/resources/assets.py +0 -0
  210. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/resources/trades.py +0 -0
  211. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/import_export/utils.py +0 -0
  212. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/jinja2/wbportfolio/sql/aum_nnm.sql +0 -0
  213. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/kpi_handlers/nnm.py +0 -0
  214. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/locale/de/LC_MESSAGES/django.mo +0 -0
  215. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/locale/de/LC_MESSAGES/django.po +0 -0
  216. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/locale/en/LC_MESSAGES/django.mo +0 -0
  217. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/locale/en/LC_MESSAGES/django.po +0 -0
  218. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/locale/fr/LC_MESSAGES/django.mo +0 -0
  219. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/locale/fr/LC_MESSAGES/django.po +0 -0
  220. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/metric/__init__.py +0 -0
  221. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/metric/backends/__init__.py +0 -0
  222. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/metric/backends/base.py +0 -0
  223. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/metric/backends/constants.py +0 -0
  224. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/metric/backends/portfolio_base.py +0 -0
  225. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/metric/backends/portfolio_esg.py +0 -0
  226. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/metric/tests/__init__.py +0 -0
  227. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/metric/tests/conftest.py +0 -0
  228. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/metric/tests/test_portfolio_base.py +0 -0
  229. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/metric/tests/test_portfolio_esg.py +0 -0
  230. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0001_initial_squashed.py +0 -0
  231. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0002_product_default_sub_account_squashed_0039_alter_assetallocation_company_and_more.py +0 -0
  232. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0040_instrument_financial_instrument.py +0 -0
  233. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0041_remove_listresearch_research_ptr_and_more.py +0 -0
  234. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0042_instrumentlist_instrumentlistthroughmodel_and_more.py +0 -0
  235. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0043_alter_instrumentlistthroughmodel_options_and_more.py +0 -0
  236. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0044_alter_instrumentlist_identifier.py +0 -0
  237. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0045_alter_instrument_financial_instrument.py +0 -0
  238. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0046_add_product_default_account.py +0 -0
  239. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0047_remove_product_default_sub_account.py +0 -0
  240. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0048_alter_trade_status.py +0 -0
  241. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0049_trade_claimed_shares.py +0 -0
  242. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0050_fees_fee_date_fees_wbportfolio_transac_1f7a29_idx.py +0 -0
  243. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0051_delete_macroreview.py +0 -0
  244. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0052_remove_cash_instrument_ptr_and_more.py +0 -0
  245. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0053_remove_product_group.py +0 -0
  246. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0054_portfolioinstrumentpreferredclassificationthroughmodel_and_more.py +0 -0
  247. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0055_remove_product__custom_management_rebates_and_more.py +0 -0
  248. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0056_remove_companyportfoliodata_assets_under_management_currency_and_more.py +0 -0
  249. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0057_alter_portfolio_preferred_instrument_classifications_and_more.py +0 -0
  250. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0058_pmsinstrument.py +0 -0
  251. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0059_fees_unique_fees.py +0 -0
  252. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0060_alter_portfolioportfoliothroughmodel_type.py +0 -0
  253. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0061_portfolio_bank_accounts_product_bank_account_and_more.py +0 -0
  254. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0062_alter_dailyportfoliocashflow_options.py +0 -0
  255. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0063_accountreconciliation_accountreconciliationline_and_more.py +0 -0
  256. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0064_alter_portfolio_managers_portfolio_is_tracked_and_more.py +0 -0
  257. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0065_alter_portfolio_managers_claim_as_shares_and_more.py +0 -0
  258. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0066_assetposition_initial_shares_at_custodian_and_more.py +0 -0
  259. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0067_assetposition_unique_asset_position.py +0 -0
  260. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0068_trade_internal_trade_trade_marked_as_internal_and_more.py +0 -0
  261. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0069_remove_portfolio_is_invested_and_more.py +0 -0
  262. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0070_remove_assetposition_unique_asset_position_and_more.py +0 -0
  263. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0071_alter_trade_options_alter_trade_order.py +0 -0
  264. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0072_trade_diff_shares.py +0 -0
  265. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0073_remove_product_price_computation_and_more.py +0 -0
  266. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0074_alter_rebalancer_frequency_and_more.py +0 -0
  267. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0075_portfolio_initial_position_date_and_more.py +0 -0
  268. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0076_alter_dividendtransaction_price_and_more.py +0 -0
  269. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0077_remove_transaction_currency_and_more.py +0 -0
  270. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0078_trade_drift_factor.py +0 -0
  271. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0079_alter_trade_drift_factor.py +0 -0
  272. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0080_alter_trade_drift_factor_alter_trade_weighting.py +0 -0
  273. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0081_alter_trade_drift_factor.py +0 -0
  274. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0082_remove_tradeproposal_creator_and_more.py +0 -0
  275. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/0083_order_alter_trade_options_and_more.py +0 -0
  276. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/migrations/__init__.py +0 -0
  277. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/models/__init__.py +0 -0
  278. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/models/adjustments.py +0 -0
  279. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/models/custodians.py +0 -0
  280. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/models/exceptions.py +0 -0
  281. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/models/graphs/__init__.py +0 -0
  282. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/models/graphs/portfolio.py +0 -0
  283. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/models/graphs/utils.py +0 -0
  284. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/models/indexes.py +0 -0
  285. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/models/llm/wbcrm/analyze_relationship.py +0 -0
  286. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/models/mixins/__init__.py +0 -0
  287. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/models/mixins/instruments.py +0 -0
  288. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/models/mixins/liquidity_stress_test.py +0 -0
  289. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/models/orders/__init__.py +0 -0
  290. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/models/portfolio_cash_flow.py +0 -0
  291. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/models/portfolio_cash_targets.py +0 -0
  292. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/models/portfolio_relationship.py +0 -0
  293. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/models/portfolio_swing_pricings.py +0 -0
  294. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/models/product_groups.py +0 -0
  295. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/models/products.py +0 -0
  296. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/models/rebalancing.py +0 -0
  297. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/models/reconciliations/__init__.py +0 -0
  298. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/models/reconciliations/account_reconciliation_lines.py +0 -0
  299. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/models/reconciliations/account_reconciliations.py +0 -0
  300. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/models/reconciliations/reconciliations.py +0 -0
  301. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/models/registers.py +0 -0
  302. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/models/roles.py +0 -0
  303. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/models/signals.py +0 -0
  304. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/models/transactions/__init__.py +0 -0
  305. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/models/transactions/claim.py +0 -0
  306. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/models/transactions/dividends.py +0 -0
  307. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/models/transactions/fees.py +0 -0
  308. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/models/transactions/trades.py +0 -0
  309. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/models/transactions/transactions.py +0 -0
  310. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/models/utils.py +0 -0
  311. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/permissions.py +0 -0
  312. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/pms/__init__.py +0 -0
  313. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/pms/analytics/__init__.py +0 -0
  314. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/pms/analytics/portfolio.py +0 -0
  315. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/pms/analytics/utils.py +0 -0
  316. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/pms/statistics/__init__.py +0 -0
  317. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/pms/trading/__init__.py +0 -0
  318. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/pms/trading/handler.py +0 -0
  319. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/pms/typing.py +0 -0
  320. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/preferences.py +0 -0
  321. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/rebalancing/__init__.py +0 -0
  322. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/rebalancing/base.py +0 -0
  323. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/rebalancing/decorators.py +0 -0
  324. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/rebalancing/models/__init__.py +0 -0
  325. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/rebalancing/models/composite.py +0 -0
  326. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/rebalancing/models/equally_weighted.py +0 -0
  327. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/rebalancing/models/market_capitalization_weighted.py +0 -0
  328. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/rebalancing/models/model_portfolio.py +0 -0
  329. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/reports/__init__.py +0 -0
  330. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/reports/monthly_position_report.py +0 -0
  331. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/risk_management/__init__.py +0 -0
  332. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/risk_management/backends/__init__.py +0 -0
  333. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/risk_management/backends/accounts.py +0 -0
  334. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/risk_management/backends/controversy_portfolio.py +0 -0
  335. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/risk_management/backends/exposure_portfolio.py +0 -0
  336. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/risk_management/backends/instrument_list_portfolio.py +0 -0
  337. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/risk_management/backends/liquidity_risk.py +0 -0
  338. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/risk_management/backends/liquidity_stress_instrument.py +0 -0
  339. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/risk_management/backends/mixins.py +0 -0
  340. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/risk_management/backends/product_integrity.py +0 -0
  341. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/risk_management/backends/stop_loss_instrument.py +0 -0
  342. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/risk_management/backends/stop_loss_portfolio.py +0 -0
  343. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/risk_management/backends/ucits_portfolio.py +0 -0
  344. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/risk_management/tests/__init__.py +0 -0
  345. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/risk_management/tests/conftest.py +0 -0
  346. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/risk_management/tests/test_accounts.py +0 -0
  347. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/risk_management/tests/test_controversy_portfolio.py +0 -0
  348. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/risk_management/tests/test_exposure_portfolio.py +0 -0
  349. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/risk_management/tests/test_instrument_list_portfolio.py +0 -0
  350. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/risk_management/tests/test_liquidity_risk.py +0 -0
  351. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/risk_management/tests/test_product_integrity.py +0 -0
  352. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/risk_management/tests/test_stop_loss_instrument.py +0 -0
  353. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/risk_management/tests/test_stop_loss_portfolio.py +0 -0
  354. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/risk_management/tests/test_ucits_portfolio.py +0 -0
  355. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/serializers/__init__.py +0 -0
  356. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/serializers/adjustments.py +0 -0
  357. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/serializers/assets.py +0 -0
  358. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/serializers/custodians.py +0 -0
  359. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/serializers/orders/__init__.py +0 -0
  360. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/serializers/orders/orders.py +0 -0
  361. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/serializers/portfolio_cash_flow.py +0 -0
  362. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/serializers/portfolio_cash_targets.py +0 -0
  363. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/serializers/portfolio_relationship.py +0 -0
  364. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/serializers/portfolio_swing_pricing.py +0 -0
  365. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/serializers/portfolios.py +0 -0
  366. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/serializers/positions.py +0 -0
  367. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/serializers/product_group.py +0 -0
  368. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/serializers/products.py +0 -0
  369. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/serializers/rebalancing.py +0 -0
  370. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/serializers/reconciliations.py +0 -0
  371. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/serializers/registers.py +0 -0
  372. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/serializers/roles.py +0 -0
  373. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/serializers/signals.py +0 -0
  374. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/serializers/transactions/__init__.py +0 -0
  375. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/serializers/transactions/claim.py +0 -0
  376. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/serializers/transactions/dividends.py +0 -0
  377. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/serializers/transactions/fees.py +0 -0
  378. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/serializers/transactions/trades.py +0 -0
  379. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/static/wbportfolio/css/macro_review.css +0 -0
  380. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/static/wbportfolio/markdown/documentation/account_holding_reconciliation.md +0 -0
  381. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/static/wbportfolio/markdown/documentation/aggregate_asset_position_liquidity.md +0 -0
  382. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/static/wbportfolio/markdown/documentation/company.md +0 -0
  383. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/static/wbportfolio/markdown/documentation/earnings_instrument.md +0 -0
  384. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/static/wbportfolio/markdown/documentation/financial_analysis_instrument_ratios.md +0 -0
  385. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/static/wbportfolio/markdown/documentation/financial_statistics.md +0 -0
  386. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/static/wbportfolio/markdown/documentation/person.md +0 -0
  387. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/tasks.py +0 -0
  388. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/templates/portfolio/email/customer_report.html +0 -0
  389. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/templates/portfolio/email/customer_trade_notification.html +0 -0
  390. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/templates/portfolio/email/email_base_template.html +0 -0
  391. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/templates/portfolio/email/rebalancing_report.html +0 -0
  392. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/templates/portfolio/macro/macro_review.html +0 -0
  393. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/tests/__init__.py +0 -0
  394. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/tests/conftest.py +0 -0
  395. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/tests/models/__init__.py +0 -0
  396. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/tests/models/orders/__init__.py +0 -0
  397. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/tests/models/test_account_reconciliation.py +0 -0
  398. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/tests/models/test_assets.py +0 -0
  399. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/tests/models/test_custodians.py +0 -0
  400. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/tests/models/test_customer_trades.py +0 -0
  401. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/tests/models/test_dividends.py +0 -0
  402. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/tests/models/test_imports.py +0 -0
  403. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/tests/models/test_instrument_mixins.py +0 -0
  404. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/tests/models/test_merge.py +0 -0
  405. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/tests/models/test_portfolio_cash_flow.py +0 -0
  406. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/tests/models/test_portfolio_cash_targets.py +0 -0
  407. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/tests/models/test_portfolio_swing_pricings.py +0 -0
  408. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/tests/models/test_product_groups.py +0 -0
  409. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/tests/models/test_products.py +0 -0
  410. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/tests/models/test_roles.py +0 -0
  411. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/tests/models/test_splits.py +0 -0
  412. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/tests/models/transactions/__init__.py +0 -0
  413. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/tests/models/transactions/test_claim.py +0 -0
  414. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/tests/models/transactions/test_fees.py +0 -0
  415. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/tests/models/transactions/test_rebalancing.py +0 -0
  416. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/tests/models/transactions/test_trades.py +0 -0
  417. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/tests/models/utils.py +0 -0
  418. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/tests/pms/__init__.py +0 -0
  419. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/tests/pms/test_analytics.py +0 -0
  420. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/tests/rebalancing/__init__.py +0 -0
  421. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/tests/rebalancing/test_models.py +0 -0
  422. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/tests/serializers/__init__.py +0 -0
  423. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/tests/serializers/test_claims.py +0 -0
  424. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/tests/signals.py +0 -0
  425. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/tests/tests.py +0 -0
  426. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/tests/viewsets/__init__.py +0 -0
  427. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/tests/viewsets/test_assets.py +0 -0
  428. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/tests/viewsets/test_performances.py +0 -0
  429. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/tests/viewsets/test_products.py +0 -0
  430. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/tests/viewsets/transactions/__init__.py +0 -0
  431. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/tests/viewsets/transactions/test_claims.py +0 -0
  432. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/urls.py +0 -0
  433. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/utils.py +0 -0
  434. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/__init__.py +0 -0
  435. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/adjustments.py +0 -0
  436. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/assets.py +0 -0
  437. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/assets_and_net_new_money_progression.py +0 -0
  438. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/charts/__init__.py +0 -0
  439. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/charts/assets.py +0 -0
  440. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/__init__.py +0 -0
  441. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/buttons/__init__.py +0 -0
  442. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/buttons/adjustments.py +0 -0
  443. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/buttons/assets.py +0 -0
  444. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/buttons/claims.py +0 -0
  445. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/buttons/custodians.py +0 -0
  446. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/buttons/fees.py +0 -0
  447. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/buttons/mixins.py +0 -0
  448. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/buttons/portfolios.py +0 -0
  449. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/buttons/products.py +0 -0
  450. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/buttons/reconciliations.py +0 -0
  451. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/buttons/registers.py +0 -0
  452. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/buttons/signals.py +0 -0
  453. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/buttons/trades.py +0 -0
  454. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/display/__init__.py +0 -0
  455. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/display/adjustments.py +0 -0
  456. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/display/assets.py +0 -0
  457. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/display/claim.py +0 -0
  458. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/display/custodians.py +0 -0
  459. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/display/esg.py +0 -0
  460. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/display/fees.py +0 -0
  461. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/display/portfolio_cash_flow.py +0 -0
  462. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/display/portfolio_relationship.py +0 -0
  463. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/display/portfolios.py +0 -0
  464. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/display/positions.py +0 -0
  465. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/display/product_groups.py +0 -0
  466. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/display/product_performance.py +0 -0
  467. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/display/products.py +0 -0
  468. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/display/rebalancing.py +0 -0
  469. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/display/reconciliations.py +0 -0
  470. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/display/registers.py +0 -0
  471. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/display/roles.py +0 -0
  472. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/display/trades.py +0 -0
  473. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/endpoints/__init__.py +0 -0
  474. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/endpoints/adjustments.py +0 -0
  475. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/endpoints/assets.py +0 -0
  476. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/endpoints/claim.py +0 -0
  477. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/endpoints/custodians.py +0 -0
  478. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/endpoints/esg.py +0 -0
  479. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/endpoints/fees.py +0 -0
  480. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/endpoints/portfolio_relationship.py +0 -0
  481. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/endpoints/portfolios.py +0 -0
  482. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/endpoints/positions.py +0 -0
  483. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/endpoints/product_groups.py +0 -0
  484. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/endpoints/product_performance.py +0 -0
  485. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/endpoints/products.py +0 -0
  486. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/endpoints/rebalancing.py +0 -0
  487. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/endpoints/reconciliations.py +0 -0
  488. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/endpoints/roles.py +0 -0
  489. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/endpoints/trades.py +0 -0
  490. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/menu/__init__.py +0 -0
  491. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/menu/adjustments.py +0 -0
  492. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/menu/assets.py +0 -0
  493. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/menu/claim.py +0 -0
  494. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/menu/custodians.py +0 -0
  495. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/menu/fees.py +0 -0
  496. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/menu/instrument_prices.py +0 -0
  497. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/menu/portfolio_cash_flow.py +0 -0
  498. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/menu/portfolios.py +0 -0
  499. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/menu/positions.py +0 -0
  500. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/menu/product_groups.py +0 -0
  501. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/menu/product_performance.py +0 -0
  502. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/menu/products.py +0 -0
  503. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/menu/reconciliations.py +0 -0
  504. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/menu/registers.py +0 -0
  505. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/menu/roles.py +0 -0
  506. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/menu/trades.py +0 -0
  507. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/previews/__init__.py +0 -0
  508. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/previews/portfolios.py +0 -0
  509. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/titles/__init__.py +0 -0
  510. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/titles/adjustments.py +0 -0
  511. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/titles/assets.py +0 -0
  512. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/titles/assets_and_net_new_money_progression.py +0 -0
  513. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/titles/claim.py +0 -0
  514. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/titles/custodians.py +0 -0
  515. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/titles/esg.py +0 -0
  516. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/titles/fees.py +0 -0
  517. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/titles/instrument_prices.py +0 -0
  518. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/titles/portfolios.py +0 -0
  519. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/titles/positions.py +0 -0
  520. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/titles/product_groups.py +0 -0
  521. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/titles/product_performance.py +0 -0
  522. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/titles/products.py +0 -0
  523. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/titles/registers.py +0 -0
  524. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/titles/roles.py +0 -0
  525. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/configs/titles/trades.py +0 -0
  526. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/custodians.py +0 -0
  527. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/esg.py +0 -0
  528. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/mixins.py +0 -0
  529. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/orders/__init__.py +0 -0
  530. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/orders/configs/__init__.py +0 -0
  531. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/orders/configs/buttons/__init__.py +0 -0
  532. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/orders/configs/buttons/order_proposals.py +0 -0
  533. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/orders/configs/buttons/orders.py +0 -0
  534. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/orders/configs/displays/__init__.py +0 -0
  535. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/orders/configs/displays/orders.py +0 -0
  536. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/orders/configs/endpoints/__init__.py +0 -0
  537. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/orders/configs/endpoints/order_proposals.py +0 -0
  538. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/orders/configs/endpoints/orders.py +0 -0
  539. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/orders/configs/titles/__init__.py +0 -0
  540. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/orders/configs/titles/orders.py +0 -0
  541. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/orders/order_proposals.py +0 -0
  542. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/portfolio_cash_flow.py +0 -0
  543. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/portfolio_cash_targets.py +0 -0
  544. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/portfolio_relationship.py +0 -0
  545. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/portfolio_swing_pricing.py +0 -0
  546. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/portfolios.py +0 -0
  547. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/positions.py +0 -0
  548. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/product_groups.py +0 -0
  549. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/product_performance.py +0 -0
  550. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/products.py +0 -0
  551. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/rebalancing.py +0 -0
  552. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/reconciliations.py +0 -0
  553. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/registers.py +0 -0
  554. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/roles.py +0 -0
  555. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/signals.py +0 -0
  556. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/transactions/__init__.py +0 -0
  557. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/transactions/claim.py +0 -0
  558. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/transactions/fees.py +0 -0
  559. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/transactions/mixins.py +0 -0
  560. {wbportfolio-1.54.20 → wbportfolio-1.54.21}/wbportfolio/viewsets/transactions/trades.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wbportfolio
3
- Version: 1.54.20
3
+ Version: 1.54.21
4
4
  Author-email: Christopher Wittlinger <c.wittlinger@stainly.com>
5
5
  License-File: LICENSE
6
6
  Requires-Dist: cryptography==3.4.*
@@ -0,0 +1,25 @@
1
+ # Generated by Django 5.0.14 on 2025-07-30 14:25
2
+
3
+ from django.db import migrations, models
4
+ from decimal import Decimal
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ('wbportfolio', '0083_order_alter_trade_options_and_more'),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.AddField(
14
+ model_name='orderproposal',
15
+ name='min_order_value',
16
+ field=models.IntegerField(default=0, help_text='Minimum Order Value in the Portfolio currency', verbose_name='Minimum Order Value'),
17
+ ),
18
+ migrations.AddField(
19
+ model_name='order',
20
+ name='desired_target_weight',
21
+ field=models.DecimalField(decimal_places=8, default=Decimal('0'),
22
+ help_text='Desired Target Weight (for compliance and audit)', max_digits=9,
23
+ verbose_name='Desired Target Weight'),
24
+ ),
25
+ ]
@@ -0,0 +1,26 @@
1
+ # Generated by Django 5.0.14 on 2025-07-30 14:40
2
+
3
+ from decimal import Decimal
4
+ from django.db import migrations, models
5
+ from tqdm import tqdm
6
+
7
+ def migrate_desired_target_weight(apps, schema_editor):
8
+ from wbportfolio.models.orders import Order, OrderProposal
9
+ objs = []
10
+ qs = OrderProposal.objects.filter(orders__isnull=False).distinct()
11
+ for op in tqdm(qs, total=qs.count()):
12
+ for o in op.get_orders():
13
+ o.desired_target_weight = o._target_weight
14
+ objs.append(o)
15
+ Order.objects.bulk_update(objs, ["desired_target_weight"], batch_size=10000)
16
+
17
+
18
+ class Migration(migrations.Migration):
19
+
20
+ dependencies = [
21
+ ('wbportfolio', '0084_orderproposal_min_order_value'),
22
+ ]
23
+
24
+ operations = [
25
+ migrations.RunPython(migrate_desired_target_weight)
26
+ ]
@@ -1,4 +1,4 @@
1
- from collections import defaultdict
1
+ import logging
2
2
  from contextlib import suppress
3
3
  from datetime import date
4
4
  from decimal import Decimal, InvalidOperation
@@ -43,6 +43,8 @@ from wbportfolio.models.portfolio_relationship import (
43
43
  from wbportfolio.models.roles import PortfolioRole
44
44
  from wbportfolio.pms.typing import Position as PositionDTO
45
45
 
46
+ logger = logging.getLogger("pms")
47
+
46
48
  MARKETCAP_S = 2_000_000_000
47
49
  MARKETCAP_M = 10_000_000_000
48
50
  MARKETCAP_L = 50_000_000_000
@@ -55,146 +57,7 @@ HOUR = MINUTE * 60
55
57
  DAY = HOUR * 24
56
58
 
57
59
  if TYPE_CHECKING:
58
- from wbportfolio.models.portfolio import Portfolio
59
-
60
-
61
- class AssetPositionIterator:
62
- """
63
- Efficiently converts position data into AssetPosition models with batch operations
64
- and proper dependency management.
65
-
66
- Features:
67
- - Bulk database fetching for performance
68
- - Thread-safe operations
69
- - Clear type hints
70
- - Memory-efficient storage
71
- """
72
-
73
- positions: dict[tuple[date, int, int | None], "AssetPosition"]
74
-
75
- _prices: dict[date, dict[int, float]]
76
- _weights: dict[date, dict[int, float]]
77
- _fx_rates: dict[date, dict[Currency, CurrencyFXRates]]
78
- _instruments: dict[int, Instrument]
79
-
80
- def __init__(
81
- self,
82
- portfolio: "Portfolio",
83
- prices: dict[date, dict[int, float]] | None = None,
84
- infer_underlying_quote_price: bool = False,
85
- ):
86
- self.portfolio = portfolio
87
- self.infer_underlying_quote_price = infer_underlying_quote_price
88
- # Initialize data stores with type hints
89
- self._instruments = {}
90
- self._fx_rates = defaultdict(dict)
91
- self._weights = defaultdict(dict)
92
- self._prices = prices or defaultdict(dict)
93
- self.positions = dict()
94
-
95
- def _get_instrument(self, instrument_id: int) -> Instrument:
96
- try:
97
- return self._instruments[instrument_id]
98
- except KeyError:
99
- instrument = Instrument.objects.get(id=instrument_id)
100
- self._instruments[instrument_id] = instrument
101
- return instrument
102
-
103
- def _get_fx_rate(self, val_date: date, currency: Currency) -> CurrencyFXRates | None:
104
- try:
105
- return self._fx_rates[val_date][currency]
106
- except KeyError:
107
- with suppress(CurrencyFXRates.DoesNotExist):
108
- fx_rate = CurrencyFXRates.objects.get(
109
- currency=currency, date=val_date
110
- ) # we create a fx rate anyway to not fail the position. The fx rate expect to be there later on
111
- self._fx_rates[val_date][currency] = fx_rate
112
- return fx_rate
113
-
114
- def _get_price(self, val_date: date, instrument: Instrument) -> float | None:
115
- try:
116
- return self._prices[val_date][instrument.id]
117
- except KeyError:
118
- return None
119
-
120
- def _dict_to_model(self, val_date: date, instrument_id: int, weighting: float, **kwargs) -> "AssetPosition":
121
- underlying_quote = self._get_instrument(instrument_id)
122
- currency_fx_rate_portfolio_to_usd = self._get_fx_rate(val_date, self.portfolio.currency)
123
- currency_fx_rate_instrument_to_usd = self._get_fx_rate(val_date, underlying_quote.currency)
124
- price = self._get_price(val_date, underlying_quote)
125
-
126
- parameters = dict(
127
- underlying_quote=underlying_quote,
128
- weighting=round(weighting, 8),
129
- date=val_date,
130
- asset_valuation_date=val_date,
131
- is_estimated=True,
132
- portfolio=self.portfolio,
133
- currency=underlying_quote.currency,
134
- initial_price=price,
135
- currency_fx_rate_portfolio_to_usd=currency_fx_rate_portfolio_to_usd,
136
- currency_fx_rate_instrument_to_usd=currency_fx_rate_instrument_to_usd,
137
- initial_currency_fx_rate=None,
138
- underlying_quote_price=None,
139
- underlying_instrument=None,
140
- )
141
- parameters.update(kwargs)
142
- position = AssetPosition(**parameters)
143
- position.pre_save(
144
- infer_underlying_quote_price=self.infer_underlying_quote_price
145
- ) # 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
146
- return position
147
-
148
- def add(self, positions: list["AssetPosition"] | tuple[date, dict[int, float]], **kwargs):
149
- """
150
- Add multiple positions efficiently with batch processing
151
-
152
- Args:
153
- positions: Iterable of AssetPosition instances or dictionary of weight {instrument_id: weight} that needs to be converted into AssetPosition
154
- """
155
- if isinstance(positions, tuple):
156
- val_date = positions[0]
157
- positions = [(val_date, i, w) for i, w in positions[1].items()] # unflatten data to make it iterable
158
- for position in positions:
159
- if not isinstance(position, AssetPosition):
160
- position = self._dict_to_model(*position, **kwargs)
161
-
162
- # Generate unique composite key
163
- key = (
164
- position.date,
165
- position.underlying_quote.id,
166
- position.portfolio_created.id if position.portfolio_created else None,
167
- )
168
- # Merge duplicate positions
169
- if existing_position := self.positions.get(key):
170
- position.weighting += existing_position.weighting
171
- if existing_position.initial_shares:
172
- position.initial_shares += existing_position.initial_shares
173
- # ensure the position portfolio is the iterator portfolio (could be different when computing look-through for instance)
174
- position.portfolio = self.portfolio
175
- if position.initial_price is not None and position.initial_currency_fx_rate is not None:
176
- self.positions[key] = position
177
- self._weights[position.date][position.underlying_quote.id] = float(position.weighting)
178
-
179
- return self
180
-
181
- def get_dates(self) -> list[date]:
182
- """Get sorted list of unique dates"""
183
- return list(self._weights.keys())
184
-
185
- def get_weights(self) -> dict[date, dict[int, float]]:
186
- """Get weight structure with instrument IDs as keys"""
187
- return dict(self._weights)
188
-
189
- def __iter__(self):
190
- # return an iterable excluding the position with a null weight if the portfolio is manageable (otherwise, we assume the 0-weight position is valid)
191
- yield from filter(lambda a: not a.portfolio.is_manageable or a.weighting, self.positions.values())
192
-
193
- def __getitem__(self, item: tuple[date, Instrument]) -> float:
194
- return self._weights[item[0]][item[1].id]
195
-
196
- def __bool__(self) -> bool:
197
- return len(self.positions.keys()) > 0
60
+ pass
198
61
 
199
62
 
200
63
  class AssetPositionDefaultQueryset(QuerySet):
@@ -0,0 +1,258 @@
1
+ import logging
2
+ from collections import defaultdict
3
+ from contextlib import suppress
4
+ from datetime import date
5
+ from typing import TYPE_CHECKING
6
+
7
+ import pandas as pd
8
+ from celery import chain, group
9
+ from django.contrib.contenttypes.models import ContentType
10
+ from pandas._libs.tslibs.offsets import BDay
11
+ from wbcore.contrib.currency.models import Currency, CurrencyFXRates
12
+ from wbfdm.contrib.metric.tasks import compute_metrics_as_task
13
+ from wbfdm.models import Instrument
14
+
15
+ from wbportfolio.models.asset import AssetPosition
16
+ from wbportfolio.pms.analytics.portfolio import Portfolio as AnalyticPortfolio
17
+
18
+ if TYPE_CHECKING:
19
+ from wbportfolio.models import Portfolio
20
+ logger = logging.getLogger("pms")
21
+
22
+
23
+ class AssetPositionBuilder:
24
+ """
25
+ Efficiently converts position data into AssetPosition models with batch operations
26
+ and proper dependency management.
27
+
28
+ Features:
29
+ - Bulk database fetching for performance
30
+ - Thread-safe operations
31
+ - Clear type hints
32
+ - Memory-efficient storage
33
+ """
34
+
35
+ _positions: dict[date, dict[tuple[int, int | None], "AssetPosition"]]
36
+
37
+ _prices: dict[date, dict[int, float]]
38
+ _fx_rates: dict[date, dict[Currency, CurrencyFXRates]]
39
+ _instruments: dict[int, Instrument]
40
+
41
+ def __init__(
42
+ self,
43
+ portfolio: "Portfolio",
44
+ ):
45
+ self.portfolio = portfolio
46
+ # Initialize data stores with type hints
47
+ self._instruments = {}
48
+ self._fx_rates = defaultdict(dict)
49
+ self.prices = defaultdict(dict)
50
+ self.returns = pd.DataFrame()
51
+ self._compute_metrics_tasks = set()
52
+ self._change_at_date_tasks = dict()
53
+ self._positions = defaultdict(dict)
54
+
55
+ def get_positions(self, **kwargs):
56
+ # return an iterable excluding the position with a null weight if the portfolio is manageable (otherwise, we assume the 0-weight position is valid)
57
+ for _, positions in self._positions.items():
58
+ for _, position in positions.items():
59
+ if not position.portfolio.is_manageable or position.weighting:
60
+ for k, v in kwargs.items():
61
+ setattr(position, k, v)
62
+ yield position
63
+
64
+ def __bool__(self) -> bool:
65
+ return len(self._positions.keys()) > 0
66
+
67
+ def _get_instrument(self, instrument_id: int) -> Instrument:
68
+ try:
69
+ return self._instruments[instrument_id]
70
+ except KeyError:
71
+ instrument = Instrument.objects.get(id=instrument_id)
72
+ self._instruments[instrument_id] = instrument
73
+ return instrument
74
+
75
+ def _get_fx_rate(self, val_date: date, currency: Currency) -> CurrencyFXRates | None:
76
+ try:
77
+ return self._fx_rates[val_date][currency]
78
+ except KeyError:
79
+ with suppress(CurrencyFXRates.DoesNotExist):
80
+ fx_rate = CurrencyFXRates.objects.get(
81
+ currency=currency, date=val_date
82
+ ) # we create a fx rate anyway to not fail the position. The fx rate expect to be there later on
83
+ self._fx_rates[val_date][currency] = fx_rate
84
+ return fx_rate
85
+
86
+ def _get_price(self, val_date: date, instrument: Instrument) -> float | None:
87
+ try:
88
+ return self.prices[val_date][instrument.id]
89
+ except KeyError:
90
+ return None
91
+
92
+ def _dict_to_model(
93
+ self,
94
+ val_date: date,
95
+ instrument_id: int,
96
+ weighting: float,
97
+ infer_underlying_quote_price: bool = False,
98
+ **kwargs,
99
+ ) -> "AssetPosition":
100
+ underlying_quote = self._get_instrument(instrument_id)
101
+ currency_fx_rate_portfolio_to_usd = self._get_fx_rate(val_date, self.portfolio.currency)
102
+ currency_fx_rate_instrument_to_usd = self._get_fx_rate(val_date, underlying_quote.currency)
103
+ price = self._get_price(val_date, underlying_quote)
104
+
105
+ parameters = dict(
106
+ underlying_quote=underlying_quote,
107
+ weighting=round(weighting, 8),
108
+ date=val_date,
109
+ asset_valuation_date=val_date,
110
+ is_estimated=True,
111
+ portfolio=self.portfolio,
112
+ currency=underlying_quote.currency,
113
+ initial_price=price,
114
+ currency_fx_rate_portfolio_to_usd=currency_fx_rate_portfolio_to_usd,
115
+ currency_fx_rate_instrument_to_usd=currency_fx_rate_instrument_to_usd,
116
+ initial_currency_fx_rate=None,
117
+ underlying_quote_price=None,
118
+ underlying_instrument=None,
119
+ )
120
+ parameters.update(kwargs)
121
+ position = AssetPosition(**parameters)
122
+ position.pre_save(
123
+ infer_underlying_quote_price=infer_underlying_quote_price
124
+ ) # 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
125
+ return position
126
+
127
+ def set_return(self, returns: pd.DataFrame):
128
+ self.returns = returns
129
+
130
+ def set_prices(self, prices: dict[date, dict[int, float]] | None = None):
131
+ self.prices = prices
132
+
133
+ def load_returns(self, instrument_ids: list[int], from_date: date, to_date: date):
134
+ self.prices, self.returns = Instrument.objects.filter(id__in=instrument_ids).get_returns_df(
135
+ from_date=from_date, to_date=to_date, to_currency=self.portfolio.currency, use_dl=True
136
+ )
137
+
138
+ def add(
139
+ self,
140
+ positions: list["AssetPosition"] | tuple[date, dict[int, float]],
141
+ infer_underlying_quote_price: bool = False,
142
+ ):
143
+ """
144
+ Add multiple positions efficiently with batch processing
145
+
146
+ Args:
147
+ positions: Iterable of AssetPosition instances or dictionary of weight {instrument_id: weight} that needs to be converted into AssetPosition
148
+ """
149
+ if isinstance(positions, tuple):
150
+ val_date = positions[0]
151
+ positions = [(val_date, i, w) for i, w in positions[1].items()] # unflatten data to make it iterable
152
+ for position in positions:
153
+ if not isinstance(position, AssetPosition):
154
+ position = self._dict_to_model(*position, infer_underlying_quote_price=infer_underlying_quote_price)
155
+
156
+ # Generate unique composite key
157
+ key = (
158
+ position.underlying_quote.id,
159
+ position.portfolio_created.id if position.portfolio_created else None,
160
+ )
161
+ # Merge duplicate positions
162
+ if existing_position := self._positions[position.date].get(key):
163
+ position.weighting += existing_position.weighting
164
+ if existing_position.initial_shares:
165
+ position.initial_shares += existing_position.initial_shares
166
+ # ensure the position portfolio is the iterator portfolio (could be different when computing look-through for instance)
167
+ position.portfolio = self.portfolio
168
+ if position.initial_price is not None and position.initial_currency_fx_rate is not None:
169
+ self._positions[position.date][key] = position
170
+ return self
171
+
172
+ def get_dates(self) -> list[date]:
173
+ """Get sorted list of unique dates"""
174
+ return list(sorted(self._positions.keys()))
175
+
176
+ def _get_portfolio(self, val_date: date) -> AnalyticPortfolio:
177
+ """Get weight structure with instrument IDs as keys"""
178
+ positions = self._positions[val_date]
179
+ next_returns = self.returns.loc[[(val_date + BDay(1)).date()], :]
180
+ weights = dict(map(lambda row: (row[1].underlying_quote.id, float(row[1].weighting)), positions.items()))
181
+ return AnalyticPortfolio(weights=weights, X=next_returns)
182
+
183
+ def bulk_create_positions(self, delete_leftovers: bool = False, force_save: bool = False, **kwargs):
184
+ positions = list(self.get_positions(**kwargs))
185
+
186
+ # we need to delete the existing estimated portfolio because otherwise we risk to have existing and not
187
+ # overlapping positions remaining (as they will not be updating by the bulk create). E.g. when someone
188
+ # change completely the trades of a portfolio model and drift it.
189
+ dates = self.get_dates()
190
+ self.portfolio.assets.filter(date__in=dates, is_estimated=True).delete()
191
+
192
+ if len(positions) > 0:
193
+ if self.portfolio.is_tracked or force_save: # if the portfolio is not "tracked", we do no drift weights
194
+ leftover_positions_ids = list(
195
+ self.portfolio.assets.filter(date__in=dates).values_list("id", flat=True)
196
+ ) # we need to get the ids otherwise the queryset is reevaluated later
197
+ logger.info(f"bulk saving {len(positions)} positions ({len(leftover_positions_ids)} leftovers) ...")
198
+ objs = AssetPosition.unannotated_objects.bulk_create(
199
+ positions,
200
+ update_fields=[
201
+ "weighting",
202
+ "initial_price",
203
+ "initial_currency_fx_rate",
204
+ "initial_shares",
205
+ "currency_fx_rate_instrument_to_usd",
206
+ "currency_fx_rate_portfolio_to_usd",
207
+ "underlying_quote_price",
208
+ "portfolio",
209
+ "portfolio_created",
210
+ "underlying_instrument",
211
+ ],
212
+ unique_fields=["portfolio", "date", "underlying_quote", "portfolio_created"],
213
+ update_conflicts=True,
214
+ batch_size=10000,
215
+ )
216
+ if delete_leftovers:
217
+ objs_ids = list(map(lambda x: x.id, objs))
218
+ leftover_positions_ids = list(filter(lambda i: i not in objs_ids, leftover_positions_ids))
219
+ logger.info(f"deleting {len(leftover_positions_ids)} leftover positions..")
220
+ AssetPosition.objects.filter(id__in=leftover_positions_ids).delete()
221
+
222
+ for val_date in self.get_dates():
223
+ if self.portfolio.is_tracked:
224
+ with suppress(KeyError):
225
+ changed_portfolio = self._get_portfolio(val_date)
226
+ self._change_at_date_tasks[val_date] = changed_portfolio
227
+ self._compute_metrics_tasks.add(val_date)
228
+ self._positions = defaultdict(dict)
229
+
230
+ def schedule_metric_computation(self):
231
+ if self._compute_metrics_tasks:
232
+ basket_id = self.portfolio.id
233
+ basket_content_type_id = ContentType.objects.get_by_natural_key("wbportfolio", "portfolio").id
234
+ group(
235
+ *[
236
+ compute_metrics_as_task.si(d, basket_id=basket_id, basket_content_type_id=basket_content_type_id)
237
+ for d in self._compute_metrics_tasks
238
+ ]
239
+ ).apply_async()
240
+ self._change_at_date_tasks = set()
241
+
242
+ def schedule_change_at_dates(self, synchronous: bool = True, **task_kwargs):
243
+ from wbportfolio.models.portfolio import trigger_portfolio_change_as_task
244
+
245
+ if self._change_at_date_tasks:
246
+ tasks = chain(
247
+ *[
248
+ trigger_portfolio_change_as_task.si(
249
+ self.portfolio.id, d, changed_portfolio=portfolio, **task_kwargs
250
+ )
251
+ for d, portfolio in self._change_at_date_tasks.items()
252
+ ]
253
+ )
254
+ if synchronous:
255
+ tasks.apply()
256
+ else:
257
+ tasks.apply_async()
258
+ self._change_at_date_tasks = dict()
@@ -33,8 +33,7 @@ from wbcore.utils.models import CloneMixin
33
33
  from wbfdm.models import InstrumentPrice
34
34
  from wbfdm.models.instruments.instruments import Cash, Instrument
35
35
 
36
- from wbportfolio.models.asset import AssetPosition, AssetPositionIterator
37
- from wbportfolio.models.exceptions import InvalidAnalyticPortfolio
36
+ from wbportfolio.models.asset import AssetPosition
38
37
  from wbportfolio.models.roles import PortfolioRole
39
38
  from wbportfolio.pms.trading import TradingService
40
39
  from wbportfolio.pms.typing import Portfolio as PortfolioDTO
@@ -79,6 +78,9 @@ class OrderProposal(CloneMixin, RiskCheckMixin, WBModel):
79
78
  on_delete=models.PROTECT,
80
79
  verbose_name="Owner",
81
80
  )
81
+ min_order_value = models.IntegerField(
82
+ default=0, verbose_name="Minimum Order Value", help_text="Minimum Order Value in the Portfolio currency"
83
+ )
82
84
 
83
85
  class Meta:
84
86
  verbose_name = "Order Proposal"
@@ -218,6 +220,12 @@ class OrderProposal(CloneMixin, RiskCheckMixin, WBModel):
218
220
  ),
219
221
  default=models.F("effective_weight"),
220
222
  ),
223
+ target_weight=models.Case(
224
+ models.When(
225
+ id=largest_order.id, then=models.F("target_weight") + models.Value(Decimal(quant_error))
226
+ ),
227
+ default=models.F("target_weight"),
228
+ ),
221
229
  )
222
230
  return orders.annotate(
223
231
  has_warnings=models.Case(
@@ -257,7 +265,7 @@ class OrderProposal(CloneMixin, RiskCheckMixin, WBModel):
257
265
  self.value_date, weights=previous_weights, use_dl=True
258
266
  ).get_contributions()
259
267
  last_returns = last_returns.to_dict()
260
- except InvalidAnalyticPortfolio:
268
+ except ValueError:
261
269
  last_returns, portfolio_contribution = {}, 1
262
270
  positions = []
263
271
  total_weighting = Decimal("0")
@@ -456,14 +464,20 @@ class OrderProposal(CloneMixin, RiskCheckMixin, WBModel):
456
464
  if approve_automatically and self.portfolio.can_be_rebalanced:
457
465
  self.approve(replay=False)
458
466
 
459
- def replay(self, broadcast_changes_at_date: bool = True):
467
+ def replay(self, broadcast_changes_at_date: bool = True, reapply_order_proposal: bool = False):
460
468
  last_order_proposal = self
461
469
  last_order_proposal_created = False
470
+ self.portfolio.load_builder_returns(self.trade_date, date.today())
462
471
  while last_order_proposal and last_order_proposal.status == OrderProposal.Status.APPROVED:
463
- logger.info(f"Replaying order proposal {last_order_proposal}")
472
+ last_order_proposal.portfolio = self.portfolio # we set the same ptf reference
464
473
  if not last_order_proposal_created:
465
- last_order_proposal.approve_workflow(silent_exception=True, force_reset_order=True)
466
- last_order_proposal.save()
474
+ if reapply_order_proposal:
475
+ logger.info(f"Replaying order proposal {last_order_proposal}")
476
+ last_order_proposal.approve_workflow(silent_exception=True, force_reset_order=True)
477
+ last_order_proposal.save()
478
+ else:
479
+ logger.info(f"Resetting order proposal {last_order_proposal}")
480
+ last_order_proposal.reset_orders()
467
481
  if last_order_proposal.status != OrderProposal.Status.APPROVED:
468
482
  break
469
483
  next_order_proposal = last_order_proposal.next_order_proposal
@@ -478,21 +492,17 @@ class OrderProposal(CloneMixin, RiskCheckMixin, WBModel):
478
492
  else:
479
493
  next_trade_date = date.today()
480
494
  next_trade_date = min(next_trade_date, date.today())
481
- positions, overriding_order_proposal = self.portfolio.drift_weights(
495
+ gen = self.portfolio.drift_weights(
482
496
  last_order_proposal.trade_date, next_trade_date, stop_at_rebalancing=True
483
497
  )
498
+ try:
499
+ while True:
500
+ self.portfolio.builder.add(next(gen))
501
+ except StopIteration as e:
502
+ overriding_order_proposal = e.value
484
503
 
485
- # self.portfolio.assets.filter(
486
- # date__gt=last_order_proposal.trade_date, date__lte=next_trade_date, is_estimated=False
487
- # ).update(
488
- # is_estimated=True
489
- # ) # ensure that we reset non estimated position leftover to estimated between order proposal during replay
490
- self.portfolio.bulk_create_positions(
491
- positions,
504
+ self.portfolio.builder.bulk_create_positions(
492
505
  delete_leftovers=True,
493
- compute_metrics=False,
494
- broadcast_changes_at_date=broadcast_changes_at_date,
495
- evaluate_rebalancer=False,
496
506
  )
497
507
  for draft_tp in OrderProposal.objects.filter(
498
508
  portfolio=self.portfolio,
@@ -507,6 +517,8 @@ class OrderProposal(CloneMixin, RiskCheckMixin, WBModel):
507
517
  else:
508
518
  last_order_proposal_created = False
509
519
  last_order_proposal = next_order_proposal
520
+ if broadcast_changes_at_date:
521
+ self.portfolio.builder.schedule_change_at_dates(synchronous=False, evaluate_rebalancer=False)
510
522
 
511
523
  def invalidate_future_order_proposal(self):
512
524
  # Delete all future automatic order proposals and set the manual one into a draft state
@@ -576,7 +588,6 @@ class OrderProposal(CloneMixin, RiskCheckMixin, WBModel):
576
588
  total_target_weight = orders.exclude(underlying_instrument__is_cash=True).aggregate(
577
589
  s=models.Sum("target_weight")
578
590
  )["s"] or Decimal(0)
579
-
580
591
  if target_cash_weight is None:
581
592
  target_cash_weight = Decimal("1") - total_target_weight
582
593
 
@@ -644,7 +655,7 @@ class OrderProposal(CloneMixin, RiskCheckMixin, WBModel):
644
655
  orders_validation_warnings.extend(order_warnings)
645
656
  orders.append(order)
646
657
 
647
- Order.objects.bulk_update(orders, ["shares", "weighting"])
658
+ Order.objects.bulk_update(orders, ["shares", "weighting", "desired_target_weight"])
648
659
 
649
660
  # If we estimate cash on this order proposal, we make sure to create the corresponding cash component
650
661
  estimated_cash_position = self.get_estimated_target_cash()
@@ -704,30 +715,25 @@ class OrderProposal(CloneMixin, RiskCheckMixin, WBModel):
704
715
  # We validate order which will create or update the initial asset positions
705
716
  if not self.portfolio.can_be_rebalanced:
706
717
  raise ValueError("Non-Rebalanceable portfolio cannot be traded manually.")
707
- assets = []
708
718
  warnings = []
709
719
  # We do not want to create the estimated cash position if there is not orders in the order proposal (shouldn't be possible anyway)
710
720
  estimated_cash_position = self.get_estimated_target_cash()
721
+ assets = {}
711
722
  for order in self.get_orders():
712
723
  with suppress(ValueError):
713
- asset = order.get_asset()
714
724
  # we add the corresponding asset only if it is not the cache position (already included in estimated_cash_position)
715
- if asset.underlying_quote != estimated_cash_position.underlying_quote:
716
- assets.append(asset)
725
+ if order.underlying_instrument != estimated_cash_position.underlying_quote:
726
+ assets[order.underlying_instrument.id] = order._target_weight
717
727
 
718
728
  # if there is cash leftover, we create an extra asset position to hold the cash component
719
729
  if estimated_cash_position.weighting and len(assets) > 0:
720
730
  warnings.append(
721
731
  f"We created automatically a cash position of weight {estimated_cash_position.weighting:.2%}"
722
732
  )
723
- estimated_cash_position.pre_save()
724
- assets.append(estimated_cash_position)
725
-
726
- self.portfolio.bulk_create_positions(
727
- AssetPositionIterator(self.portfolio).add(assets, is_estimated=False),
728
- evaluate_rebalancer=False,
729
- force_save=True,
730
- **kwargs,
733
+ assets[estimated_cash_position.underlying_quote.id] = estimated_cash_position.weighting
734
+
735
+ self.portfolio.builder.add((self.trade_date, assets)).bulk_create_positions(
736
+ force_save=True, is_estimated=False
731
737
  )
732
738
  if replay and self.portfolio.is_manageable:
733
739
  replay_as_task.delay(self.id, user_id=by.id if by else None, broadcast_changes_at_date=False)
@@ -748,7 +754,7 @@ class OrderProposal(CloneMixin, RiskCheckMixin, WBModel):
748
754
  ]
749
755
  if self.has_non_successful_checks:
750
756
  errors["non_field_errors"] = [_("The pre orders rules did not passed successfully")]
751
- if orders.filter(has_warnings=True):
757
+ if orders.filter(has_warnings=True).exclude(underlying_instrument__is_cash=True):
752
758
  errors["non_field_errors"] = [
753
759
  _("There is warning that needs to be addresses on the orders before approval.")
754
760
  ]