|
|
|
@ -15,11 +15,15 @@ import {
|
|
|
|
|
addDays,
|
|
|
|
|
addMonths,
|
|
|
|
|
addYears,
|
|
|
|
|
endOfDay,
|
|
|
|
|
format,
|
|
|
|
|
isAfter,
|
|
|
|
|
isBefore,
|
|
|
|
|
max,
|
|
|
|
|
min,
|
|
|
|
|
parse
|
|
|
|
|
} from 'date-fns';
|
|
|
|
|
import { flatten } from 'lodash';
|
|
|
|
|
|
|
|
|
|
const DATE_FORMAT = 'yyyy-MM-dd';
|
|
|
|
|
|
|
|
|
@ -168,7 +172,7 @@ export class PortfolioCalculator {
|
|
|
|
|
const start = dparse(startDate);
|
|
|
|
|
const end = dparse(endDate);
|
|
|
|
|
|
|
|
|
|
const timelinePeriodPromises: Promise<TimelinePeriod>[] = [];
|
|
|
|
|
const timelinePeriodPromises: Promise<TimelinePeriod[]>[] = [];
|
|
|
|
|
let i = 0;
|
|
|
|
|
let j = -1;
|
|
|
|
|
for (
|
|
|
|
@ -188,33 +192,50 @@ export class PortfolioCalculator {
|
|
|
|
|
) {
|
|
|
|
|
j++;
|
|
|
|
|
}
|
|
|
|
|
const timePeriodForDate = this.getTimePeriodForDate(j, currentDate);
|
|
|
|
|
if (timePeriodForDate != null) {
|
|
|
|
|
timelinePeriodPromises.push(timePeriodForDate);
|
|
|
|
|
|
|
|
|
|
let endDate = endOfDay(currentDate);
|
|
|
|
|
if (timelineSpecification[i].accuracy === 'day') {
|
|
|
|
|
let nextEndDate: Date = end;
|
|
|
|
|
if (j + 1 < this.transactionPoints.length) {
|
|
|
|
|
nextEndDate = dparse(this.transactionPoints[j + 1].date);
|
|
|
|
|
}
|
|
|
|
|
endDate = min([
|
|
|
|
|
addMonths(currentDate, 1),
|
|
|
|
|
max([currentDate, nextEndDate])
|
|
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
const timePeriodForDates = this.getTimePeriodForDate(
|
|
|
|
|
j,
|
|
|
|
|
currentDate,
|
|
|
|
|
endDate
|
|
|
|
|
);
|
|
|
|
|
if (timePeriodForDates != null) {
|
|
|
|
|
timelinePeriodPromises.push(timePeriodForDates);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
console.timeEnd('calculate-timeline-calculations');
|
|
|
|
|
|
|
|
|
|
console.time('calculate-timeline-periods');
|
|
|
|
|
|
|
|
|
|
const timelinePeriods: TimelinePeriod[] = await Promise.all(
|
|
|
|
|
const timelinePeriods: TimelinePeriod[][] = await Promise.all(
|
|
|
|
|
timelinePeriodPromises
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
console.timeEnd('calculate-timeline-periods');
|
|
|
|
|
console.timeEnd('calculate-timeline-total');
|
|
|
|
|
|
|
|
|
|
return timelinePeriods;
|
|
|
|
|
return flatten(timelinePeriods);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async getTimePeriodForDate(
|
|
|
|
|
j: number,
|
|
|
|
|
currentDate: Date
|
|
|
|
|
): Promise<TimelinePeriod> {
|
|
|
|
|
startDate: Date,
|
|
|
|
|
endDate: Date
|
|
|
|
|
): Promise<TimelinePeriod[]> {
|
|
|
|
|
let investment: Big = new Big(0);
|
|
|
|
|
|
|
|
|
|
let value = new Big(0);
|
|
|
|
|
const currentDateAsString = format(currentDate, DATE_FORMAT);
|
|
|
|
|
const currentDateAsString = format(startDate, DATE_FORMAT);
|
|
|
|
|
if (j >= 0) {
|
|
|
|
|
const currencies: { [name: string]: Currency } = {};
|
|
|
|
|
const symbols: string[] = [];
|
|
|
|
@ -229,15 +250,15 @@ export class PortfolioCalculator {
|
|
|
|
|
if (symbols.length > 0) {
|
|
|
|
|
try {
|
|
|
|
|
marketSymbols = await this.currentRateService.getValues({
|
|
|
|
|
dateRangeStart: resetHours(currentDate),
|
|
|
|
|
dateRangeEnd: resetHours(currentDate),
|
|
|
|
|
dateRangeStart: resetHours(startDate),
|
|
|
|
|
dateRangeEnd: resetHours(startDate),
|
|
|
|
|
symbols,
|
|
|
|
|
currencies,
|
|
|
|
|
userCurrency: this.currency
|
|
|
|
|
});
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error(
|
|
|
|
|
`failed to fetch info for date ${currentDate} with exception`,
|
|
|
|
|
`failed to fetch info for date ${startDate} with exception`,
|
|
|
|
|
e
|
|
|
|
|
);
|
|
|
|
|
return null;
|
|
|
|
@ -269,12 +290,14 @@ export class PortfolioCalculator {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
date: currentDateAsString,
|
|
|
|
|
grossPerformance: value.minus(investment),
|
|
|
|
|
investment,
|
|
|
|
|
value
|
|
|
|
|
};
|
|
|
|
|
return [
|
|
|
|
|
{
|
|
|
|
|
date: currentDateAsString,
|
|
|
|
|
grossPerformance: value.minus(investment),
|
|
|
|
|
investment,
|
|
|
|
|
value
|
|
|
|
|
}
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private getFactor(type: OrderType) {
|
|
|
|
|