diff --git a/apps/api/src/app/core/portfolio-calculator.ts b/apps/api/src/app/core/portfolio-calculator.ts index 11d9297b7..3bd84a5b0 100644 --- a/apps/api/src/app/core/portfolio-calculator.ts +++ b/apps/api/src/app/core/portfolio-calculator.ts @@ -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[] = []; + const timelinePeriodPromises: Promise[] = []; 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 { + startDate: Date, + endDate: Date + ): Promise { 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) {