Feature/optimize get porfolio details endpoint (#3366)
* Eliminate getPerformance() from getSummary() function * Disable cache for getDetails() * Add hint to portfolio summary * Update changelog
This commit is contained in:
parent
3f41e5c5de
commit
f2cb671c7f
@ -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…
x
Reference in New Issue
Block a user