diff --git a/CHANGELOG.md b/CHANGELOG.md index d8369f702..4c6a676dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Added the dividend and fees to the position detail dialog - Added support to link a (wealth) item to an account ### Changed diff --git a/apps/api/src/app/portfolio/interfaces/portfolio-position-detail.interface.ts b/apps/api/src/app/portfolio/interfaces/portfolio-position-detail.interface.ts index 4d13a1ae3..48a0ac671 100644 --- a/apps/api/src/app/portfolio/interfaces/portfolio-position-detail.interface.ts +++ b/apps/api/src/app/portfolio/interfaces/portfolio-position-detail.interface.ts @@ -7,6 +7,8 @@ import { Tag } from '@prisma/client'; export interface PortfolioPositionDetail { averagePrice: number; + dividendInBaseCurrency: number; + feeInBaseCurrency: number; firstBuyDate: string; grossPerformance: number; grossPerformancePercent: number; diff --git a/apps/api/src/app/portfolio/portfolio-calculator-baln-buy-and-sell.spec.ts b/apps/api/src/app/portfolio/portfolio-calculator-baln-buy-and-sell.spec.ts index 2771a5f60..c66323c72 100644 --- a/apps/api/src/app/portfolio/portfolio-calculator-baln-buy-and-sell.spec.ts +++ b/apps/api/src/app/portfolio/portfolio-calculator-baln-buy-and-sell.spec.ts @@ -82,6 +82,7 @@ describe('PortfolioCalculator', () => { averagePrice: new Big('0'), currency: 'CHF', dataSource: 'YAHOO', + fee: new Big('3.2'), firstBuyDate: '2021-11-22', grossPerformance: new Big('-12.6'), grossPerformancePercentage: new Big('-0.0440867739678096571'), diff --git a/apps/api/src/app/portfolio/portfolio-calculator-baln-buy.spec.ts b/apps/api/src/app/portfolio/portfolio-calculator-baln-buy.spec.ts index db9c0ac8c..9f49c13e0 100644 --- a/apps/api/src/app/portfolio/portfolio-calculator-baln-buy.spec.ts +++ b/apps/api/src/app/portfolio/portfolio-calculator-baln-buy.spec.ts @@ -71,6 +71,7 @@ describe('PortfolioCalculator', () => { averagePrice: new Big('136.6'), currency: 'CHF', dataSource: 'YAHOO', + fee: new Big('1.55'), firstBuyDate: '2021-11-30', grossPerformance: new Big('24.6'), grossPerformancePercentage: new Big('0.09004392386530014641'), diff --git a/apps/api/src/app/portfolio/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts b/apps/api/src/app/portfolio/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts index c374ac4c3..666ce2167 100644 --- a/apps/api/src/app/portfolio/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts +++ b/apps/api/src/app/portfolio/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts @@ -82,6 +82,7 @@ describe('PortfolioCalculator', () => { averagePrice: new Big('320.43'), currency: 'CHF', dataSource: 'YAHOO', + fee: new Big('0'), firstBuyDate: '2015-01-01', grossPerformance: new Big('27172.74'), grossPerformancePercentage: new Big('42.40043067128546016291'), diff --git a/apps/api/src/app/portfolio/portfolio-calculator-novn-buy-and-sell-partially.spec.ts b/apps/api/src/app/portfolio/portfolio-calculator-novn-buy-and-sell-partially.spec.ts index e0c19ba4b..6adfc9347 100644 --- a/apps/api/src/app/portfolio/portfolio-calculator-novn-buy-and-sell-partially.spec.ts +++ b/apps/api/src/app/portfolio/portfolio-calculator-novn-buy-and-sell-partially.spec.ts @@ -82,6 +82,7 @@ describe('PortfolioCalculator', () => { averagePrice: new Big('75.80'), currency: 'CHF', dataSource: 'YAHOO', + fee: new Big('4.25'), firstBuyDate: '2022-03-07', grossPerformance: new Big('21.93'), grossPerformancePercentage: new Big('0.14465699208443271768'), diff --git a/apps/api/src/app/portfolio/portfolio-calculator-novn-buy-and-sell.spec.ts b/apps/api/src/app/portfolio/portfolio-calculator-novn-buy-and-sell.spec.ts index 9ca188444..e41016109 100644 --- a/apps/api/src/app/portfolio/portfolio-calculator-novn-buy-and-sell.spec.ts +++ b/apps/api/src/app/portfolio/portfolio-calculator-novn-buy-and-sell.spec.ts @@ -102,6 +102,7 @@ describe('PortfolioCalculator', () => { averagePrice: new Big('0'), currency: 'CHF', dataSource: 'YAHOO', + fee: new Big('0'), firstBuyDate: '2022-03-07', grossPerformance: new Big('19.86'), grossPerformancePercentage: new Big('0.13100263852242744063'), diff --git a/apps/api/src/app/portfolio/portfolio-calculator.ts b/apps/api/src/app/portfolio/portfolio-calculator.ts index 9c659c167..f99defd53 100644 --- a/apps/api/src/app/portfolio/portfolio-calculator.ts +++ b/apps/api/src/app/portfolio/portfolio-calculator.ts @@ -431,6 +431,7 @@ export class PortfolioCalculator { : item.investment.div(item.quantity), currency: item.currency, dataSource: item.dataSource, + fee: item.fee, firstBuyDate: item.firstBuyDate, grossPerformance: !hasErrors ? grossPerformance ?? null : null, grossPerformancePercentage: !hasErrors diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index 73c24d2b5..6700eda99 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -24,7 +24,7 @@ import { MAX_CHART_ITEMS, UNKNOWN_KEY } from '@ghostfolio/common/config'; -import { DATE_FORMAT, parseDate } from '@ghostfolio/common/helper'; +import { DATE_FORMAT, getSum, parseDate } from '@ghostfolio/common/helper'; import { Accounts, EnhancedSymbolProfile, @@ -678,6 +678,8 @@ export class PortfolioService { return { tags, averagePrice: undefined, + dividendInBaseCurrency: undefined, + feeInBaseCurrency: undefined, firstBuyDate: undefined, grossPerformance: undefined, grossPerformancePercent: undefined, @@ -744,12 +746,23 @@ export class PortfolioService { averagePrice, currency, dataSource, + fee, firstBuyDate, marketPrice, quantity, transactionCount } = position; + const dividendInBaseCurrency = getSum( + orders + .filter(({ type }) => { + return type === 'DIVIDEND'; + }) + .map(({ valueInBaseCurrency }) => { + return new Big(valueInBaseCurrency); + }) + ); + // Convert investment, gross and net performance to currency of user const investment = this.exchangeRateDataService.toCurrency( position.investment?.toNumber(), @@ -836,6 +849,12 @@ export class PortfolioService { tags, transactionCount, averagePrice: averagePrice.toNumber(), + dividendInBaseCurrency: dividendInBaseCurrency.toNumber(), + feeInBaseCurrency: this.exchangeRateDataService.toCurrency( + fee.toNumber(), + SymbolProfile.currency, + userCurrency + ), grossPerformancePercent: position.grossPerformancePercentage?.toNumber(), historicalData: historicalDataArray, @@ -892,6 +911,8 @@ export class PortfolioService { SymbolProfile, tags, averagePrice: 0, + dividendInBaseCurrency: 0, + feeInBaseCurrency: 0, firstBuyDate: undefined, grossPerformance: undefined, grossPerformancePercent: undefined, diff --git a/apps/api/src/interceptors/redact-values-in-response.interceptor.ts b/apps/api/src/interceptors/redact-values-in-response.interceptor.ts index 724cdc450..0cc7b2168 100644 --- a/apps/api/src/interceptors/redact-values-in-response.interceptor.ts +++ b/apps/api/src/interceptors/redact-values-in-response.interceptor.ts @@ -35,6 +35,7 @@ export class RedactValuesInResponseInterceptor 'balanceInBaseCurrency', 'comment', 'convertedBalance', + 'dividendInBaseCurrency', 'fee', 'feeInBaseCurrency', 'filteredValueInBaseCurrency', 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 fef9011d3..acd74cdff 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 @@ -37,6 +37,8 @@ export class PositionDetailDialog implements OnDestroy, OnInit { public countries: { [code: string]: { name: string; value: number }; }; + public dividendInBaseCurrency: number; + public feeInBaseCurrency: number; public firstBuyDate: string; public grossPerformance: number; public grossPerformancePercent: number; @@ -78,6 +80,8 @@ export class PositionDetailDialog implements OnDestroy, OnInit { .subscribe( ({ averagePrice, + dividendInBaseCurrency, + feeInBaseCurrency, firstBuyDate, grossPerformance, grossPerformancePercent, @@ -98,7 +102,8 @@ export class PositionDetailDialog implements OnDestroy, OnInit { this.averagePrice = averagePrice; this.benchmarkDataItems = []; this.countries = {}; - this.reportDataGlitchMail = `mailto:hi@ghostfol.io?Subject=Ghostfolio Data Glitch Report&body=Hello%0D%0DI would like to report a data glitch for%0D%0DSymbol: ${SymbolProfile?.symbol}%0DData Source: ${SymbolProfile?.dataSource}%0D%0DAdditional notes:%0D%0DCan you please take a look?%0D%0DKind regards`; + this.dividendInBaseCurrency = dividendInBaseCurrency; + this.feeInBaseCurrency = feeInBaseCurrency; this.firstBuyDate = firstBuyDate; this.grossPerformance = grossPerformance; this.grossPerformancePercent = grossPerformancePercent; @@ -123,6 +128,7 @@ export class PositionDetailDialog implements OnDestroy, OnInit { this.netPerformancePercent = netPerformancePercent; this.orders = orders; this.quantity = quantity; + this.reportDataGlitchMail = `mailto:hi@ghostfol.io?Subject=Ghostfolio Data Glitch Report&body=Hello%0D%0DI would like to report a data glitch for%0D%0DSymbol: ${SymbolProfile?.symbol}%0DData Source: ${SymbolProfile?.dataSource}%0D%0DAdditional notes:%0D%0DCan you please take a look?%0D%0DKind regards`; this.sectors = {}; this.SymbolProfile = SymbolProfile; this.tags = tags.map(({ id, name }) => { diff --git a/apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html b/apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html index c888ab9be..fc5ea0de6 100644 --- a/apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html +++ b/apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html @@ -119,6 +119,26 @@ >Investment +
+ Dividend +
+
+ Fees +
0) { + return aArray.reduce((a, b) => a.plus(b), new Big(0)); + } + + return new Big(0); +} + export function getTextColor(aColorScheme: ColorScheme) { const cssVariable = getCssVariable( aColorScheme === 'DARK' || diff --git a/libs/common/src/lib/interfaces/timeline-position.interface.ts b/libs/common/src/lib/interfaces/timeline-position.interface.ts index 2e5aa6333..beb13a352 100644 --- a/libs/common/src/lib/interfaces/timeline-position.interface.ts +++ b/libs/common/src/lib/interfaces/timeline-position.interface.ts @@ -5,6 +5,7 @@ export interface TimelinePosition { averagePrice: Big; currency: string; dataSource: DataSource; + fee: Big; firstBuyDate: string; grossPerformance: Big; grossPerformancePercentage: Big;