Browse Source

add multi-date fetch for current values

pull/239/head
Valentin Zickner 4 years ago
committed by Thomas
parent
commit
04e03bd080
  1. 6
      apps/api/src/app/core/portfolio-calculator.spec.ts
  2. 48
      apps/api/src/app/core/portfolio-calculator.ts
  3. 4
      apps/api/src/app/portfolio/portfolio.service.ts

6
apps/api/src/app/core/portfolio-calculator.spec.ts

@ -937,7 +937,8 @@ describe('PortfolioCalculator', () => {
'2021-06-30' '2021-06-30'
); );
expect(timeline).toEqual([ expect(timeline).toEqual(
expect.objectContaining([
{ {
date: '2019-01-01', date: '2019-01-01',
grossPerformance: new Big('0'), grossPerformance: new Big('0'),
@ -1160,7 +1161,8 @@ describe('PortfolioCalculator', () => {
investment: new Big('2684.05'), investment: new Big('2684.05'),
value: new Big('3221.7') // +1.2 value: new Big('3221.7') // +1.2
} }
]); ])
);
}); });
it('with mixed portfolio', async () => { it('with mixed portfolio', async () => {

48
apps/api/src/app/core/portfolio-calculator.ts

@ -193,22 +193,23 @@ export class PortfolioCalculator {
j++; j++;
} }
let endDate = endOfDay(currentDate); let periodEndDate = currentDate;
if (timelineSpecification[i].accuracy === 'day') { if (timelineSpecification[i].accuracy === 'day') {
let nextEndDate: Date = end; let nextEndDate = end;
if (j + 1 < this.transactionPoints.length) { if (j + 1 < this.transactionPoints.length) {
nextEndDate = dparse(this.transactionPoints[j + 1].date); nextEndDate = dparse(this.transactionPoints[j + 1].date);
} }
endDate = min([ periodEndDate = min([
addMonths(currentDate, 1), addMonths(currentDate, 3),
max([currentDate, nextEndDate]) max([currentDate, nextEndDate])
]); ]);
} }
const timePeriodForDates = this.getTimePeriodForDate( const timePeriodForDates = this.getTimePeriodForDate(
j, j,
currentDate, currentDate,
endDate endOfDay(periodEndDate)
); );
currentDate = periodEndDate;
if (timePeriodForDates != null) { if (timePeriodForDates != null) {
timelinePeriodPromises.push(timePeriodForDates); timelinePeriodPromises.push(timePeriodForDates);
} }
@ -234,8 +235,9 @@ export class PortfolioCalculator {
): Promise<TimelinePeriod[]> { ): Promise<TimelinePeriod[]> {
let investment: Big = new Big(0); let investment: Big = new Big(0);
let value = new Big(0); const marketSymbolMap: {
const currentDateAsString = format(startDate, DATE_FORMAT); [date: string]: { [symbol: string]: Big };
} = {};
if (j >= 0) { if (j >= 0) {
const currencies: { [name: string]: Currency } = {}; const currencies: { [name: string]: Currency } = {};
const symbols: string[] = []; const symbols: string[] = [];
@ -250,8 +252,8 @@ export class PortfolioCalculator {
if (symbols.length > 0) { if (symbols.length > 0) {
try { try {
marketSymbols = await this.currentRateService.getValues({ marketSymbols = await this.currentRateService.getValues({
dateRangeStart: resetHours(startDate), dateRangeStart: startDate,
dateRangeEnd: resetHours(startDate), dateRangeEnd: endDate,
symbols, symbols,
currencies, currencies,
userCurrency: this.currency userCurrency: this.currency
@ -265,9 +267,6 @@ export class PortfolioCalculator {
} }
} }
const marketSymbolMap: {
[date: string]: { [symbol: string]: Big };
} = {};
for (const marketSymbol of marketSymbols) { for (const marketSymbol of marketSymbols) {
const date = format(marketSymbol.date, DATE_FORMAT); const date = format(marketSymbol.date, DATE_FORMAT);
if (!marketSymbolMap[date]) { if (!marketSymbolMap[date]) {
@ -277,27 +276,42 @@ export class PortfolioCalculator {
marketSymbol.marketPrice marketSymbol.marketPrice
); );
} }
}
const results = [];
for (
let currentDate = startDate;
isBefore(currentDate, endDate);
currentDate = addDays(currentDate, 1)
) {
let value = new Big(0);
const currentDateAsString = format(currentDate, DATE_FORMAT);
let invalid = false;
if (j >= 0) {
for (const item of this.transactionPoints[j].items) { for (const item of this.transactionPoints[j].items) {
if ( if (
!marketSymbolMap[currentDateAsString]?.hasOwnProperty(item.symbol) !marketSymbolMap[currentDateAsString]?.hasOwnProperty(item.symbol)
) { ) {
return null; invalid = true;
break;
} }
value = value.add( value = value.add(
item.quantity.mul(marketSymbolMap[currentDateAsString][item.symbol]) item.quantity.mul(marketSymbolMap[currentDateAsString][item.symbol])
); );
} }
} }
if (!invalid) {
return [ const result = {
{
date: currentDateAsString, date: currentDateAsString,
grossPerformance: value.minus(investment), grossPerformance: value.minus(investment),
investment, investment,
value value
};
results.push(result);
} }
]; }
return results;
} }
private getFactor(type: OrderType) { private getFactor(type: OrderType) {

4
apps/api/src/app/portfolio/portfolio.service.ts

@ -174,10 +174,6 @@ export class PortfolioService {
const timelineSpecification: TimelineSpecification[] = [ const timelineSpecification: TimelineSpecification[] = [
{ {
start: format(portfolioStart, dateFormat), start: format(portfolioStart, dateFormat),
accuracy: 'month'
},
{
start: format(subYears(new Date(), 1), dateFormat),
accuracy: 'day' accuracy: 'day'
} }
]; ];

Loading…
Cancel
Save