|
|
@ -88,7 +88,6 @@ import { |
|
|
parseISO, |
|
|
parseISO, |
|
|
set |
|
|
set |
|
|
} from 'date-fns'; |
|
|
} from 'date-fns'; |
|
|
import { isEmpty } from 'lodash'; |
|
|
|
|
|
|
|
|
|
|
|
import { PortfolioCalculator } from './calculator/portfolio-calculator'; |
|
|
import { PortfolioCalculator } from './calculator/portfolio-calculator'; |
|
|
import { PortfolioCalculatorFactory } from './calculator/portfolio-calculator.factory'; |
|
|
import { PortfolioCalculatorFactory } from './calculator/portfolio-calculator.factory'; |
|
|
@ -776,35 +775,7 @@ export class PortfolioService { |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
if (activities.length === 0) { |
|
|
if (activities.length === 0) { |
|
|
return { |
|
|
return undefined; |
|
|
activities: [], |
|
|
|
|
|
activitiesCount: 0, |
|
|
|
|
|
averagePrice: undefined, |
|
|
|
|
|
dataProviderInfo: undefined, |
|
|
|
|
|
dividendInBaseCurrency: undefined, |
|
|
|
|
|
dividendYieldPercent: undefined, |
|
|
|
|
|
dividendYieldPercentWithCurrencyEffect: undefined, |
|
|
|
|
|
feeInBaseCurrency: undefined, |
|
|
|
|
|
firstBuyDate: undefined, |
|
|
|
|
|
grossPerformance: undefined, |
|
|
|
|
|
grossPerformancePercent: undefined, |
|
|
|
|
|
grossPerformancePercentWithCurrencyEffect: undefined, |
|
|
|
|
|
grossPerformanceWithCurrencyEffect: undefined, |
|
|
|
|
|
historicalData: [], |
|
|
|
|
|
investmentInBaseCurrencyWithCurrencyEffect: undefined, |
|
|
|
|
|
marketPrice: undefined, |
|
|
|
|
|
marketPriceMax: undefined, |
|
|
|
|
|
marketPriceMin: undefined, |
|
|
|
|
|
netPerformance: undefined, |
|
|
|
|
|
netPerformancePercent: undefined, |
|
|
|
|
|
netPerformancePercentWithCurrencyEffect: undefined, |
|
|
|
|
|
netPerformanceWithCurrencyEffect: undefined, |
|
|
|
|
|
performances: undefined, |
|
|
|
|
|
quantity: undefined, |
|
|
|
|
|
SymbolProfile: undefined, |
|
|
|
|
|
tags: [], |
|
|
|
|
|
value: undefined |
|
|
|
|
|
}; |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
const [SymbolProfile] = await this.symbolProfileService.getSymbolProfiles([ |
|
|
const [SymbolProfile] = await this.symbolProfileService.getSymbolProfiles([ |
|
|
@ -818,7 +789,6 @@ export class PortfolioService { |
|
|
currency: userCurrency |
|
|
currency: userCurrency |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
const portfolioStart = portfolioCalculator.getStartDate(); |
|
|
|
|
|
const transactionPoints = portfolioCalculator.getTransactionPoints(); |
|
|
const transactionPoints = portfolioCalculator.getTransactionPoints(); |
|
|
|
|
|
|
|
|
const { positions } = await portfolioCalculator.getSnapshot(); |
|
|
const { positions } = await portfolioCalculator.getSnapshot(); |
|
|
@ -827,225 +797,108 @@ export class PortfolioService { |
|
|
return position.dataSource === dataSource && position.symbol === symbol; |
|
|
return position.dataSource === dataSource && position.symbol === symbol; |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
if (holding) { |
|
|
if (!holding) { |
|
|
const { |
|
|
return undefined; |
|
|
averagePrice, |
|
|
} |
|
|
currency, |
|
|
|
|
|
dividendInBaseCurrency, |
|
|
|
|
|
fee, |
|
|
|
|
|
firstBuyDate, |
|
|
|
|
|
grossPerformance, |
|
|
|
|
|
grossPerformancePercentage, |
|
|
|
|
|
grossPerformancePercentageWithCurrencyEffect, |
|
|
|
|
|
grossPerformanceWithCurrencyEffect, |
|
|
|
|
|
investmentWithCurrencyEffect, |
|
|
|
|
|
marketPrice, |
|
|
|
|
|
netPerformance, |
|
|
|
|
|
netPerformancePercentage, |
|
|
|
|
|
netPerformancePercentageWithCurrencyEffectMap, |
|
|
|
|
|
netPerformanceWithCurrencyEffectMap, |
|
|
|
|
|
quantity, |
|
|
|
|
|
tags, |
|
|
|
|
|
timeWeightedInvestment, |
|
|
|
|
|
timeWeightedInvestmentWithCurrencyEffect, |
|
|
|
|
|
transactionCount |
|
|
|
|
|
} = holding; |
|
|
|
|
|
|
|
|
|
|
|
const activitiesOfHolding = activities.filter(({ SymbolProfile }) => { |
|
|
|
|
|
return ( |
|
|
|
|
|
SymbolProfile.dataSource === dataSource && |
|
|
|
|
|
SymbolProfile.symbol === symbol |
|
|
|
|
|
); |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
const dividendYieldPercent = getAnnualizedPerformancePercent({ |
|
|
|
|
|
daysInMarket: differenceInDays(new Date(), parseDate(firstBuyDate)), |
|
|
|
|
|
netPerformancePercentage: timeWeightedInvestment.eq(0) |
|
|
|
|
|
? new Big(0) |
|
|
|
|
|
: dividendInBaseCurrency.div(timeWeightedInvestment) |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
const dividendYieldPercentWithCurrencyEffect = |
|
|
|
|
|
getAnnualizedPerformancePercent({ |
|
|
|
|
|
daysInMarket: differenceInDays(new Date(), parseDate(firstBuyDate)), |
|
|
|
|
|
netPerformancePercentage: timeWeightedInvestmentWithCurrencyEffect.eq( |
|
|
|
|
|
0 |
|
|
|
|
|
) |
|
|
|
|
|
? new Big(0) |
|
|
|
|
|
: dividendInBaseCurrency.div( |
|
|
|
|
|
timeWeightedInvestmentWithCurrencyEffect |
|
|
|
|
|
) |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
const historicalData = await this.dataProviderService.getHistorical( |
|
|
const { |
|
|
[{ dataSource, symbol }], |
|
|
averagePrice, |
|
|
'day', |
|
|
currency, |
|
|
parseISO(firstBuyDate), |
|
|
dividendInBaseCurrency, |
|
|
new Date() |
|
|
fee, |
|
|
); |
|
|
firstBuyDate, |
|
|
|
|
|
grossPerformance, |
|
|
|
|
|
grossPerformancePercentage, |
|
|
|
|
|
grossPerformancePercentageWithCurrencyEffect, |
|
|
|
|
|
grossPerformanceWithCurrencyEffect, |
|
|
|
|
|
investmentWithCurrencyEffect, |
|
|
|
|
|
marketPrice, |
|
|
|
|
|
netPerformance, |
|
|
|
|
|
netPerformancePercentage, |
|
|
|
|
|
netPerformancePercentageWithCurrencyEffectMap, |
|
|
|
|
|
netPerformanceWithCurrencyEffectMap, |
|
|
|
|
|
quantity, |
|
|
|
|
|
tags, |
|
|
|
|
|
timeWeightedInvestment, |
|
|
|
|
|
timeWeightedInvestmentWithCurrencyEffect, |
|
|
|
|
|
transactionCount |
|
|
|
|
|
} = holding; |
|
|
|
|
|
|
|
|
const historicalDataArray: HistoricalDataItem[] = []; |
|
|
const activitiesOfHolding = activities.filter(({ SymbolProfile }) => { |
|
|
let marketPriceMax = Math.max( |
|
|
return ( |
|
|
activitiesOfHolding[0].unitPriceInAssetProfileCurrency, |
|
|
SymbolProfile.dataSource === dataSource && |
|
|
marketPrice |
|
|
SymbolProfile.symbol === symbol |
|
|
); |
|
|
|
|
|
let marketPriceMaxDate = |
|
|
|
|
|
marketPrice > activitiesOfHolding[0].unitPriceInAssetProfileCurrency |
|
|
|
|
|
? new Date() |
|
|
|
|
|
: activitiesOfHolding[0].date; |
|
|
|
|
|
let marketPriceMin = Math.min( |
|
|
|
|
|
activitiesOfHolding[0].unitPriceInAssetProfileCurrency, |
|
|
|
|
|
marketPrice |
|
|
|
|
|
); |
|
|
); |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
if (historicalData[symbol]) { |
|
|
const dividendYieldPercent = getAnnualizedPerformancePercent({ |
|
|
let j = -1; |
|
|
daysInMarket: differenceInDays(new Date(), parseDate(firstBuyDate)), |
|
|
for (const [date, { marketPrice }] of Object.entries( |
|
|
netPerformancePercentage: timeWeightedInvestment.eq(0) |
|
|
historicalData[symbol] |
|
|
? new Big(0) |
|
|
)) { |
|
|
: dividendInBaseCurrency.div(timeWeightedInvestment) |
|
|
while ( |
|
|
}); |
|
|
j + 1 < transactionPoints.length && |
|
|
|
|
|
!isAfter(parseDate(transactionPoints[j + 1].date), parseDate(date)) |
|
|
|
|
|
) { |
|
|
|
|
|
j++; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
let currentAveragePrice = 0; |
|
|
|
|
|
let currentQuantity = 0; |
|
|
|
|
|
|
|
|
|
|
|
const currentSymbol = transactionPoints[j]?.items.find( |
|
|
const dividendYieldPercentWithCurrencyEffect = |
|
|
(transactionPointSymbol) => { |
|
|
getAnnualizedPerformancePercent({ |
|
|
return transactionPointSymbol.symbol === symbol; |
|
|
daysInMarket: differenceInDays(new Date(), parseDate(firstBuyDate)), |
|
|
} |
|
|
netPerformancePercentage: timeWeightedInvestmentWithCurrencyEffect.eq(0) |
|
|
); |
|
|
? new Big(0) |
|
|
|
|
|
: dividendInBaseCurrency.div(timeWeightedInvestmentWithCurrencyEffect) |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
if (currentSymbol) { |
|
|
const historicalData = await this.dataProviderService.getHistorical( |
|
|
currentAveragePrice = currentSymbol.averagePrice.toNumber(); |
|
|
[{ dataSource, symbol }], |
|
|
currentQuantity = currentSymbol.quantity.toNumber(); |
|
|
'day', |
|
|
} |
|
|
parseISO(firstBuyDate), |
|
|
|
|
|
new Date() |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
historicalDataArray.push({ |
|
|
const historicalDataArray: HistoricalDataItem[] = []; |
|
|
date, |
|
|
let marketPriceMax = Math.max( |
|
|
averagePrice: currentAveragePrice, |
|
|
activitiesOfHolding[0].unitPriceInAssetProfileCurrency, |
|
|
marketPrice: |
|
|
marketPrice |
|
|
historicalDataArray.length > 0 |
|
|
); |
|
|
? marketPrice |
|
|
let marketPriceMaxDate = |
|
|
: currentAveragePrice, |
|
|
marketPrice > activitiesOfHolding[0].unitPriceInAssetProfileCurrency |
|
|
quantity: currentQuantity |
|
|
? new Date() |
|
|
}); |
|
|
: activitiesOfHolding[0].date; |
|
|
|
|
|
let marketPriceMin = Math.min( |
|
|
|
|
|
activitiesOfHolding[0].unitPriceInAssetProfileCurrency, |
|
|
|
|
|
marketPrice |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
if (marketPrice > marketPriceMax) { |
|
|
if (historicalData[symbol]) { |
|
|
marketPriceMax = marketPrice; |
|
|
let j = -1; |
|
|
marketPriceMaxDate = parseISO(date); |
|
|
for (const [date, { marketPrice }] of Object.entries( |
|
|
} |
|
|
historicalData[symbol] |
|
|
marketPriceMin = Math.min( |
|
|
)) { |
|
|
marketPrice ?? Number.MAX_SAFE_INTEGER, |
|
|
while ( |
|
|
marketPriceMin |
|
|
j + 1 < transactionPoints.length && |
|
|
); |
|
|
!isAfter(parseDate(transactionPoints[j + 1].date), parseDate(date)) |
|
|
|
|
|
) { |
|
|
|
|
|
j++; |
|
|
} |
|
|
} |
|
|
} else { |
|
|
|
|
|
// Add historical entry for buy date, if no historical data available
|
|
|
|
|
|
historicalDataArray.push({ |
|
|
|
|
|
averagePrice: activitiesOfHolding[0].unitPriceInAssetProfileCurrency, |
|
|
|
|
|
date: firstBuyDate, |
|
|
|
|
|
marketPrice: activitiesOfHolding[0].unitPriceInAssetProfileCurrency, |
|
|
|
|
|
quantity: activitiesOfHolding[0].quantity |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const performancePercent = |
|
|
let currentAveragePrice = 0; |
|
|
this.benchmarkService.calculateChangeInPercentage( |
|
|
let currentQuantity = 0; |
|
|
marketPriceMax, |
|
|
|
|
|
marketPrice |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
return { |
|
|
const currentSymbol = transactionPoints[j]?.items.find( |
|
|
firstBuyDate, |
|
|
(transactionPointSymbol) => { |
|
|
marketPrice, |
|
|
return transactionPointSymbol.symbol === symbol; |
|
|
marketPriceMax, |
|
|
|
|
|
marketPriceMin, |
|
|
|
|
|
SymbolProfile, |
|
|
|
|
|
tags, |
|
|
|
|
|
activities: activitiesOfHolding, |
|
|
|
|
|
activitiesCount: transactionCount, |
|
|
|
|
|
averagePrice: averagePrice.toNumber(), |
|
|
|
|
|
dataProviderInfo: portfolioCalculator.getDataProviderInfos()?.[0], |
|
|
|
|
|
dividendInBaseCurrency: dividendInBaseCurrency.toNumber(), |
|
|
|
|
|
dividendYieldPercent: dividendYieldPercent.toNumber(), |
|
|
|
|
|
dividendYieldPercentWithCurrencyEffect: |
|
|
|
|
|
dividendYieldPercentWithCurrencyEffect.toNumber(), |
|
|
|
|
|
feeInBaseCurrency: this.exchangeRateDataService.toCurrency( |
|
|
|
|
|
fee.toNumber(), |
|
|
|
|
|
SymbolProfile.currency, |
|
|
|
|
|
userCurrency |
|
|
|
|
|
), |
|
|
|
|
|
grossPerformance: grossPerformance?.toNumber(), |
|
|
|
|
|
grossPerformancePercent: grossPerformancePercentage?.toNumber(), |
|
|
|
|
|
grossPerformancePercentWithCurrencyEffect: |
|
|
|
|
|
grossPerformancePercentageWithCurrencyEffect?.toNumber(), |
|
|
|
|
|
grossPerformanceWithCurrencyEffect: |
|
|
|
|
|
grossPerformanceWithCurrencyEffect?.toNumber(), |
|
|
|
|
|
historicalData: historicalDataArray, |
|
|
|
|
|
investmentInBaseCurrencyWithCurrencyEffect: |
|
|
|
|
|
investmentWithCurrencyEffect?.toNumber(), |
|
|
|
|
|
netPerformance: netPerformance?.toNumber(), |
|
|
|
|
|
netPerformancePercent: netPerformancePercentage?.toNumber(), |
|
|
|
|
|
netPerformancePercentWithCurrencyEffect: |
|
|
|
|
|
netPerformancePercentageWithCurrencyEffectMap?.['max']?.toNumber(), |
|
|
|
|
|
netPerformanceWithCurrencyEffect: |
|
|
|
|
|
netPerformanceWithCurrencyEffectMap?.['max']?.toNumber(), |
|
|
|
|
|
performances: { |
|
|
|
|
|
allTimeHigh: { |
|
|
|
|
|
performancePercent, |
|
|
|
|
|
date: marketPriceMaxDate |
|
|
|
|
|
} |
|
|
} |
|
|
}, |
|
|
); |
|
|
quantity: quantity.toNumber(), |
|
|
|
|
|
value: this.exchangeRateDataService.toCurrency( |
|
|
|
|
|
quantity.mul(marketPrice ?? 0).toNumber(), |
|
|
|
|
|
currency, |
|
|
|
|
|
userCurrency |
|
|
|
|
|
) |
|
|
|
|
|
}; |
|
|
|
|
|
} else { |
|
|
|
|
|
const currentData = await this.dataProviderService.getQuotes({ |
|
|
|
|
|
user, |
|
|
|
|
|
items: [{ symbol, dataSource: DataSource.YAHOO }] |
|
|
|
|
|
}); |
|
|
|
|
|
const marketPrice = currentData[symbol]?.marketPrice; |
|
|
|
|
|
|
|
|
|
|
|
let historicalData = await this.dataProviderService.getHistorical( |
|
|
|
|
|
[{ symbol, dataSource: DataSource.YAHOO }], |
|
|
|
|
|
'day', |
|
|
|
|
|
portfolioStart, |
|
|
|
|
|
new Date() |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
if (isEmpty(historicalData)) { |
|
|
if (currentSymbol) { |
|
|
try { |
|
|
currentAveragePrice = currentSymbol.averagePrice.toNumber(); |
|
|
historicalData = await this.dataProviderService.getHistoricalRaw({ |
|
|
currentQuantity = currentSymbol.quantity.toNumber(); |
|
|
assetProfileIdentifiers: [{ symbol, dataSource: DataSource.YAHOO }], |
|
|
|
|
|
from: portfolioStart, |
|
|
|
|
|
to: new Date() |
|
|
|
|
|
}); |
|
|
|
|
|
} catch { |
|
|
|
|
|
historicalData = { |
|
|
|
|
|
[symbol]: {} |
|
|
|
|
|
}; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const historicalDataArray: HistoricalDataItem[] = []; |
|
|
|
|
|
let marketPriceMax = marketPrice; |
|
|
|
|
|
let marketPriceMaxDate = new Date(); |
|
|
|
|
|
let marketPriceMin = marketPrice; |
|
|
|
|
|
|
|
|
|
|
|
for (const [date, { marketPrice }] of Object.entries( |
|
|
|
|
|
historicalData[symbol] |
|
|
|
|
|
)) { |
|
|
|
|
|
historicalDataArray.push({ |
|
|
historicalDataArray.push({ |
|
|
date, |
|
|
date, |
|
|
value: marketPrice |
|
|
averagePrice: currentAveragePrice, |
|
|
|
|
|
marketPrice: |
|
|
|
|
|
historicalDataArray.length > 0 ? marketPrice : currentAveragePrice, |
|
|
|
|
|
quantity: currentQuantity |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
if (marketPrice > marketPriceMax) { |
|
|
if (marketPrice > marketPriceMax) { |
|
|
@ -1057,48 +910,70 @@ export class PortfolioService { |
|
|
marketPriceMin |
|
|
marketPriceMin |
|
|
); |
|
|
); |
|
|
} |
|
|
} |
|
|
|
|
|
} else { |
|
|
|
|
|
// Add historical entry for buy date, if no historical data available
|
|
|
|
|
|
historicalDataArray.push({ |
|
|
|
|
|
averagePrice: activitiesOfHolding[0].unitPriceInAssetProfileCurrency, |
|
|
|
|
|
date: firstBuyDate, |
|
|
|
|
|
marketPrice: activitiesOfHolding[0].unitPriceInAssetProfileCurrency, |
|
|
|
|
|
quantity: activitiesOfHolding[0].quantity |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
const performancePercent = |
|
|
const performancePercent = |
|
|
this.benchmarkService.calculateChangeInPercentage( |
|
|
this.benchmarkService.calculateChangeInPercentage( |
|
|
marketPriceMax, |
|
|
|
|
|
marketPrice |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
return { |
|
|
|
|
|
marketPrice, |
|
|
|
|
|
marketPriceMax, |
|
|
marketPriceMax, |
|
|
marketPriceMin, |
|
|
marketPrice |
|
|
SymbolProfile, |
|
|
); |
|
|
activities: [], |
|
|
|
|
|
activitiesCount: 0, |
|
|
return { |
|
|
averagePrice: 0, |
|
|
firstBuyDate, |
|
|
dataProviderInfo: undefined, |
|
|
marketPrice, |
|
|
dividendInBaseCurrency: 0, |
|
|
marketPriceMax, |
|
|
dividendYieldPercent: 0, |
|
|
marketPriceMin, |
|
|
dividendYieldPercentWithCurrencyEffect: 0, |
|
|
SymbolProfile, |
|
|
feeInBaseCurrency: 0, |
|
|
tags, |
|
|
firstBuyDate: undefined, |
|
|
activities: activitiesOfHolding, |
|
|
grossPerformance: undefined, |
|
|
activitiesCount: transactionCount, |
|
|
grossPerformancePercent: undefined, |
|
|
averagePrice: averagePrice.toNumber(), |
|
|
grossPerformancePercentWithCurrencyEffect: undefined, |
|
|
dataProviderInfo: portfolioCalculator.getDataProviderInfos()?.[0], |
|
|
grossPerformanceWithCurrencyEffect: undefined, |
|
|
dividendInBaseCurrency: dividendInBaseCurrency.toNumber(), |
|
|
historicalData: historicalDataArray, |
|
|
dividendYieldPercent: dividendYieldPercent.toNumber(), |
|
|
investmentInBaseCurrencyWithCurrencyEffect: 0, |
|
|
dividendYieldPercentWithCurrencyEffect: |
|
|
netPerformance: undefined, |
|
|
dividendYieldPercentWithCurrencyEffect.toNumber(), |
|
|
netPerformancePercent: undefined, |
|
|
feeInBaseCurrency: this.exchangeRateDataService.toCurrency( |
|
|
netPerformancePercentWithCurrencyEffect: undefined, |
|
|
fee.toNumber(), |
|
|
netPerformanceWithCurrencyEffect: undefined, |
|
|
SymbolProfile.currency, |
|
|
performances: { |
|
|
userCurrency |
|
|
allTimeHigh: { |
|
|
), |
|
|
performancePercent, |
|
|
grossPerformance: grossPerformance?.toNumber(), |
|
|
date: marketPriceMaxDate |
|
|
grossPerformancePercent: grossPerformancePercentage?.toNumber(), |
|
|
} |
|
|
grossPerformancePercentWithCurrencyEffect: |
|
|
}, |
|
|
grossPerformancePercentageWithCurrencyEffect?.toNumber(), |
|
|
quantity: 0, |
|
|
grossPerformanceWithCurrencyEffect: |
|
|
tags: [], |
|
|
grossPerformanceWithCurrencyEffect?.toNumber(), |
|
|
value: 0 |
|
|
historicalData: historicalDataArray, |
|
|
}; |
|
|
investmentInBaseCurrencyWithCurrencyEffect: |
|
|
} |
|
|
investmentWithCurrencyEffect?.toNumber(), |
|
|
|
|
|
netPerformance: netPerformance?.toNumber(), |
|
|
|
|
|
netPerformancePercent: netPerformancePercentage?.toNumber(), |
|
|
|
|
|
netPerformancePercentWithCurrencyEffect: |
|
|
|
|
|
netPerformancePercentageWithCurrencyEffectMap?.['max']?.toNumber(), |
|
|
|
|
|
netPerformanceWithCurrencyEffect: |
|
|
|
|
|
netPerformanceWithCurrencyEffectMap?.['max']?.toNumber(), |
|
|
|
|
|
performances: { |
|
|
|
|
|
allTimeHigh: { |
|
|
|
|
|
performancePercent, |
|
|
|
|
|
date: marketPriceMaxDate |
|
|
|
|
|
} |
|
|
|
|
|
}, |
|
|
|
|
|
quantity: quantity.toNumber(), |
|
|
|
|
|
value: this.exchangeRateDataService.toCurrency( |
|
|
|
|
|
quantity.mul(marketPrice ?? 0).toNumber(), |
|
|
|
|
|
currency, |
|
|
|
|
|
userCurrency |
|
|
|
|
|
) |
|
|
|
|
|
}; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public async getPerformance({ |
|
|
public async getPerformance({ |
|
|
|