|
|
|
@ -319,6 +319,92 @@ export class PortfolioService { |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
public async getCashActivities({ |
|
|
|
cashDetails, |
|
|
|
userCurrency, |
|
|
|
userId |
|
|
|
}: { |
|
|
|
cashDetails: CashDetails; |
|
|
|
userCurrency: string; |
|
|
|
userId: string; |
|
|
|
}) { |
|
|
|
const syntheticActivities: Activity[] = []; |
|
|
|
|
|
|
|
for (const account of cashDetails.accounts) { |
|
|
|
const { balances } = await this.accountBalanceService.getAccountBalances({ |
|
|
|
filters: [{ id: account.id, type: 'ACCOUNT' }], |
|
|
|
userCurrency, |
|
|
|
userId |
|
|
|
}); |
|
|
|
|
|
|
|
let currentBalance = 0; |
|
|
|
let currentBalanceInBaseCurrency = 0; |
|
|
|
for (const balanceItem of balances) { |
|
|
|
const syntheticActivityTemplate: Activity = { |
|
|
|
userId, |
|
|
|
accountId: account.id, |
|
|
|
accountUserId: account.userId, |
|
|
|
comment: account.name, |
|
|
|
createdAt: new Date(balanceItem.date), |
|
|
|
currency: account.currency, |
|
|
|
date: new Date(balanceItem.date), |
|
|
|
fee: 0, |
|
|
|
feeInAssetProfileCurrency: 0, |
|
|
|
feeInBaseCurrency: 0, |
|
|
|
id: balanceItem.id, |
|
|
|
isDraft: false, |
|
|
|
quantity: 1, |
|
|
|
SymbolProfile: { |
|
|
|
activitiesCount: 0, |
|
|
|
assetClass: 'LIQUIDITY', |
|
|
|
assetSubClass: 'CASH', |
|
|
|
countries: [], |
|
|
|
createdAt: new Date(balanceItem.date), |
|
|
|
currency: account.currency, |
|
|
|
dataSource: 'YAHOO', |
|
|
|
holdings: [], |
|
|
|
id: account.currency, |
|
|
|
isActive: true, |
|
|
|
sectors: [], |
|
|
|
symbol: account.currency, |
|
|
|
updatedAt: new Date(balanceItem.date) |
|
|
|
}, |
|
|
|
symbolProfileId: account.currency, |
|
|
|
type: 'BUY', |
|
|
|
unitPrice: 1, |
|
|
|
unitPriceInAssetProfileCurrency: 1, |
|
|
|
updatedAt: new Date(balanceItem.date), |
|
|
|
valueInBaseCurrency: 0, |
|
|
|
value: 0 |
|
|
|
}; |
|
|
|
|
|
|
|
if (currentBalance < balanceItem.value) { |
|
|
|
// BUY
|
|
|
|
syntheticActivities.push({ |
|
|
|
...syntheticActivityTemplate, |
|
|
|
type: 'BUY', |
|
|
|
value: balanceItem.value - currentBalance, |
|
|
|
valueInBaseCurrency: |
|
|
|
balanceItem.valueInBaseCurrency - currentBalanceInBaseCurrency |
|
|
|
}); |
|
|
|
} else if (currentBalance > balanceItem.value) { |
|
|
|
// SELL
|
|
|
|
syntheticActivities.push({ |
|
|
|
...syntheticActivityTemplate, |
|
|
|
type: 'SELL', |
|
|
|
value: currentBalance - balanceItem.value, |
|
|
|
valueInBaseCurrency: |
|
|
|
currentBalanceInBaseCurrency - balanceItem.valueInBaseCurrency |
|
|
|
}); |
|
|
|
} |
|
|
|
currentBalance = balanceItem.value; |
|
|
|
currentBalanceInBaseCurrency = balanceItem.valueInBaseCurrency; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return syntheticActivities; |
|
|
|
} |
|
|
|
|
|
|
|
public async getDividends({ |
|
|
|
activities, |
|
|
|
groupBy |
|
|
|
@ -488,6 +574,7 @@ export class PortfolioService { |
|
|
|
(user.settings?.settings as UserSettings)?.emergencyFund ?? 0 |
|
|
|
); |
|
|
|
|
|
|
|
// Activities for non-cash assets
|
|
|
|
const { activities } = |
|
|
|
await this.orderService.getOrdersForPortfolioCalculator({ |
|
|
|
filters, |
|
|
|
@ -495,23 +582,29 @@ export class PortfolioService { |
|
|
|
userId |
|
|
|
}); |
|
|
|
|
|
|
|
const portfolioCalculator = this.calculatorFactory.createCalculator({ |
|
|
|
activities, |
|
|
|
// Synthetic activities for cash
|
|
|
|
const cashDetails = await this.accountService.getCashDetails({ |
|
|
|
filters, |
|
|
|
userId, |
|
|
|
calculationType: this.getUserPerformanceCalculationType(user), |
|
|
|
currency: userCurrency |
|
|
|
}); |
|
|
|
const cashActivities = await this.getCashActivities({ |
|
|
|
cashDetails, |
|
|
|
userCurrency, |
|
|
|
userId |
|
|
|
}); |
|
|
|
|
|
|
|
const { createdAt, currentValueInBaseCurrency, hasErrors, positions } = |
|
|
|
await portfolioCalculator.getSnapshot(); |
|
|
|
|
|
|
|
const cashDetails = await this.accountService.getCashDetails({ |
|
|
|
const portfolioCalculator = this.calculatorFactory.createCalculator({ |
|
|
|
filters, |
|
|
|
userId, |
|
|
|
activities: [...activities, ...cashActivities], |
|
|
|
calculationType: this.getUserPerformanceCalculationType(user), |
|
|
|
currency: userCurrency |
|
|
|
}); |
|
|
|
|
|
|
|
const { createdAt, currentValueInBaseCurrency, hasErrors, positions } = |
|
|
|
await portfolioCalculator.getSnapshot(); |
|
|
|
|
|
|
|
const holdings: PortfolioDetails['holdings'] = {}; |
|
|
|
|
|
|
|
const totalValueInBaseCurrency = currentValueInBaseCurrency.plus( |
|
|
|
|