|
|
@ -211,6 +211,7 @@ export class RoaiPortfolioCalculator extends PortfolioCalculator { |
|
|
}): { [date: string]: PerformancePercentages } { |
|
|
}): { [date: string]: PerformancePercentages } { |
|
|
let grossPerformanceAtStartDate: number; |
|
|
let grossPerformanceAtStartDate: number; |
|
|
let grossPerformanceWithCurrencyEffectAtStartDate: number; |
|
|
let grossPerformanceWithCurrencyEffectAtStartDate: number; |
|
|
|
|
|
let previousDate: Date; |
|
|
let sumOfWeightedInvestments = 0; |
|
|
let sumOfWeightedInvestments = 0; |
|
|
let sumOfWeightedInvestmentsWithCurrencyEffect = 0; |
|
|
let sumOfWeightedInvestmentsWithCurrencyEffect = 0; |
|
|
let totalInvestmentDays = 0; |
|
|
let totalInvestmentDays = 0; |
|
|
@ -221,6 +222,8 @@ export class RoaiPortfolioCalculator extends PortfolioCalculator { |
|
|
} = {}; |
|
|
} = {}; |
|
|
|
|
|
|
|
|
for (const [index, historicalDataItem] of historicalDataItems.entries()) { |
|
|
for (const [index, historicalDataItem] of historicalDataItems.entries()) { |
|
|
|
|
|
const date = parseDate(historicalDataItem.date); |
|
|
|
|
|
|
|
|
// Take the values at the start date from the first day of the date
|
|
|
// Take the values at the start date from the first day of the date
|
|
|
// range
|
|
|
// range
|
|
|
if (index === 0) { |
|
|
if (index === 0) { |
|
|
@ -236,10 +239,7 @@ export class RoaiPortfolioCalculator extends PortfolioCalculator { |
|
|
// applies to each day until this chart date.
|
|
|
// applies to each day until this chart date.
|
|
|
const previousHistoricalDataItem = historicalDataItems[index - 1]; |
|
|
const previousHistoricalDataItem = historicalDataItems[index - 1]; |
|
|
|
|
|
|
|
|
const daysSincePreviousChartDate = differenceInDays( |
|
|
const daysSincePreviousChartDate = differenceInDays(date, previousDate); |
|
|
parseDate(historicalDataItem.date), |
|
|
|
|
|
parseDate(previousHistoricalDataItem.date) |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
if (previousHistoricalDataItem.totalInvestment > 0) { |
|
|
if (previousHistoricalDataItem.totalInvestment > 0) { |
|
|
sumOfWeightedInvestments += |
|
|
sumOfWeightedInvestments += |
|
|
@ -264,28 +264,22 @@ export class RoaiPortfolioCalculator extends PortfolioCalculator { |
|
|
|
|
|
|
|
|
// Add the gross performance at the start date of the range to the
|
|
|
// Add the gross performance at the start date of the range to the
|
|
|
// investment of each day. Thus the range starts with the value of its
|
|
|
// investment of each day. Thus the range starts with the value of its
|
|
|
// first day, and subsequent buy and sell activities stay included. The
|
|
|
// first day, and subsequent buy and sell activities stay included.
|
|
|
// investment of this chart date counts for this day only.
|
|
|
const averageInvestmentValue = this.getAverageInvestment({ |
|
|
const averageInvestmentValue = |
|
|
grossPerformanceAtStartDate, |
|
|
historicalDataItem.totalInvestment > 0 |
|
|
sumOfWeightedInvestments, |
|
|
? (sumOfWeightedInvestments + |
|
|
totalInvestmentDays, |
|
|
(historicalDataItem.totalInvestment + |
|
|
investment: historicalDataItem.totalInvestment |
|
|
grossPerformanceAtStartDate)) / |
|
|
}); |
|
|
(totalInvestmentDays + 1) |
|
|
|
|
|
: totalInvestmentDays > 0 |
|
|
|
|
|
? sumOfWeightedInvestments / totalInvestmentDays |
|
|
|
|
|
: 0; |
|
|
|
|
|
|
|
|
|
|
|
const averageInvestmentValueWithCurrencyEffect = |
|
|
const averageInvestmentValueWithCurrencyEffect = |
|
|
historicalDataItem.totalInvestmentValueWithCurrencyEffect > 0 |
|
|
this.getAverageInvestment({ |
|
|
? (sumOfWeightedInvestmentsWithCurrencyEffect + |
|
|
grossPerformanceAtStartDate: |
|
|
(historicalDataItem.totalInvestmentValueWithCurrencyEffect + |
|
|
grossPerformanceWithCurrencyEffectAtStartDate, |
|
|
grossPerformanceWithCurrencyEffectAtStartDate)) / |
|
|
investment: historicalDataItem.totalInvestmentValueWithCurrencyEffect, |
|
|
(totalInvestmentDaysWithCurrencyEffect + 1) |
|
|
sumOfWeightedInvestments: sumOfWeightedInvestmentsWithCurrencyEffect, |
|
|
: totalInvestmentDaysWithCurrencyEffect > 0 |
|
|
totalInvestmentDays: totalInvestmentDaysWithCurrencyEffect |
|
|
? sumOfWeightedInvestmentsWithCurrencyEffect / |
|
|
}); |
|
|
totalInvestmentDaysWithCurrencyEffect |
|
|
|
|
|
: 0; |
|
|
|
|
|
|
|
|
|
|
|
performancePercentagesByDate[historicalDataItem.date] = { |
|
|
performancePercentagesByDate[historicalDataItem.date] = { |
|
|
dividendInPercentageWithCurrencyEffect: |
|
|
dividendInPercentageWithCurrencyEffect: |
|
|
@ -303,6 +297,8 @@ export class RoaiPortfolioCalculator extends PortfolioCalculator { |
|
|
averageInvestmentValueWithCurrencyEffect |
|
|
averageInvestmentValueWithCurrencyEffect |
|
|
: 0 |
|
|
: 0 |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
previousDate = date; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return performancePercentagesByDate; |
|
|
return performancePercentagesByDate; |
|
|
@ -311,6 +307,7 @@ export class RoaiPortfolioCalculator extends PortfolioCalculator { |
|
|
protected getHoldingPerformance({ |
|
|
protected getHoldingPerformance({ |
|
|
chartDates, |
|
|
chartDates, |
|
|
dataSource, |
|
|
dataSource, |
|
|
|
|
|
daysUntilNextChartDate, |
|
|
end, |
|
|
end, |
|
|
exchangeRates, |
|
|
exchangeRates, |
|
|
marketSymbolMap, |
|
|
marketSymbolMap, |
|
|
@ -318,6 +315,7 @@ export class RoaiPortfolioCalculator extends PortfolioCalculator { |
|
|
symbol |
|
|
symbol |
|
|
}: { |
|
|
}: { |
|
|
chartDates: string[]; |
|
|
chartDates: string[]; |
|
|
|
|
|
daysUntilNextChartDate: { [date: string]: number }; |
|
|
end: Date; |
|
|
end: Date; |
|
|
exchangeRates: { [dateString: string]: number }; |
|
|
exchangeRates: { [dateString: string]: number }; |
|
|
marketSymbolMap: { |
|
|
marketSymbolMap: { |
|
|
@ -661,7 +659,6 @@ export class RoaiPortfolioCalculator extends PortfolioCalculator { |
|
|
|
|
|
|
|
|
let average = new Big(0); |
|
|
let average = new Big(0); |
|
|
let dayCount = 0; |
|
|
let dayCount = 0; |
|
|
let nextChartDateString: string; |
|
|
|
|
|
|
|
|
|
|
|
for (let i = chartDates.length - 1; i >= 0; i -= 1) { |
|
|
for (let i = chartDates.length - 1; i >= 0; i -= 1) { |
|
|
const date = chartDates[i]; |
|
|
const date = chartDates[i]; |
|
|
@ -672,15 +669,16 @@ export class RoaiPortfolioCalculator extends PortfolioCalculator { |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const isLastChartDateOfRange = |
|
|
|
|
|
i === chartDates.length - 1 || chartDates[i + 1] > rangeEndDateString; |
|
|
|
|
|
|
|
|
// The chart dates are not evenly spaced, and the investment changes
|
|
|
// The chart dates are not evenly spaced, and the investment changes
|
|
|
// on a chart date only. Thus the investment of a chart date applies to
|
|
|
// on a chart date only. Thus the investment of a chart date applies to
|
|
|
// each day until the next chart date. The investment of the last chart
|
|
|
// each day until the next chart date. The investment of the last chart
|
|
|
// date of the range counts for this day only.
|
|
|
// date of the range counts for this day only.
|
|
|
const daysUntilNextChartDate = nextChartDateString |
|
|
const investmentDays = isLastChartDateOfRange |
|
|
? differenceInDays(parseDate(nextChartDateString), parseDate(date)) |
|
|
? 1 |
|
|
: 1; |
|
|
: daysUntilNextChartDate[date]; |
|
|
|
|
|
|
|
|
nextChartDateString = date; |
|
|
|
|
|
|
|
|
|
|
|
if ( |
|
|
if ( |
|
|
investmentValuesAccumulatedWithCurrencyEffect[date] instanceof Big && |
|
|
investmentValuesAccumulatedWithCurrencyEffect[date] instanceof Big && |
|
|
@ -689,10 +687,10 @@ export class RoaiPortfolioCalculator extends PortfolioCalculator { |
|
|
average = average.add( |
|
|
average = average.add( |
|
|
investmentValuesAccumulatedWithCurrencyEffect[date] |
|
|
investmentValuesAccumulatedWithCurrencyEffect[date] |
|
|
.add(grossPerformanceAtDateRangeStartWithCurrencyEffect) |
|
|
.add(grossPerformanceAtDateRangeStartWithCurrencyEffect) |
|
|
.mul(daysUntilNextChartDate) |
|
|
.mul(investmentDays) |
|
|
); |
|
|
); |
|
|
|
|
|
|
|
|
dayCount += daysUntilNextChartDate; |
|
|
dayCount += investmentDays; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -793,4 +791,29 @@ export class RoaiPortfolioCalculator extends PortfolioCalculator { |
|
|
protected getPerformanceCalculationType() { |
|
|
protected getPerformanceCalculationType() { |
|
|
return PerformanceCalculationType.ROAI; |
|
|
return PerformanceCalculationType.ROAI; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private getAverageInvestment({ |
|
|
|
|
|
grossPerformanceAtStartDate, |
|
|
|
|
|
investment, |
|
|
|
|
|
sumOfWeightedInvestments, |
|
|
|
|
|
totalInvestmentDays |
|
|
|
|
|
}: { |
|
|
|
|
|
grossPerformanceAtStartDate: number; |
|
|
|
|
|
investment: number; |
|
|
|
|
|
sumOfWeightedInvestments: number; |
|
|
|
|
|
totalInvestmentDays: number; |
|
|
|
|
|
}) { |
|
|
|
|
|
// The investment of the current chart date counts for this day only
|
|
|
|
|
|
if (investment > 0) { |
|
|
|
|
|
return ( |
|
|
|
|
|
(sumOfWeightedInvestments + |
|
|
|
|
|
(investment + grossPerformanceAtStartDate)) / |
|
|
|
|
|
(totalInvestmentDays + 1) |
|
|
|
|
|
); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return totalInvestmentDays > 0 |
|
|
|
|
|
? sumOfWeightedInvestments / totalInvestmentDays |
|
|
|
|
|
: 0; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|