Feature/reuse markets calculation in portfolio details endpoint (#3883)
* Reuse markets calculation in portfolio details endpoint * Update changelog
This commit is contained in:
parent
b50a1fc63d
commit
f48ce4e1ae
@ -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…
x
Reference in New Issue
Block a user