|  |  | @ -6,6 +6,8 @@ import { PortfolioOrder } from '@ghostfolio/api/app/portfolio/interfaces/portfol | 
			
		
	
		
			
				
					|  |  |  | import { TimelineSpecification } from '@ghostfolio/api/app/portfolio/interfaces/timeline-specification.interface'; | 
			
		
	
		
			
				
					|  |  |  | import { TransactionPoint } from '@ghostfolio/api/app/portfolio/interfaces/transaction-point.interface'; | 
			
		
	
		
			
				
					|  |  |  | import { PortfolioCalculator } from '@ghostfolio/api/app/portfolio/portfolio-calculator'; | 
			
		
	
		
			
				
					|  |  |  | import { UserSettings } from '@ghostfolio/api/app/user/interfaces/user-settings.interface'; | 
			
		
	
		
			
				
					|  |  |  | import { UserService } from '@ghostfolio/api/app/user/user.service'; | 
			
		
	
		
			
				
					|  |  |  | import { AccountClusterRiskCurrentInvestment } from '@ghostfolio/api/models/rules/account-cluster-risk/current-investment'; | 
			
		
	
		
			
				
					|  |  |  | import { AccountClusterRiskInitialInvestment } from '@ghostfolio/api/models/rules/account-cluster-risk/initial-investment'; | 
			
		
	
		
			
				
					|  |  |  | import { AccountClusterRiskSingleAccount } from '@ghostfolio/api/models/rules/account-cluster-risk/single-account'; | 
			
		
	
	
		
			
				
					|  |  | @ -20,7 +22,11 @@ import { ImpersonationService } from '@ghostfolio/api/services/impersonation.ser | 
			
		
	
		
			
				
					|  |  |  | import { MarketState } from '@ghostfolio/api/services/interfaces/interfaces'; | 
			
		
	
		
			
				
					|  |  |  | import { EnhancedSymbolProfile } from '@ghostfolio/api/services/interfaces/symbol-profile.interface'; | 
			
		
	
		
			
				
					|  |  |  | import { SymbolProfileService } from '@ghostfolio/api/services/symbol-profile.service'; | 
			
		
	
		
			
				
					|  |  |  | import { UNKNOWN_KEY, baseCurrency } from '@ghostfolio/common/config'; | 
			
		
	
		
			
				
					|  |  |  | import { | 
			
		
	
		
			
				
					|  |  |  |   ASSET_SUB_CLASS_EMERGENCY_FUND, | 
			
		
	
		
			
				
					|  |  |  |   UNKNOWN_KEY, | 
			
		
	
		
			
				
					|  |  |  |   baseCurrency | 
			
		
	
		
			
				
					|  |  |  | } from '@ghostfolio/common/config'; | 
			
		
	
		
			
				
					|  |  |  | import { DATE_FORMAT, parseDate } from '@ghostfolio/common/helper'; | 
			
		
	
		
			
				
					|  |  |  | import { | 
			
		
	
		
			
				
					|  |  |  |   Accounts, | 
			
		
	
	
		
			
				
					|  |  | @ -75,7 +81,8 @@ export class PortfolioService { | 
			
		
	
		
			
				
					|  |  |  |     private readonly orderService: OrderService, | 
			
		
	
		
			
				
					|  |  |  |     @Inject(REQUEST) private readonly request: RequestWithUser, | 
			
		
	
		
			
				
					|  |  |  |     private readonly rulesService: RulesService, | 
			
		
	
		
			
				
					|  |  |  |     private readonly symbolProfileService: SymbolProfileService | 
			
		
	
		
			
				
					|  |  |  |     private readonly symbolProfileService: SymbolProfileService, | 
			
		
	
		
			
				
					|  |  |  |     private readonly userService: UserService | 
			
		
	
		
			
				
					|  |  |  |   ) {} | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |   public async getAccounts(aUserId: string): Promise<AccountWithValue[]> { | 
			
		
	
	
		
			
				
					|  |  | @ -286,7 +293,11 @@ export class PortfolioService { | 
			
		
	
		
			
				
					|  |  |  |     aDateRange: DateRange = 'max' | 
			
		
	
		
			
				
					|  |  |  |   ): Promise<PortfolioDetails & { hasErrors: boolean }> { | 
			
		
	
		
			
				
					|  |  |  |     const userId = await this.getUserId(aImpersonationId, aUserId); | 
			
		
	
		
			
				
					|  |  |  |     const user = await this.userService.user({ id: userId }); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     const emergencyFund = new Big( | 
			
		
	
		
			
				
					|  |  |  |       (user.Settings?.settings as UserSettings)?.emergencyFund ?? 0 | 
			
		
	
		
			
				
					|  |  |  |     ); | 
			
		
	
		
			
				
					|  |  |  |     const userCurrency = this.request.user?.Settings?.currency ?? baseCurrency; | 
			
		
	
		
			
				
					|  |  |  |     const portfolioCalculator = new PortfolioCalculator( | 
			
		
	
		
			
				
					|  |  |  |       this.currentRateService, | 
			
		
	
	
		
			
				
					|  |  | @ -381,6 +392,7 @@ export class PortfolioService { | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     const cashPositions = await this.getCashPositions({ | 
			
		
	
		
			
				
					|  |  |  |       cashDetails, | 
			
		
	
		
			
				
					|  |  |  |       emergencyFund, | 
			
		
	
		
			
				
					|  |  |  |       userCurrency, | 
			
		
	
		
			
				
					|  |  |  |       investment: totalInvestment, | 
			
		
	
		
			
				
					|  |  |  |       value: totalValue | 
			
		
	
	
		
			
				
					|  |  | @ -861,6 +873,7 @@ export class PortfolioService { | 
			
		
	
		
			
				
					|  |  |  |   public async getSummary(aImpersonationId: string): Promise<PortfolioSummary> { | 
			
		
	
		
			
				
					|  |  |  |     const userCurrency = this.request.user.Settings.currency; | 
			
		
	
		
			
				
					|  |  |  |     const userId = await this.getUserId(aImpersonationId, this.request.user.id); | 
			
		
	
		
			
				
					|  |  |  |     const user = await this.userService.user({ id: userId }); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     const performanceInformation = await this.getPerformance(aImpersonationId); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  | @ -873,6 +886,9 @@ export class PortfolioService { | 
			
		
	
		
			
				
					|  |  |  |       userId | 
			
		
	
		
			
				
					|  |  |  |     }); | 
			
		
	
		
			
				
					|  |  |  |     const dividend = this.getDividend(orders).toNumber(); | 
			
		
	
		
			
				
					|  |  |  |     const emergencyFund = new Big( | 
			
		
	
		
			
				
					|  |  |  |       (user.Settings?.settings as UserSettings)?.emergencyFund ?? 0 | 
			
		
	
		
			
				
					|  |  |  |     ); | 
			
		
	
		
			
				
					|  |  |  |     const fees = this.getFees(orders).toNumber(); | 
			
		
	
		
			
				
					|  |  |  |     const firstOrderDate = orders[0]?.date; | 
			
		
	
		
			
				
					|  |  |  |     const items = this.getItems(orders).toNumber(); | 
			
		
	
	
		
			
				
					|  |  | @ -880,6 +896,7 @@ export class PortfolioService { | 
			
		
	
		
			
				
					|  |  |  |     const totalBuy = this.getTotalByType(orders, userCurrency, 'BUY'); | 
			
		
	
		
			
				
					|  |  |  |     const totalSell = this.getTotalByType(orders, userCurrency, 'SELL'); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     const cash = new Big(balanceInBaseCurrency).minus(emergencyFund).toNumber(); | 
			
		
	
		
			
				
					|  |  |  |     const committedFunds = new Big(totalBuy).minus(totalSell); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     const netWorth = new Big(balanceInBaseCurrency) | 
			
		
	
	
		
			
				
					|  |  | @ -889,6 +906,7 @@ export class PortfolioService { | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     return { | 
			
		
	
		
			
				
					|  |  |  |       ...performanceInformation.performance, | 
			
		
	
		
			
				
					|  |  |  |       cash, | 
			
		
	
		
			
				
					|  |  |  |       dividend, | 
			
		
	
		
			
				
					|  |  |  |       fees, | 
			
		
	
		
			
				
					|  |  |  |       firstOrderDate, | 
			
		
	
	
		
			
				
					|  |  | @ -898,8 +916,8 @@ export class PortfolioService { | 
			
		
	
		
			
				
					|  |  |  |       totalSell, | 
			
		
	
		
			
				
					|  |  |  |       annualizedPerformancePercent: | 
			
		
	
		
			
				
					|  |  |  |         performanceInformation.performance.annualizedPerformancePercent, | 
			
		
	
		
			
				
					|  |  |  |       cash: balanceInBaseCurrency, | 
			
		
	
		
			
				
					|  |  |  |       committedFunds: committedFunds.toNumber(), | 
			
		
	
		
			
				
					|  |  |  |       emergencyFund: emergencyFund.toNumber(), | 
			
		
	
		
			
				
					|  |  |  |       ordersCount: orders.filter((order) => { | 
			
		
	
		
			
				
					|  |  |  |         return order.type === 'BUY' || order.type === 'SELL'; | 
			
		
	
		
			
				
					|  |  |  |       }).length | 
			
		
	
	
		
			
				
					|  |  | @ -908,16 +926,18 @@ export class PortfolioService { | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |   private async getCashPositions({ | 
			
		
	
		
			
				
					|  |  |  |     cashDetails, | 
			
		
	
		
			
				
					|  |  |  |     emergencyFund, | 
			
		
	
		
			
				
					|  |  |  |     investment, | 
			
		
	
		
			
				
					|  |  |  |     userCurrency, | 
			
		
	
		
			
				
					|  |  |  |     value | 
			
		
	
		
			
				
					|  |  |  |   }: { | 
			
		
	
		
			
				
					|  |  |  |     cashDetails: CashDetails; | 
			
		
	
		
			
				
					|  |  |  |     emergencyFund: Big; | 
			
		
	
		
			
				
					|  |  |  |     investment: Big; | 
			
		
	
		
			
				
					|  |  |  |     userCurrency: string; | 
			
		
	
		
			
				
					|  |  |  |     value: Big; | 
			
		
	
		
			
				
					|  |  |  |   }) { | 
			
		
	
		
			
				
					|  |  |  |     const cashPositions = {}; | 
			
		
	
		
			
				
					|  |  |  |     const cashPositions: PortfolioDetails['holdings'] = {}; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     for (const account of cashDetails.accounts) { | 
			
		
	
		
			
				
					|  |  |  |       const convertedBalance = this.exchangeRateDataService.toCurrency( | 
			
		
	
	
		
			
				
					|  |  | @ -941,6 +961,7 @@ export class PortfolioService { | 
			
		
	
		
			
				
					|  |  |  |           assetSubClass: AssetClass.CASH, | 
			
		
	
		
			
				
					|  |  |  |           countries: [], | 
			
		
	
		
			
				
					|  |  |  |           currency: account.currency, | 
			
		
	
		
			
				
					|  |  |  |           dataSource: undefined, | 
			
		
	
		
			
				
					|  |  |  |           grossPerformance: 0, | 
			
		
	
		
			
				
					|  |  |  |           grossPerformancePercent: 0, | 
			
		
	
		
			
				
					|  |  |  |           investment: convertedBalance, | 
			
		
	
	
		
			
				
					|  |  | @ -958,6 +979,28 @@ export class PortfolioService { | 
			
		
	
		
			
				
					|  |  |  |       } | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     if (emergencyFund.gt(0)) { | 
			
		
	
		
			
				
					|  |  |  |       cashPositions[ASSET_SUB_CLASS_EMERGENCY_FUND] = { | 
			
		
	
		
			
				
					|  |  |  |         ...cashPositions[userCurrency], | 
			
		
	
		
			
				
					|  |  |  |         assetSubClass: ASSET_SUB_CLASS_EMERGENCY_FUND, | 
			
		
	
		
			
				
					|  |  |  |         investment: emergencyFund.toNumber(), | 
			
		
	
		
			
				
					|  |  |  |         name: ASSET_SUB_CLASS_EMERGENCY_FUND, | 
			
		
	
		
			
				
					|  |  |  |         symbol: ASSET_SUB_CLASS_EMERGENCY_FUND, | 
			
		
	
		
			
				
					|  |  |  |         value: emergencyFund.toNumber() | 
			
		
	
		
			
				
					|  |  |  |       }; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |       cashPositions[userCurrency].investment = new Big( | 
			
		
	
		
			
				
					|  |  |  |         cashPositions[userCurrency].investment | 
			
		
	
		
			
				
					|  |  |  |       ) | 
			
		
	
		
			
				
					|  |  |  |         .minus(emergencyFund) | 
			
		
	
		
			
				
					|  |  |  |         .toNumber(); | 
			
		
	
		
			
				
					|  |  |  |       cashPositions[userCurrency].value = new Big( | 
			
		
	
		
			
				
					|  |  |  |         cashPositions[userCurrency].value | 
			
		
	
		
			
				
					|  |  |  |       ) | 
			
		
	
		
			
				
					|  |  |  |         .minus(emergencyFund) | 
			
		
	
		
			
				
					|  |  |  |         .toNumber(); | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     for (const symbol of Object.keys(cashPositions)) { | 
			
		
	
		
			
				
					|  |  |  |       // Calculate allocations for each currency
 | 
			
		
	
		
			
				
					|  |  |  |       cashPositions[symbol].allocationCurrent = new Big( | 
			
		
	
	
		
			
				
					|  |  | 
 |