Browse Source

Merge 4daa663be7 into 37adca2abe

pull/7991/merge
Thomas Kaul 2 days ago
committed by GitHub
parent
commit
2875eb6c12
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 8
      apps/api/src/app/portfolio/calculator/portfolio-calculator.ts
  2. 2
      apps/api/src/app/portfolio/portfolio.service.spec.ts
  3. 41
      apps/api/src/app/portfolio/portfolio.service.ts
  4. 31
      libs/common/src/lib/models/portfolio-snapshot-holding.ts

8
apps/api/src/app/portfolio/calculator/portfolio-calculator.ts

@ -1427,10 +1427,8 @@ export abstract class PortfolioCalculator {
// Take the values at the start date from the first day of the date // Take the values at the start date from the first day of the date
// range // range
if (historicalDataItemsOfDateRange.length === 0) { if (historicalDataItemsOfDateRange.length === 0) {
// TODO: Remove the fallback to 0 with the next release, when each
// cached portfolio snapshot contains the dividend
dividendInBaseCurrencyAtStartDate = dividendInBaseCurrencyAtStartDate =
historicalDataItem.dividendInBaseCurrency ?? 0; historicalDataItem.dividendInBaseCurrency;
netPerformanceAtStartDate = historicalDataItem.netPerformance; netPerformanceAtStartDate = historicalDataItem.netPerformance;
@ -1440,10 +1438,8 @@ export abstract class PortfolioCalculator {
historicalDataItemsOfDateRange.push({ historicalDataItemsOfDateRange.push({
...historicalDataItem, ...historicalDataItem,
// TODO: Remove the fallback to 0 with the next release, when each
// cached portfolio snapshot contains the dividend
dividendInBaseCurrency: dividendInBaseCurrency:
(historicalDataItem.dividendInBaseCurrency ?? 0) - historicalDataItem.dividendInBaseCurrency -
dividendInBaseCurrencyAtStartDate, dividendInBaseCurrencyAtStartDate,
netPerformance: netPerformance:
historicalDataItem.netPerformance - netPerformanceAtStartDate, historicalDataItem.netPerformance - netPerformanceAtStartDate,

2
apps/api/src/app/portfolio/portfolio.service.spec.ts

@ -1241,6 +1241,8 @@ describe('PortfolioService', () => {
getLiabilitiesInBaseCurrency: jest.fn().mockResolvedValue(new Big(0)), getLiabilitiesInBaseCurrency: jest.fn().mockResolvedValue(new Big(0)),
getSnapshot: jest.fn().mockResolvedValue({ getSnapshot: jest.fn().mockResolvedValue({
currentValueInBaseCurrency: new Big(3000), currentValueInBaseCurrency: new Big(3000),
dividendYieldPercent: new Big(0),
dividendYieldPercentWithCurrencyEffect: new Big(0),
totalCashInBaseCurrency: new Big(1000), totalCashInBaseCurrency: new Big(1000),
totalInvestment: new Big(2000), totalInvestment: new Big(2000),
totalInvestmentWithCurrencyEffect: new Big(2000) totalInvestmentWithCurrencyEffect: new Big(2000)

41
apps/api/src/app/portfolio/portfolio.service.ts

@ -996,15 +996,12 @@ export class PortfolioService {
const { const {
activitiesCount, activitiesCount,
averageInvestment,
averageInvestmentWithCurrencyEffect,
averagePrice, averagePrice,
currency, currency,
dateOfFirstActivity, dateOfFirstActivity,
dividendInBaseCurrency, dividendInBaseCurrency,
dividendYieldPercent: dividendYieldPercentOfSnapshot, dividendYieldPercent,
dividendYieldPercentWithCurrencyEffect: dividendYieldPercentWithCurrencyEffect,
dividendYieldPercentWithCurrencyEffectOfSnapshot,
feeInBaseCurrency, feeInBaseCurrency,
grossPerformance, grossPerformance,
grossPerformancePercentage, grossPerformancePercentage,
@ -1020,34 +1017,6 @@ export class PortfolioService {
tags tags
} = holding; } = holding;
// TODO: Remove the block below with the next release, when each cached
// portfolio snapshot contains the dividend yield. Then take
// dividendYieldPercent and dividendYieldPercentWithCurrencyEffect
// directly from the holding and remove averageInvestment and
// averageInvestmentWithCurrencyEffect from the properties above
const daysInMarket = differenceInDays(
new Date(),
parseDate(dateOfFirstActivity)
);
const dividendYieldPercent =
dividendYieldPercentOfSnapshot ??
getAnnualizedPerformancePercent({
daysInMarket,
netPerformancePercentage: averageInvestment.eq(0)
? new Big(0)
: dividendInBaseCurrency.div(averageInvestment)
});
const dividendYieldPercentWithCurrencyEffect =
dividendYieldPercentWithCurrencyEffectOfSnapshot ??
getAnnualizedPerformancePercent({
daysInMarket,
netPerformancePercentage: averageInvestmentWithCurrencyEffect.eq(0)
? new Big(0)
: dividendInBaseCurrency.div(averageInvestmentWithCurrencyEffect)
});
const activitiesOfHolding = activities.filter((activity) => { const activitiesOfHolding = activities.filter((activity) => {
return ( return (
activity.assetProfile.dataSource === dataSource && activity.assetProfile.dataSource === dataSource &&
@ -2323,11 +2292,9 @@ export class PortfolioService {
activityCount: activities.filter(({ type }) => { activityCount: activities.filter(({ type }) => {
return ['BUY', 'SELL'].includes(type); return ['BUY', 'SELL'].includes(type);
}).length, }).length,
// TODO: Remove the fallback to 0 with the next release, when each dividendYieldPercent: dividendYieldPercent.toNumber(),
// cached portfolio snapshot contains the dividend yield
dividendYieldPercent: dividendYieldPercent?.toNumber() ?? 0,
dividendYieldPercentWithCurrencyEffect: dividendYieldPercentWithCurrencyEffect:
dividendYieldPercentWithCurrencyEffect?.toNumber() ?? 0, dividendYieldPercentWithCurrencyEffect.toNumber(),
emergencyFund: { emergencyFund: {
assets: emergencyFundHoldingsValueInBaseCurrency, assets: emergencyFundHoldingsValueInBaseCurrency,
cash: totalEmergencyFund cash: totalEmergencyFund

31
libs/common/src/lib/models/portfolio-snapshot-holding.ts

@ -7,41 +7,16 @@ import type { Tag } from '@ghostfolio/prisma/browser';
import { DataSource } from '@ghostfolio/prisma/enums'; import { DataSource } from '@ghostfolio/prisma/enums';
import { Big } from 'big.js'; import { Big } from 'big.js';
import { Expose, Transform, Type } from 'class-transformer'; import { Transform, Type } from 'class-transformer';
/**
* @deprecated Backward compatibility to read the portfolio snapshots which
* have been cached with the former name of the property
*
* TODO: Remove the fallback with the next release, together with the
* `@Expose()` decorators of `averageInvestment` and
* `averageInvestmentWithCurrencyEffect`
*/
function transformToBigWithFallback(formerKey: string) {
return ({ obj, value }: { obj: Record<string, string>; value: string }) => {
const valueOrFallback = value ?? obj[formerKey];
return valueOrFallback === undefined
? undefined
: transformToBig({ value: valueOrFallback });
};
}
export class PortfolioSnapshotHolding { export class PortfolioSnapshotHolding {
activitiesCount: number; activitiesCount: number;
@Expose() @Transform(transformToBig, { toClassOnly: true })
@Transform(transformToBigWithFallback('timeWeightedInvestment'), {
toClassOnly: true
})
@Type(() => Big) @Type(() => Big)
averageInvestment: Big; averageInvestment: Big;
@Expose() @Transform(transformToBig, { toClassOnly: true })
@Transform(
transformToBigWithFallback('timeWeightedInvestmentWithCurrencyEffect'),
{ toClassOnly: true }
)
@Type(() => Big) @Type(() => Big)
averageInvestmentWithCurrencyEffect: Big; averageInvestmentWithCurrencyEffect: Big;

Loading…
Cancel
Save