Feature/add dividend and fees to position detail dialog (#1643)
* Add dividend and fees to position detail dialog * Update changelog
This commit is contained in:
parent
2e7f46ad78
commit
f7597c213d
@ -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
|
||||
|
@ -7,6 +7,8 @@ import { Tag } from '@prisma/client';
|
||||
|
||||
export interface PortfolioPositionDetail {
|
||||
averagePrice: number;
|
||||
dividendInBaseCurrency: number;
|
||||
feeInBaseCurrency: number;
|
||||
firstBuyDate: string;
|
||||
grossPerformance: number;
|
||||
grossPerformancePercent: number;
|
||||
|
@ -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'),
|
||||
|
@ -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'),
|
||||
|
@ -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'),
|
||||
|
@ -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'),
|
||||
|
@ -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'),
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -35,6 +35,7 @@ export class RedactValuesInResponseInterceptor<T>
|
||||
'balanceInBaseCurrency',
|
||||
'comment',
|
||||
'convertedBalance',
|
||||
'dividendInBaseCurrency',
|
||||
'fee',
|
||||
'feeInBaseCurrency',
|
||||
'filteredValueInBaseCurrency',
|
||||
|
@ -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 }) => {
|
||||
|
@ -119,6 +119,26 @@
|
||||
>Investment</gf-value
|
||||
>
|
||||
</div>
|
||||
<div class="col-6 mb-3">
|
||||
<gf-value
|
||||
i18n
|
||||
size="medium"
|
||||
[currency]="data.baseCurrency"
|
||||
[locale]="data.locale"
|
||||
[value]="dividendInBaseCurrency"
|
||||
>Dividend</gf-value
|
||||
>
|
||||
</div>
|
||||
<div class="col-6 mb-3">
|
||||
<gf-value
|
||||
i18n
|
||||
size="medium"
|
||||
[currency]="data.baseCurrency"
|
||||
[locale]="data.locale"
|
||||
[value]="feeInBaseCurrency"
|
||||
>Fees</gf-value
|
||||
>
|
||||
</div>
|
||||
<div class="col-6 mb-3">
|
||||
<gf-value
|
||||
i18n
|
||||
|
@ -1,5 +1,6 @@
|
||||
import * as currencies from '@dinero.js/currencies';
|
||||
import { DataSource } from '@prisma/client';
|
||||
import Big from 'big.js';
|
||||
import { getDate, getMonth, getYear, parse, subDays } from 'date-fns';
|
||||
import { de, es, fr, it, nl, pt } from 'date-fns/locale';
|
||||
|
||||
@ -139,6 +140,14 @@ export function getNumberFormatGroup(aLocale?: string) {
|
||||
}).value;
|
||||
}
|
||||
|
||||
export function getSum(aArray: Big[]) {
|
||||
if (aArray?.length > 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' ||
|
||||
|
@ -5,6 +5,7 @@ export interface TimelinePosition {
|
||||
averagePrice: Big;
|
||||
currency: string;
|
||||
dataSource: DataSource;
|
||||
fee: Big;
|
||||
firstBuyDate: string;
|
||||
grossPerformance: Big;
|
||||
grossPerformancePercentage: Big;
|
||||
|
Loading…
x
Reference in New Issue
Block a user