wbportfolio 1.44.4__py2.py3-none-any.whl → 1.45.0__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of wbportfolio might be problematic. Click here for more details.

Files changed (315) hide show
  1. wbportfolio/admin/__init__.py +1 -1
  2. wbportfolio/admin/asset.py +2 -1
  3. wbportfolio/admin/custodians.py +1 -0
  4. wbportfolio/admin/indexes.py +15 -0
  5. wbportfolio/admin/portfolio.py +12 -7
  6. wbportfolio/admin/portfolio_relationships.py +1 -0
  7. wbportfolio/admin/product_groups.py +2 -0
  8. wbportfolio/admin/products.py +2 -1
  9. wbportfolio/admin/reconciliations.py +1 -0
  10. wbportfolio/admin/registers.py +1 -0
  11. wbportfolio/admin/roles.py +1 -0
  12. wbportfolio/admin/transactions/__init__.py +1 -0
  13. wbportfolio/admin/transactions/claim.py +1 -0
  14. wbportfolio/admin/transactions/dividends.py +1 -0
  15. wbportfolio/admin/transactions/fees.py +1 -0
  16. wbportfolio/admin/transactions/rebalancing.py +26 -0
  17. wbportfolio/admin/transactions/trades.py +4 -3
  18. wbportfolio/admin/transactions/transactions.py +1 -0
  19. wbportfolio/analysis/claims.py +2 -1
  20. wbportfolio/contrib/company_portfolio/models.py +3 -6
  21. wbportfolio/contrib/company_portfolio/tests/conftest.py +0 -12
  22. wbportfolio/contrib/company_portfolio/tests/test_models.py +1 -0
  23. wbportfolio/defaults/fees/default.py +1 -0
  24. wbportfolio/factories/__init__.py +1 -7
  25. wbportfolio/factories/adjustments.py +1 -0
  26. wbportfolio/factories/assets.py +13 -7
  27. wbportfolio/factories/claim.py +1 -0
  28. wbportfolio/factories/custodians.py +1 -0
  29. wbportfolio/factories/dividends.py +1 -0
  30. wbportfolio/factories/fees.py +1 -0
  31. wbportfolio/factories/indexes.py +1 -0
  32. wbportfolio/factories/portfolio_cash_flow.py +1 -0
  33. wbportfolio/factories/portfolio_cash_targets.py +1 -0
  34. wbportfolio/factories/portfolio_swing_pricings.py +1 -0
  35. wbportfolio/factories/portfolios.py +3 -0
  36. wbportfolio/factories/product_groups.py +1 -0
  37. wbportfolio/factories/products.py +1 -0
  38. wbportfolio/factories/rebalancing.py +23 -0
  39. wbportfolio/factories/reconciliations.py +1 -0
  40. wbportfolio/factories/roles.py +1 -0
  41. wbportfolio/factories/trades.py +1 -0
  42. wbportfolio/factories/transactions.py +1 -0
  43. wbportfolio/fdm/tasks.py +1 -0
  44. wbportfolio/filters/__init__.py +1 -1
  45. wbportfolio/filters/assets.py +8 -9
  46. wbportfolio/filters/assets_and_net_new_money_progression.py +1 -0
  47. wbportfolio/filters/custodians.py +1 -0
  48. wbportfolio/filters/esg.py +1 -0
  49. wbportfolio/filters/performances.py +7 -6
  50. wbportfolio/filters/portfolios.py +21 -1
  51. wbportfolio/filters/positions.py +1 -0
  52. wbportfolio/filters/products.py +1 -0
  53. wbportfolio/filters/roles.py +1 -0
  54. wbportfolio/filters/signals.py +1 -0
  55. wbportfolio/filters/transactions/claim.py +1 -0
  56. wbportfolio/filters/transactions/fees.py +1 -0
  57. wbportfolio/filters/transactions/trades.py +2 -1
  58. wbportfolio/filters/transactions/transactions.py +1 -0
  59. wbportfolio/import_export/backends/ubs/mixin.py +1 -0
  60. wbportfolio/import_export/backends/wbfdm/adjustment.py +1 -0
  61. wbportfolio/import_export/handlers/asset_position.py +11 -13
  62. wbportfolio/import_export/handlers/fees.py +1 -0
  63. wbportfolio/import_export/handlers/portfolio_cash_flow.py +1 -0
  64. wbportfolio/import_export/handlers/trade.py +1 -0
  65. wbportfolio/import_export/parsers/jpmorgan/customer_trade.py +1 -0
  66. wbportfolio/import_export/parsers/jpmorgan/fees.py +1 -0
  67. wbportfolio/import_export/parsers/jpmorgan/strategy.py +5 -4
  68. wbportfolio/import_export/parsers/jpmorgan/valuation.py +1 -0
  69. wbportfolio/import_export/parsers/leonteq/customer_trade.py +1 -0
  70. wbportfolio/import_export/parsers/leonteq/equity.py +13 -12
  71. wbportfolio/import_export/parsers/leonteq/fees.py +1 -0
  72. wbportfolio/import_export/parsers/leonteq/trade.py +1 -0
  73. wbportfolio/import_export/parsers/leonteq/valuation.py +1 -0
  74. wbportfolio/import_export/parsers/natixis/customer_trade.py +1 -0
  75. wbportfolio/import_export/parsers/natixis/d1_customer_trade.py +1 -0
  76. wbportfolio/import_export/parsers/natixis/d1_equity.py +3 -2
  77. wbportfolio/import_export/parsers/natixis/d1_fees.py +1 -0
  78. wbportfolio/import_export/parsers/natixis/d1_trade.py +1 -0
  79. wbportfolio/import_export/parsers/natixis/d1_valuation.py +1 -0
  80. wbportfolio/import_export/parsers/natixis/equity.py +5 -5
  81. wbportfolio/import_export/parsers/natixis/trade.py +1 -0
  82. wbportfolio/import_export/parsers/natixis/utils.py +8 -7
  83. wbportfolio/import_export/parsers/sg_lux/custodian_positions.py +1 -0
  84. wbportfolio/import_export/parsers/sg_lux/customer_trade.py +1 -0
  85. wbportfolio/import_export/parsers/sg_lux/customer_trade_pending_slk.py +2 -1
  86. wbportfolio/import_export/parsers/sg_lux/customer_trade_slk.py +2 -1
  87. wbportfolio/import_export/parsers/sg_lux/customer_trade_without_pw.py +1 -0
  88. wbportfolio/import_export/parsers/sg_lux/equity.py +7 -8
  89. wbportfolio/import_export/parsers/sg_lux/portfolio_cash_flow.py +1 -0
  90. wbportfolio/import_export/parsers/sg_lux/portfolio_future_cash_flow.py +1 -0
  91. wbportfolio/import_export/parsers/sg_lux/registers.py +2 -1
  92. wbportfolio/import_export/parsers/societe_generale/customer_trade.py +1 -0
  93. wbportfolio/import_export/parsers/societe_generale/strategy.py +8 -9
  94. wbportfolio/import_export/parsers/societe_generale/valuation.py +1 -0
  95. wbportfolio/import_export/parsers/tellco/equity.py +5 -4
  96. wbportfolio/import_export/parsers/ubs/api/asset_position.py +15 -14
  97. wbportfolio/import_export/parsers/ubs/api/fees.py +1 -0
  98. wbportfolio/import_export/parsers/ubs/customer_trade.py +1 -0
  99. wbportfolio/import_export/parsers/ubs/equity.py +3 -2
  100. wbportfolio/import_export/parsers/ubs/historical_customer_trade.py +1 -0
  101. wbportfolio/import_export/parsers/ubs/valuation.py +1 -0
  102. wbportfolio/import_export/parsers/vontobel/asset_position.py +19 -19
  103. wbportfolio/import_export/parsers/vontobel/customer_trade.py +1 -0
  104. wbportfolio/import_export/parsers/vontobel/historical_customer_trade.py +1 -0
  105. wbportfolio/import_export/parsers/vontobel/management_fees.py +1 -0
  106. wbportfolio/import_export/parsers/vontobel/performance_fees.py +1 -0
  107. wbportfolio/import_export/parsers/vontobel/trade.py +1 -0
  108. wbportfolio/import_export/parsers/vontobel/valuation_api.py +20 -0
  109. wbportfolio/import_export/resources/assets.py +4 -3
  110. wbportfolio/import_export/resources/trades.py +1 -0
  111. wbportfolio/metric/backends/base.py +1 -0
  112. wbportfolio/metric/backends/portfolio_base.py +1 -0
  113. wbportfolio/metric/backends/portfolio_esg.py +1 -0
  114. wbportfolio/metric/tests/test_portfolio_base.py +1 -0
  115. wbportfolio/migrations/0052_remove_cash_instrument_ptr_and_more.py +1 -131
  116. wbportfolio/migrations/0067_assetposition_unique_asset_position.py +1 -1
  117. wbportfolio/migrations/0070_remove_assetposition_unique_asset_position_and_more.py +1 -1
  118. wbportfolio/migrations/0073_remove_product_price_computation_and_more.py +407 -0
  119. wbportfolio/models/__init__.py +0 -5
  120. wbportfolio/models/adjustments.py +8 -2
  121. wbportfolio/models/asset.py +117 -98
  122. wbportfolio/models/graphs/portfolio.py +144 -0
  123. wbportfolio/models/graphs/utils.py +83 -0
  124. wbportfolio/models/indexes.py +2 -13
  125. wbportfolio/models/mixins/instruments.py +30 -8
  126. wbportfolio/models/portfolio.py +538 -332
  127. wbportfolio/models/portfolio_cash_flow.py +1 -0
  128. wbportfolio/models/portfolio_relationship.py +6 -2
  129. wbportfolio/models/product_groups.py +3 -2
  130. wbportfolio/models/products.py +3 -17
  131. wbportfolio/models/reconciliations/account_reconciliation_lines.py +1 -0
  132. wbportfolio/models/reconciliations/account_reconciliations.py +1 -0
  133. wbportfolio/models/registers.py +1 -0
  134. wbportfolio/models/transactions/__init__.py +1 -0
  135. wbportfolio/models/transactions/claim.py +8 -8
  136. wbportfolio/models/transactions/dividends.py +1 -0
  137. wbportfolio/models/transactions/fees.py +1 -0
  138. wbportfolio/models/transactions/rebalancing.py +153 -0
  139. wbportfolio/models/transactions/trade_proposals.py +153 -155
  140. wbportfolio/models/transactions/trades.py +48 -40
  141. wbportfolio/models/transactions/transactions.py +6 -12
  142. wbportfolio/models/utils.py +1 -0
  143. wbportfolio/pms/analytics/__init__.py +0 -0
  144. wbportfolio/pms/analytics/portfolio.py +28 -0
  145. wbportfolio/pms/trading/handler.py +13 -16
  146. wbportfolio/pms/typing.py +13 -29
  147. wbportfolio/rebalancing/__init__.py +0 -0
  148. wbportfolio/rebalancing/base.py +16 -0
  149. wbportfolio/rebalancing/decorators.py +17 -0
  150. wbportfolio/rebalancing/models/__init__.py +3 -0
  151. wbportfolio/rebalancing/models/composite.py +31 -0
  152. wbportfolio/rebalancing/models/equally_weighted.py +21 -0
  153. wbportfolio/rebalancing/models/model_portfolio.py +35 -0
  154. wbportfolio/reports/monthly_position_report.py +1 -1
  155. wbportfolio/risk_management/backends/accounts.py +7 -6
  156. wbportfolio/risk_management/backends/controversy_portfolio.py +1 -0
  157. wbportfolio/risk_management/backends/exposure_portfolio.py +1 -0
  158. wbportfolio/risk_management/backends/instrument_list_portfolio.py +1 -0
  159. wbportfolio/risk_management/backends/liquidity_risk.py +1 -0
  160. wbportfolio/risk_management/backends/liquidity_stress_instrument.py +1 -0
  161. wbportfolio/risk_management/backends/mixins.py +1 -0
  162. wbportfolio/risk_management/backends/product_integrity.py +6 -1
  163. wbportfolio/risk_management/backends/stop_loss_instrument.py +1 -0
  164. wbportfolio/risk_management/backends/stop_loss_portfolio.py +1 -0
  165. wbportfolio/risk_management/backends/ucits_portfolio.py +1 -0
  166. wbportfolio/risk_management/tests/test_accounts.py +1 -0
  167. wbportfolio/risk_management/tests/test_controversy_portfolio.py +1 -0
  168. wbportfolio/risk_management/tests/test_exposure_portfolio.py +1 -0
  169. wbportfolio/risk_management/tests/test_instrument_list_portfolio.py +1 -0
  170. wbportfolio/risk_management/tests/test_liquidity_risk.py +1 -0
  171. wbportfolio/risk_management/tests/test_product_integrity.py +1 -0
  172. wbportfolio/risk_management/tests/test_stop_loss_instrument.py +1 -0
  173. wbportfolio/risk_management/tests/test_stop_loss_portfolio.py +1 -0
  174. wbportfolio/risk_management/tests/test_ucits_portfolio.py +1 -0
  175. wbportfolio/serializers/__init__.py +5 -5
  176. wbportfolio/serializers/adjustments.py +1 -0
  177. wbportfolio/serializers/assets.py +18 -19
  178. wbportfolio/serializers/custodians.py +1 -0
  179. wbportfolio/serializers/portfolio_cash_flow.py +1 -0
  180. wbportfolio/serializers/portfolio_cash_targets.py +1 -0
  181. wbportfolio/serializers/portfolio_relationship.py +1 -0
  182. wbportfolio/serializers/portfolio_swing_pricing.py +1 -0
  183. wbportfolio/serializers/portfolios.py +61 -40
  184. wbportfolio/serializers/positions.py +1 -0
  185. wbportfolio/serializers/product_group.py +1 -0
  186. wbportfolio/serializers/products.py +4 -7
  187. wbportfolio/serializers/rebalancing.py +57 -0
  188. wbportfolio/serializers/reconciliations.py +2 -1
  189. wbportfolio/serializers/registers.py +1 -0
  190. wbportfolio/serializers/roles.py +1 -0
  191. wbportfolio/serializers/signals.py +10 -15
  192. wbportfolio/serializers/transactions/__init__.py +1 -1
  193. wbportfolio/serializers/transactions/claim.py +1 -0
  194. wbportfolio/serializers/transactions/fees.py +1 -0
  195. wbportfolio/serializers/transactions/trade_proposals.py +85 -0
  196. wbportfolio/serializers/transactions/trades.py +9 -51
  197. wbportfolio/serializers/transactions/transactions.py +4 -3
  198. wbportfolio/tasks.py +1 -78
  199. wbportfolio/tests/conftest.py +6 -13
  200. wbportfolio/tests/models/test_account_reconciliation.py +2 -0
  201. wbportfolio/tests/models/test_assets.py +27 -19
  202. wbportfolio/tests/models/test_customer_trades.py +1 -0
  203. wbportfolio/tests/models/test_imports.py +5 -1
  204. wbportfolio/tests/models/test_merge.py +5 -4
  205. wbportfolio/tests/models/test_portfolio_cash_flow.py +8 -6
  206. wbportfolio/tests/models/test_portfolios.py +594 -154
  207. wbportfolio/tests/models/test_product_groups.py +1 -0
  208. wbportfolio/tests/models/test_products.py +6 -3
  209. wbportfolio/tests/models/test_roles.py +1 -0
  210. wbportfolio/tests/models/test_splits.py +1 -0
  211. wbportfolio/tests/models/transactions/test_claim.py +1 -0
  212. wbportfolio/tests/models/transactions/test_fees.py +1 -0
  213. wbportfolio/tests/models/transactions/test_rebalancing.py +81 -0
  214. wbportfolio/tests/models/transactions/test_trades.py +1 -0
  215. wbportfolio/tests/models/utils.py +1 -0
  216. wbportfolio/tests/pms/__init__.py +0 -0
  217. wbportfolio/tests/pms/test_analytics.py +35 -0
  218. wbportfolio/tests/rebalancing/__init__.py +0 -0
  219. wbportfolio/tests/rebalancing/test_models.py +127 -0
  220. wbportfolio/tests/serializers/test_claims.py +1 -0
  221. wbportfolio/tests/signals.py +1 -7
  222. wbportfolio/tests/tests.py +2 -0
  223. wbportfolio/tests/viewsets/test_assets.py +1 -0
  224. wbportfolio/tests/viewsets/test_performances.py +1 -0
  225. wbportfolio/tests/viewsets/test_products.py +1 -0
  226. wbportfolio/tests/viewsets/transactions/test_claims.py +1 -0
  227. wbportfolio/urls.py +26 -12
  228. wbportfolio/viewsets/__init__.py +2 -5
  229. wbportfolio/viewsets/adjustments.py +1 -0
  230. wbportfolio/viewsets/assets.py +62 -51
  231. wbportfolio/viewsets/assets_and_net_new_money_progression.py +1 -0
  232. wbportfolio/viewsets/charts/assets.py +3 -1
  233. wbportfolio/viewsets/configs/buttons/__init__.py +1 -1
  234. wbportfolio/viewsets/configs/buttons/assets.py +1 -0
  235. wbportfolio/viewsets/configs/buttons/custodians.py +1 -0
  236. wbportfolio/viewsets/configs/buttons/mixins.py +1 -20
  237. wbportfolio/viewsets/configs/buttons/portfolios.py +90 -76
  238. wbportfolio/viewsets/configs/buttons/signals.py +1 -0
  239. wbportfolio/viewsets/configs/buttons/trades.py +1 -0
  240. wbportfolio/viewsets/configs/display/__init__.py +2 -1
  241. wbportfolio/viewsets/configs/display/adjustments.py +1 -0
  242. wbportfolio/viewsets/configs/display/assets.py +7 -6
  243. wbportfolio/viewsets/configs/display/claim.py +1 -0
  244. wbportfolio/viewsets/configs/display/portfolios.py +127 -79
  245. wbportfolio/viewsets/configs/display/product_performance.py +1 -0
  246. wbportfolio/viewsets/configs/display/rebalancing.py +27 -0
  247. wbportfolio/viewsets/configs/display/trade_proposals.py +7 -4
  248. wbportfolio/viewsets/configs/display/trades.py +75 -42
  249. wbportfolio/viewsets/configs/endpoints/__init__.py +3 -1
  250. wbportfolio/viewsets/configs/endpoints/claim.py +1 -0
  251. wbportfolio/viewsets/configs/endpoints/portfolios.py +23 -7
  252. wbportfolio/viewsets/configs/endpoints/rebalancing.py +6 -0
  253. wbportfolio/viewsets/configs/endpoints/reconciliations.py +1 -0
  254. wbportfolio/viewsets/configs/endpoints/trade_proposals.py +1 -0
  255. wbportfolio/viewsets/configs/endpoints/trades.py +1 -0
  256. wbportfolio/viewsets/configs/menu/adjustments.py +1 -0
  257. wbportfolio/viewsets/configs/menu/assets.py +1 -0
  258. wbportfolio/viewsets/configs/menu/fees.py +1 -0
  259. wbportfolio/viewsets/configs/menu/portfolio_cash_flow.py +1 -0
  260. wbportfolio/viewsets/configs/menu/portfolios.py +4 -2
  261. wbportfolio/viewsets/configs/menu/positions.py +1 -0
  262. wbportfolio/viewsets/configs/menu/roles.py +1 -0
  263. wbportfolio/viewsets/configs/menu/transactions.py +1 -0
  264. wbportfolio/viewsets/configs/previews/portfolios.py +1 -6
  265. wbportfolio/viewsets/configs/titles/__init__.py +1 -1
  266. wbportfolio/viewsets/configs/titles/assets.py +1 -0
  267. wbportfolio/viewsets/configs/titles/fees.py +1 -0
  268. wbportfolio/viewsets/configs/titles/instrument_prices.py +1 -0
  269. wbportfolio/viewsets/configs/titles/portfolios.py +13 -11
  270. wbportfolio/viewsets/configs/titles/roles.py +1 -0
  271. wbportfolio/viewsets/configs/titles/trades.py +1 -0
  272. wbportfolio/viewsets/configs/titles/transactions.py +1 -0
  273. wbportfolio/viewsets/custodians.py +1 -0
  274. wbportfolio/viewsets/esg.py +1 -0
  275. wbportfolio/viewsets/mixins.py +1 -0
  276. wbportfolio/viewsets/portfolio_cash_flow.py +1 -0
  277. wbportfolio/viewsets/portfolio_cash_targets.py +1 -0
  278. wbportfolio/viewsets/portfolio_relationship.py +1 -0
  279. wbportfolio/viewsets/portfolio_swing_pricing.py +1 -0
  280. wbportfolio/viewsets/portfolios.py +228 -61
  281. wbportfolio/viewsets/positions.py +3 -2
  282. wbportfolio/viewsets/product_groups.py +1 -0
  283. wbportfolio/viewsets/product_performance.py +1 -0
  284. wbportfolio/viewsets/products.py +1 -0
  285. wbportfolio/viewsets/reconciliations.py +1 -0
  286. wbportfolio/viewsets/registers.py +1 -0
  287. wbportfolio/viewsets/roles.py +1 -0
  288. wbportfolio/viewsets/signals.py +1 -0
  289. wbportfolio/viewsets/transactions/__init__.py +1 -0
  290. wbportfolio/viewsets/transactions/claim.py +2 -1
  291. wbportfolio/viewsets/transactions/fees.py +1 -0
  292. wbportfolio/viewsets/transactions/mixins.py +1 -0
  293. wbportfolio/viewsets/transactions/rebalancing.py +31 -0
  294. wbportfolio/viewsets/transactions/trade_proposals.py +25 -5
  295. wbportfolio/viewsets/transactions/trades.py +16 -9
  296. wbportfolio/viewsets/transactions/transactions.py +1 -0
  297. {wbportfolio-1.44.4.dist-info → wbportfolio-1.45.0.dist-info}/METADATA +4 -1
  298. {wbportfolio-1.44.4.dist-info → wbportfolio-1.45.0.dist-info}/RECORD +301 -288
  299. wbportfolio/admin/synchronization/__init__.py +0 -2
  300. wbportfolio/admin/synchronization/admin.py +0 -114
  301. wbportfolio/admin/synchronization/portfolio_synchronization.py +0 -18
  302. wbportfolio/admin/synchronization/price_computation.py +0 -21
  303. wbportfolio/defaults/portfolio/default_rebalancing.py +0 -45
  304. wbportfolio/factories/pytest_utils.py +0 -121
  305. wbportfolio/factories/synchronization.py +0 -40
  306. wbportfolio/models/synchronization/__init__.py +0 -3
  307. wbportfolio/models/synchronization/portfolio_synchronization.py +0 -292
  308. wbportfolio/models/synchronization/price_computation.py +0 -200
  309. wbportfolio/models/synchronization/synchronization.py +0 -188
  310. wbportfolio/serializers/synchronization.py +0 -18
  311. wbportfolio/tests/models/test_synchronization.py +0 -617
  312. wbportfolio/viewsets/synchronization.py +0 -25
  313. /wbportfolio/{defaults/portfolio → models/graphs}/__init__.py +0 -0
  314. {wbportfolio-1.44.4.dist-info → wbportfolio-1.45.0.dist-info}/WHEEL +0 -0
  315. {wbportfolio-1.44.4.dist-info → wbportfolio-1.45.0.dist-info}/licenses/LICENSE +0 -0
@@ -11,6 +11,7 @@ from wbcore.contrib.directory.models import Entry
11
11
  from wbcrm.models import Account
12
12
  from wbfdm.models import Classification
13
13
  from wbfdm.preferences import get_default_classification_group
14
+
14
15
  from wbportfolio.analysis.claims import ConsolidatedTradeSummary
15
16
  from wbportfolio.models import Product, ProductGroup
16
17
  from wbportfolio.models.transactions.claim import Claim, ClaimGroupbyChoice
@@ -149,13 +150,13 @@ class RuleBackend(backend.AbstractRuleBackend):
149
150
  }
150
151
  color = "red" if percentage < 0 else "green"
151
152
  if self.field == "AUM":
152
- report_details[
153
- "AUM Change"
154
- ] = f'<span style="color:{color}">{start_df.loc[breached_obj_id]:.0f} $ → {end_df.loc[breached_obj_id]:.0f} $</span>'
153
+ report_details["AUM Change"] = (
154
+ f'<span style="color:{color}">{start_df.loc[breached_obj_id]:.0f} $ → {end_df.loc[breached_obj_id]:.0f} $</span>'
155
+ )
155
156
  else:
156
- report_details[
157
- "Shares Change"
158
- ] = f"<span style='color:{color}'>{start_df.loc[breached_obj_id]:.0f} → {end_df.loc[breached_obj_id]:.0f}</span>"
157
+ report_details["Shares Change"] = (
158
+ f"<span style='color:{color}'>{start_df.loc[breached_obj_id]:.0f} → {end_df.loc[breached_obj_id]:.0f}</span>"
159
+ )
159
160
  report_details["Group By"] = self.group_by.value
160
161
  yield backend.IncidentResult(
161
162
  breached_object=breached_obj,
@@ -7,6 +7,7 @@ from wbcore import serializers as wb_serializers
7
7
  from wbfdm.enums import ESGControveryFlag
8
8
  from wbfdm.models import Instrument
9
9
  from wbfdm.models.esg.controversies import Controversy
10
+
10
11
  from wbportfolio.pms.typing import Portfolio as PortfolioDTO
11
12
 
12
13
  from .mixins import ActivePortfolioRelationshipMixin
@@ -14,6 +14,7 @@ from wbfdm.serializers import (
14
14
  ClassificationRepresentationSerializer,
15
15
  InstrumentTypeRepresentationSerializer,
16
16
  )
17
+
17
18
  from wbportfolio.pms.typing import Portfolio as PortfolioDTO
18
19
 
19
20
  from .mixins import ActivePortfolioRelationshipMixin
@@ -8,6 +8,7 @@ from wbfdm.models import Instrument, InstrumentList, InstrumentListThroughModel
8
8
  from wbfdm.serializers.instruments.instrument_lists import (
9
9
  InstrumentListRepresentationSerializer,
10
10
  )
11
+
11
12
  from wbportfolio.pms.typing import Portfolio as PortfolioDTO
12
13
 
13
14
  from .mixins import ActivePortfolioRelationshipMixin
@@ -9,6 +9,7 @@ from wbcompliance.models.risk_management import backend
9
9
  from wbcompliance.models.risk_management.dispatch import register
10
10
  from wbcore import serializers as wb_serializers
11
11
  from wbfdm.models import Instrument, InstrumentPrice
12
+
12
13
  from wbportfolio.models import AssetPosition
13
14
 
14
15
 
@@ -6,6 +6,7 @@ from wbcompliance.models.risk_management.dispatch import register
6
6
  from wbcore import serializers as wb_serializers
7
7
  from wbcore.serializers.fields.number import percent_decorator
8
8
  from wbfdm.models import Instrument
9
+
9
10
  from wbportfolio.pms.typing import Portfolio as PortfolioDTO
10
11
 
11
12
  from .mixins import ActiveProductRelationshipMixin
@@ -13,6 +13,7 @@ from wbfdm.serializers import (
13
13
  InstrumentTypeRepresentationSerializer,
14
14
  SecurityRepresentationSerializer,
15
15
  )
16
+
16
17
  from wbportfolio.models import InstrumentPortfolioThroughModel, Portfolio
17
18
 
18
19
 
@@ -7,6 +7,7 @@ from wbcompliance.models.risk_management import backend
7
7
  from wbcompliance.models.risk_management.dispatch import register
8
8
  from wbcore import serializers as wb_serializers
9
9
  from wbfdm.models import InstrumentPrice
10
+
10
11
  from wbportfolio.models import AssetPosition, Product
11
12
 
12
13
 
@@ -21,7 +22,11 @@ class RuleBackend(backend.AbstractRuleBackend):
21
22
  product: Product
22
23
 
23
24
  def is_passive_evaluation_valid(self) -> bool:
24
- return self.product.is_active_at_date(self.evaluation_date)
25
+ return (
26
+ self.product.is_active_at_date(self.evaluation_date)
27
+ and AssetPosition.objects.filter(is_estimated=False, portfolio=self.product.portfolio).exists()
28
+ and InstrumentPrice.objects.filter(calculated=False, instrument=self.product).exists()
29
+ )
25
30
 
26
31
  @classmethod
27
32
  def get_allowed_content_type(cls) -> "ContentType":
@@ -2,6 +2,7 @@ from typing import Generator
2
2
 
3
3
  from wbcompliance.models.risk_management import backend
4
4
  from wbcompliance.models.risk_management.dispatch import register
5
+
5
6
  from wbportfolio.pms.typing import Valuation as ValuationDTO
6
7
 
7
8
  from .mixins import ActiveProductRelationshipMixin, StopLossMixin
@@ -2,6 +2,7 @@ from typing import Generator
2
2
 
3
3
  from wbcompliance.models.risk_management import backend
4
4
  from wbcompliance.models.risk_management.dispatch import register
5
+
5
6
  from wbportfolio.pms.typing import Portfolio as PortfolioDTO
6
7
  from wbportfolio.pms.typing import Valuation as ValuationDTO
7
8
 
@@ -7,6 +7,7 @@ from wbcompliance.models.risk_management.dispatch import register
7
7
  from wbcore import serializers as wb_serializers
8
8
  from wbcore.serializers.fields.number import percent_decorator
9
9
  from wbfdm.models import Instrument
10
+
10
11
  from wbportfolio.pms.typing import Portfolio as PortfolioDTO
11
12
 
12
13
  from .mixins import ActivePortfolioRelationshipMixin
@@ -3,6 +3,7 @@ from faker import Faker
3
3
  from pandas.tseries.offsets import BDay
4
4
  from psycopg.types.range import NumericRange
5
5
  from wbcompliance.factories.risk_management import RuleThresholdFactory
6
+
6
7
  from wbportfolio.models.transactions.claim import ClaimGroupbyChoice
7
8
  from wbportfolio.risk_management.backends.accounts import (
8
9
  RuleBackend as AccountRuleBackend,
@@ -1,6 +1,7 @@
1
1
  import pytest
2
2
  from faker import Faker
3
3
  from wbfdm.enums import ESGControveryFlag
4
+
4
5
  from wbportfolio.risk_management.backends.controversy_portfolio import (
5
6
  RuleBackend as ControversyPortfolio,
6
7
  )
@@ -4,6 +4,7 @@ import pytest
4
4
  from faker import Faker
5
5
  from psycopg.types.range import NumericRange
6
6
  from wbcompliance.factories.risk_management import RuleThresholdFactory
7
+
7
8
  from wbportfolio.risk_management.backends.exposure_portfolio import (
8
9
  RuleBackend as ExposurePortfolioRuleBackend,
9
10
  )
@@ -1,6 +1,7 @@
1
1
  import pytest
2
2
  from faker import Faker
3
3
  from wbfdm.models.instruments.instrument_lists import InstrumentListThroughModel
4
+
4
5
  from wbportfolio.risk_management.backends.instrument_list_portfolio import (
5
6
  RuleBackend as InstrumentListPortfolio,
6
7
  )
@@ -2,6 +2,7 @@ import pytest
2
2
  from faker import Faker
3
3
  from psycopg.types.range import NumericRange
4
4
  from wbcompliance.factories.risk_management import RuleThresholdFactory
5
+
5
6
  from wbportfolio.risk_management.backends.liquidity_risk import (
6
7
  RuleBackend as LiquidityRiskRuleBackend,
7
8
  )
@@ -3,6 +3,7 @@ from faker import Faker
3
3
  from pandas.tseries.offsets import BDay
4
4
  from psycopg.types.range import NumericRange
5
5
  from wbcompliance.factories.risk_management import RuleThresholdFactory
6
+
6
7
  from wbportfolio.risk_management.backends.product_integrity import (
7
8
  RuleBackend as ProductRuleBackend,
8
9
  )
@@ -6,6 +6,7 @@ from faker import Faker
6
6
  from psycopg.types.range import NumericRange
7
7
  from wbcompliance.factories.risk_management import RuleThresholdFactory
8
8
  from wbfdm.models import RelatedInstrumentThroughModel
9
+
9
10
  from wbportfolio.risk_management.backends.stop_loss_instrument import (
10
11
  RuleBackend as StopLossInstrumentRuleBackend,
11
12
  )
@@ -5,6 +5,7 @@ import pytest
5
5
  from faker import Faker
6
6
  from psycopg.types.range import NumericRange
7
7
  from wbcompliance.factories.risk_management import RuleThresholdFactory
8
+
8
9
  from wbportfolio.risk_management.backends.stop_loss_instrument import (
9
10
  RuleBackend as StopLossInstrumentRuleBackend,
10
11
  )
@@ -1,5 +1,6 @@
1
1
  import pytest
2
2
  from faker import Faker
3
+
3
4
  from wbportfolio.risk_management.backends.ucits_portfolio import (
4
5
  RuleBackend as UCITPortfolioRuleBackend,
5
6
  )
@@ -1,3 +1,8 @@
1
+ from .rebalancing import (
2
+ RebalancingModelRepresentationSerializer,
3
+ RebalancerRepresentationSerializer,
4
+ RebalancerModelSerializer,
5
+ )
1
6
  from .assets import (
2
7
  AssetPositionInstrumentModelSerializer,
3
8
  AssetPositionModelSerializer,
@@ -11,7 +16,6 @@ from .portfolio_relationship import (
11
16
  InstrumentPortfolioThroughModelSerializer,
12
17
  )
13
18
  from .portfolios import (
14
- ModelPortfolioModelSerializer,
15
19
  PortfolioModelSerializer,
16
20
  PortfolioPortfolioThroughModelSerializer,
17
21
  PortfolioRepresentationSerializer,
@@ -22,10 +26,6 @@ from .positions import AggregatedAssetPositionModelSerializer
22
26
  from .registers import RegisterModelSerializer, RegisterRepresentationSerializer
23
27
  from .roles import PortfolioRoleModelSerializer, PortfolioRoleProjectModelSerializer
24
28
  from .signals import *
25
- from .synchronization import (
26
- PortfolioSynchronizationRepresentationSerializer,
27
- PriceComputationRepresentationSerializer,
28
- )
29
29
  from .transactions import *
30
30
  from .products import (
31
31
  ProductRepresentationSerializer,
@@ -1,6 +1,7 @@
1
1
  from wbcore import serializers as wb_serializers
2
2
  from wbcore.contrib.directory.serializers import PersonRepresentationSerializer
3
3
  from wbfdm.serializers import SecurityRepresentationSerializer
4
+
4
5
  from wbportfolio.models import Adjustment
5
6
 
6
7
 
@@ -2,18 +2,17 @@ from wbcore import serializers as wb_serializers
2
2
  from wbcore.contrib.currency.serializers import CurrencyRepresentationSerializer
3
3
  from wbfdm.serializers import InvestableInstrumentRepresentationSerializer
4
4
  from wbfdm.serializers.exchanges import ExchangeRepresentationSerializer
5
+
5
6
  from wbportfolio.models import AssetPosition, Portfolio
6
7
 
7
8
  from .portfolios import PortfolioRepresentationSerializer
8
9
 
9
10
 
10
11
  class AssetPositionModelSerializer(wb_serializers.ModelSerializer):
11
- underlying_instrument_isin = wb_serializers.CharField(read_only=True)
12
- underlying_instrument_ticker = wb_serializers.CharField(read_only=True)
13
- underlying_instrument_name = wb_serializers.CharField(read_only=True)
14
- _underlying_instrument = InvestableInstrumentRepresentationSerializer(
15
- source="underlying_instrument", label_key="name"
16
- )
12
+ underlying_quote_isin = wb_serializers.CharField(read_only=True)
13
+ underlying_quote_ticker = wb_serializers.CharField(read_only=True)
14
+ underlying_quote_name = wb_serializers.CharField(read_only=True)
15
+ _underlying_quote = InvestableInstrumentRepresentationSerializer(source="underlying_quote", label_key="name")
17
16
  _currency = CurrencyRepresentationSerializer(source="currency")
18
17
  _portfolio = PortfolioRepresentationSerializer(source="portfolio")
19
18
  _exchange = ExchangeRepresentationSerializer(source="exchange")
@@ -70,11 +69,11 @@ class AssetPositionModelSerializer(wb_serializers.ModelSerializer):
70
69
  "total_value_fx_portfolio",
71
70
  "liquidity",
72
71
  "is_estimated",
73
- "underlying_instrument_name",
74
- "underlying_instrument_isin",
75
- "underlying_instrument_ticker",
76
- "underlying_instrument",
77
- "_underlying_instrument",
72
+ "underlying_quote_name",
73
+ "underlying_quote_isin",
74
+ "underlying_quote_ticker",
75
+ "underlying_quote",
76
+ "_underlying_quote",
78
77
  "_portfolio",
79
78
  "_portfolio_created",
80
79
  "_exchange",
@@ -93,11 +92,11 @@ class AssetPositionPortfolioModelSerializer(AssetPositionModelSerializer):
93
92
  fields = (
94
93
  "id",
95
94
  "is_estimated",
96
- "underlying_instrument_name",
97
- "underlying_instrument_isin",
98
- "underlying_instrument_ticker",
99
- "underlying_instrument",
100
- "_underlying_instrument",
95
+ "underlying_quote_name",
96
+ "underlying_quote_isin",
97
+ "underlying_quote_ticker",
98
+ "underlying_quote",
99
+ "_underlying_quote",
101
100
  "currency",
102
101
  "_currency",
103
102
  "exchange",
@@ -128,9 +127,9 @@ class AssetPositionAggregatedPortfolioModelSerializer(AssetPositionPortfolioMode
128
127
  fields = (
129
128
  "id",
130
129
  "is_estimated",
131
- "underlying_instrument_isin",
132
- "underlying_instrument_ticker",
133
- "underlying_instrument_name",
130
+ "underlying_quote_isin",
131
+ "underlying_quote_ticker",
132
+ "underlying_quote_name",
134
133
  "currency",
135
134
  "price",
136
135
  "shares",
@@ -1,5 +1,6 @@
1
1
  from rest_framework.reverse import reverse
2
2
  from wbcore import serializers as wb_serializers
3
+
3
4
  from wbportfolio.models import Custodian
4
5
 
5
6
 
@@ -2,6 +2,7 @@ from datetime import date, timedelta
2
2
 
3
3
  from rest_framework.exceptions import ValidationError
4
4
  from wbcore import serializers
5
+
5
6
  from wbportfolio.models.portfolio_cash_flow import DailyPortfolioCashFlow
6
7
  from wbportfolio.serializers.portfolios import PortfolioRepresentationSerializer
7
8
 
@@ -1,4 +1,5 @@
1
1
  from wbcore import serializers
2
+
2
3
  from wbportfolio.models.portfolio_cash_targets import PortfolioCashTarget
3
4
  from wbportfolio.serializers.portfolios import PortfolioRepresentationSerializer
4
5
 
@@ -7,6 +7,7 @@ from wbfdm.serializers import (
7
7
  from wbfdm.serializers.instruments.classifications import (
8
8
  ClassificationGroupRepresentationSerializer,
9
9
  )
10
+
10
11
  from wbportfolio.models.portfolio_relationship import (
11
12
  InstrumentPortfolioThroughModel,
12
13
  PortfolioInstrumentPreferredClassificationThroughModel,
@@ -1,4 +1,5 @@
1
1
  from wbcore import serializers
2
+
2
3
  from wbportfolio.models.portfolio_swing_pricings import PortfolioSwingPricing
3
4
  from wbportfolio.serializers.portfolios import PortfolioRepresentationSerializer
4
5
 
@@ -2,13 +2,15 @@ from rest_framework.reverse import reverse
2
2
  from wbcore import serializers as wb_serializers
3
3
  from wbcore.contrib.currency.serializers import CurrencyRepresentationSerializer
4
4
  from wbcore.contrib.directory.models import BankingContact
5
+
5
6
  from wbportfolio.models import Portfolio, PortfolioPortfolioThroughModel
6
- from wbportfolio.serializers.synchronization import (
7
- PortfolioSynchronizationRepresentationSerializer,
8
- )
7
+ from wbportfolio.serializers.rebalancing import RebalancerRepresentationSerializer
9
8
 
10
9
 
11
10
  class PortfolioRepresentationSerializer(wb_serializers.RepresentationSerializer):
11
+ def get_filter_params(self, request):
12
+ return {"is_tracked": True}
13
+
12
14
  _detail = wb_serializers.HyperlinkField(reverse_name="wbportfolio:portfolio-detail")
13
15
  _detail_preview = wb_serializers.HyperlinkField(reverse_name="wbportfolio:portfolio-detail")
14
16
 
@@ -20,11 +22,17 @@ class PortfolioRepresentationSerializer(wb_serializers.RepresentationSerializer)
20
22
  class PortfolioModelSerializer(wb_serializers.ModelSerializer):
21
23
  _currency = CurrencyRepresentationSerializer(source="currency")
22
24
  _depends_on = PortfolioRepresentationSerializer(source="depends_on", many=True)
23
- _portfolio_synchronization = PortfolioSynchronizationRepresentationSerializer(source="portfolio_synchronization")
24
- dependent_portfolios = wb_serializers.PrimaryKeyRelatedField(
25
- many=True, read_only=True, label="Dependency Portfolios"
26
- )
27
- _dependent_portfolios = PortfolioSynchronizationRepresentationSerializer(many=True, source="dependent_portfolios")
25
+ automatic_rebalancer = wb_serializers.PrimaryKeyRelatedField(read_only=True)
26
+ _automatic_rebalancer = RebalancerRepresentationSerializer(source="automatic_rebalancer")
27
+
28
+ create_index = wb_serializers.BooleanField(write_only=True, default=False)
29
+
30
+ def create(self, validated_data):
31
+ create_index = validated_data.pop("create_index", False)
32
+ obj = super().create(validated_data)
33
+ if create_index:
34
+ obj.get_or_create_index()
35
+ return obj
28
36
 
29
37
  @wb_serializers.register_only_instance_resource()
30
38
  def cash_management(self, instance, request, user, **kwargs):
@@ -36,9 +44,9 @@ class PortfolioModelSerializer(wb_serializers.ModelSerializer):
36
44
  b = BankingContact.objects.filter(wbportfolio_products__id__in=instance.instruments.all().values("id"))
37
45
  if b.exists():
38
46
  base_url = reverse("wbaccounting:futurecashflow-list", request=request)
39
- additional_resources[
40
- "cash_flow"
41
- ] = f'{base_url}?banking_contact={",".join([str(i) for i in b.distinct("id").values_list("id", flat=True)])}'
47
+ additional_resources["cash_flow"] = (
48
+ f'{base_url}?banking_contact={",".join([str(i) for i in b.distinct("id").values_list("id", flat=True)])}'
49
+ )
42
50
 
43
51
  return additional_resources
44
52
 
@@ -67,22 +75,11 @@ class PortfolioModelSerializer(wb_serializers.ModelSerializer):
67
75
  request=request,
68
76
  )
69
77
 
70
- if instance.portfolio_synchronization:
71
- additional_resources["resynchronize"] = reverse(
72
- "wbportfolio:portfolio-resynchronize",
73
- args=[instance.id],
74
- request=request,
75
- )
76
78
  additional_resources["dependencyportfolios"] = reverse(
77
79
  "wbportfolio:portfolio-dependencyportfolio-list",
78
80
  args=[instance.id],
79
81
  request=request,
80
82
  )
81
- additional_resources["trade_proposals"] = reverse(
82
- "wbportfolio:portfolio-tradeproposal-list",
83
- args=[instance.id],
84
- request=request,
85
- )
86
83
 
87
84
  additional_resources["preferredclassification"] = reverse(
88
85
  "wbportfolio:portfolio-preferredclassification-list",
@@ -94,7 +91,38 @@ class PortfolioModelSerializer(wb_serializers.ModelSerializer):
94
91
  args=[instance.id],
95
92
  request=request,
96
93
  )
97
-
94
+ additional_resources["trade_proposals"] = reverse(
95
+ "wbportfolio:portfolio-tradeproposal-list",
96
+ args=[instance.id],
97
+ request=request,
98
+ )
99
+ additional_resources["rebalance"] = reverse(
100
+ "wbportfolio:portfolio-rebalance",
101
+ args=[instance.id],
102
+ request=request,
103
+ )
104
+ if not getattr(instance, "automatic_rebalancer", None):
105
+ additional_resources["add_automatic_rebalancer"] = reverse(
106
+ "wbportfolio:portfolio-attachrebalancer",
107
+ args=[instance.id],
108
+ request=request,
109
+ )
110
+ if user.is_superuser and instance.is_lookthrough:
111
+ additional_resources["recompute_lookthrough"] = reverse(
112
+ "wbportfolio:portfolio-recomputelookthrough",
113
+ args=[instance.id],
114
+ request=request,
115
+ )
116
+ additional_resources["treegraphchart"] = reverse(
117
+ "wbportfolio:portfolio-treegraphchart-list",
118
+ args=[instance.id],
119
+ request=request,
120
+ )
121
+ additional_resources["topdowncomposition"] = reverse(
122
+ "wbportfolio:portfolio-topdowncomposition-list",
123
+ args=[instance.id],
124
+ request=request,
125
+ )
98
126
  return additional_resources
99
127
 
100
128
  class Meta:
@@ -102,31 +130,24 @@ class PortfolioModelSerializer(wb_serializers.ModelSerializer):
102
130
  fields = (
103
131
  "id",
104
132
  "name",
105
- "last_synchronization",
133
+ "updated_at",
106
134
  "_depends_on",
107
- "_portfolio_synchronization",
108
135
  "depends_on",
109
- "portfolio_synchronization",
110
- "_dependent_portfolios",
111
- "dependent_portfolios",
112
136
  "_currency",
113
137
  "currency",
138
+ "automatic_rebalancer",
139
+ "_automatic_rebalancer",
140
+ "invested_timespan",
141
+ "is_manageable",
142
+ "is_tracked",
143
+ "only_weighting",
144
+ "is_lookthrough",
145
+ "is_composition",
114
146
  "_additional_resources",
147
+ "create_index",
115
148
  )
116
149
 
117
150
 
118
- class ModelPortfolioModelSerializer(PortfolioModelSerializer):
119
- @wb_serializers.register_only_instance_resource()
120
- def rebalance(self, instance, request, user, **kwargs):
121
- return {
122
- "modelcomposition": reverse(
123
- "wbportfolio:portfolio-modelcompositionpandas-list",
124
- args=[instance.id],
125
- request=request,
126
- )
127
- }
128
-
129
-
130
151
  class PortfolioPortfolioThroughModelSerializer(wb_serializers.ModelSerializer):
131
152
  _portfolio = PortfolioRepresentationSerializer(source="portfolio")
132
153
  _dependency_portfolio = PortfolioRepresentationSerializer(source="dependency_portfolio")
@@ -1,4 +1,5 @@
1
1
  from wbcore import serializers as wb_serializers
2
+
2
3
  from wbportfolio.models import AssetPosition
3
4
 
4
5
 
@@ -3,6 +3,7 @@ from wbcore.contrib.directory.models import Company
3
3
  from wbcore.contrib.directory.serializers import CompanyRepresentationSerializer
4
4
  from wbcore.contrib.geography.serializers import GeographyRepresentationSerializer
5
5
  from wbfdm.serializers.instruments import InstrumentModelSerializer
6
+
6
7
  from wbportfolio.models import ProductGroup, ProductGroupRepresentant
7
8
  from wbportfolio.serializers.portfolios import PortfolioRepresentationSerializer
8
9
 
@@ -11,11 +11,11 @@ from wbcore.contrib.directory.serializers import (
11
11
  from wbcore.contrib.geography.serializers import GeographyRepresentationSerializer
12
12
  from wbfdm.models import Instrument
13
13
  from wbfdm.serializers.instruments.instruments import InstrumentModelSerializer
14
+
14
15
  from wbportfolio.models import Portfolio, Product
15
16
  from wbportfolio.serializers.portfolios import PortfolioRepresentationSerializer
16
17
 
17
18
  from .product_group import ProductGroupRepresentationSerializer
18
- from .synchronization import PriceComputationRepresentationSerializer
19
19
 
20
20
 
21
21
  class ProductRepresentationSerializer(wb_serializers.RepresentationSerializer):
@@ -179,16 +179,15 @@ class ProductModelSerializer(ProductListModelSerializer):
179
179
  is_next_factsheet_available = wb_serializers.BooleanField(default=False, read_only=True)
180
180
 
181
181
  _portfolios = PortfolioRepresentationSerializer(source="portfolios", many=True)
182
- _price_computation = PriceComputationRepresentationSerializer(source="price_computation")
183
182
 
184
183
  @wb_serializers.register_resource()
185
184
  def additional_resources(self, instance, request, user):
186
185
  additional_resources = dict()
187
186
 
188
187
  if user.profile.is_internal or user.is_superuser:
189
- additional_resources[
190
- "aum"
191
- ] = f'{reverse("wbportfolio:aumtable-list", args=[], request=request)}?product={instance.id}&group_by=ACCOUNT'
188
+ additional_resources["aum"] = (
189
+ f'{reverse("wbportfolio:aumtable-list", args=[], request=request)}?product={instance.id}&group_by=ACCOUNT'
190
+ )
192
191
  additional_resources["claims"] = reverse(
193
192
  "wbportfolio:product-claim-list",
194
193
  args=[instance.id],
@@ -248,8 +247,6 @@ class ProductModelSerializer(ProductListModelSerializer):
248
247
  "_parent",
249
248
  "_portfolios",
250
249
  "portfolios",
251
- "_price_computation",
252
- "price_computation",
253
250
  ) + InstrumentModelSerializer.Meta.fields
254
251
 
255
252
 
@@ -0,0 +1,57 @@
1
+ from datetime import date
2
+
3
+ from wbcore import serializers as wb_serializers
4
+ from wbcore.serializers import DefaultFromGET
5
+
6
+ from wbportfolio.models import Portfolio, Rebalancer, RebalancingModel
7
+
8
+
9
+ class RebalancingModelRepresentationSerializer(wb_serializers.RepresentationSerializer):
10
+ class Meta:
11
+ model = RebalancingModel
12
+ fields = (
13
+ "id",
14
+ "name",
15
+ )
16
+
17
+
18
+ class RebalancerRepresentationSerializer(wb_serializers.RepresentationSerializer):
19
+ _detail = wb_serializers.HyperlinkField(reverse_name="wbportfolio:rebalancer-detail")
20
+
21
+ class Meta:
22
+ model = Rebalancer
23
+ fields = ("id", "computed_str", "_detail")
24
+
25
+
26
+ class RebalancerModelSerializer(wb_serializers.ModelSerializer):
27
+ _rebalancing_model = RebalancingModelRepresentationSerializer(source="rebalancing_model")
28
+ frequency_repr = wb_serializers.SerializerMethodField()
29
+ portfolio = wb_serializers.PrimaryKeyRelatedField(
30
+ queryset=Portfolio.objects.all(), default=DefaultFromGET("portfolio")
31
+ )
32
+ activation_date = wb_serializers.DateField(default=lambda: date.today())
33
+
34
+ rebalancing_dates = wb_serializers.SerializerMethodField(
35
+ label="Next 10 Rebalancing Dates", field_class=wb_serializers.ListField
36
+ )
37
+
38
+ def get_rebalancing_dates(self, obj):
39
+ return list(map(lambda d: d.strftime("%Y-%m-%d"), obj.get_rrule(count=10)))
40
+
41
+ def get_frequency_repr(self, obj):
42
+ return obj.frequency_repr
43
+
44
+ class Meta:
45
+ model = Rebalancer
46
+ fields = (
47
+ "id",
48
+ "portfolio",
49
+ "computed_str",
50
+ "_rebalancing_model",
51
+ "rebalancing_model",
52
+ "approve_trade_proposal_automatically",
53
+ "activation_date",
54
+ "frequency",
55
+ "frequency_repr",
56
+ "rebalancing_dates",
57
+ )