add draft integration of new portfolio calculator to chart

pull/239/head
Valentin Zickner 3 years ago committed by Thomas
parent 19bcd601d1
commit cfee6c1ddd

@ -18,6 +18,8 @@ import { Module } from '@nestjs/common';
import { PortfolioController } from './portfolio.controller';
import { PortfolioService } from './portfolio.service';
import { CurrentRateService } from '@ghostfolio/api/app/core/current-rate.service';
import { MarketDataService } from '@ghostfolio/api/app/core/market-data.service';
@Module({
imports: [RedisCacheModule],
@ -26,6 +28,7 @@ import { PortfolioService } from './portfolio.service';
AccountService,
AlphaVantageService,
CacheService,
CurrentRateService,
ConfigurationService,
DataGatheringService,
DataProviderService,
@ -37,6 +40,7 @@ import { PortfolioService } from './portfolio.service';
PrismaService,
RakutenRapidApiService,
RulesService,
MarketDataService,
UserService,
YahooFinanceService
]

@ -26,11 +26,15 @@ import {
getYear,
isAfter,
isSameDay,
max,
parse,
parseISO,
setDate,
setDayOfYear,
setMonth,
sub
sub,
subDays,
subYears
} from 'date-fns';
import { isEmpty } from 'lodash';
import * as roundTo from 'round-to';
@ -39,6 +43,14 @@ import {
HistoricalDataItem,
PortfolioPositionDetail
} from './interfaces/portfolio-position-detail.interface';
import {
PortfolioCalculator,
PortfolioOrder,
TimelineSpecification
} from '@ghostfolio/api/app/core/portfolio-calculator';
import { CurrentRateService } from '@ghostfolio/api/app/core/current-rate.service';
import Big from 'big.js';
import { port } from 'envalid';
@Injectable()
export class PortfolioService {
@ -51,7 +63,8 @@ export class PortfolioService {
private readonly redisCacheService: RedisCacheService,
@Inject(REQUEST) private readonly request: RequestWithUser,
private readonly rulesService: RulesService,
private readonly userService: UserService
private readonly userService: UserService,
private readonly currentRateService: CurrentRateService
) {}
public async createPortfolio(aUserId: string): Promise<Portfolio> {
@ -148,7 +161,8 @@ export class PortfolioService {
impersonationUserId || this.request.user.id
);
if (portfolio.getOrders().length <= 0) {
const orders = portfolio.getOrders();
if (orders.length <= 0) {
return [];
}
@ -157,10 +171,14 @@ export class PortfolioService {
portfolio.getMinDate()
);
return portfolio
.get()
const portfolioCalculator = new PortfolioCalculator(
this.currentRateService,
this.request.user.Settings.currency
);
const portfolioOrders: PortfolioOrder[] = orders
.filter((portfolioItem) => {
if (isAfter(parseISO(portfolioItem.date), endOfToday())) {
if (isAfter(parseISO(portfolioItem.getDate()), endOfToday())) {
// Filter out future dates
return false;
}
@ -170,18 +188,70 @@ export class PortfolioService {
}
return (
isSameDay(parseISO(portfolioItem.date), dateRangeDate) ||
isAfter(parseISO(portfolioItem.date), dateRangeDate)
isSameDay(parseISO(portfolioItem.getDate()), dateRangeDate) ||
isAfter(parseISO(portfolioItem.getDate()), dateRangeDate)
);
})
.map((portfolioItem) => {
return {
date: format(parseISO(portfolioItem.date), 'yyyy-MM-dd'),
grossPerformancePercent: portfolioItem.grossPerformancePercent,
marketPrice: portfolioItem.value ?? null,
value: portfolioItem.value - portfolioItem.investment ?? null
};
});
.map((order) => ({
date: order.getDate().substr(0, 10),
quantity: new Big(order.getQuantity()),
symbol: order.getSymbol(),
type: order.getType(),
unitPrice: new Big(order.getUnitPrice()),
currency: order.getCurrency()
}));
portfolioCalculator.computeTransactionPoints(portfolioOrders);
const transactionPoints = portfolioCalculator.getTransactionPoints();
if (transactionPoints.length === 0) {
return [];
}
const dateFormat = 'yyyy-MM-dd';
let portfolioStart = parse(
transactionPoints[0].date,
dateFormat,
new Date()
);
portfolioStart = this.getStartDate(aDateRange, portfolioStart);
const timelineSpecification: TimelineSpecification[] = [
{
start: format(portfolioStart, dateFormat),
accuracy: 'month'
},
{
start: format(subYears(new Date(), 1), dateFormat),
accuracy: 'day'
}
];
const timeline = await portfolioCalculator.calculateTimeline(
timelineSpecification,
format(new Date(), dateFormat)
);
return timeline.map((timelineItem) => ({
date: timelineItem.date,
value: timelineItem.grossPerformance,
marketPrice: timelineItem.value
}));
}
private getStartDate(aDateRange: DateRange, portfolioStart: Date) {
switch (aDateRange) {
case '1d':
portfolioStart = max([portfolioStart, subDays(new Date(), 1)]);
break;
case 'ytd':
portfolioStart = max([portfolioStart, setDayOfYear(new Date(), 1)]);
break;
case '1y':
portfolioStart = max([portfolioStart, subYears(new Date(), 1)]);
break;
case '5y':
portfolioStart = max([portfolioStart, subYears(new Date(), 5)]);
break;
}
return portfolioStart;
}
public async getOverview(

Loading…
Cancel
Save