wbportfolio 1.44.5__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 +28 -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.5.dist-info → wbportfolio-1.45.0.dist-info}/METADATA +4 -1
  298. {wbportfolio-1.44.5.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.5.dist-info → wbportfolio-1.45.0.dist-info}/WHEEL +0 -0
  315. {wbportfolio-1.44.5.dist-info → wbportfolio-1.45.0.dist-info}/licenses/LICENSE +0 -0
@@ -21,6 +21,7 @@ from wbcore.utils.figures import (
21
21
  from wbcore.utils.strings import format_number
22
22
  from wbfdm.contrib.metric.viewsets.mixins import InstrumentMetricMixin
23
23
  from wbfdm.models import Instrument
24
+
24
25
  from wbportfolio.filters import (
25
26
  AssetPositionFilter,
26
27
  AssetPositionInstrumentFilter,
@@ -45,7 +46,7 @@ from wbportfolio.models import (
45
46
  Portfolio,
46
47
  Product,
47
48
  )
48
- from wbportfolio.serializers import (
49
+ from wbportfolio.serializers.assets import (
49
50
  AssetPositionAggregatedPortfolioModelSerializer,
50
51
  AssetPositionInstrumentModelSerializer,
51
52
  AssetPositionModelSerializer,
@@ -98,10 +99,10 @@ class AssetPositionModelViewSet(
98
99
  "total_value",
99
100
  "portfolio__name",
100
101
  "portfolio_created__name",
101
- "underlying_instrument",
102
- "underlying_instrument_name",
103
- "underlying_instrument_ticker",
104
- "underlying_instrument_isin",
102
+ "underlying_quote",
103
+ "underlying_quote_name",
104
+ "underlying_quote_ticker",
105
+ "underlying_quote_isin",
105
106
  "price",
106
107
  "currency__key",
107
108
  "currency_fx_rate",
@@ -113,7 +114,7 @@ class AssetPositionModelViewSet(
113
114
  "liquidity",
114
115
  ]
115
116
  ordering = ["-weighting"]
116
- search_fields = ["underlying_instrument_ticker", "underlying_instrument_name", "underlying_instrument_isin"]
117
+ search_fields = ["underlying_quote_ticker", "underlying_quote_name", "underlying_quote_isin"]
117
118
 
118
119
  display_config_class = AssetPositionDisplayConfig
119
120
  button_config_class = AssetPositionButtonConfig
@@ -142,12 +143,12 @@ class AssetPositionModelViewSet(
142
143
  super()
143
144
  .get_queryset()
144
145
  .annotate(
145
- underlying_instrument_isin=F("underlying_instrument__isin"),
146
- underlying_instrument_ticker=F("underlying_instrument__ticker"),
147
- underlying_instrument_name=F("underlying_instrument__name"),
146
+ underlying_quote_isin=F("underlying_quote__isin"),
147
+ underlying_quote_ticker=F("underlying_quote__ticker"),
148
+ underlying_quote_name=F("underlying_quote__name"),
148
149
  )
149
150
  .select_related(
150
- "underlying_instrument",
151
+ "underlying_quote",
151
152
  "currency",
152
153
  "portfolio",
153
154
  "exchange",
@@ -170,7 +171,7 @@ class AssetPositionPortfolioModelViewSet(InstrumentMetricMixin, AssetPositionMod
170
171
  *PORTFOLIO_ESG_KEYS,
171
172
  )
172
173
  METRIC_BASKET_LABEL = "portfolio"
173
- METRIC_INSTRUMENT_LABEL = "underlying_instrument"
174
+ METRIC_INSTRUMENT_LABEL = "underlying_quote"
174
175
  METRIC_SHOW_BY_DEFAULT = False
175
176
  METRIC_SHOW_FILTERS = True
176
177
 
@@ -210,7 +211,7 @@ class AssetPositionPortfolioModelViewSet(InstrumentMetricMixin, AssetPositionMod
210
211
  super()
211
212
  .get_queryset()
212
213
  .filter(portfolio=self.portfolio)
213
- .select_related("underlying_instrument", "currency", "exchange", "portfolio_created")
214
+ .select_related("underlying_quote", "currency", "exchange", "portfolio_created")
214
215
  )
215
216
  return AssetPosition.objects.none()
216
217
 
@@ -238,9 +239,7 @@ class AssetPositionInstrumentModelViewSet(AssetPositionModelViewSet):
238
239
  return {}
239
240
 
240
241
  def get_queryset(self):
241
- qs = (
242
- super().get_queryset().filter(underlying_instrument__in=self.instrument.get_descendants(include_self=True))
243
- )
242
+ qs = super().get_queryset().filter(underlying_quote__in=self.instrument.get_descendants(include_self=True))
244
243
  if self.request.GET.get("filter_last_positions", "false") == "true":
245
244
  if self.instrument.assets.exists():
246
245
  qs = qs.filter(date=self.instrument.assets.latest("date").date)
@@ -364,10 +363,10 @@ class ContributorPortfolioChartView(UserPortfolioRequestPermissionMixin, viewset
364
363
  )
365
364
  df = Portfolio.get_contribution_df(queryset, hedged_currency=hedged_currency)
366
365
  if not df.empty:
367
- df = df[["contribution_total", "contribution_forex", "underlying_security"]].sort_values(
366
+ df = df[["contribution_total", "contribution_forex", "underlying_instrument"]].sort_values(
368
367
  by="contribution_total", ascending=True
369
368
  )
370
- df["instrument_id"] = df.underlying_security.apply(lambda x: Instrument.objects.get(id=x).name_repr)
369
+ df["instrument_id"] = df.underlying_instrument.apply(lambda x: Instrument.objects.get(id=x).name_repr)
371
370
  df_forex = df[["instrument_id", "contribution_forex"]]
372
371
  df_forex = df_forex[df_forex.contribution_forex != 0]
373
372
 
@@ -486,7 +485,7 @@ class AssetPositionUnderlyingInstrumentChartViewSet(UserPortfolioRequestPermissi
486
485
  class CompositionModelPortfolioPandasView(
487
486
  UserPortfolioRequestPermissionMixin, InternalUserPermissionMixin, ExportPandasAPIViewSet
488
487
  ):
489
- IDENTIFIER = "wbportfolio:compositionmodelportfolio"
488
+ IDENTIFIER = "wbportfolio:topdowncomposition"
490
489
  filterset_class = CompositionModelPortfolioPandasFilter
491
490
  queryset = AssetPosition.objects.all()
492
491
 
@@ -494,22 +493,24 @@ class CompositionModelPortfolioPandasView(
494
493
  title_config_class = CompositionModelPortfolioPandasTitleConfig
495
494
  endpoint_config_class = CompositionModelPortfolioPandasEndpointConfig
496
495
 
496
+ @cached_property
497
+ def val_date(self) -> date:
498
+ return parse_date(self.request.GET["date"])
499
+
497
500
  @cached_property
498
501
  def dependant_portfolios(self):
499
502
  return Portfolio.objects.filter(
500
503
  Q(depends_on__in=[self.portfolio]) | Q(dependent_portfolios__in=[self.portfolio])
501
504
  )
502
505
 
503
- @cached_property
504
- def instrument_map(self) -> dict[int, str]:
505
- instrument_qs = Instrument.objects.filter(
506
- id__in=self.get_queryset().values("underlying_instrument__parent")
507
- ).values("id", "computed_str")
508
- return {item["id"]: item["computed_str"] for item in instrument_qs}
506
+ def get_queryset(self):
507
+ if self.has_portfolio_access:
508
+ return super().get_queryset().filter(portfolio=self.portfolio)
509
+ return AssetPosition.objects.none()
509
510
 
510
511
  def get_pandas_fields(self, request):
511
512
  fields = [
512
- pf.PKField(key="underlying_instrument__parent", label="ID"),
513
+ pf.PKField(key="underlying_instrument", label="ID"),
513
514
  pf.CharField(key="underlying_instrument_repr", label="Instrument"),
514
515
  ]
515
516
  if not self.portfolio.only_weighting:
@@ -529,34 +530,44 @@ class CompositionModelPortfolioPandasView(
529
530
  search_fields = ["underlying_instrument_repr"]
530
531
  ordering_fields = ["underlying_instrument_repr", "model_portfolio"]
531
532
 
532
- def get_queryset(self):
533
- if self.has_portfolio_access:
534
- return AssetPosition.objects.filter(portfolio__in=[*self.dependant_portfolios, self.portfolio])
535
- return AssetPosition.objects.none()
536
-
537
533
  def get_dataframe(self, request, queryset, **kwargs):
538
- df = pd.DataFrame()
539
- if queryset.exists():
540
- df = pd.DataFrame(
541
- queryset.values("underlying_instrument__parent", "portfolio", "weighting", "shares")
542
- ).pivot_table(
543
- index="underlying_instrument__parent",
544
- columns=["portfolio"],
545
- values=["weighting", "shares"],
546
- aggfunc="sum",
547
- fill_value=0,
534
+ rows = []
535
+ for portfolio in [*self.dependant_portfolios, self.portfolio]:
536
+ rows.extend(
537
+ list(
538
+ map(
539
+ lambda x: {
540
+ "underlying_instrument": x.underlying_instrument.id,
541
+ "weighting": x.weighting,
542
+ "shares": x.shares,
543
+ "portfolio": portfolio.id,
544
+ },
545
+ portfolio.get_positions(self.val_date),
546
+ )
547
+ )
548
548
  )
549
+ df = pd.DataFrame(rows)
550
+ df = df.pivot_table(
551
+ index="underlying_instrument",
552
+ columns=["portfolio"],
553
+ values=["weighting", "shares"],
554
+ aggfunc="sum",
555
+ fill_value=0,
556
+ )
557
+ for portfolio in self.dependant_portfolios:
558
+ with suppress(KeyError):
559
+ if portfolio.only_weighting:
560
+ df["difference", portfolio.id] = df["weighting"][self.portfolio.id] - df["weighting"][portfolio.id]
561
+ else:
562
+ df["difference", portfolio.id] = df["shares"][self.portfolio.id] - df["shares"][portfolio.id]
549
563
 
550
- for portfolio in self.dependant_portfolios:
551
- with suppress(KeyError):
552
- if portfolio.only_weighting:
553
- df["difference", portfolio.id] = (
554
- df["weighting"][self.portfolio.id] - df["weighting"][portfolio.id]
555
- )
556
- else:
557
- df["difference", portfolio.id] = df["shares"][self.portfolio.id] - df["shares"][portfolio.id]
558
- df.columns = ["_".join([str(item) for item in col]) for col in df.columns.to_flat_index()]
559
- df = df.reset_index()
560
- df["underlying_instrument_repr"] = df.underlying_instrument__parent.map(self.instrument_map)
564
+ df.columns = ["_".join([str(item) for item in col]) for col in df.columns.to_flat_index()]
565
+ df = df.reset_index()
561
566
 
562
567
  return df
568
+
569
+ def manipulate_dataframe(self, df):
570
+ df["underlying_instrument_repr"] = df["underlying_instrument"].map(
571
+ dict(Instrument.objects.filter(id__in=df["underlying_instrument"]).values_list("id", "computed_str"))
572
+ )
573
+ return df
@@ -5,6 +5,7 @@ import pandas as pd
5
5
  import plotly.graph_objects as go
6
6
  from wbcore import viewsets
7
7
  from wbcrm.models.accounts import Account
8
+
8
9
  from wbportfolio.analysis.claims import get_assets_and_net_new_money_progression
9
10
  from wbportfolio.filters import AssetsAndNetNewMoneyProgressionFilterSet
10
11
  from wbportfolio.models.products import Product
@@ -15,7 +15,9 @@ from wbfdm.models import (
15
15
  ClassificationGroup,
16
16
  Instrument,
17
17
  InstrumentClassificationThroughModel,
18
+ InstrumentType,
18
19
  )
20
+
19
21
  from wbportfolio.filters.assets import DistributionFilter
20
22
  from wbportfolio.models import (
21
23
  AssetPosition,
@@ -68,7 +70,7 @@ class AbstractDistributionMixin:
68
70
 
69
71
  def _generate_classification_df(self, queryset):
70
72
  df = pd.DataFrame(
71
- queryset.filter(underlying_security_instrument_type_key="equity").values(
73
+ queryset.filter(underlying_instrument__instrument_type=InstrumentType.EQUITY).values(
72
74
  "weighting", "underlying_instrument"
73
75
  ),
74
76
  columns=["weighting", "underlying_instrument"],
@@ -10,7 +10,7 @@ from .claims import ClaimTradeButtonConfig, ConsolidatedTradeSummaryButtonConfig
10
10
 
11
11
  from .custodians import CustodianButtonConfig
12
12
  from .fees import FeesButtonConfig
13
- from .portfolios import ModelPortfolioButtonConfig, PortfolioButtonConfig
13
+ from .portfolios import PortfolioButtonConfig
14
14
  from .products import ProductButtonConfig, ProductCustomerButtonConfig
15
15
  from .registers import RegisterButtonConfig
16
16
  from .trades import (
@@ -3,6 +3,7 @@ from contextlib import suppress
3
3
  from rest_framework.reverse import reverse
4
4
  from wbcore.metadata.configs import buttons as bt
5
5
  from wbcore.metadata.configs.buttons.view_config import ButtonViewConfig
6
+
6
7
  from wbportfolio.models.portfolio import Portfolio, PortfolioPortfolioThroughModel
7
8
 
8
9
 
@@ -6,6 +6,7 @@ from wbcore.metadata.configs.buttons.view_config import ButtonViewConfig
6
6
  from wbcore.metadata.configs.display.instance_display.shortcuts import (
7
7
  create_simple_display,
8
8
  )
9
+
9
10
  from wbportfolio.models import Custodian
10
11
  from wbportfolio.serializers import CustodianRepresentationSerializer
11
12
 
@@ -1,15 +1,9 @@
1
1
  from contextlib import suppress
2
2
 
3
3
  from wbcore.contrib.icons import WBIcon
4
- from wbcore.enums import RequestType
5
4
  from wbcore.metadata.configs import buttons as bt
6
- from wbcore.metadata.configs.display.instance_display.shortcuts import (
7
- create_simple_display,
8
- )
9
5
  from wbfdm.models.instruments import Instrument
10
6
 
11
- from .portfolios import get_portfolio_start_end_serializer_class
12
-
13
7
 
14
8
  class InstrumentButtonMixin:
15
9
  @classmethod
@@ -25,22 +19,9 @@ class InstrumentButtonMixin:
25
19
  with suppress(Instrument.DoesNotExist):
26
20
  instrument = Instrument.objects.get(id=pk)
27
21
  asset_instrument_btn_label = "Asset Portfolio"
28
- if portfolio := instrument.portfolio:
22
+ if instrument.portfolio:
29
23
  buttons.extend(
30
24
  [
31
- bt.ActionButton(
32
- method=RequestType.PATCH,
33
- identifiers=("wbportfolio:portfolio",),
34
- key="resynchronize",
35
- label="Resynchronize/Rebalance",
36
- description_fields="""
37
- <p>Resynchronize portfolio from {{start}} to {{end}}</p>
38
- """,
39
- serializer=get_portfolio_start_end_serializer_class(portfolio),
40
- action_label="resynchronize",
41
- title="Resynchronize/Rebalance",
42
- instance_display=create_simple_display([["start"], ["end"]]),
43
- ),
44
25
  bt.WidgetButton(key="portfolio_positions", label=asset_instrument_btn_label),
45
26
  bt.DropDownButton(
46
27
  label="Charts",
@@ -1,7 +1,7 @@
1
+ from contextlib import suppress
1
2
  from datetime import date
2
3
 
3
- from django.shortcuts import get_object_or_404
4
- from rest_framework.reverse import reverse
4
+ from pandas._libs.tslibs.offsets import BDay
5
5
  from wbcore import serializers as wb_serializers
6
6
  from wbcore.contrib.currency.serializers import CurrencyRepresentationSerializer
7
7
  from wbcore.contrib.icons import WBIcon
@@ -11,14 +11,28 @@ from wbcore.metadata.configs.buttons.view_config import ButtonViewConfig
11
11
  from wbcore.metadata.configs.display.instance_display.shortcuts import (
12
12
  create_simple_display,
13
13
  )
14
- from wbportfolio.models import Portfolio, PriceComputation
15
- from wbportfolio.serializers import (
16
- PortfolioSynchronizationRepresentationSerializer,
17
- PriceComputationRepresentationSerializer,
18
- )
19
14
 
15
+ from wbportfolio.models import AssetPosition, Portfolio
16
+ from wbportfolio.serializers import RebalancerModelSerializer
17
+ from wbportfolio.viewsets.configs.display.rebalancing import RebalancerDisplayConfig
18
+
19
+
20
+ class CreateModelPortfolioSerializer(wb_serializers.ModelSerializer):
21
+ create_index = wb_serializers.BooleanField(default=False, label="Create Underlying Index")
22
+ name = wb_serializers.CharField(required=True)
23
+ _currency = CurrencyRepresentationSerializer(source="currency")
20
24
 
21
- def get_portfolio_start_end_serializer_class(portfolio):
25
+ class Meta:
26
+ model = Portfolio
27
+ fields = (
28
+ "name",
29
+ "currency",
30
+ "create_index",
31
+ "_currency",
32
+ )
33
+
34
+
35
+ def _get_portfolio_start_end_serializer_class(portfolio):
22
36
  today = date.today()
23
37
 
24
38
  class StartEndDateSerializer(wb_serializers.Serializer):
@@ -33,83 +47,83 @@ def get_portfolio_start_end_serializer_class(portfolio):
33
47
  return StartEndDateSerializer
34
48
 
35
49
 
50
+ def _get_rebalance_serializer_class(portfolio):
51
+ try:
52
+ default_trade_date = (portfolio.assets.latest("date").date + BDay(1)).date()
53
+ except AssetPosition.DoesNotExist:
54
+ default_trade_date = date.today()
55
+
56
+ class RebalanceSerializer(wb_serializers.Serializer):
57
+ trade_date = wb_serializers.DateField(default=default_trade_date)
58
+
59
+ return RebalanceSerializer
60
+
61
+
36
62
  class PortfolioButtonConfig(ButtonViewConfig):
37
63
  def get_custom_instance_buttons(self):
38
- portfolio_buttons = [
39
- bt.WidgetButton(key="assets", label="Assets"),
40
- bt.WidgetButton(key="contributor", label="Contributor"),
41
- bt.WidgetButton(key="distribution_chart", label="Distribution Chart"),
42
- bt.WidgetButton(key="distribution_table", label="Distribution Table"),
43
- bt.WidgetButton(key="modelcomposition", label="Portfolio Composition vs. Dependant Portfolios"),
64
+ admin_buttons = [
65
+ bt.ActionButton(
66
+ method=RequestType.POST,
67
+ identifiers=("wbportfolio:portfolio",),
68
+ key="add_automatic_rebalancer",
69
+ label="Attach Rebalancer",
70
+ serializer=RebalancerModelSerializer,
71
+ action_label="Attach Rebalancer",
72
+ title="Attach Rebalancer",
73
+ instance_display=RebalancerDisplayConfig(
74
+ self.view, self.request, self.instance
75
+ ).get_instance_display(),
76
+ )
44
77
  ]
45
- if pk := self.view.kwargs.get("pk", None):
46
- portfolio = get_object_or_404(Portfolio, pk=pk)
47
-
48
- portfolio_buttons.append(
78
+ buttons = [bt.WidgetButton(key="treegraphchart", label="Visualize Tree Graph Chart")]
79
+ with suppress(Portfolio.DoesNotExist, KeyError):
80
+ portfolio = Portfolio.objects.get(id=self.view.kwargs["pk"])
81
+ buttons.append(
49
82
  bt.ActionButton(
50
- method=RequestType.PATCH,
83
+ method=RequestType.POST,
51
84
  identifiers=("wbportfolio:portfolio",),
52
- key="resynchronize",
53
- label="Resynchronize/Rebalance",
54
- description_fields="""
55
- <p>Resynchronize portfolio from {{start}} to {{end}}</p>
56
- """,
57
- serializer=get_portfolio_start_end_serializer_class(portfolio),
58
- action_label="resynchronize",
59
- title="Resynchronize/Rebalance",
60
- instance_display=create_simple_display([["start"], ["end"]]),
85
+ key="rebalance",
86
+ label="Rebalance",
87
+ serializer=_get_rebalance_serializer_class(portfolio),
88
+ action_label="Rebalance",
89
+ title="Rebalance",
90
+ instance_display=create_simple_display([["trade_date"]]),
61
91
  )
62
92
  )
63
93
 
64
- return {
65
- bt.DropDownButton(label="Portfolio", icon=WBIcon.UNFOLD.icon, buttons=tuple(portfolio_buttons)),
66
- }
94
+ if primary_portfolio := portfolio.primary_portfolio:
95
+ admin_buttons.append(
96
+ bt.ActionButton(
97
+ method=RequestType.POST,
98
+ identifiers=("wbportfolio:portfolio",),
99
+ key="recompute_lookthrough",
100
+ label="Recompute Look-Through Portfolio",
101
+ serializer=_get_portfolio_start_end_serializer_class(primary_portfolio),
102
+ action_label="Recompute Look-Through Portfolio",
103
+ title="Recompute Look-Through Portfolio",
104
+ instance_display=create_simple_display([["start", "end"]]),
105
+ )
106
+ )
107
+ buttons.append(
108
+ bt.DropDownButton(label="Admin", icon=WBIcon.UNFOLD.icon, buttons=tuple(admin_buttons)),
109
+ )
110
+ return set(buttons)
67
111
 
68
112
  def get_custom_list_instance_buttons(self):
69
113
  return self.get_custom_instance_buttons()
70
114
 
71
-
72
- class CreateModelPortfolioSerializer(wb_serializers.ModelSerializer):
73
- create_index = wb_serializers.BooleanField(default=False, label="Create Underlying Index")
74
- name = wb_serializers.CharField(required=True)
75
- _currency = CurrencyRepresentationSerializer(source="currency")
76
- _portfolio_synchronization = PortfolioSynchronizationRepresentationSerializer(source="portfolio_synchronization")
77
- price_computation = wb_serializers.PrimaryKeyRelatedField(queryset=PriceComputation.objects.all(), required=False)
78
- _price_computation = PriceComputationRepresentationSerializer(source="price_computation")
79
-
80
- class Meta:
81
- model = Portfolio
82
- dependency_map = {
83
- "price_computation": ["create_index"],
84
- }
85
- fields = (
86
- "name",
87
- "currency",
88
- "portfolio_synchronization",
89
- "create_index",
90
- "price_computation",
91
- "_price_computation",
92
- "_currency",
93
- "_portfolio_synchronization",
94
- )
95
-
96
-
97
- class ModelPortfolioButtonConfig(PortfolioButtonConfig):
98
- # pass
99
- def get_custom_buttons(self):
100
- if not self.view.kwargs.get("pk", None):
101
- return {
102
- bt.ActionButton(
103
- method=RequestType.POST,
104
- identifiers=("wbportfolio:portfolio",),
105
- endpoint=reverse("wbportfolio:modelportfolio-createmodelportfolio", request=self.request),
106
- label="Create New Model Portfolio",
107
- serializer=CreateModelPortfolioSerializer,
108
- action_label="create",
109
- title="Create Model Portfolio",
110
- instance_display=create_simple_display(
111
- [["name", "currency", "portfolio_synchronization"], ["create_index", "price_computation", "."]]
112
- ),
113
- )
114
- }
115
- return set()
115
+ # def get_custom_buttons(self):
116
+ # if not self.view.kwargs.get("pk", None):
117
+ # return {
118
+ # bt.ActionButton(
119
+ # method=RequestType.POST,
120
+ # identifiers=("wbportfolio:portfolio",),
121
+ # endpoint=reverse("wbportfolio:portfolio-createmodelportfolio", request=self.request),
122
+ # label="Create New Model Portfolio",
123
+ # serializer=CreateModelPortfolioSerializer,
124
+ # action_label="create",
125
+ # title="Create Model Portfolio",
126
+ # instance_display=create_simple_display([["name", "currency"], ["create_index", "."]]),
127
+ # )
128
+ # }
129
+ # return set()
@@ -11,6 +11,7 @@ from wbcore.metadata.configs.display import create_simple_display
11
11
  from wbcore.signals.instance_buttons import add_instance_button
12
12
  from wbcrm.viewsets import AccountModelViewSet
13
13
  from wbfdm.viewsets.instruments import InstrumentModelViewSet
14
+
14
15
  from wbportfolio.serializers.reconciliations import AccountReconciliationModelSerializer
15
16
 
16
17
  from .mixins import InstrumentButtonMixin
@@ -4,6 +4,7 @@ from wbcore.enums import RequestType
4
4
  from wbcore.metadata.configs import buttons as bt
5
5
  from wbcore.metadata.configs.buttons.view_config import ButtonViewConfig
6
6
  from wbfdm.models import Instrument
7
+
7
8
  from wbportfolio.models import TradeProposal
8
9
 
9
10
 
@@ -1,4 +1,5 @@
1
1
  from .adjustments import AdjustmentDisplayConfig
2
+ from .rebalancing import RebalancerDisplayConfig
2
3
  from .assets import (
3
4
  AssetPositionDisplayConfig,
4
5
  AssetPositionInstrumentDisplayConfig,
@@ -23,9 +24,9 @@ from .fees import (
23
24
  FeesPortfolioDisplayConfig,
24
25
  )
25
26
  from .portfolios import (
26
- ModelPortfolioDisplayConfig,
27
27
  PortfolioDisplayConfig,
28
28
  PortfolioPortfolioThroughModelDisplayConfig,
29
+ TopDownPortfolioCompositionPandasDisplayConfig
29
30
  )
30
31
  from .positions import (
31
32
  AggregatedAssetPositionLiquidityDisplayConfig,
@@ -8,6 +8,7 @@ from wbcore.metadata.configs.display.instance_display.shortcuts import (
8
8
  )
9
9
  from wbcore.metadata.configs.display.instance_display.utils import repeat_field
10
10
  from wbcore.metadata.configs.display.view_config import DisplayViewConfig
11
+
11
12
  from wbportfolio.models import Adjustment
12
13
 
13
14
 
@@ -73,9 +73,9 @@ class AssetPositionPortfolioDisplayConfig(AssetPositionDisplayConfig):
73
73
  open_by_default=False,
74
74
  key=None,
75
75
  children=[
76
- dp.Field(key="underlying_instrument_name", label="Name"),
77
- dp.Field(key="underlying_instrument_isin", label="ISIN"),
78
- dp.Field(key="underlying_instrument_ticker", label="Ticker"),
76
+ dp.Field(key="underlying_quote_name", label="Name"),
77
+ dp.Field(key="underlying_quote_isin", label="ISIN"),
78
+ dp.Field(key="underlying_quote_ticker", label="Ticker"),
79
79
  dp.Field(key="exchange", label="Exchange", width=Unit.PIXEL(250)),
80
80
  ],
81
81
  ),
@@ -88,14 +88,15 @@ class AssetPositionPortfolioDisplayConfig(AssetPositionDisplayConfig):
88
88
  dp.Field(key="price", label="Price"),
89
89
  dp.Field(key="shares", label="Shares"),
90
90
  dp.Field(key="currency_fx_rate", label="Currency Rate", show="open"),
91
- dp.Field(key="total_value", label="Total Value", show="open"),
92
91
  dp.Field(
93
92
  key="total_value_fx_portfolio",
94
93
  label="Total Value Portfolio",
95
94
  width=Unit.PIXEL(150),
96
- show="open",
97
95
  ),
98
- dp.Field(key="total_value_fx_usd", label="Total Value ($)", width=Unit.PIXEL(150)),
96
+ dp.Field(key="total_value", label="Total Value", show="open"),
97
+ dp.Field(
98
+ key="total_value_fx_usd", label="Total Value ($)", width=Unit.PIXEL(150), show="open"
99
+ ),
99
100
  ],
100
101
  ),
101
102
  dp.Field(
@@ -10,6 +10,7 @@ from wbcore.metadata.configs.display.instance_display.styles import Style
10
10
  from wbcore.metadata.configs.display.instance_display.utils import repeat
11
11
  from wbcore.metadata.configs.display.view_config import DisplayViewConfig
12
12
  from wbcore.metadata.configs.display.windows import Window
13
+
13
14
  from wbportfolio.models.transactions.claim import Claim
14
15
 
15
16