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
- 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
### Fixed

@ -13,7 +13,10 @@ import { ApiService } from '@ghostfolio/api/services/api/api.service';
import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service';
import { ImpersonationService } from '@ghostfolio/api/services/impersonation/impersonation.service';
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 {
PortfolioDetails,
PortfolioDividends,
@ -95,7 +98,7 @@ export class PortfolioController {
filterByTags
});
const { accounts, hasErrors, holdings, platforms, summary } =
const { accounts, hasErrors, holdings, markets, platforms, summary } =
await this.portfolioService.getDetails({
dateRange,
filters,
@ -162,6 +165,10 @@ export class PortfolioController {
}) ||
isRestrictedView(this.request.user)
) {
Object.values(markets).forEach((market) => {
delete market.valueInBaseCurrency;
});
portfolioSummary = nullifyValuesInObject(summary, [
'cash',
'committedFunds',
@ -214,6 +221,26 @@ export class PortfolioController {
hasError,
holdings,
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
};
}

@ -47,7 +47,7 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
public hasImpersonationId: boolean;
public isLoading = false;
public markets: {
[key in Market]: { name: string; value: number };
[key in Market]: { id: Market; valueInPercentage: number };
};
public marketsAdvanced: {
[key in MarketAdvanced]: {
@ -219,24 +219,6 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
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 = {
[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(
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
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 +=
position.marketsAdvanced.asiaPacific *
(isNumber(position.valueInBaseCurrency)
@ -440,12 +408,6 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
? this.portfolioDetails.holdings[symbol].valueInBaseCurrency
: 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(
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)
.map(({ name, value }) => {
if (this.hasImpersonationId || this.user.settings.isRestrictedView) {

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

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

Loading…
Cancel
Save