diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e91d46a5..77ee76628 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Improved the language localization for Italian (`it`) - Improved the language localization for Portuguese (`pt`) - Improved the language localization for Spanish (`es`) +- Improved the holdings dialog not to include non-investment activities ### Fixed diff --git a/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts b/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts index 185c1cd80..cdfd7adbf 100644 --- a/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts +++ b/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts @@ -13,6 +13,7 @@ import { IDataGatheringItem } from '@ghostfolio/api/services/interfaces/interfac import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service'; import { getIntervalFromDateRange } from '@ghostfolio/common/calculation-helper'; import { + INVESTMENT_ACTIVITY_TYPES, PORTFOLIO_SNAPSHOT_PROCESS_JOB_NAME, PORTFOLIO_SNAPSHOT_PROCESS_JOB_OPTIONS, PORTFOLIO_SNAPSHOT_COMPUTATION_QUEUE_PRIORITY_HIGH, @@ -287,7 +288,9 @@ export abstract class PortfolioCalculator { firstIndex--; } - const positions: TimelinePosition[] = []; + const positions: (TimelinePosition & { + isInvestmentAssetProfilePosition: boolean; + })[] = []; let hasAnySymbolMetricsErrors = false; const errors: ResponseError['errors'] = []; @@ -411,6 +414,7 @@ export abstract class PortfolioCalculator { : null, investment: totalInvestment, investmentWithCurrencyEffect: totalInvestmentWithCurrencyEffect, + isInvestmentAssetProfilePosition: item.isInvestmentAssetProfileItem, marketPrice: marketSymbolMap[endDateString]?.[item.symbol]?.toNumber() ?? null, marketPriceInBaseCurrency: @@ -605,14 +609,23 @@ export abstract class PortfolioCalculator { const overall = this.calculateOverallPerformance(positions); + const investmentPositions = positions + .filter(({ isInvestmentAssetProfilePosition }) => { + return isInvestmentAssetProfilePosition; + }) + // eslint-disable-next-line @typescript-eslint/no-unused-vars + .map(({ isInvestmentAssetProfilePosition, ...rest }) => { + return rest; + }); + return { ...overall, errors, historicalData, - positions, totalInterestWithCurrencyEffect, totalLiabilitiesWithCurrencyEffect, - hasErrors: hasAnySymbolMetricsErrors || overall.hasErrors + hasErrors: hasAnySymbolMetricsErrors || overall.hasErrors, + positions: investmentPositions }; } @@ -935,6 +948,8 @@ export abstract class PortfolioCalculator { dividend: new Big(0), fee: oldAccumulatedSymbol.fee.plus(fee), firstBuyDate: oldAccumulatedSymbol.firstBuyDate, + isInvestmentAssetProfileItem: + oldAccumulatedSymbol.isInvestmentAssetProfileItem, quantity: newQuantity, tags: oldAccumulatedSymbol.tags.concat(tags), transactionCount: oldAccumulatedSymbol.transactionCount + 1 @@ -951,6 +966,8 @@ export abstract class PortfolioCalculator { dividend: new Big(0), firstBuyDate: date, investment: unitPrice.mul(quantity).mul(factor), + isInvestmentAssetProfileItem: + INVESTMENT_ACTIVITY_TYPES.includes(type), quantity: quantity.mul(factor), transactionCount: 1 }; diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-fee.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-fee.spec.ts index 31c6afe66..aaf2c4302 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-fee.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-fee.spec.ts @@ -116,37 +116,7 @@ describe('PortfolioCalculator', () => { currentValueInBaseCurrency: new Big('0'), errors: [], hasErrors: true, - positions: [ - { - averagePrice: new Big('0'), - currency: 'USD', - dataSource: 'MANUAL', - dividend: new Big('0'), - dividendInBaseCurrency: new Big('0'), - fee: new Big('49'), - feeInBaseCurrency: new Big('49'), - firstBuyDate: '2021-09-01', - grossPerformance: null, - grossPerformancePercentage: null, - grossPerformancePercentageWithCurrencyEffect: null, - grossPerformanceWithCurrencyEffect: null, - investment: new Big('0'), - investmentWithCurrencyEffect: new Big('0'), - marketPrice: null, - marketPriceInBaseCurrency: 0, - netPerformance: null, - netPerformancePercentage: null, - netPerformancePercentageWithCurrencyEffectMap: null, - netPerformanceWithCurrencyEffectMap: null, - quantity: new Big('0'), - symbol: '2c463fb3-af07-486e-adb0-8301b3d72141', - tags: [], - timeWeightedInvestment: new Big('0'), - timeWeightedInvestmentWithCurrencyEffect: new Big('0'), - transactionCount: 1, - valueInBaseCurrency: new Big('0') - } - ], + positions: [], totalFeesWithCurrencyEffect: new Big('49'), totalInterestWithCurrencyEffect: new Big('0'), totalInvestment: new Big('0'), diff --git a/apps/api/src/app/portfolio/interfaces/transaction-point-symbol.interface.ts b/apps/api/src/app/portfolio/interfaces/transaction-point-symbol.interface.ts index 0d648322f..04d867b2a 100644 --- a/apps/api/src/app/portfolio/interfaces/transaction-point-symbol.interface.ts +++ b/apps/api/src/app/portfolio/interfaces/transaction-point-symbol.interface.ts @@ -9,6 +9,7 @@ export interface TransactionPointSymbol { fee: Big; firstBuyDate: string; investment: Big; + isInvestmentAssetProfileItem: boolean; quantity: Big; skipErrors: boolean; symbol: string; diff --git a/libs/common/src/lib/config.ts b/libs/common/src/lib/config.ts index 5aee7e0e6..91460e373 100644 --- a/libs/common/src/lib/config.ts +++ b/libs/common/src/lib/config.ts @@ -1,4 +1,4 @@ -import { AssetClass, AssetSubClass, DataSource } from '@prisma/client'; +import { AssetClass, AssetSubClass, DataSource, Type } from '@prisma/client'; import { JobOptions, JobStatus } from 'bull'; import ms from 'ms'; @@ -118,6 +118,13 @@ export const GATHER_HISTORICAL_MARKET_DATA_PROCESS_JOB_OPTIONS: JobOptions = { removeOnComplete: true }; +export const INVESTMENT_ACTIVITY_TYPES = [ + Type.BUY, + Type.DIVIDEND, + Type.ITEM, + Type.SELL +] as Type[]; + export const PORTFOLIO_SNAPSHOT_PROCESS_JOB_NAME = 'PORTFOLIO'; export const PORTFOLIO_SNAPSHOT_PROCESS_JOB_OPTIONS: JobOptions = { removeOnComplete: true