Browse Source

Fix Constant portfolio Rate of return

pull/5027/head
Dan 1 year ago
parent
commit
969aa2ae4a
  1. 96
      apps/api/src/app/portfolio/calculator/constantPortfolioReturn/portfolio-calculator.ts
  2. 17
      apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts

96
apps/api/src/app/portfolio/calculator/constantPortfolioReturn/portfolio-calculator.ts

@ -55,52 +55,40 @@ export class CPRPortfolioCalculator extends TWRPortfolioCalculator {
if (!withTimeWeightedReturn) { if (!withTimeWeightedReturn) {
return item; return item;
} else { } else {
let itemResult = await item;
let dates = itemResult.map((item) => parseDate(item.date));
let timeWeighted = await this.getTimeWeightedChartData({ let timeWeighted = await this.getTimeWeightedChartData({
step, dates
end: endDate,
start: startDate
}); });
return item.then((data) => { return itemResult.map((item) => {
return data.map((item) => { let timeWeightedItem = timeWeighted.find(
let timeWeightedItem = timeWeighted.find( (timeWeightedItem) => timeWeightedItem.date === item.date
(timeWeightedItem) => timeWeightedItem.date === item.date );
); if (timeWeightedItem) {
if (timeWeightedItem) { item.timeWeightedPerformance =
item.timeWeightedPerformance = timeWeightedItem.netPerformanceInPercentage;
timeWeightedItem.netPerformanceInPercentage; item.timeWeightedPerformanceWithCurrencyEffect =
item.timeWeightedPerformanceWithCurrencyEffect = timeWeightedItem.netPerformanceInPercentageWithCurrencyEffect;
timeWeightedItem.netPerformanceInPercentageWithCurrencyEffect; }
}
return item;
return item;
});
}); });
} }
} }
@LogPerformance @LogPerformance
private async getTimeWeightedChartData({ private async getTimeWeightedChartData({
end = new Date(Date.now()), dates
start,
step = 1
}: { }: {
end?: Date; dates?: Date[];
start: Date;
step?: number;
}): Promise<HistoricalDataItem[]> { }): Promise<HistoricalDataItem[]> {
dates = dates.sort((a, b) => a.getTime() - b.getTime());
const start = dates[0];
const end = dates[dates.length - 1];
let marketMapTask = this.computeMarketMap({ gte: start, lte: end }); let marketMapTask = this.computeMarketMap({ gte: start, lte: end });
const timelineHoldings = await this.getHoldings(start, end); const timelineHoldings = await this.getHoldings(start, end);
const calculationDates = Object.keys(timelineHoldings)
.filter((date) => {
let parsed = parseDate(date);
return (
isAfter(parsed, subDays(start, 1)) &&
isBefore(parsed, addDays(end, 1))
);
})
.sort((a, b) => parseDate(a).getTime() - parseDate(b).getTime());
let data: HistoricalDataItem[] = []; let data: HistoricalDataItem[] = [];
const startString = format(start, DATE_FORMAT); const startString = format(start, DATE_FORMAT);
@ -135,9 +123,9 @@ export class CPRPortfolioCalculator extends TWRPortfolioCalculator {
let previousNetPerformanceInPercentage = new Big(0); let previousNetPerformanceInPercentage = new Big(0);
let previousNetPerformanceInPercentageWithCurrencyEffect = new Big(0); let previousNetPerformanceInPercentageWithCurrencyEffect = new Big(0);
for (let i = 1; i < calculationDates.length; i++) { for (let i = 1; i < dates.length; i++) {
const date = calculationDates[i]; const date = format(dates[i], DATE_FORMAT);
const previousDate = calculationDates[i - 1]; const previousDate = format(dates[i - 1], DATE_FORMAT);
const holdings = timelineHoldings[previousDate]; const holdings = timelineHoldings[previousDate];
let newTotalInvestment = new Big(0); let newTotalInvestment = new Big(0);
let netPerformanceInPercentage = new Big(0); let netPerformanceInPercentage = new Big(0);
@ -158,24 +146,28 @@ export class CPRPortfolioCalculator extends TWRPortfolioCalculator {
netPerformanceInPercentageWithCurrencyEffect, netPerformanceInPercentageWithCurrencyEffect,
newTotalInvestment newTotalInvestment
)); ));
totalInvestment = newTotalInvestment;
} }
totalInvestment = newTotalInvestment;
previousNetPerformanceInPercentage = previousNetPerformanceInPercentage = previousNetPerformanceInPercentage
previousNetPerformanceInPercentage.mul( .plus(1)
netPerformanceInPercentage.plus(1) .mul(netPerformanceInPercentage.plus(1))
); .minus(1);
previousNetPerformanceInPercentageWithCurrencyEffect = previousNetPerformanceInPercentageWithCurrencyEffect =
previousNetPerformanceInPercentageWithCurrencyEffect.mul( previousNetPerformanceInPercentageWithCurrencyEffect
netPerformanceInPercentageWithCurrencyEffect.plus(1) .plus(1)
); .mul(netPerformanceInPercentageWithCurrencyEffect.plus(1))
.minus(1);
data.push({ data.push({
date, date,
netPerformanceInPercentage: netPerformanceInPercentage: previousNetPerformanceInPercentage
previousNetPerformanceInPercentage.toNumber(), .mul(100)
.toNumber(),
netPerformanceInPercentageWithCurrencyEffect: netPerformanceInPercentageWithCurrencyEffect:
previousNetPerformanceInPercentageWithCurrencyEffect.toNumber() previousNetPerformanceInPercentageWithCurrencyEffect
.mul(100)
.toNumber()
}); });
} }
@ -210,8 +202,9 @@ export class CPRPortfolioCalculator extends TWRPortfolioCalculator {
if (previousHolding.eq(0)) { if (previousHolding.eq(0)) {
return { return {
netPerformanceInPercentage: new Big(0), netPerformanceInPercentage: netPerformanceInPercentage,
netPerformanceInPercentageWithCurrencyEffect: new Big(0), netPerformanceInPercentageWithCurrencyEffect:
netPerformanceInPercentageWithCurrencyEffect,
newTotalInvestment: newTotalInvestment.plus( newTotalInvestment: newTotalInvestment.plus(
timelineHoldings[date][holding].mul(priceInBaseCurrency) timelineHoldings[date][holding].mul(priceInBaseCurrency)
) )
@ -223,8 +216,9 @@ export class CPRPortfolioCalculator extends TWRPortfolioCalculator {
'PortfolioCalculator' 'PortfolioCalculator'
); );
return { return {
netPerformanceInPercentage: new Big(0), netPerformanceInPercentage: netPerformanceInPercentage,
netPerformanceInPercentageWithCurrencyEffect: new Big(0), netPerformanceInPercentageWithCurrencyEffect:
netPerformanceInPercentageWithCurrencyEffect,
newTotalInvestment: newTotalInvestment.plus( newTotalInvestment: newTotalInvestment.plus(
timelineHoldings[date][holding].mul(priceInBaseCurrency) timelineHoldings[date][holding].mul(priceInBaseCurrency)
) )
@ -242,7 +236,7 @@ export class CPRPortfolioCalculator extends TWRPortfolioCalculator {
: new Big(0); : new Big(0);
const portfolioWeight = totalInvestment.toNumber() const portfolioWeight = totalInvestment.toNumber()
? previousHolding.mul(previousPriceInBaseCurrency).div(totalInvestment) ? previousHolding.mul(previousPriceInBaseCurrency).div(totalInvestment)
: 0; : new Big(0);
netPerformanceInPercentage = netPerformanceInPercentage.plus( netPerformanceInPercentage = netPerformanceInPercentage.plus(
currentPrice.div(previousPrice).minus(1).mul(portfolioWeight) currentPrice.div(previousPrice).minus(1).mul(portfolioWeight)

17
apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts

@ -337,24 +337,9 @@ export class AnalysisPageComponent implements OnDestroy, OnInit {
value: netPerformanceInPercentageWithCurrencyEffect value: netPerformanceInPercentageWithCurrencyEffect
}); });
if ((this.timeWeightedPerformance ?? 'N') !== 'N') { if ((this.timeWeightedPerformance ?? 'N') !== 'N') {
let lastPerformance = 0;
if (index > 0) {
lastPerformance = new Big(
chart[index - 1].timeWeightedPerformance
)
.div(100)
.plus(1)
.mul(
new Big(chart[index].timeWeightedPerformance).div(100).plus(1)
)
.minus(1)
.mul(100)
.toNumber();
}
chart[index].timeWeightedPerformance = lastPerformance;
this.performanceDataItemsTimeWeightedInPercentage.push({ this.performanceDataItemsTimeWeightedInPercentage.push({
date, date,
value: lastPerformance value: chart[index].timeWeightedPerformance
}); });
} }
} }

Loading…
Cancel
Save