Feature/switch to performance calculations with currency effects (#3039)
* Switch to performance calculations with currency effects * Improve value redaction in portfolio details endpoint * Update changelog
This commit is contained in:
parent
c002e37285
commit
2e9d40c201
@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
- Switched the performance calculations to take the currency effects into account
|
||||||
- Removed the `isDefault` flag from the `Account` database schema
|
- Removed the `isDefault` flag from the `Account` database schema
|
||||||
- Exposed the database index of _Redis_ as an environment variable (`REDIS_DB`)
|
- Exposed the database index of _Redis_ as an environment variable (`REDIS_DB`)
|
||||||
- Improved the language localization for German (`de`)
|
- Improved the language localization for German (`de`)
|
||||||
|
@ -118,27 +118,23 @@ export class PortfolioController {
|
|||||||
this.userService.isRestrictedView(this.request.user)
|
this.userService.isRestrictedView(this.request.user)
|
||||||
) {
|
) {
|
||||||
const totalInvestment = Object.values(holdings)
|
const totalInvestment = Object.values(holdings)
|
||||||
.map((portfolioPosition) => {
|
.map(({ investment }) => {
|
||||||
return portfolioPosition.investment;
|
return investment;
|
||||||
})
|
})
|
||||||
.reduce((a, b) => a + b, 0);
|
.reduce((a, b) => a + b, 0);
|
||||||
|
|
||||||
const totalValue = Object.values(holdings)
|
const totalValue = Object.values(holdings)
|
||||||
.map((portfolioPosition) => {
|
.filter(({ assetClass, assetSubClass }) => {
|
||||||
return this.exchangeRateDataService.toCurrency(
|
return assetClass !== 'CASH' && assetSubClass !== 'CASH';
|
||||||
portfolioPosition.quantity * portfolioPosition.marketPrice,
|
})
|
||||||
portfolioPosition.currency,
|
.map(({ valueInBaseCurrency }) => {
|
||||||
this.request.user.Settings.settings.baseCurrency
|
return valueInBaseCurrency;
|
||||||
);
|
|
||||||
})
|
})
|
||||||
.reduce((a, b) => a + b, 0);
|
.reduce((a, b) => a + b, 0);
|
||||||
|
|
||||||
for (const [symbol, portfolioPosition] of Object.entries(holdings)) {
|
for (const [symbol, portfolioPosition] of Object.entries(holdings)) {
|
||||||
portfolioPosition.grossPerformance = null;
|
|
||||||
portfolioPosition.investment =
|
portfolioPosition.investment =
|
||||||
portfolioPosition.investment / totalInvestment;
|
portfolioPosition.investment / totalInvestment;
|
||||||
portfolioPosition.netPerformance = null;
|
|
||||||
portfolioPosition.quantity = null;
|
|
||||||
portfolioPosition.valueInPercentage =
|
portfolioPosition.valueInPercentage =
|
||||||
portfolioPosition.valueInBaseCurrency / totalValue;
|
portfolioPosition.valueInBaseCurrency / totalValue;
|
||||||
}
|
}
|
||||||
|
@ -529,12 +529,20 @@ export class PortfolioService {
|
|||||||
grossPerformance: item.grossPerformance?.toNumber() ?? 0,
|
grossPerformance: item.grossPerformance?.toNumber() ?? 0,
|
||||||
grossPerformancePercent:
|
grossPerformancePercent:
|
||||||
item.grossPerformancePercentage?.toNumber() ?? 0,
|
item.grossPerformancePercentage?.toNumber() ?? 0,
|
||||||
|
grossPerformancePercentWithCurrencyEffect:
|
||||||
|
item.grossPerformancePercentageWithCurrencyEffect?.toNumber() ?? 0,
|
||||||
|
grossPerformanceWithCurrencyEffect:
|
||||||
|
item.grossPerformanceWithCurrencyEffect?.toNumber() ?? 0,
|
||||||
investment: item.investment.toNumber(),
|
investment: item.investment.toNumber(),
|
||||||
marketPrice: item.marketPrice,
|
marketPrice: item.marketPrice,
|
||||||
marketState: dataProviderResponse?.marketState ?? 'delayed',
|
marketState: dataProviderResponse?.marketState ?? 'delayed',
|
||||||
name: symbolProfile.name,
|
name: symbolProfile.name,
|
||||||
netPerformance: item.netPerformance?.toNumber() ?? 0,
|
netPerformance: item.netPerformance?.toNumber() ?? 0,
|
||||||
netPerformancePercent: item.netPerformancePercentage?.toNumber() ?? 0,
|
netPerformancePercent: item.netPerformancePercentage?.toNumber() ?? 0,
|
||||||
|
netPerformancePercentWithCurrencyEffect:
|
||||||
|
item.netPerformancePercentageWithCurrencyEffect?.toNumber() ?? 0,
|
||||||
|
netPerformanceWithCurrencyEffect:
|
||||||
|
item.netPerformanceWithCurrencyEffect?.toNumber() ?? 0,
|
||||||
quantity: item.quantity.toNumber(),
|
quantity: item.quantity.toNumber(),
|
||||||
sectors: symbolProfile.sectors,
|
sectors: symbolProfile.sectors,
|
||||||
symbol: item.symbol,
|
symbol: item.symbol,
|
||||||
@ -1600,12 +1608,16 @@ export class PortfolioService {
|
|||||||
dateOfFirstActivity: undefined,
|
dateOfFirstActivity: undefined,
|
||||||
grossPerformance: 0,
|
grossPerformance: 0,
|
||||||
grossPerformancePercent: 0,
|
grossPerformancePercent: 0,
|
||||||
|
grossPerformancePercentWithCurrencyEffect: 0,
|
||||||
|
grossPerformanceWithCurrencyEffect: 0,
|
||||||
investment: balance,
|
investment: balance,
|
||||||
marketPrice: 0,
|
marketPrice: 0,
|
||||||
marketState: 'open',
|
marketState: 'open',
|
||||||
name: currency,
|
name: currency,
|
||||||
netPerformance: 0,
|
netPerformance: 0,
|
||||||
netPerformancePercent: 0,
|
netPerformancePercent: 0,
|
||||||
|
netPerformancePercentWithCurrencyEffect: 0,
|
||||||
|
netPerformanceWithCurrencyEffect: 0,
|
||||||
quantity: 0,
|
quantity: 0,
|
||||||
sectors: [],
|
sectors: [],
|
||||||
symbol: currency,
|
symbol: currency,
|
||||||
@ -1814,9 +1826,25 @@ export class PortfolioService {
|
|||||||
})
|
})
|
||||||
?.toNumber();
|
?.toNumber();
|
||||||
|
|
||||||
|
const annualizedPerformancePercentWithCurrencyEffect =
|
||||||
|
new PortfolioCalculator({
|
||||||
|
currency: userCurrency,
|
||||||
|
currentRateService: this.currentRateService,
|
||||||
|
exchangeRateDataService: this.exchangeRateDataService,
|
||||||
|
orders: []
|
||||||
|
})
|
||||||
|
.getAnnualizedPerformancePercent({
|
||||||
|
daysInMarket,
|
||||||
|
netPerformancePercent: new Big(
|
||||||
|
performanceInformation.performance.currentNetPerformancePercentWithCurrencyEffect
|
||||||
|
)
|
||||||
|
})
|
||||||
|
?.toNumber();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...performanceInformation.performance,
|
...performanceInformation.performance,
|
||||||
annualizedPerformancePercent,
|
annualizedPerformancePercent,
|
||||||
|
annualizedPerformancePercentWithCurrencyEffect,
|
||||||
cash,
|
cash,
|
||||||
dividend,
|
dividend,
|
||||||
excludedAccountsAndActivities,
|
excludedAccountsAndActivities,
|
||||||
|
@ -51,8 +51,10 @@ export class RedactValuesInResponseInterceptor<T>
|
|||||||
'feeInBaseCurrency',
|
'feeInBaseCurrency',
|
||||||
'filteredValueInBaseCurrency',
|
'filteredValueInBaseCurrency',
|
||||||
'grossPerformance',
|
'grossPerformance',
|
||||||
|
'grossPerformanceWithCurrencyEffect',
|
||||||
'investment',
|
'investment',
|
||||||
'netPerformance',
|
'netPerformance',
|
||||||
|
'netPerformanceWithCurrencyEffect',
|
||||||
'quantity',
|
'quantity',
|
||||||
'symbolMapping',
|
'symbolMapping',
|
||||||
'totalBalanceInBaseCurrency',
|
'totalBalanceInBaseCurrency',
|
||||||
|
@ -154,8 +154,8 @@ export class HomeHoldingsComponent implements OnDestroy, OnInit {
|
|||||||
this.dataService
|
this.dataService
|
||||||
.fetchPositions({ range: this.user?.settings?.dateRange })
|
.fetchPositions({ range: this.user?.settings?.dateRange })
|
||||||
.pipe(takeUntil(this.unsubscribeSubject))
|
.pipe(takeUntil(this.unsubscribeSubject))
|
||||||
.subscribe((response) => {
|
.subscribe(({ positions }) => {
|
||||||
this.positions = response.positions;
|
this.positions = positions;
|
||||||
|
|
||||||
this.changeDetectorRef.markForCheck();
|
this.changeDetectorRef.markForCheck();
|
||||||
});
|
});
|
||||||
|
@ -127,10 +127,10 @@ export class HomeOverviewComponent implements OnDestroy, OnInit {
|
|||||||
this.isLoadingPerformance = false;
|
this.isLoadingPerformance = false;
|
||||||
|
|
||||||
this.historicalDataItems = chart.map(
|
this.historicalDataItems = chart.map(
|
||||||
({ date, netPerformanceInPercentage }) => {
|
({ date, netPerformanceInPercentageWithCurrencyEffect }) => {
|
||||||
return {
|
return {
|
||||||
date,
|
date,
|
||||||
value: netPerformanceInPercentage
|
value: netPerformanceInPercentageWithCurrencyEffect
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -40,7 +40,11 @@
|
|||||||
[colorizeSign]="true"
|
[colorizeSign]="true"
|
||||||
[isCurrency]="true"
|
[isCurrency]="true"
|
||||||
[locale]="locale"
|
[locale]="locale"
|
||||||
[value]="isLoading ? undefined : performance?.currentNetPerformance"
|
[value]="
|
||||||
|
isLoading
|
||||||
|
? undefined
|
||||||
|
: performance?.currentNetPerformanceWithCurrencyEffect
|
||||||
|
"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
@ -49,7 +53,9 @@
|
|||||||
[isPercent]="true"
|
[isPercent]="true"
|
||||||
[locale]="locale"
|
[locale]="locale"
|
||||||
[value]="
|
[value]="
|
||||||
isLoading ? undefined : performance?.currentNetPerformancePercent
|
isLoading
|
||||||
|
? undefined
|
||||||
|
: performance?.currentNetPerformancePercentWithCurrencyEffect
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -63,7 +63,8 @@ export class PortfolioPerformanceComponent implements OnChanges, OnInit {
|
|||||||
} else if (this.showDetails === false) {
|
} else if (this.showDetails === false) {
|
||||||
new CountUp(
|
new CountUp(
|
||||||
'value',
|
'value',
|
||||||
this.performance?.currentNetPerformancePercent * 100,
|
this.performance?.currentNetPerformancePercentWithCurrencyEffect *
|
||||||
|
100,
|
||||||
{
|
{
|
||||||
decimal: getNumberFormatDecimal(this.locale),
|
decimal: getNumberFormatDecimal(this.locale),
|
||||||
decimalPlaces: 2,
|
decimalPlaces: 2,
|
||||||
|
@ -64,7 +64,11 @@
|
|||||||
[isCurrency]="true"
|
[isCurrency]="true"
|
||||||
[locale]="locale"
|
[locale]="locale"
|
||||||
[unit]="baseCurrency"
|
[unit]="baseCurrency"
|
||||||
[value]="isLoading ? undefined : summary?.currentGrossPerformance"
|
[value]="
|
||||||
|
isLoading
|
||||||
|
? undefined
|
||||||
|
: summary?.currentGrossPerformanceWithCurrencyEffect
|
||||||
|
"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -85,7 +89,9 @@
|
|||||||
[isPercent]="true"
|
[isPercent]="true"
|
||||||
[locale]="locale"
|
[locale]="locale"
|
||||||
[value]="
|
[value]="
|
||||||
isLoading ? undefined : summary?.currentGrossPerformancePercent
|
isLoading
|
||||||
|
? undefined
|
||||||
|
: summary?.currentGrossPerformancePercentWithCurrencyEffect
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -114,7 +120,11 @@
|
|||||||
[isCurrency]="true"
|
[isCurrency]="true"
|
||||||
[locale]="locale"
|
[locale]="locale"
|
||||||
[unit]="baseCurrency"
|
[unit]="baseCurrency"
|
||||||
[value]="isLoading ? undefined : summary?.currentNetPerformance"
|
[value]="
|
||||||
|
isLoading
|
||||||
|
? undefined
|
||||||
|
: summary?.currentNetPerformanceWithCurrencyEffect
|
||||||
|
"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -134,7 +144,11 @@
|
|||||||
[colorizeSign]="true"
|
[colorizeSign]="true"
|
||||||
[isPercent]="true"
|
[isPercent]="true"
|
||||||
[locale]="locale"
|
[locale]="locale"
|
||||||
[value]="isLoading ? undefined : summary?.currentNetPerformancePercent"
|
[value]="
|
||||||
|
isLoading
|
||||||
|
? undefined
|
||||||
|
: summary?.currentNetPerformancePercentWithCurrencyEffect
|
||||||
|
"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -283,7 +297,11 @@
|
|||||||
[colorizeSign]="true"
|
[colorizeSign]="true"
|
||||||
[isPercent]="true"
|
[isPercent]="true"
|
||||||
[locale]="locale"
|
[locale]="locale"
|
||||||
[value]="isLoading ? undefined : summary?.annualizedPerformancePercent"
|
[value]="
|
||||||
|
isLoading
|
||||||
|
? undefined
|
||||||
|
: summary?.annualizedPerformancePercentWithCurrencyEffect
|
||||||
|
"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -50,15 +50,13 @@ export class PositionDetailDialog implements OnDestroy, OnInit {
|
|||||||
public dividendInBaseCurrency: number;
|
public dividendInBaseCurrency: number;
|
||||||
public feeInBaseCurrency: number;
|
public feeInBaseCurrency: number;
|
||||||
public firstBuyDate: string;
|
public firstBuyDate: string;
|
||||||
public grossPerformance: number;
|
|
||||||
public grossPerformancePercent: number;
|
|
||||||
public historicalDataItems: LineChartItem[];
|
public historicalDataItems: LineChartItem[];
|
||||||
public investment: number;
|
public investment: number;
|
||||||
public marketPrice: number;
|
public marketPrice: number;
|
||||||
public maxPrice: number;
|
public maxPrice: number;
|
||||||
public minPrice: number;
|
public minPrice: number;
|
||||||
public netPerformance: number;
|
public netPerformancePercentWithCurrencyEffect: number;
|
||||||
public netPerformancePercent: number;
|
public netPerformanceWithCurrencyEffect: number;
|
||||||
public quantity: number;
|
public quantity: number;
|
||||||
public quantityPrecision = 2;
|
public quantityPrecision = 2;
|
||||||
public reportDataGlitchMail: string;
|
public reportDataGlitchMail: string;
|
||||||
@ -99,15 +97,13 @@ export class PositionDetailDialog implements OnDestroy, OnInit {
|
|||||||
dividendInBaseCurrency,
|
dividendInBaseCurrency,
|
||||||
feeInBaseCurrency,
|
feeInBaseCurrency,
|
||||||
firstBuyDate,
|
firstBuyDate,
|
||||||
grossPerformance,
|
|
||||||
grossPerformancePercent,
|
|
||||||
historicalData,
|
historicalData,
|
||||||
investment,
|
investment,
|
||||||
marketPrice,
|
marketPrice,
|
||||||
maxPrice,
|
maxPrice,
|
||||||
minPrice,
|
minPrice,
|
||||||
netPerformance,
|
netPerformancePercentWithCurrencyEffect,
|
||||||
netPerformancePercent,
|
netPerformanceWithCurrencyEffect,
|
||||||
orders,
|
orders,
|
||||||
quantity,
|
quantity,
|
||||||
SymbolProfile,
|
SymbolProfile,
|
||||||
@ -125,8 +121,6 @@ export class PositionDetailDialog implements OnDestroy, OnInit {
|
|||||||
this.dividendInBaseCurrency = dividendInBaseCurrency;
|
this.dividendInBaseCurrency = dividendInBaseCurrency;
|
||||||
this.feeInBaseCurrency = feeInBaseCurrency;
|
this.feeInBaseCurrency = feeInBaseCurrency;
|
||||||
this.firstBuyDate = firstBuyDate;
|
this.firstBuyDate = firstBuyDate;
|
||||||
this.grossPerformance = grossPerformance;
|
|
||||||
this.grossPerformancePercent = grossPerformancePercent;
|
|
||||||
this.historicalDataItems = historicalData.map(
|
this.historicalDataItems = historicalData.map(
|
||||||
(historicalDataItem) => {
|
(historicalDataItem) => {
|
||||||
this.benchmarkDataItems.push({
|
this.benchmarkDataItems.push({
|
||||||
@ -144,8 +138,10 @@ export class PositionDetailDialog implements OnDestroy, OnInit {
|
|||||||
this.marketPrice = marketPrice;
|
this.marketPrice = marketPrice;
|
||||||
this.maxPrice = maxPrice;
|
this.maxPrice = maxPrice;
|
||||||
this.minPrice = minPrice;
|
this.minPrice = minPrice;
|
||||||
this.netPerformance = netPerformance;
|
this.netPerformancePercentWithCurrencyEffect =
|
||||||
this.netPerformancePercent = netPerformancePercent;
|
netPerformancePercentWithCurrencyEffect;
|
||||||
|
this.netPerformanceWithCurrencyEffect =
|
||||||
|
netPerformanceWithCurrencyEffect;
|
||||||
this.quantity = quantity;
|
this.quantity = quantity;
|
||||||
this.reportDataGlitchMail = `mailto:hi@ghostfol.io?Subject=Ghostfolio Data Glitch Report&body=Hello%0D%0DI would like to report a data glitch for%0D%0DSymbol: ${SymbolProfile?.symbol}%0DData Source: ${SymbolProfile?.dataSource}%0D%0DAdditional notes:%0D%0DCan you please take a look?%0D%0DKind regards`;
|
this.reportDataGlitchMail = `mailto:hi@ghostfol.io?Subject=Ghostfolio Data Glitch Report&body=Hello%0D%0DI would like to report a data glitch for%0D%0DSymbol: ${SymbolProfile?.symbol}%0DData Source: ${SymbolProfile?.dataSource}%0D%0DAdditional notes:%0D%0DCan you please take a look?%0D%0DKind regards`;
|
||||||
this.sectors = {};
|
this.sectors = {};
|
||||||
|
@ -44,7 +44,7 @@
|
|||||||
[isCurrency]="true"
|
[isCurrency]="true"
|
||||||
[locale]="data.locale"
|
[locale]="data.locale"
|
||||||
[unit]="data.baseCurrency"
|
[unit]="data.baseCurrency"
|
||||||
[value]="netPerformance"
|
[value]="netPerformanceWithCurrencyEffect"
|
||||||
>Change</gf-value
|
>Change</gf-value
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
@ -55,7 +55,7 @@
|
|||||||
[colorizeSign]="true"
|
[colorizeSign]="true"
|
||||||
[isPercent]="true"
|
[isPercent]="true"
|
||||||
[locale]="data.locale"
|
[locale]="data.locale"
|
||||||
[value]="netPerformancePercent"
|
[value]="netPerformancePercentWithCurrencyEffect"
|
||||||
>Performance</gf-value
|
>Performance</gf-value
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
[isLoading]="isLoading"
|
[isLoading]="isLoading"
|
||||||
[marketState]="position?.marketState"
|
[marketState]="position?.marketState"
|
||||||
[range]="range"
|
[range]="range"
|
||||||
[value]="position?.netPerformancePercentage"
|
[value]="position?.netPerformancePercentageWithCurrencyEffect"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="isLoading" class="flex-grow-1">
|
<div *ngIf="isLoading" class="flex-grow-1">
|
||||||
@ -49,13 +49,13 @@
|
|||||||
[isCurrency]="true"
|
[isCurrency]="true"
|
||||||
[locale]="locale"
|
[locale]="locale"
|
||||||
[unit]="baseCurrency"
|
[unit]="baseCurrency"
|
||||||
[value]="position?.netPerformance"
|
[value]="position?.netPerformanceWithCurrencyEffect"
|
||||||
/>
|
/>
|
||||||
<gf-value
|
<gf-value
|
||||||
[colorizeSign]="true"
|
[colorizeSign]="true"
|
||||||
[isPercent]="true"
|
[isPercent]="true"
|
||||||
[locale]="locale"
|
[locale]="locale"
|
||||||
[value]="position?.netPerformancePercentage"
|
[value]="position?.netPerformancePercentageWithCurrencyEffect"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -270,23 +270,28 @@ export class AnalysisPageComponent implements OnDestroy, OnInit {
|
|||||||
index,
|
index,
|
||||||
{
|
{
|
||||||
date,
|
date,
|
||||||
netPerformanceInPercentage,
|
netPerformanceInPercentageWithCurrencyEffect,
|
||||||
totalInvestment,
|
totalInvestmentValueWithCurrencyEffect,
|
||||||
value,
|
valueInPercentage,
|
||||||
valueInPercentage
|
valueWithCurrencyEffect
|
||||||
}
|
}
|
||||||
] of chart.entries()) {
|
] of chart.entries()) {
|
||||||
if (index > 0 || this.user?.settings?.dateRange === 'max') {
|
if (index > 0 || this.user?.settings?.dateRange === 'max') {
|
||||||
// Ignore first item where value is 0
|
// Ignore first item where value is 0
|
||||||
this.investments.push({ date, investment: totalInvestment });
|
this.investments.push({
|
||||||
|
date,
|
||||||
|
investment: totalInvestmentValueWithCurrencyEffect
|
||||||
|
});
|
||||||
this.performanceDataItems.push({
|
this.performanceDataItems.push({
|
||||||
date,
|
date,
|
||||||
value: isNumber(value) ? value : valueInPercentage
|
value: isNumber(valueWithCurrencyEffect)
|
||||||
|
? valueWithCurrencyEffect
|
||||||
|
: valueInPercentage
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.performanceDataItemsInPercentage.push({
|
this.performanceDataItemsInPercentage.push({
|
||||||
date,
|
date,
|
||||||
value: netPerformanceInPercentage
|
value: netPerformanceInPercentageWithCurrencyEffect
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -305,10 +310,10 @@ export class AnalysisPageComponent implements OnDestroy, OnInit {
|
|||||||
.pipe(takeUntil(this.unsubscribeSubject))
|
.pipe(takeUntil(this.unsubscribeSubject))
|
||||||
.subscribe(({ positions }) => {
|
.subscribe(({ positions }) => {
|
||||||
const positionsSorted = sortBy(
|
const positionsSorted = sortBy(
|
||||||
positions.filter(({ netPerformancePercentage }) => {
|
positions.filter(({ netPerformancePercentageWithCurrencyEffect }) => {
|
||||||
return isNumber(netPerformancePercentage);
|
return isNumber(netPerformancePercentageWithCurrencyEffect);
|
||||||
}),
|
}),
|
||||||
'netPerformancePercentage'
|
'netPerformancePercentageWithCurrencyEffect'
|
||||||
).reverse();
|
).reverse();
|
||||||
|
|
||||||
this.top3 = positionsSorted.slice(0, 3);
|
this.top3 = positionsSorted.slice(0, 3);
|
||||||
|
@ -17,6 +17,8 @@ export interface PortfolioPosition {
|
|||||||
exchange?: string;
|
exchange?: string;
|
||||||
grossPerformance: number;
|
grossPerformance: number;
|
||||||
grossPerformancePercent: number;
|
grossPerformancePercent: number;
|
||||||
|
grossPerformancePercentWithCurrencyEffect: number;
|
||||||
|
grossPerformanceWithCurrencyEffect: number;
|
||||||
investment: number;
|
investment: number;
|
||||||
marketChange?: number;
|
marketChange?: number;
|
||||||
marketChangePercent?: number;
|
marketChangePercent?: number;
|
||||||
@ -27,6 +29,8 @@ export interface PortfolioPosition {
|
|||||||
name: string;
|
name: string;
|
||||||
netPerformance: number;
|
netPerformance: number;
|
||||||
netPerformancePercent: number;
|
netPerformancePercent: number;
|
||||||
|
netPerformancePercentWithCurrencyEffect: number;
|
||||||
|
netPerformanceWithCurrencyEffect: number;
|
||||||
quantity: number;
|
quantity: number;
|
||||||
sectors: Sector[];
|
sectors: Sector[];
|
||||||
symbol: string;
|
symbol: string;
|
||||||
|
@ -2,6 +2,7 @@ import { PortfolioPerformance } from './portfolio-performance.interface';
|
|||||||
|
|
||||||
export interface PortfolioSummary extends PortfolioPerformance {
|
export interface PortfolioSummary extends PortfolioPerformance {
|
||||||
annualizedPerformancePercent: number;
|
annualizedPerformancePercent: number;
|
||||||
|
annualizedPerformancePercentWithCurrencyEffect: number;
|
||||||
cash: number;
|
cash: number;
|
||||||
committedFunds: number;
|
committedFunds: number;
|
||||||
dividend: number;
|
dividend: number;
|
||||||
|
@ -18,6 +18,8 @@ export interface Position {
|
|||||||
name?: string;
|
name?: string;
|
||||||
netPerformance?: number;
|
netPerformance?: number;
|
||||||
netPerformancePercentage?: number;
|
netPerformancePercentage?: number;
|
||||||
|
netPerformancePercentageWithCurrencyEffect?: number;
|
||||||
|
netPerformanceWithCurrencyEffect?: number;
|
||||||
quantity: number;
|
quantity: number;
|
||||||
symbol: string;
|
symbol: string;
|
||||||
transactionCount: number;
|
transactionCount: number;
|
||||||
|
@ -114,7 +114,7 @@
|
|||||||
*matHeaderCellDef
|
*matHeaderCellDef
|
||||||
class="justify-content-end px-1"
|
class="justify-content-end px-1"
|
||||||
mat-header-cell
|
mat-header-cell
|
||||||
mat-sort-header="netPerformancePercent"
|
mat-sort-header="netPerformancePercentWithCurrencyEffect"
|
||||||
>
|
>
|
||||||
<span class="d-none d-sm-block" i18n>Performance</span>
|
<span class="d-none d-sm-block" i18n>Performance</span>
|
||||||
<span class="d-block d-sm-none" title="Performance">±</span>
|
<span class="d-block d-sm-none" title="Performance">±</span>
|
||||||
@ -125,7 +125,11 @@
|
|||||||
[colorizeSign]="true"
|
[colorizeSign]="true"
|
||||||
[isPercent]="true"
|
[isPercent]="true"
|
||||||
[locale]="locale"
|
[locale]="locale"
|
||||||
[value]="isLoading ? undefined : element.netPerformancePercent"
|
[value]="
|
||||||
|
isLoading
|
||||||
|
? undefined
|
||||||
|
: element.netPerformancePercentWithCurrencyEffect
|
||||||
|
"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user