diff --git a/README.md b/README.md index b9352e3bd3..142d3199cc 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ Ghostfolio is for you if you are... - ✅ Create, update and delete transactions - ✅ Multi account management -- ✅ Portfolio performance: Return on Average Investment (ROAI) for `Today`, `WTD`, `MTD`, `YTD`, `1Y`, `5Y`, `Max` +- ✅ Portfolio performance: Return on Average Investment (ROAI) including dividends (total return) for `Today`, `WTD`, `MTD`, `YTD`, `1Y`, `5Y`, `Max` - ✅ Various charts - ✅ Static analysis to identify potential risks in your portfolio - ✅ Import and export transactions diff --git a/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts b/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts index e03b530258..9c5f1a26e3 100644 --- a/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts +++ b/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts @@ -946,6 +946,7 @@ export abstract class PortfolioCalculator { const currentExchangeRate = exchangeRates[format(new Date(), DATE_FORMAT)]; const currentValues: { [date: string]: Big } = {}; const currentValuesWithCurrencyEffect: { [date: string]: Big } = {}; + let dividends = new Big(0); let fees = new Big(0); let feesAtStartDate = new Big(0); let feesAtStartDateWithCurrencyEffect = new Big(0); @@ -1188,14 +1189,26 @@ export abstract class PortfolioCalculator { ); } + if (activity.type === 'DIVIDEND') { + // The amount of a dividend in the base currency is the same with and + // without currency effect, like the dividend of the holding + dividends = dividends.plus( + activity.quantity + .mul(activity.unitPrice) + .mul(exchangeRateAtActivityDate ?? 1) + ); + } + const newGrossPerformance = valueOfInvestment .minus(totalInvestment) - .plus(grossPerformanceFromSells); + .plus(grossPerformanceFromSells) + .plus(dividends); const newGrossPerformanceWithCurrencyEffect = valueOfInvestmentWithCurrencyEffect .minus(totalInvestmentWithCurrencyEffect) - .plus(grossPerformanceFromSellsWithCurrencyEffect); + .plus(grossPerformanceFromSellsWithCurrencyEffect) + .plus(dividends); grossPerformance = newGrossPerformance; diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-msft-buy-with-dividend.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-msft-buy-with-dividend.spec.ts index 2c6ff79b6d..151a2a914c 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-msft-buy-with-dividend.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-msft-buy-with-dividend.spec.ts @@ -155,25 +155,25 @@ describe('PortfolioCalculator', () => { '0.001144362748184' ), fee: new Big('19'), - grossPerformance: new Big('33.25'), - grossPerformancePercentage: new Big('0.11136043941322258691'), + grossPerformance: new Big('33.87'), + grossPerformancePercentage: new Big('0.11343693482483756447'), grossPerformancePercentageWithCurrencyEffect: new Big( - '0.11136043941322258691' + '0.11343693482483756447' ), - grossPerformanceWithCurrencyEffect: new Big('33.25'), + grossPerformanceWithCurrencyEffect: new Big('33.87'), investment: new Big('298.58'), investmentWithCurrencyEffect: new Big('298.58'), marketPrice: 331.83, marketPriceInBaseCurrency: 331.83, - netPerformance: new Big('14.25'), - netPerformancePercentage: new Big('0.04772590260566682296'), + netPerformance: new Big('14.87'), + netPerformancePercentage: new Big('0.04980239801728180052'), netPerformancePercentageWithCurrencyEffectMap: { - max: new Big('0.04772590260566682296') + max: new Big('0.04980239801728180052') }, netPerformanceWithCurrencyEffectMap: { '1d': new Big('-5.39'), - '5y': new Big('14.25'), - max: new Big('14.25'), + '5y': new Big('14.87'), + max: new Big('14.87'), wtd: new Big('-5.39') }, quantity: new Big('1'), @@ -200,10 +200,10 @@ describe('PortfolioCalculator', () => { date: '2023-07-10', dividendInBaseCurrency: 0, dividendInPercentageWithCurrencyEffect: 0, - netPerformance: -5.390000000000001, - netPerformanceInPercentage: -0.015983630864124312, - netPerformanceInPercentageWithCurrencyEffect: -0.015983630864124312, - netPerformanceWithCurrencyEffect: -5.390000000000001, + netPerformance: -5.390000000000002, + netPerformanceInPercentage: -0.015983630864124316, + netPerformanceInPercentageWithCurrencyEffect: -0.015983630864124316, + netPerformanceWithCurrencyEffect: -5.390000000000002, totalInvestmentValueWithCurrencyEffect: 298.58, valueWithCurrencyEffect: 331.83 }, @@ -211,10 +211,10 @@ describe('PortfolioCalculator', () => { date: '2023-07-10', dividendInBaseCurrency: 0.62, dividendInPercentageWithCurrencyEffect: 0.002076495411614967, - netPerformance: 14.25, - netPerformanceInPercentage: 0.04772590260566659, - netPerformanceInPercentageWithCurrencyEffect: 0.04772590260566659, - netPerformanceWithCurrencyEffect: 14.25, + netPerformance: 14.87, + netPerformanceInPercentage: 0.049802398017281556, + netPerformanceInPercentageWithCurrencyEffect: 0.049802398017281556, + netPerformanceWithCurrencyEffect: 14.87, totalInvestmentValueWithCurrencyEffect: 298.58, valueWithCurrencyEffect: 331.83 }, @@ -222,10 +222,10 @@ describe('PortfolioCalculator', () => { date: '2023-07-10', dividendInBaseCurrency: 0, dividendInPercentageWithCurrencyEffect: 0, - netPerformance: -7.68, - netPerformanceInPercentage: -0.022620835910577012, - netPerformanceInPercentageWithCurrencyEffect: -0.022620835910577012, - netPerformanceWithCurrencyEffect: -7.68, + netPerformance: -7.6800000000000015, + netPerformanceInPercentage: -0.022620835910577015, + netPerformanceInPercentageWithCurrencyEffect: -0.022620835910577015, + netPerformanceWithCurrencyEffect: -7.6800000000000015, totalInvestmentValueWithCurrencyEffect: 298.58, valueWithCurrencyEffect: 331.83 } diff --git a/apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html b/apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html index 0a0beba910..0ed3b0527a 100644 --- a/apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html +++ b/apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html @@ -98,25 +98,20 @@ /> - @if (user?.settings?.isExperimentalFeatures) { -
-
Dividend
-
- @if (isNumber(summary?.dividendInBaseCurrency)) { - + - } - -
+
+
thereof Dividend
+
+
- } +
Fees
@@ -147,7 +142,7 @@ [locale]="locale" [precision]="precision" [unit]="displayedCurrency" - [value]="netPerformanceWithCurrencyEffect" + [value]="summary?.netPerformanceWithCurrencyEffect" />
@@ -160,7 +155,8 @@ ) { (ROAI) } @@ -173,7 +169,7 @@ [isLoading]="isLoading" [isPercent]="true" [locale]="locale" - [value]="netPerformancePercentageWithCurrencyEffect" + [value]="summary?.netPerformancePercentageWithCurrencyEffect" />
@@ -506,20 +502,4 @@ /> - @if (!user?.settings?.isExperimentalFeatures) { -
-
Dividend
-
- -
-
- } diff --git a/apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts b/apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts index 13686624f7..8a0d83b941 100644 --- a/apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts +++ b/apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts @@ -137,36 +137,6 @@ export class GfPortfolioSummaryComponent implements OnChanges { ); } - protected get netPerformancePercentageWithCurrencyEffect() { - if ( - !this.user?.settings?.isExperimentalFeatures || - !isNumber(this.summary?.netPerformancePercentageWithCurrencyEffect) - ) { - return this.summary?.netPerformancePercentageWithCurrencyEffect; - } - - // Include the dividends (total return) - return ( - this.summary.netPerformancePercentageWithCurrencyEffect + - (this.summary.dividendPercentageWithCurrencyEffect ?? 0) - ); - } - - protected get netPerformanceWithCurrencyEffect() { - if ( - !this.user?.settings?.isExperimentalFeatures || - !isNumber(this.summary?.netPerformanceWithCurrencyEffect) - ) { - return this.summary?.netPerformanceWithCurrencyEffect; - } - - // Include the dividends (total return) - return ( - this.summary.netPerformanceWithCurrencyEffect + - this.summary.dividendInBaseCurrency - ); - } - public ngOnChanges() { if (this.summary) { if ( diff --git a/apps/client/src/app/pages/faq/overview/faq-overview-page.html b/apps/client/src/app/pages/faq/overview/faq-overview-page.html index 77c23789e6..66b416fbab 100644 --- a/apps/client/src/app/pages/faq/overview/faq-overview-page.html +++ b/apps/client/src/app/pages/faq/overview/faq-overview-page.html @@ -52,8 +52,8 @@ calculation method based on the average amount of capital invested over time. ROAI aims to provide a more insightful view of investment performance than simpler approaches, especially when contributions are - made over time. Dividends are not part of the - calculation. diff --git a/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts b/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts index 880753cce5..f85ed9ecfc 100644 --- a/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts +++ b/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts @@ -133,36 +133,6 @@ export class GfAnalysisPageComponent implements OnInit { addIcons({ copyOutline, ellipsisVertical }); } - protected get netPerformancePercentageWithCurrencyEffect() { - if ( - !this.user?.settings?.isExperimentalFeatures || - !isNumber(this.performance?.netPerformancePercentageWithCurrencyEffect) - ) { - return this.performance?.netPerformancePercentageWithCurrencyEffect; - } - - // Include the dividends (total return) - return ( - this.performance.netPerformancePercentageWithCurrencyEffect + - (this.performance.dividendPercentageWithCurrencyEffect ?? 0) - ); - } - - protected get netPerformanceWithCurrencyEffect() { - if ( - !this.user?.settings?.isExperimentalFeatures || - !isNumber(this.performance?.netPerformanceWithCurrencyEffect) - ) { - return this.performance?.netPerformanceWithCurrencyEffect; - } - - // Include the dividends (total return) - return ( - this.performance.netPerformanceWithCurrencyEffect + - this.performance.dividendInBaseCurrency - ); - } - get savingsRate() { if (!this.savingsRatePerMonth) { return undefined; diff --git a/apps/client/src/app/pages/portfolio/analysis/analysis-page.html b/apps/client/src/app/pages/portfolio/analysis/analysis-page.html index 2756076b7a..c9cc8d93c0 100644 --- a/apps/client/src/app/pages/portfolio/analysis/analysis-page.html +++ b/apps/client/src/app/pages/portfolio/analysis/analysis-page.html @@ -171,7 +171,7 @@ /> -
+
Asset Performance
@@ -187,45 +187,42 @@ />
- @if (user?.settings?.isExperimentalFeatures) { -
-
- Absolute Dividend Performance - @if (user?.subscription?.type === 'Basic') { - - } -
-
- -
+
+
+ thereof Dividend + @if (user?.subscription?.type === 'Basic') { + + }
-
-
- Dividend Performance -
-
- -
+
+
- } +
+
+
+ thereof Dividend Performance +
+
+ +
+
@@ -299,7 +296,8 @@ ) { (ROAI) } @@ -312,7 +310,9 @@ [isLoading]="isLoadingInvestmentChart" [isPercent]="true" [locale]="user?.settings?.locale" - [value]="netPerformancePercentageWithCurrencyEffect" + [value]=" + performance?.netPerformancePercentageWithCurrencyEffect + " />