Remove unused timeline calculation (#2947)
This commit is contained in:
parent
8b10695353
commit
4434d0315f
@ -1,8 +0,0 @@
|
|||||||
import { TimelinePeriod } from '@ghostfolio/api/app/portfolio/interfaces/timeline-period.interface';
|
|
||||||
import Big from 'big.js';
|
|
||||||
|
|
||||||
export interface TimelineInfoInterface {
|
|
||||||
maxNetPerformance: Big;
|
|
||||||
minNetPerformance: Big;
|
|
||||||
timelinePeriods: TimelinePeriod[];
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
import Big from 'big.js';
|
|
||||||
|
|
||||||
export interface TimelinePeriod {
|
|
||||||
date: string;
|
|
||||||
grossPerformance: Big;
|
|
||||||
investment: Big;
|
|
||||||
netPerformance: Big;
|
|
||||||
value: Big;
|
|
||||||
}
|
|
@ -1,4 +1,3 @@
|
|||||||
import { TimelineInfoInterface } from '@ghostfolio/api/app/portfolio/interfaces/timeline-info.interface';
|
|
||||||
import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service';
|
import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service';
|
||||||
import { IDataGatheringItem } from '@ghostfolio/api/services/interfaces/interfaces';
|
import { IDataGatheringItem } from '@ghostfolio/api/services/interfaces/interfaces';
|
||||||
import { DATE_FORMAT, parseDate, resetHours } from '@ghostfolio/common/helper';
|
import { DATE_FORMAT, parseDate, resetHours } from '@ghostfolio/common/helper';
|
||||||
@ -20,32 +19,19 @@ import {
|
|||||||
differenceInDays,
|
differenceInDays,
|
||||||
endOfDay,
|
endOfDay,
|
||||||
format,
|
format,
|
||||||
isAfter,
|
|
||||||
isBefore,
|
isBefore,
|
||||||
isSameDay,
|
isSameDay,
|
||||||
isSameMonth,
|
isSameMonth,
|
||||||
isSameYear,
|
isSameYear,
|
||||||
max,
|
|
||||||
min,
|
|
||||||
set,
|
set,
|
||||||
subDays
|
subDays
|
||||||
} from 'date-fns';
|
} from 'date-fns';
|
||||||
import {
|
import { cloneDeep, first, isNumber, last, sortBy, uniq } from 'lodash';
|
||||||
cloneDeep,
|
|
||||||
first,
|
|
||||||
flatten,
|
|
||||||
isNumber,
|
|
||||||
last,
|
|
||||||
sortBy,
|
|
||||||
uniq
|
|
||||||
} from 'lodash';
|
|
||||||
|
|
||||||
import { CurrentRateService } from './current-rate.service';
|
import { CurrentRateService } from './current-rate.service';
|
||||||
import { CurrentPositions } from './interfaces/current-positions.interface';
|
import { CurrentPositions } from './interfaces/current-positions.interface';
|
||||||
import { GetValueObject } from './interfaces/get-value-object.interface';
|
|
||||||
import { PortfolioOrderItem } from './interfaces/portfolio-calculator.interface';
|
import { PortfolioOrderItem } from './interfaces/portfolio-calculator.interface';
|
||||||
import { PortfolioOrder } from './interfaces/portfolio-order.interface';
|
import { PortfolioOrder } from './interfaces/portfolio-order.interface';
|
||||||
import { TimelinePeriod } from './interfaces/timeline-period.interface';
|
|
||||||
import {
|
import {
|
||||||
Accuracy,
|
Accuracy,
|
||||||
TimelineSpecification
|
TimelineSpecification
|
||||||
@ -776,107 +762,6 @@ export class PortfolioCalculator {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async calculateTimeline(
|
|
||||||
timelineSpecification: TimelineSpecification[],
|
|
||||||
endDate: string
|
|
||||||
): Promise<TimelineInfoInterface> {
|
|
||||||
if (timelineSpecification.length === 0) {
|
|
||||||
return {
|
|
||||||
maxNetPerformance: new Big(0),
|
|
||||||
minNetPerformance: new Big(0),
|
|
||||||
timelinePeriods: []
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const startDate = timelineSpecification[0].start;
|
|
||||||
const start = parseDate(startDate);
|
|
||||||
const end = parseDate(endDate);
|
|
||||||
|
|
||||||
const timelinePeriodPromises: Promise<TimelineInfoInterface>[] = [];
|
|
||||||
let i = 0;
|
|
||||||
let j = -1;
|
|
||||||
for (
|
|
||||||
let currentDate = start;
|
|
||||||
!isAfter(currentDate, end);
|
|
||||||
currentDate = this.addToDate(
|
|
||||||
currentDate,
|
|
||||||
timelineSpecification[i].accuracy
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
if (this.isNextItemActive(timelineSpecification, currentDate, i)) {
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
while (
|
|
||||||
j + 1 < this.transactionPoints.length &&
|
|
||||||
!isAfter(parseDate(this.transactionPoints[j + 1].date), currentDate)
|
|
||||||
) {
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
|
|
||||||
let periodEndDate = currentDate;
|
|
||||||
if (timelineSpecification[i].accuracy === 'day') {
|
|
||||||
let nextEndDate = end;
|
|
||||||
if (j + 1 < this.transactionPoints.length) {
|
|
||||||
nextEndDate = parseDate(this.transactionPoints[j + 1].date);
|
|
||||||
}
|
|
||||||
periodEndDate = min([
|
|
||||||
addMonths(currentDate, 3),
|
|
||||||
max([currentDate, nextEndDate])
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
const timePeriodForDates = this.getTimePeriodForDate(
|
|
||||||
j,
|
|
||||||
currentDate,
|
|
||||||
endOfDay(periodEndDate)
|
|
||||||
);
|
|
||||||
currentDate = periodEndDate;
|
|
||||||
if (timePeriodForDates != null) {
|
|
||||||
timelinePeriodPromises.push(timePeriodForDates);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let minNetPerformance = new Big(0);
|
|
||||||
let maxNetPerformance = new Big(0);
|
|
||||||
|
|
||||||
const timelineInfoInterfaces: TimelineInfoInterface[] = await Promise.all(
|
|
||||||
timelinePeriodPromises
|
|
||||||
);
|
|
||||||
|
|
||||||
try {
|
|
||||||
minNetPerformance = timelineInfoInterfaces
|
|
||||||
.map((timelineInfo) => timelineInfo.minNetPerformance)
|
|
||||||
.filter((performance) => performance !== null)
|
|
||||||
.reduce((minPerformance, current) => {
|
|
||||||
if (minPerformance.lt(current)) {
|
|
||||||
return minPerformance;
|
|
||||||
} else {
|
|
||||||
return current;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
maxNetPerformance = timelineInfoInterfaces
|
|
||||||
.map((timelineInfo) => timelineInfo.maxNetPerformance)
|
|
||||||
.filter((performance) => performance !== null)
|
|
||||||
.reduce((maxPerformance, current) => {
|
|
||||||
if (maxPerformance.gt(current)) {
|
|
||||||
return maxPerformance;
|
|
||||||
} else {
|
|
||||||
return current;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch {}
|
|
||||||
|
|
||||||
const timelinePeriods = timelineInfoInterfaces.map(
|
|
||||||
(timelineInfo) => timelineInfo.timelinePeriods
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
|
||||||
maxNetPerformance,
|
|
||||||
minNetPerformance,
|
|
||||||
timelinePeriods: flatten(timelinePeriods)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private calculateOverallPerformance(positions: TimelinePosition[]) {
|
private calculateOverallPerformance(positions: TimelinePosition[]) {
|
||||||
let currentValue = new Big(0);
|
let currentValue = new Big(0);
|
||||||
let grossPerformance = new Big(0);
|
let grossPerformance = new Big(0);
|
||||||
@ -983,123 +868,6 @@ export class PortfolioCalculator {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getTimePeriodForDate(
|
|
||||||
j: number,
|
|
||||||
startDate: Date,
|
|
||||||
endDate: Date
|
|
||||||
): Promise<TimelineInfoInterface> {
|
|
||||||
let investment: Big = new Big(0);
|
|
||||||
let fees: Big = new Big(0);
|
|
||||||
|
|
||||||
const marketSymbolMap: {
|
|
||||||
[date: string]: { [symbol: string]: Big };
|
|
||||||
} = {};
|
|
||||||
if (j >= 0) {
|
|
||||||
const currencies: { [name: string]: string } = {};
|
|
||||||
const dataGatheringItems: IDataGatheringItem[] = [];
|
|
||||||
|
|
||||||
for (const item of this.transactionPoints[j].items) {
|
|
||||||
currencies[item.symbol] = item.currency;
|
|
||||||
dataGatheringItems.push({
|
|
||||||
dataSource: item.dataSource,
|
|
||||||
symbol: item.symbol
|
|
||||||
});
|
|
||||||
investment = investment.plus(item.investment);
|
|
||||||
fees = fees.plus(item.fee);
|
|
||||||
}
|
|
||||||
|
|
||||||
let marketSymbols: GetValueObject[] = [];
|
|
||||||
if (dataGatheringItems.length > 0) {
|
|
||||||
try {
|
|
||||||
const { values } = await this.currentRateService.getValues({
|
|
||||||
dataGatheringItems,
|
|
||||||
dateQuery: {
|
|
||||||
gte: startDate,
|
|
||||||
lt: endOfDay(endDate)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
marketSymbols = values;
|
|
||||||
} catch (error) {
|
|
||||||
Logger.error(
|
|
||||||
`Failed to fetch info for date ${startDate} with exception`,
|
|
||||||
error,
|
|
||||||
'PortfolioCalculator'
|
|
||||||
);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const marketSymbol of marketSymbols) {
|
|
||||||
const date = format(marketSymbol.date, DATE_FORMAT);
|
|
||||||
if (!marketSymbolMap[date]) {
|
|
||||||
marketSymbolMap[date] = {};
|
|
||||||
}
|
|
||||||
if (marketSymbol.marketPrice) {
|
|
||||||
marketSymbolMap[date][marketSymbol.symbol] = new Big(
|
|
||||||
marketSymbol.marketPrice
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const results: TimelinePeriod[] = [];
|
|
||||||
let maxNetPerformance: Big = null;
|
|
||||||
let minNetPerformance: Big = null;
|
|
||||||
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) {
|
|
||||||
if (
|
|
||||||
!marketSymbolMap[currentDateAsString]?.hasOwnProperty(item.symbol)
|
|
||||||
) {
|
|
||||||
invalid = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
value = value.plus(
|
|
||||||
item.quantity.mul(marketSymbolMap[currentDateAsString][item.symbol])
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!invalid) {
|
|
||||||
const grossPerformance = value.minus(investment);
|
|
||||||
const netPerformance = grossPerformance.minus(fees);
|
|
||||||
if (
|
|
||||||
minNetPerformance === null ||
|
|
||||||
minNetPerformance.gt(netPerformance)
|
|
||||||
) {
|
|
||||||
minNetPerformance = netPerformance;
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
maxNetPerformance === null ||
|
|
||||||
maxNetPerformance.lt(netPerformance)
|
|
||||||
) {
|
|
||||||
maxNetPerformance = netPerformance;
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = {
|
|
||||||
grossPerformance,
|
|
||||||
investment,
|
|
||||||
netPerformance,
|
|
||||||
value,
|
|
||||||
date: currentDateAsString
|
|
||||||
};
|
|
||||||
results.push(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
maxNetPerformance,
|
|
||||||
minNetPerformance,
|
|
||||||
timelinePeriods: results
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private getFactor(type: TypeOfOrder) {
|
private getFactor(type: TypeOfOrder) {
|
||||||
let factor: number;
|
let factor: number;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user