| 
						
						
							
								
							
						
						
					 | 
					@ -3,7 +3,7 @@ import { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					  GetValueObject | 
					 | 
					 | 
					  GetValueObject | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					} from '@ghostfolio/api/app/core/current-rate.service'; | 
					 | 
					 | 
					} from '@ghostfolio/api/app/core/current-rate.service'; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					import { OrderType } from '@ghostfolio/api/models/order-type'; | 
					 | 
					 | 
					import { OrderType } from '@ghostfolio/api/models/order-type'; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					import { resetHours } from '@ghostfolio/common/helper'; | 
					 | 
					 | 
					import { DATE_FORMAT, parseDate, resetHours } from '@ghostfolio/common/helper'; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					import { TimelinePosition } from '@ghostfolio/common/interfaces'; | 
					 | 
					 | 
					import { TimelinePosition } from '@ghostfolio/common/interfaces'; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					import { Currency } from '@prisma/client'; | 
					 | 
					 | 
					import { Currency } from '@prisma/client'; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					import Big from 'big.js'; | 
					 | 
					 | 
					import Big from 'big.js'; | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					@ -17,17 +17,10 @@ import { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					  isBefore, | 
					 | 
					 | 
					  isBefore, | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					  max, | 
					 | 
					 | 
					  max, | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					  min, | 
					 | 
					 | 
					  min, | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					  parse, | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					  subDays | 
					 | 
					 | 
					  subDays | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					} from 'date-fns'; | 
					 | 
					 | 
					} from 'date-fns'; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					import { flatten } from 'lodash'; | 
					 | 
					 | 
					import { flatten } from 'lodash'; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					const DATE_FORMAT = 'yyyy-MM-dd'; | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					function dparse(date: string) { | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					  return parse(date, DATE_FORMAT, new Date()); | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					export class PortfolioCalculator { | 
					 | 
					 | 
					export class PortfolioCalculator { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					  private transactionPoints: TransactionPoint[]; | 
					 | 
					 | 
					  private transactionPoints: TransactionPoint[]; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					@ -115,7 +108,7 @@ export class PortfolioCalculator { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    return this.transactionPoints; | 
					 | 
					 | 
					    return this.transactionPoints; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					  } | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					  public async getCurrentPositions(): Promise<{ | 
					 | 
					 | 
					  public async getCurrentPositions(start: Date): Promise<{ | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					    [symbol: string]: TimelinePosition; | 
					 | 
					 | 
					    [symbol: string]: TimelinePosition; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					  }> { | 
					 | 
					 | 
					  }> { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    if (!this.transactionPoints?.length) { | 
					 | 
					 | 
					    if (!this.transactionPoints?.length) { | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					@ -126,29 +119,117 @@ export class PortfolioCalculator { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					      this.transactionPoints[this.transactionPoints.length - 1]; | 
					 | 
					 | 
					      this.transactionPoints[this.transactionPoints.length - 1]; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    const result: { [symbol: string]: TimelinePosition } = {}; | 
					 | 
					 | 
					    const result: { [symbol: string]: TimelinePosition } = {}; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					    const marketValues = await this.getMarketValues( | 
					 | 
					 | 
					    // use Date.now() to use the mock for today
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					      lastTransactionPoint, | 
					 | 
					 | 
					    const today = new Date(Date.now()); | 
				
			
			
				
				
			
		
	
		
		
			
				
					 | 
					 | 
					      resetHours(subDays(new Date(), 3)), | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					      endOfDay(new Date()) | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    ); | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					    for (const item of lastTransactionPoint.items) { | 
					 | 
					 | 
					    let firstTransactionPoint: TransactionPoint = null; | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					      const marketValue = marketValues[item.symbol]; | 
					 | 
					 | 
					    let firstIndex = this.transactionPoints.length; | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					      const grossPerformance = marketValue | 
					 | 
					 | 
					    const dates = []; | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					        ? new Big(marketValue.marketPrice) | 
					 | 
					 | 
					    const symbols = new Set<string>(); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    const currencies: { [symbol: string]: Currency } = {}; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    dates.push(resetHours(start)); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    for (const item of this.transactionPoints[firstIndex - 1].items) { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					      symbols.add(item.symbol); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					      currencies[item.symbol] = item.currency; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    for (let i = 0; i < this.transactionPoints.length; i++) { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					      if ( | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        !isBefore(parseDate(this.transactionPoints[i].date), start) && | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        firstTransactionPoint === null | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					      ) { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        firstTransactionPoint = this.transactionPoints[i]; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        firstIndex = i; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					      } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					      if (firstTransactionPoint !== null) { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        dates.push(resetHours(parseDate(this.transactionPoints[i].date))); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					      } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    const yesterday = resetHours(subDays(today, 1)); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    if (dates.indexOf(yesterday) === -1) { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					      dates.push(yesterday); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    dates.push(resetHours(today)); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    const marketSymbols = await this.currentRateService.getValues({ | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					      currencies, | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					      dateQuery: { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        in: dates | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					      }, | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					      symbols: Array.from(symbols), | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					      userCurrency: this.currency | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    }); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    const marketSymbolMap: { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					      [date: string]: { [symbol: string]: Big }; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    } = {}; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    for (const marketSymbol of marketSymbols) { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					      const date = format(marketSymbol.date, DATE_FORMAT); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					      if (!marketSymbolMap[date]) { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        marketSymbolMap[date] = {}; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					      } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					      marketSymbolMap[date][marketSymbol.symbol] = new Big( | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        marketSymbol.marketPrice | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					      ); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    const startString = format(start, DATE_FORMAT); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    const holdingPeriodReturns: { [symbol: string]: Big } = {}; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    const grossPerformance: { [symbol: string]: Big } = {}; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    let todayString = format(today, DATE_FORMAT); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    // in case no symbols are there for today, use yesterday
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    if (!marketSymbolMap[todayString]) { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					      todayString = format(subDays(today, 1), DATE_FORMAT); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    if (firstIndex > 0) { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					      firstIndex--; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    for (let i = firstIndex; i < this.transactionPoints.length; i++) { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					      const currentDate = | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        i === firstIndex ? startString : this.transactionPoints[i].date; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					      const nextDate = | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        i + 1 < this.transactionPoints.length | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					          ? this.transactionPoints[i + 1].date | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					          : todayString; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					      const items = this.transactionPoints[i].items; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					      for (const item of items) { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        let oldHoldingPeriodReturn = holdingPeriodReturns[item.symbol]; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        if (!oldHoldingPeriodReturn) { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					          oldHoldingPeriodReturn = new Big(1); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        holdingPeriodReturns[item.symbol] = oldHoldingPeriodReturn.mul( | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					          marketSymbolMap[nextDate][item.symbol].div( | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            marketSymbolMap[currentDate][item.symbol] | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					          ) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        ); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        let oldGrossPerformance = grossPerformance[item.symbol]; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        if (!oldGrossPerformance) { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					          oldGrossPerformance = new Big(0); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        grossPerformance[item.symbol] = oldGrossPerformance.plus( | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					          marketSymbolMap[nextDate][item.symbol] | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            .minus(marketSymbolMap[currentDate][item.symbol]) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            .mul(item.quantity) | 
					 | 
					 | 
					            .mul(item.quantity) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					            .minus(item.investment) | 
					 | 
					 | 
					        ); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					        : null; | 
					 | 
					 | 
					      } | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    for (const item of lastTransactionPoint.items) { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					      const marketValue = marketSymbolMap[todayString][item.symbol]; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					      result[item.symbol] = { | 
					 | 
					 | 
					      result[item.symbol] = { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        averagePrice: item.investment.div(item.quantity), | 
					 | 
					 | 
					        averagePrice: item.investment.div(item.quantity), | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        currency: item.currency, | 
					 | 
					 | 
					        currency: item.currency, | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        firstBuyDate: item.firstBuyDate, | 
					 | 
					 | 
					        firstBuyDate: item.firstBuyDate, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					        grossPerformance, | 
					 | 
					 | 
					        grossPerformance: grossPerformance[item.symbol] ?? null, | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					        grossPerformancePercentage: marketValue | 
					 | 
					 | 
					        grossPerformancePercentage: holdingPeriodReturns[item.symbol] | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					          ? grossPerformance.div(item.investment) | 
					 | 
					 | 
					          ? holdingPeriodReturns[item.symbol].minus(1) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					          : null, | 
					 | 
					 | 
					          : null, | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        investment: item.investment, | 
					 | 
					 | 
					        investment: item.investment, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					        marketPrice: marketValue?.marketPrice, | 
					 | 
					 | 
					        marketPrice: marketValue.toNumber(), | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					        name: item.name, | 
					 | 
					 | 
					        name: item.name, | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        quantity: item.quantity, | 
					 | 
					 | 
					        quantity: item.quantity, | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        symbol: item.symbol, | 
					 | 
					 | 
					        symbol: item.symbol, | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					@ -170,8 +251,8 @@ export class PortfolioCalculator { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    console.time('calculate-timeline-calculations'); | 
					 | 
					 | 
					    console.time('calculate-timeline-calculations'); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    const startDate = timelineSpecification[0].start; | 
					 | 
					 | 
					    const startDate = timelineSpecification[0].start; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					    const start = dparse(startDate); | 
					 | 
					 | 
					    const start = parseDate(startDate); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					    const end = dparse(endDate); | 
					 | 
					 | 
					    const end = parseDate(endDate); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    const timelinePeriodPromises: Promise<TimelinePeriod[]>[] = []; | 
					 | 
					 | 
					    const timelinePeriodPromises: Promise<TimelinePeriod[]>[] = []; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    let i = 0; | 
					 | 
					 | 
					    let i = 0; | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					@ -189,7 +270,7 @@ export class PortfolioCalculator { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					      } | 
					 | 
					 | 
					      } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					      while ( | 
					 | 
					 | 
					      while ( | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        j + 1 < this.transactionPoints.length && | 
					 | 
					 | 
					        j + 1 < this.transactionPoints.length && | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					        !isAfter(dparse(this.transactionPoints[j + 1].date), currentDate) | 
					 | 
					 | 
					        !isAfter(parseDate(this.transactionPoints[j + 1].date), currentDate) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					      ) { | 
					 | 
					 | 
					      ) { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        j++; | 
					 | 
					 | 
					        j++; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					      } | 
					 | 
					 | 
					      } | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					@ -198,7 +279,7 @@ export class PortfolioCalculator { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					      if (timelineSpecification[i].accuracy === 'day') { | 
					 | 
					 | 
					      if (timelineSpecification[i].accuracy === 'day') { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        let nextEndDate = end; | 
					 | 
					 | 
					        let nextEndDate = end; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        if (j + 1 < this.transactionPoints.length) { | 
					 | 
					 | 
					        if (j + 1 < this.transactionPoints.length) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					          nextEndDate = dparse(this.transactionPoints[j + 1].date); | 
					 | 
					 | 
					          nextEndDate = parseDate(this.transactionPoints[j + 1].date); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					        } | 
					 | 
					 | 
					        } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        periodEndDate = min([ | 
					 | 
					 | 
					        periodEndDate = min([ | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					          addMonths(currentDate, 3), | 
					 | 
					 | 
					          addMonths(currentDate, 3), | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					@ -242,8 +323,10 @@ export class PortfolioCalculator { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					      currencies[item.symbol] = item.currency; | 
					 | 
					 | 
					      currencies[item.symbol] = item.currency; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    } | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    const values = await this.currentRateService.getValues({ | 
					 | 
					 | 
					    const values = await this.currentRateService.getValues({ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					      dateRangeStart, | 
					 | 
					 | 
					      dateQuery: { | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					      dateRangeEnd, | 
					 | 
					 | 
					        gte: dateRangeStart, | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        lt: endOfDay(dateRangeEnd) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					      }, | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					      symbols, | 
					 | 
					 | 
					      symbols, | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					      currencies, | 
					 | 
					 | 
					      currencies, | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					      userCurrency: this.currency | 
					 | 
					 | 
					      userCurrency: this.currency | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					@ -280,8 +363,10 @@ export class PortfolioCalculator { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					      if (symbols.length > 0) { | 
					 | 
					 | 
					      if (symbols.length > 0) { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        try { | 
					 | 
					 | 
					        try { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					          marketSymbols = await this.currentRateService.getValues({ | 
					 | 
					 | 
					          marketSymbols = await this.currentRateService.getValues({ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					            dateRangeStart: startDate, | 
					 | 
					 | 
					            dateQuery: { | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					            dateRangeEnd: endDate, | 
					 | 
					 | 
					              gte: startDate, | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					              lt: endOfDay(endDate) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            }, | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            symbols, | 
					 | 
					 | 
					            symbols, | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            currencies, | 
					 | 
					 | 
					            currencies, | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            userCurrency: this.currency | 
					 | 
					 | 
					            userCurrency: this.currency | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					@ -376,7 +461,7 @@ export class PortfolioCalculator { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					  ) { | 
					 | 
					 | 
					  ) { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    return ( | 
					 | 
					 | 
					    return ( | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					      i + 1 < timelineSpecification.length && | 
					 | 
					 | 
					      i + 1 < timelineSpecification.length && | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					      !isBefore(currentDate, dparse(timelineSpecification[i + 1].start)) | 
					 | 
					 | 
					      !isBefore(currentDate, parseDate(timelineSpecification[i + 1].start)) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					    ); | 
					 | 
					 | 
					    ); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					  } | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					} | 
					 | 
					 | 
					} | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
					
  |