Attila Cseh 2 days ago
committed by GitHub
parent
commit
0d39a9f896
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 1
      CHANGELOG.md
  2. 23
      apps/api/src/app/portfolio/calculator/portfolio-calculator.ts
  3. 32
      apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-fee.spec.ts
  4. 1
      apps/api/src/app/portfolio/interfaces/transaction-point-symbol.interface.ts
  5. 9
      libs/common/src/lib/config.ts

1
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 Italian (`it`)
- Improved the language localization for Portuguese (`pt`) - Improved the language localization for Portuguese (`pt`)
- Improved the language localization for Spanish (`es`) - Improved the language localization for Spanish (`es`)
- Improved the holdings dialog not to include non-investment activities
### Fixed ### Fixed

23
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 { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service';
import { getIntervalFromDateRange } from '@ghostfolio/common/calculation-helper'; import { getIntervalFromDateRange } from '@ghostfolio/common/calculation-helper';
import { import {
INVESTMENT_ACTIVITY_TYPES,
PORTFOLIO_SNAPSHOT_PROCESS_JOB_NAME, PORTFOLIO_SNAPSHOT_PROCESS_JOB_NAME,
PORTFOLIO_SNAPSHOT_PROCESS_JOB_OPTIONS, PORTFOLIO_SNAPSHOT_PROCESS_JOB_OPTIONS,
PORTFOLIO_SNAPSHOT_COMPUTATION_QUEUE_PRIORITY_HIGH, PORTFOLIO_SNAPSHOT_COMPUTATION_QUEUE_PRIORITY_HIGH,
@ -287,7 +288,9 @@ export abstract class PortfolioCalculator {
firstIndex--; firstIndex--;
} }
const positions: TimelinePosition[] = []; const positions: (TimelinePosition & {
isInvestmentAssetProfilePosition: boolean;
})[] = [];
let hasAnySymbolMetricsErrors = false; let hasAnySymbolMetricsErrors = false;
const errors: ResponseError['errors'] = []; const errors: ResponseError['errors'] = [];
@ -411,6 +414,7 @@ export abstract class PortfolioCalculator {
: null, : null,
investment: totalInvestment, investment: totalInvestment,
investmentWithCurrencyEffect: totalInvestmentWithCurrencyEffect, investmentWithCurrencyEffect: totalInvestmentWithCurrencyEffect,
isInvestmentAssetProfilePosition: item.isInvestmentAssetProfileItem,
marketPrice: marketPrice:
marketSymbolMap[endDateString]?.[item.symbol]?.toNumber() ?? null, marketSymbolMap[endDateString]?.[item.symbol]?.toNumber() ?? null,
marketPriceInBaseCurrency: marketPriceInBaseCurrency:
@ -605,14 +609,23 @@ export abstract class PortfolioCalculator {
const overall = this.calculateOverallPerformance(positions); 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 { return {
...overall, ...overall,
errors, errors,
historicalData, historicalData,
positions,
totalInterestWithCurrencyEffect, totalInterestWithCurrencyEffect,
totalLiabilitiesWithCurrencyEffect, totalLiabilitiesWithCurrencyEffect,
hasErrors: hasAnySymbolMetricsErrors || overall.hasErrors hasErrors: hasAnySymbolMetricsErrors || overall.hasErrors,
positions: investmentPositions
}; };
} }
@ -935,6 +948,8 @@ export abstract class PortfolioCalculator {
dividend: new Big(0), dividend: new Big(0),
fee: oldAccumulatedSymbol.fee.plus(fee), fee: oldAccumulatedSymbol.fee.plus(fee),
firstBuyDate: oldAccumulatedSymbol.firstBuyDate, firstBuyDate: oldAccumulatedSymbol.firstBuyDate,
isInvestmentAssetProfileItem:
oldAccumulatedSymbol.isInvestmentAssetProfileItem,
quantity: newQuantity, quantity: newQuantity,
tags: oldAccumulatedSymbol.tags.concat(tags), tags: oldAccumulatedSymbol.tags.concat(tags),
transactionCount: oldAccumulatedSymbol.transactionCount + 1 transactionCount: oldAccumulatedSymbol.transactionCount + 1
@ -951,6 +966,8 @@ export abstract class PortfolioCalculator {
dividend: new Big(0), dividend: new Big(0),
firstBuyDate: date, firstBuyDate: date,
investment: unitPrice.mul(quantity).mul(factor), investment: unitPrice.mul(quantity).mul(factor),
isInvestmentAssetProfileItem:
INVESTMENT_ACTIVITY_TYPES.includes(type),
quantity: quantity.mul(factor), quantity: quantity.mul(factor),
transactionCount: 1 transactionCount: 1
}; };

32
apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-fee.spec.ts

@ -116,37 +116,7 @@ describe('PortfolioCalculator', () => {
currentValueInBaseCurrency: new Big('0'), currentValueInBaseCurrency: new Big('0'),
errors: [], errors: [],
hasErrors: true, hasErrors: true,
positions: [ 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')
}
],
totalFeesWithCurrencyEffect: new Big('49'), totalFeesWithCurrencyEffect: new Big('49'),
totalInterestWithCurrencyEffect: new Big('0'), totalInterestWithCurrencyEffect: new Big('0'),
totalInvestment: new Big('0'), totalInvestment: new Big('0'),

1
apps/api/src/app/portfolio/interfaces/transaction-point-symbol.interface.ts

@ -9,6 +9,7 @@ export interface TransactionPointSymbol {
fee: Big; fee: Big;
firstBuyDate: string; firstBuyDate: string;
investment: Big; investment: Big;
isInvestmentAssetProfileItem: boolean;
quantity: Big; quantity: Big;
skipErrors: boolean; skipErrors: boolean;
symbol: string; symbol: string;

9
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 { JobOptions, JobStatus } from 'bull';
import ms from 'ms'; import ms from 'ms';
@ -118,6 +118,13 @@ export const GATHER_HISTORICAL_MARKET_DATA_PROCESS_JOB_OPTIONS: JobOptions = {
removeOnComplete: true 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_NAME = 'PORTFOLIO';
export const PORTFOLIO_SNAPSHOT_PROCESS_JOB_OPTIONS: JobOptions = { export const PORTFOLIO_SNAPSHOT_PROCESS_JOB_OPTIONS: JobOptions = {
removeOnComplete: true removeOnComplete: true

Loading…
Cancel
Save