|
|
|
@ -439,15 +439,33 @@ export class PortfolioService {
|
|
|
|
|
portfolioItemsNow[position.symbol] = position;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (const item of currentPositions.positions) {
|
|
|
|
|
if (item.quantity.lte(0)) {
|
|
|
|
|
for (const {
|
|
|
|
|
currency,
|
|
|
|
|
firstBuyDate,
|
|
|
|
|
grossPerformance,
|
|
|
|
|
grossPerformanceWithCurrencyEffect,
|
|
|
|
|
grossPerformancePercentage,
|
|
|
|
|
grossPerformancePercentageWithCurrencyEffect,
|
|
|
|
|
investment,
|
|
|
|
|
marketPrice,
|
|
|
|
|
marketPriceInBaseCurrency,
|
|
|
|
|
netPerformance,
|
|
|
|
|
netPerformancePercentage,
|
|
|
|
|
netPerformancePercentageWithCurrencyEffect,
|
|
|
|
|
netPerformanceWithCurrencyEffect,
|
|
|
|
|
quantity,
|
|
|
|
|
symbol,
|
|
|
|
|
tags,
|
|
|
|
|
transactionCount
|
|
|
|
|
} of currentPositions.positions) {
|
|
|
|
|
if (quantity.eq(0)) {
|
|
|
|
|
// Ignore positions without any quantity
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const value = item.quantity.mul(item.marketPriceInBaseCurrency ?? 0);
|
|
|
|
|
const symbolProfile = symbolProfileMap[item.symbol];
|
|
|
|
|
const dataProviderResponse = dataProviderResponses[item.symbol];
|
|
|
|
|
const value = quantity.mul(marketPriceInBaseCurrency ?? 0);
|
|
|
|
|
const symbolProfile = symbolProfileMap[symbol];
|
|
|
|
|
const dataProviderResponse = dataProviderResponses[symbol];
|
|
|
|
|
|
|
|
|
|
const markets: PortfolioPosition['markets'] = {
|
|
|
|
|
[UNKNOWN_KEY]: 0,
|
|
|
|
@ -519,40 +537,39 @@ export class PortfolioService {
|
|
|
|
|
.toNumber();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
holdings[item.symbol] = {
|
|
|
|
|
holdings[symbol] = {
|
|
|
|
|
currency,
|
|
|
|
|
markets,
|
|
|
|
|
marketsAdvanced,
|
|
|
|
|
marketPrice,
|
|
|
|
|
symbol,
|
|
|
|
|
tags,
|
|
|
|
|
transactionCount,
|
|
|
|
|
allocationInPercentage: filteredValueInBaseCurrency.eq(0)
|
|
|
|
|
? 0
|
|
|
|
|
: value.div(filteredValueInBaseCurrency).toNumber(),
|
|
|
|
|
assetClass: symbolProfile.assetClass,
|
|
|
|
|
assetSubClass: symbolProfile.assetSubClass,
|
|
|
|
|
countries: symbolProfile.countries,
|
|
|
|
|
currency: item.currency,
|
|
|
|
|
dataSource: symbolProfile.dataSource,
|
|
|
|
|
dateOfFirstActivity: parseDate(item.firstBuyDate),
|
|
|
|
|
grossPerformance: item.grossPerformance?.toNumber() ?? 0,
|
|
|
|
|
grossPerformancePercent:
|
|
|
|
|
item.grossPerformancePercentage?.toNumber() ?? 0,
|
|
|
|
|
dateOfFirstActivity: parseDate(firstBuyDate),
|
|
|
|
|
grossPerformance: grossPerformance?.toNumber() ?? 0,
|
|
|
|
|
grossPerformancePercent: grossPerformancePercentage?.toNumber() ?? 0,
|
|
|
|
|
grossPerformancePercentWithCurrencyEffect:
|
|
|
|
|
item.grossPerformancePercentageWithCurrencyEffect?.toNumber() ?? 0,
|
|
|
|
|
grossPerformancePercentageWithCurrencyEffect?.toNumber() ?? 0,
|
|
|
|
|
grossPerformanceWithCurrencyEffect:
|
|
|
|
|
item.grossPerformanceWithCurrencyEffect?.toNumber() ?? 0,
|
|
|
|
|
investment: item.investment.toNumber(),
|
|
|
|
|
marketPrice: item.marketPrice,
|
|
|
|
|
grossPerformanceWithCurrencyEffect?.toNumber() ?? 0,
|
|
|
|
|
investment: investment.toNumber(),
|
|
|
|
|
marketState: dataProviderResponse?.marketState ?? 'delayed',
|
|
|
|
|
name: symbolProfile.name,
|
|
|
|
|
netPerformance: item.netPerformance?.toNumber() ?? 0,
|
|
|
|
|
netPerformancePercent: item.netPerformancePercentage?.toNumber() ?? 0,
|
|
|
|
|
netPerformance: netPerformance?.toNumber() ?? 0,
|
|
|
|
|
netPerformancePercent: netPerformancePercentage?.toNumber() ?? 0,
|
|
|
|
|
netPerformancePercentWithCurrencyEffect:
|
|
|
|
|
item.netPerformancePercentageWithCurrencyEffect?.toNumber() ?? 0,
|
|
|
|
|
netPerformancePercentageWithCurrencyEffect?.toNumber() ?? 0,
|
|
|
|
|
netPerformanceWithCurrencyEffect:
|
|
|
|
|
item.netPerformanceWithCurrencyEffect?.toNumber() ?? 0,
|
|
|
|
|
quantity: item.quantity.toNumber(),
|
|
|
|
|
netPerformanceWithCurrencyEffect?.toNumber() ?? 0,
|
|
|
|
|
quantity: quantity.toNumber(),
|
|
|
|
|
sectors: symbolProfile.sectors,
|
|
|
|
|
symbol: item.symbol,
|
|
|
|
|
tags: item.tags,
|
|
|
|
|
transactionCount: item.transactionCount,
|
|
|
|
|
url: symbolProfile.url,
|
|
|
|
|
valueInBaseCurrency: value.toNumber()
|
|
|
|
|
};
|
|
|
|
@ -1770,24 +1787,33 @@ export class PortfolioService {
|
|
|
|
|
activityType: 'INTEREST'
|
|
|
|
|
}).toNumber();
|
|
|
|
|
|
|
|
|
|
const items = Object.keys(holdings)
|
|
|
|
|
.filter((symbol) => {
|
|
|
|
|
return isUUID(symbol) && holdings[symbol].dataSource === 'MANUAL';
|
|
|
|
|
})
|
|
|
|
|
.map((symbol) => {
|
|
|
|
|
return holdings[symbol].valueInBaseCurrency;
|
|
|
|
|
})
|
|
|
|
|
.reduce(
|
|
|
|
|
(previous, current) => new Big(previous).plus(current),
|
|
|
|
|
new Big(0)
|
|
|
|
|
)
|
|
|
|
|
.toNumber();
|
|
|
|
|
|
|
|
|
|
const liabilities = this.getSumOfActivityType({
|
|
|
|
|
activities,
|
|
|
|
|
userCurrency,
|
|
|
|
|
activityType: 'LIABILITY'
|
|
|
|
|
}).toNumber();
|
|
|
|
|
const items = getSum(
|
|
|
|
|
Object.keys(holdings)
|
|
|
|
|
.filter((symbol) => {
|
|
|
|
|
return (
|
|
|
|
|
isUUID(symbol) &&
|
|
|
|
|
holdings[symbol].dataSource === 'MANUAL' &&
|
|
|
|
|
holdings[symbol].valueInBaseCurrency > 0
|
|
|
|
|
);
|
|
|
|
|
})
|
|
|
|
|
.map((symbol) => {
|
|
|
|
|
return new Big(holdings[symbol].valueInBaseCurrency).abs();
|
|
|
|
|
})
|
|
|
|
|
).toNumber();
|
|
|
|
|
|
|
|
|
|
const liabilities = getSum(
|
|
|
|
|
Object.keys(holdings)
|
|
|
|
|
.filter((symbol) => {
|
|
|
|
|
return (
|
|
|
|
|
isUUID(symbol) &&
|
|
|
|
|
holdings[symbol].dataSource === 'MANUAL' &&
|
|
|
|
|
holdings[symbol].valueInBaseCurrency < 0
|
|
|
|
|
);
|
|
|
|
|
})
|
|
|
|
|
.map((symbol) => {
|
|
|
|
|
return new Big(holdings[symbol].valueInBaseCurrency).abs();
|
|
|
|
|
})
|
|
|
|
|
).toNumber();
|
|
|
|
|
|
|
|
|
|
const totalBuy = this.getSumOfActivityType({
|
|
|
|
|
userCurrency,
|
|
|
|
@ -1941,7 +1967,7 @@ export class PortfolioService {
|
|
|
|
|
private async getTransactionPoints({
|
|
|
|
|
filters,
|
|
|
|
|
includeDrafts = false,
|
|
|
|
|
types = ['BUY', 'ITEM', 'SELL'],
|
|
|
|
|
types = ['BUY', 'ITEM', 'LIABILITY', 'SELL'],
|
|
|
|
|
userId,
|
|
|
|
|
withExcludedAccounts = false
|
|
|
|
|
}: {
|
|
|
|
@ -2076,19 +2102,10 @@ export class PortfolioService {
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
for (const account of currentAccounts) {
|
|
|
|
|
let ordersByAccount = orders.filter(({ accountId }) => {
|
|
|
|
|
const ordersByAccount = orders.filter(({ accountId }) => {
|
|
|
|
|
return accountId === account.id;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const ordersOfTypeItemOrLiabilityByAccount =
|
|
|
|
|
ordersOfTypeItemOrLiability.filter(({ accountId }) => {
|
|
|
|
|
return accountId === account.id;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
ordersByAccount = ordersByAccount.concat(
|
|
|
|
|
ordersOfTypeItemOrLiabilityByAccount
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
accounts[account.id] = {
|
|
|
|
|
balance: account.balance,
|
|
|
|
|
currency: account.currency,
|
|
|
|
@ -2128,8 +2145,8 @@ export class PortfolioService {
|
|
|
|
|
} of ordersByAccount) {
|
|
|
|
|
let currentValueOfSymbolInBaseCurrency =
|
|
|
|
|
quantity *
|
|
|
|
|
portfolioItemsNow[SymbolProfile.symbol]
|
|
|
|
|
?.marketPriceInBaseCurrency ?? 0;
|
|
|
|
|
(portfolioItemsNow[SymbolProfile.symbol]?.marketPriceInBaseCurrency ??
|
|
|
|
|
0);
|
|
|
|
|
|
|
|
|
|
if (['LIABILITY', 'SELL'].includes(type)) {
|
|
|
|
|
currentValueOfSymbolInBaseCurrency *= getFactor(type);
|
|
|
|
|