|
@ -44,7 +44,7 @@ import { |
|
|
min, |
|
|
min, |
|
|
subDays |
|
|
subDays |
|
|
} from 'date-fns'; |
|
|
} from 'date-fns'; |
|
|
import { first, last, uniq, uniqBy } from 'lodash'; |
|
|
import { first, last, sum, uniq, uniqBy } from 'lodash'; |
|
|
|
|
|
|
|
|
export abstract class PortfolioCalculator { |
|
|
export abstract class PortfolioCalculator { |
|
|
protected static readonly ENABLE_LOGGING = false; |
|
|
protected static readonly ENABLE_LOGGING = false; |
|
@ -99,6 +99,8 @@ export abstract class PortfolioCalculator { |
|
|
this.dateRange = dateRange; |
|
|
this.dateRange = dateRange; |
|
|
this.exchangeRateDataService = exchangeRateDataService; |
|
|
this.exchangeRateDataService = exchangeRateDataService; |
|
|
|
|
|
|
|
|
|
|
|
let dateOfFirstActivity = new Date(); |
|
|
|
|
|
|
|
|
this.activities = activities |
|
|
this.activities = activities |
|
|
.map( |
|
|
.map( |
|
|
({ |
|
|
({ |
|
@ -110,6 +112,10 @@ export abstract class PortfolioCalculator { |
|
|
type, |
|
|
type, |
|
|
unitPrice |
|
|
unitPrice |
|
|
}) => { |
|
|
}) => { |
|
|
|
|
|
if (isBefore(date, dateOfFirstActivity)) { |
|
|
|
|
|
dateOfFirstActivity = date; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (isAfter(date, new Date(Date.now()))) { |
|
|
if (isAfter(date, new Date(Date.now()))) { |
|
|
// Adapt date to today if activity is in future (e.g. liability)
|
|
|
// Adapt date to today if activity is in future (e.g. liability)
|
|
|
// to include it in the interval
|
|
|
// to include it in the interval
|
|
@ -132,10 +138,13 @@ export abstract class PortfolioCalculator { |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
this.redisCacheService = redisCacheService; |
|
|
this.redisCacheService = redisCacheService; |
|
|
this.useCache = useCache; |
|
|
this.useCache = false; // useCache;
|
|
|
this.userId = userId; |
|
|
this.userId = userId; |
|
|
|
|
|
|
|
|
const { endDate, startDate } = getInterval(dateRange); |
|
|
const { endDate, startDate } = getInterval( |
|
|
|
|
|
'max', |
|
|
|
|
|
subDays(dateOfFirstActivity, 1) |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
this.endDate = endDate; |
|
|
this.endDate = endDate; |
|
|
this.startDate = startDate; |
|
|
this.startDate = startDate; |
|
@ -1082,6 +1091,57 @@ export abstract class PortfolioCalculator { |
|
|
return this.snapshot; |
|
|
return this.snapshot; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public async getPerformance({ end, start }) { |
|
|
|
|
|
await this.snapshotPromise; |
|
|
|
|
|
|
|
|
|
|
|
const { chartData } = this.snapshot; |
|
|
|
|
|
|
|
|
|
|
|
const newChartData = []; |
|
|
|
|
|
|
|
|
|
|
|
let netPerformanceAtStartDate; |
|
|
|
|
|
let netPerformanceWithCurrencyEffectAtStartDate; |
|
|
|
|
|
let netPerformanceInPercentageWithCurrencyEffectAtStartDate; |
|
|
|
|
|
let investmentValuesWithCurrencyEffect = []; |
|
|
|
|
|
|
|
|
|
|
|
for (let historicalDataItem of chartData) { |
|
|
|
|
|
if ( |
|
|
|
|
|
!isBefore(parseDate(historicalDataItem.date), start) && |
|
|
|
|
|
!isAfter(parseDate(historicalDataItem.date), end) |
|
|
|
|
|
) { |
|
|
|
|
|
if (!netPerformanceAtStartDate) { |
|
|
|
|
|
netPerformanceAtStartDate = historicalDataItem.netPerformance; |
|
|
|
|
|
|
|
|
|
|
|
netPerformanceWithCurrencyEffectAtStartDate = |
|
|
|
|
|
historicalDataItem.netPerformanceWithCurrencyEffect; |
|
|
|
|
|
|
|
|
|
|
|
netPerformanceInPercentageWithCurrencyEffectAtStartDate = |
|
|
|
|
|
historicalDataItem.netPerformanceInPercentageWithCurrencyEffect; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
investmentValuesWithCurrencyEffect.push( |
|
|
|
|
|
historicalDataItem.investmentValueWithCurrencyEffect |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
// TODO: Normalize remaining metrics
|
|
|
|
|
|
newChartData.push({ |
|
|
|
|
|
...historicalDataItem, |
|
|
|
|
|
netPerformance: |
|
|
|
|
|
historicalDataItem.netPerformance - netPerformanceAtStartDate, |
|
|
|
|
|
netPerformanceWithCurrencyEffect: |
|
|
|
|
|
historicalDataItem.netPerformanceWithCurrencyEffect - |
|
|
|
|
|
netPerformanceWithCurrencyEffectAtStartDate, |
|
|
|
|
|
netPerformanceInPercentageWithCurrencyEffect: |
|
|
|
|
|
historicalDataItem.netPerformanceWithCurrencyEffect / |
|
|
|
|
|
// TODO: This is not correct yet
|
|
|
|
|
|
(sum(investmentValuesWithCurrencyEffect) / |
|
|
|
|
|
investmentValuesWithCurrencyEffect.length) |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return newChartData; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
public getStartDate() { |
|
|
public getStartDate() { |
|
|
let firstAccountBalanceDate: Date; |
|
|
let firstAccountBalanceDate: Date; |
|
|
let firstActivityDate: Date; |
|
|
let firstActivityDate: Date; |
|
|