Browse Source

feat(api): create getCashSymbolProfiles method

pull/5650/head
KenTandrian 1 week ago
parent
commit
543a44a1a7
  1. 1
      apps/api/src/app/portfolio/calculator/portfolio-calculator.ts
  2. 50
      apps/api/src/app/portfolio/portfolio.service.ts
  3. 4
      libs/common/src/lib/models/timeline-position.ts

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

@ -405,7 +405,6 @@ export abstract class PortfolioCalculator {
feeInBaseCurrency, feeInBaseCurrency,
timeWeightedInvestment, timeWeightedInvestment,
timeWeightedInvestmentWithCurrencyEffect, timeWeightedInvestmentWithCurrencyEffect,
assetSubClass: item.assetSubClass,
dividend: totalDividend, dividend: totalDividend,
dividendInBaseCurrency: totalDividendInBaseCurrency, dividendInBaseCurrency: totalDividendInBaseCurrency,
averagePrice: item.averagePrice, averagePrice: item.averagePrice,

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

@ -553,6 +553,9 @@ export class PortfolioService {
assetProfileIdentifiers assetProfileIdentifiers
); );
const cashSymbolProfiles = this.getCashSymbolProfiles(cashDetails);
symbolProfiles.push(...cashSymbolProfiles);
const symbolProfileMap: { [symbol: string]: EnhancedSymbolProfile } = {}; const symbolProfileMap: { [symbol: string]: EnhancedSymbolProfile } = {};
for (const symbolProfile of symbolProfiles) { for (const symbolProfile of symbolProfiles) {
symbolProfileMap[symbolProfile.symbol] = symbolProfile; symbolProfileMap[symbolProfile.symbol] = symbolProfile;
@ -564,7 +567,6 @@ export class PortfolioService {
} }
for (const { for (const {
assetSubClass,
currency, currency,
dividend, dividend,
firstBuyDate, firstBuyDate,
@ -608,7 +610,6 @@ export class PortfolioService {
} }
holdings[symbol] = { holdings[symbol] = {
assetSubClass,
currency, currency,
markets, markets,
marketsAdvanced, marketsAdvanced,
@ -619,9 +620,10 @@ export class PortfolioService {
allocationInPercentage: filteredValueInBaseCurrency.eq(0) allocationInPercentage: filteredValueInBaseCurrency.eq(0)
? 0 ? 0
: valueInBaseCurrency.div(filteredValueInBaseCurrency).toNumber(), : valueInBaseCurrency.div(filteredValueInBaseCurrency).toNumber(),
assetClass: assetProfile?.assetClass, assetClass: assetProfile.assetClass,
countries: assetProfile?.countries, assetSubClass: assetProfile.assetSubClass,
dataSource: assetProfile?.dataSource, countries: assetProfile.countries,
dataSource: assetProfile.dataSource,
dateOfFirstActivity: parseDate(firstBuyDate), dateOfFirstActivity: parseDate(firstBuyDate),
dividend: dividend?.toNumber() ?? 0, dividend: dividend?.toNumber() ?? 0,
grossPerformance: grossPerformance?.toNumber() ?? 0, grossPerformance: grossPerformance?.toNumber() ?? 0,
@ -631,7 +633,7 @@ export class PortfolioService {
grossPerformanceWithCurrencyEffect: grossPerformanceWithCurrencyEffect:
grossPerformanceWithCurrencyEffect?.toNumber() ?? 0, grossPerformanceWithCurrencyEffect?.toNumber() ?? 0,
holdings: holdings:
assetProfile?.holdings.map(({ allocationInPercentage, name }) => { assetProfile.holdings.map(({ allocationInPercentage, name }) => {
return { return {
allocationInPercentage, allocationInPercentage,
name, name,
@ -641,8 +643,7 @@ export class PortfolioService {
}; };
}) ?? [], }) ?? [],
investment: investment.toNumber(), investment: investment.toNumber(),
name: name: assetProfile.name,
assetSubClass === AssetSubClass.CASH ? currency : assetProfile?.name,
netPerformance: netPerformance?.toNumber() ?? 0, netPerformance: netPerformance?.toNumber() ?? 0,
netPerformancePercent: netPerformancePercentage?.toNumber() ?? 0, netPerformancePercent: netPerformancePercentage?.toNumber() ?? 0,
netPerformancePercentWithCurrencyEffect: netPerformancePercentWithCurrencyEffect:
@ -652,8 +653,8 @@ export class PortfolioService {
netPerformanceWithCurrencyEffect: netPerformanceWithCurrencyEffect:
netPerformanceWithCurrencyEffectMap?.[dateRange]?.toNumber() ?? 0, netPerformanceWithCurrencyEffectMap?.[dateRange]?.toNumber() ?? 0,
quantity: quantity.toNumber(), quantity: quantity.toNumber(),
sectors: assetProfile?.sectors, sectors: assetProfile.sectors,
url: assetProfile?.url, url: assetProfile.url,
valueInBaseCurrency: valueInBaseCurrency.toNumber() valueInBaseCurrency: valueInBaseCurrency.toNumber()
}; };
} }
@ -1533,6 +1534,35 @@ export class PortfolioService {
return cashPositions; return cashPositions;
} }
private getCashSymbolProfiles(cashDetails: CashDetails) {
const cashSymbols = [
...new Set(cashDetails.accounts.map(({ currency }) => currency))
];
return cashSymbols.map<EnhancedSymbolProfile>((currency) => {
const account = cashDetails.accounts.find(
({ currency: accountCurrency }) => accountCurrency === currency
);
return {
currency,
activitiesCount: 0,
assetClass: AssetClass.LIQUIDITY,
assetSubClass: AssetSubClass.CASH,
countries: [],
createdAt: account.createdAt,
dataSource: DataSource.MANUAL,
holdings: [],
id: currency,
isActive: true,
name: currency,
sectors: [],
symbol: currency,
updatedAt: account.updatedAt
};
});
}
private getDividendsByGroup({ private getDividendsByGroup({
dividends, dividends,
groupBy groupBy

4
libs/common/src/lib/models/timeline-position.ts

@ -4,13 +4,11 @@ import {
} from '@ghostfolio/common/class-transformer'; } from '@ghostfolio/common/class-transformer';
import { DateRange } from '@ghostfolio/common/types'; import { DateRange } from '@ghostfolio/common/types';
import { AssetSubClass, DataSource, Tag } from '@prisma/client'; import { DataSource, Tag } from '@prisma/client';
import { Big } from 'big.js'; import { Big } from 'big.js';
import { Transform, Type } from 'class-transformer'; import { Transform, Type } from 'class-transformer';
export class TimelinePosition { export class TimelinePosition {
assetSubClass: AssetSubClass;
@Transform(transformToBig, { toClassOnly: true }) @Transform(transformToBig, { toClassOnly: true })
@Type(() => Big) @Type(() => Big)
averagePrice: Big; averagePrice: Big;

Loading…
Cancel
Save