From 71a3115fc6db2c903655e834f049dec7e8a96b49 Mon Sep 17 00:00:00 2001 From: Valentin Zickner Date: Sat, 31 Jul 2021 22:13:57 +0200 Subject: [PATCH] refactor get position endpoint Co-authored-by: Thomas --- .../src/app/portfolio/portfolio.service.ts | 128 +++++++++--------- .../position-detail-dialog.component.ts | 2 +- 2 files changed, 63 insertions(+), 67 deletions(-) diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index 99b235a68..bc719b66d 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -321,9 +321,44 @@ export class PortfolioService { aSymbol: string ): Promise { const userId = await this.getUserId(aImpersonationId); - const portfolio = await this.createPortfolio(userId); - const position = portfolio.getPositions(new Date())[aSymbol]; + const portfolioCalculator = new PortfolioCalculator( + this.currentRateService, + this.request.user.Settings.currency + ); + + const { transactionPoints, orders } = await this.getTransactionPoints( + userId + ); + + if (transactionPoints?.length <= 0) { + return { + averagePrice: undefined, + currency: undefined, + firstBuyDate: undefined, + grossPerformance: undefined, + grossPerformancePercent: undefined, + historicalData: [], + investment: undefined, + marketPrice: undefined, + maxPrice: undefined, + minPrice: undefined, + quantity: undefined, + symbol: aSymbol, + transactionCount: undefined + }; + } + + portfolioCalculator.setTransactionPoints(transactionPoints); + + const portfolioStart = parseDate(transactionPoints[0].date); + const currentPositions = await portfolioCalculator.getCurrentPositions( + portfolioStart + ); + + const position = currentPositions.positions.find( + (item) => item.symbol === aSymbol + ); if (position) { const { @@ -331,11 +366,10 @@ export class PortfolioService { currency, firstBuyDate, investment, + marketPrice, quantity, transactionCount } = position; - let marketPrice = position.marketPrice; - const orders = portfolio.getOrders(aSymbol); const historicalData = await this.dataProviderService.getHistorical( [aSymbol], @@ -344,33 +378,29 @@ export class PortfolioService { new Date() ); - if (marketPrice === 0) { - marketPrice = averagePrice; - } - const historicalDataArray: HistoricalDataItem[] = []; - let currentAveragePrice: number; let maxPrice = marketPrice; let minPrice = marketPrice; if (historicalData[aSymbol]) { + let j = -1; for (const [date, { marketPrice }] of Object.entries( historicalData[aSymbol] )) { - const currentDate = parse(date, DATE_FORMAT, new Date()); - if ( - isSameDay(currentDate, parseISO(orders[0]?.getDate())) || - isAfter(currentDate, parseISO(orders[0]?.getDate())) + while ( + j + 1 < transactionPoints.length && + !isAfter(parseDate(transactionPoints[j + 1].date), parseDate(date)) ) { - // Get snapshot of first day of next month - const snapshot = portfolio.get( - addMonths(setDate(currentDate, 1), 1) - )?.[0]?.positions[aSymbol]; - orders.shift(); - - if (snapshot?.averagePrice) { - currentAveragePrice = snapshot.averagePrice; - } + j++; + } + let currentAveragePrice = 0; + const currentSymbol = transactionPoints[j].items.find( + (item) => item.symbol === aSymbol + ); + if (currentSymbol) { + currentAveragePrice = currentSymbol.investment + .div(currentSymbol.quantity) + .toNumber(); } historicalDataArray.push({ @@ -379,58 +409,40 @@ export class PortfolioService { value: marketPrice }); - if ( - marketPrice && - (marketPrice > maxPrice || maxPrice === undefined) - ) { - maxPrice = marketPrice; - } - - if ( - marketPrice && - (marketPrice < minPrice || minPrice === undefined) - ) { - minPrice = marketPrice; - } + maxPrice = Math.max(marketPrice ?? 0, maxPrice); + minPrice = Math.min(marketPrice ?? Number.MAX_SAFE_INTEGER, minPrice); } } return { - averagePrice, + averagePrice: averagePrice.toNumber(), currency, firstBuyDate, - investment, + investment: investment.toNumber(), marketPrice, maxPrice, minPrice, - quantity, + quantity: quantity.toNumber(), transactionCount, - grossPerformance: this.exchangeRateDataService.toCurrency( - marketPrice - averagePrice, - currency, - this.request.user.Settings.currency - ), - grossPerformancePercent: roundTo( - (marketPrice - averagePrice) / averagePrice, - 4 - ), + grossPerformance: position.grossPerformance.toNumber(), + grossPerformancePercent: position.grossPerformancePercentage.toNumber(), historicalData: historicalDataArray, symbol: aSymbol }; - } else if (portfolio.getMinDate()) { + } else { const currentData = await this.dataProviderService.get([aSymbol]); let historicalData = await this.dataProviderService.getHistorical( [aSymbol], 'day', - portfolio.getMinDate(), + portfolioStart, new Date() ); if (isEmpty(historicalData)) { historicalData = await this.dataProviderService.getHistoricalRaw( [{ dataSource: DataSource.YAHOO, symbol: aSymbol }], - portfolio.getMinDate(), + portfolioStart, new Date() ); } @@ -462,22 +474,6 @@ export class PortfolioService { transactionCount: undefined }; } - - return { - averagePrice: undefined, - currency: undefined, - firstBuyDate: undefined, - grossPerformance: undefined, - grossPerformancePercent: undefined, - historicalData: [], - investment: undefined, - marketPrice: undefined, - maxPrice: undefined, - minPrice: undefined, - quantity: undefined, - symbol: aSymbol, - transactionCount: undefined - }; } public async getPositions( diff --git a/apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.component.ts b/apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.component.ts index 947a9f214..e9820c9eb 100644 --- a/apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.component.ts +++ b/apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.component.ts @@ -67,7 +67,7 @@ export class PositionDetailDialog implements OnDestroy { this.benchmarkDataItems = []; this.currency = currency; this.firstBuyDate = firstBuyDate; - this.grossPerformance = quantity * grossPerformance; + this.grossPerformance = grossPerformance; this.grossPerformancePercent = grossPerformancePercent; this.historicalDataItems = historicalData.map( (historicalDataItem) => {