Feature/optimize get porfolio details endpoint (#3366)

* Eliminate getPerformance() from getSummary() function

* Disable cache for getDetails()

* Add hint to portfolio summary

* Update changelog
pull/3371/head
Thomas Kaul 5 months ago committed by GitHub
parent 3f41e5c5de
commit f2cb671c7f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Moved the holdings table to the holdings tab of the home page - Moved the holdings table to the holdings tab of the home page
- Improved the performance labels (with and without currency effects) in the position detail dialog - Improved the performance labels (with and without currency effects) in the position detail dialog
- Optimized the calculations of the of the portfolio details endpoint
### Fixed ### Fixed

@ -165,21 +165,21 @@ export class PortfolioController {
portfolioSummary = nullifyValuesInObject(summary, [ portfolioSummary = nullifyValuesInObject(summary, [
'cash', 'cash',
'committedFunds', 'committedFunds',
'currentGrossPerformance',
'currentGrossPerformanceWithCurrencyEffect',
'currentNetPerformance',
'currentNetPerformanceWithCurrencyEffect',
'currentNetWorth', 'currentNetWorth',
'currentValue', 'currentValueInBaseCurrency',
'dividendInBaseCurrency', 'dividendInBaseCurrency',
'emergencyFund', 'emergencyFund',
'excludedAccountsAndActivities', 'excludedAccountsAndActivities',
'fees', 'fees',
'filteredValueInBaseCurrency', 'filteredValueInBaseCurrency',
'fireWealth', 'fireWealth',
'grossPerformance',
'grossPerformanceWithCurrencyEffect',
'interest', 'interest',
'items', 'items',
'liabilities', 'liabilities',
'netPerformance',
'netPerformanceWithCurrencyEffect',
'totalBuy', 'totalBuy',
'totalInvestment', 'totalInvestment',
'totalSell', 'totalSell',
@ -449,10 +449,14 @@ export class PortfolioController {
.div(performanceInformation.performance.totalInvestment) .div(performanceInformation.performance.totalInvestment)
.toNumber(), .toNumber(),
valueInPercentage: valueInPercentage:
performanceInformation.performance.currentValue === 0 performanceInformation.performance.currentValueInBaseCurrency ===
0
? 0 ? 0
: new Big(value) : new Big(value)
.div(performanceInformation.performance.currentValue) .div(
performanceInformation.performance
.currentValueInBaseCurrency
)
.toNumber() .toNumber()
}; };
} }
@ -461,12 +465,12 @@ export class PortfolioController {
performanceInformation.performance = nullifyValuesInObject( performanceInformation.performance = nullifyValuesInObject(
performanceInformation.performance, performanceInformation.performance,
[ [
'currentGrossPerformance',
'currentGrossPerformanceWithCurrencyEffect',
'currentNetPerformance',
'currentNetPerformanceWithCurrencyEffect',
'currentNetWorth', 'currentNetWorth',
'currentValue', 'currentValueInBaseCurrency',
'grossPerformance',
'grossPerformanceWithCurrencyEffect',
'netPerformance',
'netPerformanceWithCurrencyEffect',
'totalInvestment' 'totalInvestment'
] ]
); );
@ -483,7 +487,7 @@ export class PortfolioController {
); );
performanceInformation.performance = nullifyValuesInObject( performanceInformation.performance = nullifyValuesInObject(
performanceInformation.performance, performanceInformation.performance,
['currentNetPerformance', 'currentNetPerformancePercent'] ['netPerformance']
); );
} }

@ -27,7 +27,7 @@ describe('PortfolioService', () => {
portfolioService portfolioService
.getAnnualizedPerformancePercent({ .getAnnualizedPerformancePercent({
daysInMarket: NaN, // differenceInDays of date-fns returns NaN for the same day daysInMarket: NaN, // differenceInDays of date-fns returns NaN for the same day
netPerformancePercent: new Big(0) netPerformancePercentage: new Big(0)
}) })
.toNumber() .toNumber()
).toEqual(0); ).toEqual(0);
@ -36,7 +36,7 @@ describe('PortfolioService', () => {
portfolioService portfolioService
.getAnnualizedPerformancePercent({ .getAnnualizedPerformancePercent({
daysInMarket: 0, daysInMarket: 0,
netPerformancePercent: new Big(0) netPerformancePercentage: new Big(0)
}) })
.toNumber() .toNumber()
).toEqual(0); ).toEqual(0);
@ -48,7 +48,7 @@ describe('PortfolioService', () => {
portfolioService portfolioService
.getAnnualizedPerformancePercent({ .getAnnualizedPerformancePercent({
daysInMarket: 65, // < 1 year daysInMarket: 65, // < 1 year
netPerformancePercent: new Big(0.1025) netPerformancePercentage: new Big(0.1025)
}) })
.toNumber() .toNumber()
).toBeCloseTo(0.729705); ).toBeCloseTo(0.729705);
@ -57,7 +57,7 @@ describe('PortfolioService', () => {
portfolioService portfolioService
.getAnnualizedPerformancePercent({ .getAnnualizedPerformancePercent({
daysInMarket: 365, // 1 year daysInMarket: 365, // 1 year
netPerformancePercent: new Big(0.05) netPerformancePercentage: new Big(0.05)
}) })
.toNumber() .toNumber()
).toBeCloseTo(0.05); ).toBeCloseTo(0.05);
@ -69,7 +69,7 @@ describe('PortfolioService', () => {
portfolioService portfolioService
.getAnnualizedPerformancePercent({ .getAnnualizedPerformancePercent({
daysInMarket: 575, // > 1 year daysInMarket: 575, // > 1 year
netPerformancePercent: new Big(0.2374) netPerformancePercentage: new Big(0.2374)
}) })
.toNumber() .toNumber()
).toBeCloseTo(0.145); ).toBeCloseTo(0.145);

@ -208,16 +208,16 @@ export class PortfolioService {
public getAnnualizedPerformancePercent({ public getAnnualizedPerformancePercent({
daysInMarket, daysInMarket,
netPerformancePercent netPerformancePercentage
}: { }: {
daysInMarket: number; daysInMarket: number;
netPerformancePercent: Big; netPerformancePercentage: Big;
}): Big { }): Big {
if (isNumber(daysInMarket) && daysInMarket > 0) { if (isNumber(daysInMarket) && daysInMarket > 0) {
const exponent = new Big(365).div(daysInMarket).toNumber(); const exponent = new Big(365).div(daysInMarket).toNumber();
return new Big( return new Big(
Math.pow(netPerformancePercent.plus(1).toNumber(), exponent) Math.pow(netPerformancePercentage.plus(1).toNumber(), exponent)
).minus(1); ).minus(1);
} }
@ -360,7 +360,7 @@ export class PortfolioService {
userId, userId,
calculationType: PerformanceCalculationType.TWR, calculationType: PerformanceCalculationType.TWR,
currency: userCurrency, currency: userCurrency,
hasFilters: filters?.length > 0, hasFilters: true, // disable cache
isExperimentalFeatures: isExperimentalFeatures:
this.request.user?.Settings.settings.isExperimentalFeatures this.request.user?.Settings.settings.isExperimentalFeatures
}); });
@ -704,7 +704,7 @@ export class PortfolioService {
const dividendYieldPercent = this.getAnnualizedPerformancePercent({ const dividendYieldPercent = this.getAnnualizedPerformancePercent({
daysInMarket: differenceInDays(new Date(), parseDate(firstBuyDate)), daysInMarket: differenceInDays(new Date(), parseDate(firstBuyDate)),
netPerformancePercent: timeWeightedInvestment.eq(0) netPerformancePercentage: timeWeightedInvestment.eq(0)
? new Big(0) ? new Big(0)
: dividendInBaseCurrency.div(timeWeightedInvestment) : dividendInBaseCurrency.div(timeWeightedInvestment)
}); });
@ -712,7 +712,9 @@ export class PortfolioService {
const dividendYieldPercentWithCurrencyEffect = const dividendYieldPercentWithCurrencyEffect =
this.getAnnualizedPerformancePercent({ this.getAnnualizedPerformancePercent({
daysInMarket: differenceInDays(new Date(), parseDate(firstBuyDate)), daysInMarket: differenceInDays(new Date(), parseDate(firstBuyDate)),
netPerformancePercent: timeWeightedInvestmentWithCurrencyEffect.eq(0) netPerformancePercentage: timeWeightedInvestmentWithCurrencyEffect.eq(
0
)
? new Big(0) ? new Big(0)
: dividendInBaseCurrency.div( : dividendInBaseCurrency.div(
timeWeightedInvestmentWithCurrencyEffect timeWeightedInvestmentWithCurrencyEffect
@ -1108,16 +1110,16 @@ export class PortfolioService {
firstOrderDate: undefined, firstOrderDate: undefined,
hasErrors: false, hasErrors: false,
performance: { performance: {
currentGrossPerformance: 0,
currentGrossPerformancePercent: 0,
currentGrossPerformancePercentWithCurrencyEffect: 0,
currentGrossPerformanceWithCurrencyEffect: 0,
currentNetPerformance: 0,
currentNetPerformancePercent: 0,
currentNetPerformancePercentWithCurrencyEffect: 0,
currentNetPerformanceWithCurrencyEffect: 0,
currentNetWorth: 0, currentNetWorth: 0,
currentValue: 0, currentValueInBaseCurrency: 0,
grossPerformance: 0,
grossPerformancePercentage: 0,
grossPerformancePercentageWithCurrencyEffect: 0,
grossPerformanceWithCurrencyEffect: 0,
netPerformance: 0,
netPerformancePercentage: 0,
netPerformancePercentageWithCurrencyEffect: 0,
netPerformanceWithCurrencyEffect: 0,
totalInvestment: 0 totalInvestment: 0
} }
}; };
@ -1152,9 +1154,9 @@ export class PortfolioService {
let currentNetPerformance = netPerformance; let currentNetPerformance = netPerformance;
let currentNetPerformancePercent = netPerformancePercentage; let currentNetPerformancePercentage = netPerformancePercentage;
let currentNetPerformancePercentWithCurrencyEffect = let currentNetPerformancePercentageWithCurrencyEffect =
netPerformancePercentageWithCurrencyEffect; netPerformancePercentageWithCurrencyEffect;
let currentNetPerformanceWithCurrencyEffect = let currentNetPerformanceWithCurrencyEffect =
@ -1173,11 +1175,11 @@ export class PortfolioService {
if (itemOfToday) { if (itemOfToday) {
currentNetPerformance = new Big(itemOfToday.netPerformance); currentNetPerformance = new Big(itemOfToday.netPerformance);
currentNetPerformancePercent = new Big( currentNetPerformancePercentage = new Big(
itemOfToday.netPerformanceInPercentage itemOfToday.netPerformanceInPercentage
).div(100); ).div(100);
currentNetPerformancePercentWithCurrencyEffect = new Big( currentNetPerformancePercentageWithCurrencyEffect = new Big(
itemOfToday.netPerformanceInPercentageWithCurrencyEffect itemOfToday.netPerformanceInPercentageWithCurrencyEffect
).div(100); ).div(100);
@ -1195,19 +1197,19 @@ export class PortfolioService {
firstOrderDate: parseDate(items[0]?.date), firstOrderDate: parseDate(items[0]?.date),
performance: { performance: {
currentNetWorth, currentNetWorth,
currentGrossPerformance: grossPerformance.toNumber(), currentValueInBaseCurrency: currentValueInBaseCurrency.toNumber(),
currentGrossPerformancePercent: grossPerformancePercentage.toNumber(), grossPerformance: grossPerformance.toNumber(),
currentGrossPerformancePercentWithCurrencyEffect: grossPerformancePercentage: grossPerformancePercentage.toNumber(),
grossPerformancePercentageWithCurrencyEffect:
grossPerformancePercentageWithCurrencyEffect.toNumber(), grossPerformancePercentageWithCurrencyEffect.toNumber(),
currentGrossPerformanceWithCurrencyEffect: grossPerformanceWithCurrencyEffect:
grossPerformanceWithCurrencyEffect.toNumber(), grossPerformanceWithCurrencyEffect.toNumber(),
currentNetPerformance: currentNetPerformance.toNumber(), netPerformance: currentNetPerformance.toNumber(),
currentNetPerformancePercent: currentNetPerformancePercent.toNumber(), netPerformancePercentage: currentNetPerformancePercentage.toNumber(),
currentNetPerformancePercentWithCurrencyEffect: netPerformancePercentageWithCurrencyEffect:
currentNetPerformancePercentWithCurrencyEffect.toNumber(), currentNetPerformancePercentageWithCurrencyEffect.toNumber(),
currentNetPerformanceWithCurrencyEffect: netPerformanceWithCurrencyEffect:
currentNetPerformanceWithCurrencyEffect.toNumber(), currentNetPerformanceWithCurrencyEffect.toNumber(),
currentValue: currentValueInBaseCurrency.toNumber(),
totalInvestment: totalInvestment.toNumber() totalInvestment: totalInvestment.toNumber()
} }
}; };
@ -1604,11 +1606,6 @@ export class PortfolioService {
userId = await this.getUserId(impersonationId, userId); userId = await this.getUserId(impersonationId, userId);
const user = await this.userService.user({ id: userId }); const user = await this.userService.user({ id: userId });
const { performance } = await this.getPerformance({
impersonationId,
userId
});
const { activities } = await this.orderService.getOrders({ const { activities } = await this.orderService.getOrders({
userCurrency, userCurrency,
userId, userId,
@ -1626,6 +1623,19 @@ export class PortfolioService {
} }
} }
const {
currentValueInBaseCurrency,
grossPerformance,
grossPerformancePercentage,
grossPerformancePercentageWithCurrencyEffect,
grossPerformanceWithCurrencyEffect,
netPerformance,
netPerformancePercentage,
netPerformancePercentageWithCurrencyEffect,
netPerformanceWithCurrencyEffect,
totalInvestment
} = await portfolioCalculator.getSnapshot();
const dividendInBaseCurrency = const dividendInBaseCurrency =
await portfolioCalculator.getDividendInBaseCurrency(); await portfolioCalculator.getDividendInBaseCurrency();
@ -1694,7 +1704,7 @@ export class PortfolioService {
.toNumber(); .toNumber();
const netWorth = new Big(balanceInBaseCurrency) const netWorth = new Big(balanceInBaseCurrency)
.plus(performance.currentValue) .plus(currentValueInBaseCurrency)
.plus(valuables) .plus(valuables)
.plus(excludedAccountsAndActivities) .plus(excludedAccountsAndActivities)
.minus(liabilities) .minus(liabilities)
@ -1704,19 +1714,18 @@ export class PortfolioService {
const annualizedPerformancePercent = this.getAnnualizedPerformancePercent({ const annualizedPerformancePercent = this.getAnnualizedPerformancePercent({
daysInMarket, daysInMarket,
netPerformancePercent: new Big(performance.currentNetPerformancePercent) netPerformancePercentage: new Big(netPerformancePercentage)
})?.toNumber(); })?.toNumber();
const annualizedPerformancePercentWithCurrencyEffect = const annualizedPerformancePercentWithCurrencyEffect =
this.getAnnualizedPerformancePercent({ this.getAnnualizedPerformancePercent({
daysInMarket, daysInMarket,
netPerformancePercent: new Big( netPerformancePercentage: new Big(
performance.currentNetPerformancePercentWithCurrencyEffect netPerformancePercentageWithCurrencyEffect
) )
})?.toNumber(); })?.toNumber();
return { return {
...performance,
annualizedPerformancePercent, annualizedPerformancePercent,
annualizedPerformancePercentWithCurrencyEffect, annualizedPerformancePercentWithCurrencyEffect,
cash, cash,
@ -1725,6 +1734,7 @@ export class PortfolioService {
totalBuy, totalBuy,
totalSell, totalSell,
committedFunds: committedFunds.toNumber(), committedFunds: committedFunds.toNumber(),
currentValueInBaseCurrency: currentValueInBaseCurrency.toNumber(),
dividendInBaseCurrency: dividendInBaseCurrency.toNumber(), dividendInBaseCurrency: dividendInBaseCurrency.toNumber(),
emergencyFund: { emergencyFund: {
assets: emergencyFundPositionsValueInBaseCurrency, assets: emergencyFundPositionsValueInBaseCurrency,
@ -1738,15 +1748,28 @@ export class PortfolioService {
filteredValueInPercentage: netWorth filteredValueInPercentage: netWorth
? filteredValueInBaseCurrency.div(netWorth).toNumber() ? filteredValueInBaseCurrency.div(netWorth).toNumber()
: undefined, : undefined,
fireWealth: new Big(performance.currentValue) fireWealth: new Big(currentValueInBaseCurrency)
.minus(emergencyFundPositionsValueInBaseCurrency) .minus(emergencyFundPositionsValueInBaseCurrency)
.toNumber(), .toNumber(),
grossPerformance: grossPerformance.toNumber(),
grossPerformancePercentage: grossPerformancePercentage.toNumber(),
grossPerformancePercentageWithCurrencyEffect:
grossPerformancePercentageWithCurrencyEffect.toNumber(),
grossPerformanceWithCurrencyEffect:
grossPerformanceWithCurrencyEffect.toNumber(),
interest: interest.toNumber(), interest: interest.toNumber(),
items: valuables.toNumber(), items: valuables.toNumber(),
liabilities: liabilities.toNumber(), liabilities: liabilities.toNumber(),
netPerformance: netPerformance.toNumber(),
netPerformancePercentage: netPerformancePercentage.toNumber(),
netPerformancePercentageWithCurrencyEffect:
netPerformancePercentageWithCurrencyEffect.toNumber(),
netPerformanceWithCurrencyEffect:
netPerformanceWithCurrencyEffect.toNumber(),
ordersCount: activities.filter(({ type }) => { ordersCount: activities.filter(({ type }) => {
return type === 'BUY' || type === 'SELL'; return ['BUY', 'SELL'].includes(type);
}).length, }).length,
totalInvestment: totalInvestment.toNumber(),
totalValueInBaseCurrency: netWorth totalValueInBaseCurrency: netWorth
}; };
} }

@ -41,9 +41,7 @@
[isCurrency]="true" [isCurrency]="true"
[locale]="locale" [locale]="locale"
[value]=" [value]="
isLoading isLoading ? undefined : performance?.netPerformanceWithCurrencyEffect
? undefined
: performance?.currentNetPerformanceWithCurrencyEffect
" "
/> />
</div> </div>
@ -55,7 +53,7 @@
[value]=" [value]="
isLoading isLoading
? undefined ? undefined
: performance?.currentNetPerformancePercentWithCurrencyEffect : performance?.netPerformancePercentageWithCurrencyEffect
" "
/> />
</div> </div>

@ -49,12 +49,12 @@ export class PortfolioPerformanceComponent implements OnChanges, OnInit {
this.value.nativeElement.innerHTML = ''; this.value.nativeElement.innerHTML = '';
} }
} else { } else {
if (isNumber(this.performance?.currentValue)) { if (isNumber(this.performance?.currentValueInBaseCurrency)) {
new CountUp('value', this.performance?.currentValue, { new CountUp('value', this.performance?.currentValueInBaseCurrency, {
decimal: getNumberFormatDecimal(this.locale), decimal: getNumberFormatDecimal(this.locale),
decimalPlaces: decimalPlaces:
this.deviceType === 'mobile' && this.deviceType === 'mobile' &&
this.performance?.currentValue >= 100000 this.performance?.currentValueInBaseCurrency >= 100000
? 0 ? 0
: 2, : 2,
duration: 1, duration: 1,
@ -63,8 +63,7 @@ export class PortfolioPerformanceComponent implements OnChanges, OnInit {
} else if (this.showDetails === false) { } else if (this.showDetails === false) {
new CountUp( new CountUp(
'value', 'value',
this.performance?.currentNetPerformancePercentWithCurrencyEffect * this.performance?.netPerformancePercentageWithCurrencyEffect * 100,
100,
{ {
decimal: getNumberFormatDecimal(this.locale), decimal: getNumberFormatDecimal(this.locale),
decimalPlaces: 2, decimalPlaces: 2,

@ -9,9 +9,19 @@
class="flex-nowrap px-3 py-1 row" class="flex-nowrap px-3 py-1 row"
[hidden]="summary?.ordersCount === null" [hidden]="summary?.ordersCount === null"
> >
<div class="flex-grow-1 ml-3 text-truncate" i18n> <div class="d-flex flex-grow-1 ml-3 text-truncate">
{{ summary?.ordersCount }} {{ summary?.ordersCount }}
{summary?.ordersCount, plural, =1 {transaction} other {transactions}} <ng-container i18n>{summary?.ordersCount, plural,
=1 {activity}
other {activities}
}</ng-container>
<span
class="align-items-center d-flex ml-1"
matTooltipPosition="above"
[matTooltip]="buyAndSellActivitiesTooltip"
>
<ion-icon name="information-circle-outline" />
</span>
</div> </div>
</div> </div>
<div class="row"> <div class="row">
@ -65,9 +75,7 @@
[locale]="locale" [locale]="locale"
[unit]="baseCurrency" [unit]="baseCurrency"
[value]=" [value]="
isLoading isLoading ? undefined : summary?.grossPerformanceWithCurrencyEffect
? undefined
: summary?.currentGrossPerformanceWithCurrencyEffect
" "
/> />
</div> </div>
@ -91,7 +99,7 @@
[value]=" [value]="
isLoading isLoading
? undefined ? undefined
: summary?.currentGrossPerformancePercentWithCurrencyEffect : summary?.grossPerformancePercentageWithCurrencyEffect
" "
/> />
</div> </div>
@ -121,9 +129,7 @@
[locale]="locale" [locale]="locale"
[unit]="baseCurrency" [unit]="baseCurrency"
[value]=" [value]="
isLoading isLoading ? undefined : summary?.netPerformanceWithCurrencyEffect
? undefined
: summary?.currentNetPerformanceWithCurrencyEffect
" "
/> />
</div> </div>
@ -147,7 +153,7 @@
[value]=" [value]="
isLoading isLoading
? undefined ? undefined
: summary?.currentNetPerformancePercentWithCurrencyEffect : summary?.netPerformancePercentageWithCurrencyEffect
" "
/> />
</div> </div>
@ -164,7 +170,7 @@
[isCurrency]="true" [isCurrency]="true"
[locale]="locale" [locale]="locale"
[unit]="baseCurrency" [unit]="baseCurrency"
[value]="isLoading ? undefined : summary?.currentValue" [value]="isLoading ? undefined : summary?.currentValueInBaseCurrency"
/> />
</div> </div>
</div> </div>

@ -1,5 +1,6 @@
import { getDateFnsLocale, getLocale } from '@ghostfolio/common/helper'; import { getDateFnsLocale, getLocale } from '@ghostfolio/common/helper';
import { PortfolioSummary } from '@ghostfolio/common/interfaces'; import { PortfolioSummary } from '@ghostfolio/common/interfaces';
import { translate } from '@ghostfolio/ui/i18n';
import { import {
ChangeDetectionStrategy, ChangeDetectionStrategy,
@ -28,6 +29,9 @@ export class PortfolioSummaryComponent implements OnChanges, OnInit {
@Output() emergencyFundChanged = new EventEmitter<number>(); @Output() emergencyFundChanged = new EventEmitter<number>();
public buyAndSellActivitiesTooltip = translate(
'BUY_AND_SELL_ACTIVITIES_TOOLTIP'
);
public timeInMarket: string; public timeInMarket: string;
public constructor() {} public constructor() {}

@ -2,13 +2,14 @@ import { GfValueComponent } from '@ghostfolio/ui/value';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { MatTooltipModule } from '@angular/material/tooltip';
import { PortfolioSummaryComponent } from './portfolio-summary.component'; import { PortfolioSummaryComponent } from './portfolio-summary.component';
@NgModule({ @NgModule({
declarations: [PortfolioSummaryComponent], declarations: [PortfolioSummaryComponent],
exports: [PortfolioSummaryComponent], exports: [PortfolioSummaryComponent],
imports: [CommonModule, GfValueComponent], imports: [CommonModule, GfValueComponent, MatTooltipModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA] schemas: [CUSTOM_ELEMENTS_SCHEMA]
}) })
export class GfPortfolioSummaryModule {} export class GfPortfolioSummaryModule {}

@ -42,7 +42,7 @@
[value]=" [value]="
isLoadingInvestmentChart isLoadingInvestmentChart
? undefined ? undefined
: performance?.currentNetPerformance : performance?.netPerformance
" "
/> />
</div> </div>
@ -61,7 +61,7 @@
[value]=" [value]="
isLoadingInvestmentChart isLoadingInvestmentChart
? undefined ? undefined
: performance?.currentNetPerformancePercent : performance?.netPerformancePercentage
" "
/> />
</div> </div>
@ -86,10 +86,10 @@
[value]=" [value]="
isLoadingInvestmentChart isLoadingInvestmentChart
? undefined ? undefined
: performance?.currentNetPerformance === null : performance?.netPerformance === null
? null ? null
: performance?.currentNetPerformanceWithCurrencyEffect - : performance?.netPerformanceWithCurrencyEffect -
performance?.currentNetPerformance performance?.netPerformance
" "
/> />
</div> </div>
@ -108,10 +108,10 @@
[value]=" [value]="
isLoadingInvestmentChart isLoadingInvestmentChart
? undefined ? undefined
: performance?.currentNetPerformancePercent === null : performance?.netPerformancePercentage === null
? null ? null
: performance?.currentNetPerformancePercentWithCurrencyEffect - : performance?.netPerformancePercentageWithCurrencyEffect -
performance?.currentNetPerformancePercent performance?.netPerformancePercentage
" "
/> />
</div> </div>
@ -131,7 +131,7 @@
[value]=" [value]="
isLoadingInvestmentChart isLoadingInvestmentChart
? undefined ? undefined
: performance?.currentNetPerformanceWithCurrencyEffect : performance?.netPerformanceWithCurrencyEffect
" "
/> />
</div> </div>
@ -150,7 +150,7 @@
[value]=" [value]="
isLoadingInvestmentChart isLoadingInvestmentChart
? undefined ? undefined
: performance?.currentNetPerformancePercentWithCurrencyEffect : performance?.netPerformancePercentageWithCurrencyEffect
" "
/> />
</div> </div>

@ -1,14 +1,14 @@
export interface PortfolioPerformance { export interface PortfolioPerformance {
annualizedPerformancePercent?: number; annualizedPerformancePercent?: number;
currentGrossPerformance: number; currentNetWorth?: number;
currentGrossPerformancePercent: number; currentValueInBaseCurrency: number;
currentGrossPerformancePercentWithCurrencyEffect: number; grossPerformance: number;
currentGrossPerformanceWithCurrencyEffect: number; grossPerformancePercentage: number;
currentNetPerformance: number; grossPerformancePercentageWithCurrencyEffect: number;
currentNetPerformancePercent: number; grossPerformanceWithCurrencyEffect: number;
currentNetPerformancePercentWithCurrencyEffect: number; netPerformance: number;
currentNetPerformanceWithCurrencyEffect: number; netPerformancePercentage: number;
currentNetWorth: number; netPerformancePercentageWithCurrencyEffect: number;
currentValue: number; netPerformanceWithCurrencyEffect: number;
totalInvestment: number; totalInvestment: number;
} }

@ -5,6 +5,7 @@ const locales = {
'Asia-Pacific': $localize`Asia-Pacific`, 'Asia-Pacific': $localize`Asia-Pacific`,
ASSET_CLASS: $localize`Asset Class`, ASSET_CLASS: $localize`Asset Class`,
ASSET_SUB_CLASS: $localize`Asset Sub Class`, ASSET_SUB_CLASS: $localize`Asset Sub Class`,
BUY_AND_SELL_ACTIVITIES_TOOLTIP: $localize`Buy and sell`,
CORE: $localize`Core`, CORE: $localize`Core`,
DATA_IMPORT_AND_EXPORT_TOOLTIP_BASIC: $localize`Switch to Ghostfolio Premium or Ghostfolio Open Source easily`, DATA_IMPORT_AND_EXPORT_TOOLTIP_BASIC: $localize`Switch to Ghostfolio Premium or Ghostfolio Open Source easily`,
DATA_IMPORT_AND_EXPORT_TOOLTIP_OSS: $localize`Switch to Ghostfolio Premium easily`, DATA_IMPORT_AND_EXPORT_TOOLTIP_OSS: $localize`Switch to Ghostfolio Premium easily`,

Loading…
Cancel
Save