Feature/reuse markets calculation in portfolio details endpoint (#3883)

* Reuse markets calculation in portfolio details endpoint

* Update changelog
pull/3884/head
Thomas Kaul 2 weeks ago committed by GitHub
parent b50a1fc63d
commit f48ce4e1ae
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed ### Changed
- Optimized the portfolio calculations by reusing date intervals - Optimized the portfolio calculations by reusing date intervals
- Refactored the calculation of the allocations by market on the allocations page
- Refactored the calculation of the allocations by market on the public page - Refactored the calculation of the allocations by market on the public page
### Fixed ### Fixed

@ -13,7 +13,10 @@ import { ApiService } from '@ghostfolio/api/services/api/api.service';
import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service';
import { ImpersonationService } from '@ghostfolio/api/services/impersonation/impersonation.service'; import { ImpersonationService } from '@ghostfolio/api/services/impersonation/impersonation.service';
import { getIntervalFromDateRange } from '@ghostfolio/common/calculation-helper'; import { getIntervalFromDateRange } from '@ghostfolio/common/calculation-helper';
import { HEADER_KEY_IMPERSONATION } from '@ghostfolio/common/config'; import {
HEADER_KEY_IMPERSONATION,
UNKNOWN_KEY
} from '@ghostfolio/common/config';
import { import {
PortfolioDetails, PortfolioDetails,
PortfolioDividends, PortfolioDividends,
@ -95,7 +98,7 @@ export class PortfolioController {
filterByTags filterByTags
}); });
const { accounts, hasErrors, holdings, platforms, summary } = const { accounts, hasErrors, holdings, markets, platforms, summary } =
await this.portfolioService.getDetails({ await this.portfolioService.getDetails({
dateRange, dateRange,
filters, filters,
@ -162,6 +165,10 @@ export class PortfolioController {
}) || }) ||
isRestrictedView(this.request.user) isRestrictedView(this.request.user)
) { ) {
Object.values(markets).forEach((market) => {
delete market.valueInBaseCurrency;
});
portfolioSummary = nullifyValuesInObject(summary, [ portfolioSummary = nullifyValuesInObject(summary, [
'cash', 'cash',
'committedFunds', 'committedFunds',
@ -214,6 +221,26 @@ export class PortfolioController {
hasError, hasError,
holdings, holdings,
platforms, platforms,
markets: hasDetails
? markets
: {
[UNKNOWN_KEY]: {
id: UNKNOWN_KEY,
valueInPercentage: 1
},
developedMarkets: {
id: 'developedMarkets',
valueInPercentage: 0
},
emergingMarkets: {
id: 'emergingMarkets',
valueInPercentage: 0
},
otherMarkets: {
id: 'otherMarkets',
valueInPercentage: 0
}
},
summary: portfolioSummary summary: portfolioSummary
}; };
} }

@ -47,7 +47,7 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
public hasImpersonationId: boolean; public hasImpersonationId: boolean;
public isLoading = false; public isLoading = false;
public markets: { public markets: {
[key in Market]: { name: string; value: number }; [key in Market]: { id: Market; valueInPercentage: number };
}; };
public marketsAdvanced: { public marketsAdvanced: {
[key in MarketAdvanced]: { [key in MarketAdvanced]: {
@ -219,24 +219,6 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
value: 0 value: 0
} }
}; };
this.markets = {
[UNKNOWN_KEY]: {
name: UNKNOWN_KEY,
value: 0
},
developedMarkets: {
name: 'developedMarkets',
value: 0
},
emergingMarkets: {
name: 'emergingMarkets',
value: 0
},
otherMarkets: {
name: 'otherMarkets',
value: 0
}
};
this.marketsAdvanced = { this.marketsAdvanced = {
[UNKNOWN_KEY]: { [UNKNOWN_KEY]: {
id: UNKNOWN_KEY, id: UNKNOWN_KEY,
@ -318,6 +300,8 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
}; };
} }
this.markets = this.portfolioDetails.markets;
for (const [symbol, position] of Object.entries( for (const [symbol, position] of Object.entries(
this.portfolioDetails.holdings this.portfolioDetails.holdings
)) { )) {
@ -348,22 +332,6 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
// Prepare analysis data by continents, countries, holdings and sectors except for liquidity // Prepare analysis data by continents, countries, holdings and sectors except for liquidity
if (position.countries.length > 0) { if (position.countries.length > 0) {
this.markets.developedMarkets.value +=
position.markets.developedMarkets *
(isNumber(position.valueInBaseCurrency)
? position.valueInBaseCurrency
: position.valueInPercentage);
this.markets.emergingMarkets.value +=
position.markets.emergingMarkets *
(isNumber(position.valueInBaseCurrency)
? position.valueInBaseCurrency
: position.valueInPercentage);
this.markets.otherMarkets.value +=
position.markets.otherMarkets *
(isNumber(position.valueInBaseCurrency)
? position.valueInBaseCurrency
: position.valueInPercentage);
this.marketsAdvanced.asiaPacific.value += this.marketsAdvanced.asiaPacific.value +=
position.marketsAdvanced.asiaPacific * position.marketsAdvanced.asiaPacific *
(isNumber(position.valueInBaseCurrency) (isNumber(position.valueInBaseCurrency)
@ -440,12 +408,6 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
? this.portfolioDetails.holdings[symbol].valueInBaseCurrency ? this.portfolioDetails.holdings[symbol].valueInBaseCurrency
: this.portfolioDetails.holdings[symbol].valueInPercentage; : this.portfolioDetails.holdings[symbol].valueInPercentage;
this.markets[UNKNOWN_KEY].value += isNumber(
position.valueInBaseCurrency
)
? this.portfolioDetails.holdings[symbol].valueInBaseCurrency
: this.portfolioDetails.holdings[symbol].valueInPercentage;
this.marketsAdvanced[UNKNOWN_KEY].value += isNumber( this.marketsAdvanced[UNKNOWN_KEY].value += isNumber(
position.valueInBaseCurrency position.valueInBaseCurrency
) )
@ -538,21 +500,6 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
}; };
} }
const marketsTotal =
this.markets.developedMarkets.value +
this.markets.emergingMarkets.value +
this.markets.otherMarkets.value +
this.markets[UNKNOWN_KEY].value;
this.markets.developedMarkets.value =
this.markets.developedMarkets.value / marketsTotal;
this.markets.emergingMarkets.value =
this.markets.emergingMarkets.value / marketsTotal;
this.markets.otherMarkets.value =
this.markets.otherMarkets.value / marketsTotal;
this.markets[UNKNOWN_KEY].value =
this.markets[UNKNOWN_KEY].value / marketsTotal;
this.topHoldings = Object.values(this.topHoldingsMap) this.topHoldings = Object.values(this.topHoldingsMap)
.map(({ name, value }) => { .map(({ name, value }) => {
if (this.hasImpersonationId || this.user.settings.isRestrictedView) { if (this.hasImpersonationId || this.user.settings.isRestrictedView) {

@ -218,7 +218,7 @@
i18n i18n
size="large" size="large"
[isPercent]="true" [isPercent]="true"
[value]="markets?.developedMarkets?.value" [value]="markets?.developedMarkets?.valueInPercentage"
>Developed Markets</gf-value >Developed Markets</gf-value
> >
</div> </div>
@ -227,7 +227,7 @@
i18n i18n
size="large" size="large"
[isPercent]="true" [isPercent]="true"
[value]="markets?.emergingMarkets?.value" [value]="markets?.emergingMarkets?.valueInPercentage"
>Emerging Markets</gf-value >Emerging Markets</gf-value
> >
</div> </div>
@ -236,17 +236,17 @@
i18n i18n
size="large" size="large"
[isPercent]="true" [isPercent]="true"
[value]="markets?.otherMarkets?.value" [value]="markets?.otherMarkets?.valueInPercentage"
>Other Markets</gf-value >Other Markets</gf-value
> >
</div> </div>
@if (markets?.[UNKNOWN_KEY]?.value > 0) { @if (markets?.[UNKNOWN_KEY]?.valueInPercentage > 0) {
<div class="col-xs-12 col-md my-2"> <div class="col-xs-12 col-md my-2">
<gf-value <gf-value
i18n i18n
size="large" size="large"
[isPercent]="true" [isPercent]="true"
[value]="markets?.[UNKNOWN_KEY]?.value" [value]="markets?.[UNKNOWN_KEY]?.valueInPercentage"
>No data available</gf-value >No data available</gf-value
> >
</div> </div>

@ -18,7 +18,7 @@ export interface PortfolioDetails {
markets?: { markets?: {
[key in Market]: { [key in Market]: {
id: Market; id: Market;
valueInBaseCurrency: number; valueInBaseCurrency?: number;
valueInPercentage: number; valueInPercentage: number;
}; };
}; };

Loading…
Cancel
Save