From 1c9805bb96929261af4c61ac986b14d546d0996c Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Thu, 4 Jul 2024 20:25:15 +0200 Subject: [PATCH] Feature/improve allocations by etf holding for impersonation mode (#3534) * Improve allocations by ETF holding for impersonation mode * Update changelog --- CHANGELOG.md | 1 + .../src/app/portfolio/portfolio.service.ts | 12 ++++- .../symbol-profile/symbol-profile.service.ts | 3 +- .../allocations/allocations-page.component.ts | 50 +++++++++---------- 4 files changed, 39 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 850d2a7a1..d158171fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- Improved the allocations by ETF holding on the allocations page for the impersonation mode (experimental) - Improved the detection of REST APIs (`JSON`) used via the scraper configuration ## 2.92.0 - 2024-06-30 diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index f088fa7c7..b5443c9cd 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -499,7 +499,17 @@ export class PortfolioService { grossPerformancePercentageWithCurrencyEffect?.toNumber() ?? 0, grossPerformanceWithCurrencyEffect: grossPerformanceWithCurrencyEffect?.toNumber() ?? 0, - holdings: assetProfile.holdings, + holdings: assetProfile.holdings.map( + ({ allocationInPercentage, name }) => { + return { + allocationInPercentage, + name, + valueInBaseCurrency: valueInBaseCurrency + .mul(allocationInPercentage) + .toNumber() + }; + } + ), investment: investment.toNumber(), marketState: dataProviderResponse?.marketState ?? 'delayed', name: assetProfile.name, diff --git a/apps/api/src/services/symbol-profile/symbol-profile.service.ts b/apps/api/src/services/symbol-profile/symbol-profile.service.ts index ae3ecafcd..1d7ea556b 100644 --- a/apps/api/src/services/symbol-profile/symbol-profile.service.ts +++ b/apps/api/src/services/symbol-profile/symbol-profile.service.ts @@ -221,8 +221,9 @@ export class SymbolProfileService { const { name, weight } = holding as Prisma.JsonObject; return { + allocationInPercentage: weight as number, name: (name as string) ?? UNKNOWN_KEY, - valueInBaseCurrency: weight as number + valueInBaseCurrency: undefined }; } ); diff --git a/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts b/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts index 18c839d10..27c6326e9 100644 --- a/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts +++ b/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts @@ -454,30 +454,22 @@ export class AllocationsPageComponent implements OnDestroy, OnInit { if (position.holdings.length > 0) { for (const holding of position.holdings) { - const { name, valueInBaseCurrency } = holding; - - if ( - !this.hasImpersonationId && - !this.user.settings.isRestrictedView - ) { - if (this.topHoldingsMap[name]?.value) { - this.topHoldingsMap[name].value += - valueInBaseCurrency * - (isNumber(position.valueInBaseCurrency) - ? position.valueInBaseCurrency - : position.valueInPercentage); - } else { - this.topHoldingsMap[name] = { - name, - value: - valueInBaseCurrency * - (isNumber(position.valueInBaseCurrency) - ? this.portfolioDetails.holdings[symbol] - .valueInBaseCurrency - : this.portfolioDetails.holdings[symbol] - .valueInPercentage) - }; - } + const { allocationInPercentage, name, valueInBaseCurrency } = + holding; + + if (this.topHoldingsMap[name]?.value) { + this.topHoldingsMap[name].value += isNumber(valueInBaseCurrency) + ? valueInBaseCurrency + : allocationInPercentage * + this.portfolioDetails.holdings[symbol].valueInPercentage; + } else { + this.topHoldingsMap[name] = { + name, + value: isNumber(valueInBaseCurrency) + ? valueInBaseCurrency + : allocationInPercentage * + this.portfolioDetails.holdings[symbol].valueInPercentage + }; } } } @@ -562,6 +554,14 @@ export class AllocationsPageComponent implements OnDestroy, OnInit { this.topHoldings = Object.values(this.topHoldingsMap) .map(({ name, value }) => { + if (this.hasImpersonationId || this.user.settings.isRestrictedView) { + return { + name, + allocationInPercentage: value, + valueInBaseCurrency: null + }; + } + return { name, allocationInPercentage: @@ -570,7 +570,7 @@ export class AllocationsPageComponent implements OnDestroy, OnInit { }; }) .sort((a, b) => { - return b.valueInBaseCurrency - a.valueInBaseCurrency; + return b.allocationInPercentage - a.allocationInPercentage; }); if (this.topHoldings.length > MAX_TOP_HOLDINGS) {