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
|
### 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…
x
Reference in New Issue
Block a user