Browse Source

Merge 3c9e70ffad into 78134020a2

pull/6866/merge
Andrea Bugeja 4 days ago
committed by GitHub
parent
commit
5821579882
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 6
      apps/api/src/app/import/import.service.ts
  2. 144
      apps/api/src/services/exchange-rate-data/exchange-rate-data.service.ts
  3. 5
      apps/api/src/services/market-data/market-data.service.ts
  4. 3
      package.json

6
apps/api/src/app/import/import.service.ts

@ -284,7 +284,11 @@ export class ImportService {
);
// If there is no asset profile or if the asset profile belongs to a different user, then create a new asset profile
if (!existingAssetProfile || existingAssetProfile.userId !== user.id) {
if (
!existingAssetProfile ||
(existingAssetProfile.userId !== null &&
existingAssetProfile.userId !== user.id)
) {
const assetProfile: CreateAssetProfileDto = omit(
assetProfileWithMarketData,
'marketData'

144
apps/api/src/services/exchange-rate-data/exchange-rate-data.service.ts

@ -229,32 +229,59 @@ export class ExchangeRateDataService {
return 0;
}
let normalizedValue = aValue;
let normalizedFromCurrency = aFromCurrency;
let normalizedToCurrency = aToCurrency;
const fromDerived = DERIVED_CURRENCIES.find(
(c) => c.currency === aFromCurrency
);
if (fromDerived) {
normalizedFromCurrency = fromDerived.rootCurrency;
normalizedValue = normalizedValue / fromDerived.factor;
}
const toDerived = DERIVED_CURRENCIES.find(
(c) => c.currency === aToCurrency
);
if (toDerived) {
normalizedToCurrency = toDerived.rootCurrency;
normalizedValue = normalizedValue * toDerived.factor;
}
let factor: number;
if (aFromCurrency === aToCurrency) {
if (normalizedFromCurrency === normalizedToCurrency) {
factor = 1;
} else {
if (this.exchangeRates[`${aFromCurrency}${aToCurrency}`]) {
factor = this.exchangeRates[`${aFromCurrency}${aToCurrency}`];
if (
this.exchangeRates[`${normalizedFromCurrency}${normalizedToCurrency}`]
) {
factor =
this.exchangeRates[
`${normalizedFromCurrency}${normalizedToCurrency}`
];
} else {
// Calculate indirectly via base currency
const factor1 =
this.exchangeRates[`${aFromCurrency}${DEFAULT_CURRENCY}`];
const factor2 = this.exchangeRates[`${DEFAULT_CURRENCY}${aToCurrency}`];
this.exchangeRates[`${normalizedFromCurrency}${DEFAULT_CURRENCY}`];
const factor2 =
this.exchangeRates[`${DEFAULT_CURRENCY}${normalizedToCurrency}`];
factor = factor1 * factor2;
this.exchangeRates[`${aFromCurrency}${aToCurrency}`] = factor;
this.exchangeRates[`${normalizedFromCurrency}${normalizedToCurrency}`] =
factor;
}
}
if (isNumber(factor) && !isNaN(factor)) {
return factor * aValue;
return factor * normalizedValue;
}
// Fallback with error, if currencies are not available
Logger.error(
`No exchange rate has been found for ${aFromCurrency}${aToCurrency}`,
`No exchange rate has been found for ${normalizedFromCurrency}${normalizedToCurrency}. Please complement market data for USD${normalizedFromCurrency} and USD${normalizedToCurrency}.`,
'ExchangeRateDataService'
);
@ -271,22 +298,42 @@ export class ExchangeRateDataService {
return 0;
}
let normalizedValue = aValue;
let normalizedFromCurrency = aFromCurrency;
let normalizedToCurrency = aToCurrency;
const fromDerived = DERIVED_CURRENCIES.find(
(c) => c.currency === aFromCurrency
);
if (fromDerived) {
normalizedFromCurrency = fromDerived.rootCurrency;
normalizedValue = normalizedValue / fromDerived.factor;
}
const toDerived = DERIVED_CURRENCIES.find(
(c) => c.currency === aToCurrency
);
if (toDerived) {
normalizedToCurrency = toDerived.rootCurrency;
normalizedValue = normalizedValue * toDerived.factor;
}
if (isToday(aDate)) {
return this.toCurrency(aValue, aFromCurrency, aToCurrency);
return this.toCurrency(
normalizedValue,
normalizedFromCurrency,
normalizedToCurrency
);
}
const derivedCurrencyFactor =
this.derivedCurrencyFactors[`${aFromCurrency}${aToCurrency}`];
let factor: number;
if (aFromCurrency === aToCurrency) {
if (normalizedFromCurrency === normalizedToCurrency) {
factor = 1;
} else if (derivedCurrencyFactor) {
factor = derivedCurrencyFactor;
} else {
const dataSource =
this.dataProviderService.getDataSourceForExchangeRates();
const symbol = `${aFromCurrency}${aToCurrency}`;
const symbol = `${normalizedFromCurrency}${normalizedToCurrency}`;
const marketData = await this.marketDataService.get({
dataSource,
@ -303,28 +350,28 @@ export class ExchangeRateDataService {
let marketPriceBaseCurrencyToCurrency: number;
try {
if (aFromCurrency === DEFAULT_CURRENCY) {
if (normalizedFromCurrency === DEFAULT_CURRENCY) {
marketPriceBaseCurrencyFromCurrency = 1;
} else {
marketPriceBaseCurrencyFromCurrency = (
await this.marketDataService.get({
dataSource,
date: aDate,
symbol: `${DEFAULT_CURRENCY}${aFromCurrency}`
symbol: `${DEFAULT_CURRENCY}${normalizedFromCurrency}`
})
)?.marketPrice;
}
} catch {}
try {
if (aToCurrency === DEFAULT_CURRENCY) {
if (normalizedToCurrency === DEFAULT_CURRENCY) {
marketPriceBaseCurrencyToCurrency = 1;
} else {
marketPriceBaseCurrencyToCurrency = (
await this.marketDataService.get({
dataSource,
date: aDate,
symbol: `${DEFAULT_CURRENCY}${aToCurrency}`
symbol: `${DEFAULT_CURRENCY}${normalizedToCurrency}`
})
)?.marketPrice;
}
@ -338,18 +385,18 @@ export class ExchangeRateDataService {
}
if (isNumber(factor) && !isNaN(factor)) {
return factor * aValue;
return factor * normalizedValue;
}
Logger.error(
`No exchange rate has been found for ${aFromCurrency}${aToCurrency} at ${format(
`No exchange rate has been found for ${normalizedFromCurrency}${normalizedToCurrency} at ${format(
aDate,
DATE_FORMAT
)}`,
)}. Please complement market data for USD${normalizedFromCurrency} and USD${normalizedToCurrency}.`,
'ExchangeRateDataService'
);
return undefined;
return aValue;
}
private async getExchangeRates({
@ -366,27 +413,36 @@ export class ExchangeRateDataService {
const dates = eachDayOfInterval({ end: endDate, start: startDate });
const factors: { [dateString: string]: number } = {};
if (currencyFrom === currencyTo) {
for (const date of dates) {
factors[format(date, DATE_FORMAT)] = 1;
}
let normalizedCurrencyFrom = currencyFrom;
let normalizedCurrencyTo = currencyTo;
let conversionFactorFrom = 1;
let conversionFactorTo = 1;
return factors;
const fromDerived = DERIVED_CURRENCIES.find(
(c) => c.currency === currencyFrom
);
if (fromDerived) {
normalizedCurrencyFrom = fromDerived.rootCurrency;
conversionFactorFrom = 1 / fromDerived.factor;
}
const derivedCurrencyFactor =
this.derivedCurrencyFactors[`${currencyFrom}${currencyTo}`];
const toDerived = DERIVED_CURRENCIES.find((c) => c.currency === currencyTo);
if (toDerived) {
normalizedCurrencyTo = toDerived.rootCurrency;
conversionFactorTo = toDerived.factor;
}
if (derivedCurrencyFactor) {
if (normalizedCurrencyFrom === normalizedCurrencyTo) {
for (const date of dates) {
factors[format(date, DATE_FORMAT)] = derivedCurrencyFactor;
factors[format(date, DATE_FORMAT)] =
conversionFactorFrom * conversionFactorTo;
}
return factors;
}
const dataSource = this.dataProviderService.getDataSourceForExchangeRates();
const symbol = `${currencyFrom}${currencyTo}`;
const symbol = `${normalizedCurrencyFrom}${normalizedCurrencyTo}`;
const marketData = await this.marketDataService.getRange({
assetProfileIdentifiers: [
@ -400,7 +456,8 @@ export class ExchangeRateDataService {
if (marketData?.length > 0) {
for (const { date, marketPrice } of marketData) {
factors[format(date, DATE_FORMAT)] = marketPrice;
factors[format(date, DATE_FORMAT)] =
conversionFactorFrom * marketPrice * conversionFactorTo;
}
} else {
// Calculate indirectly via base currency
@ -413,7 +470,7 @@ export class ExchangeRateDataService {
} = {};
try {
if (currencyFrom === DEFAULT_CURRENCY) {
if (normalizedCurrencyFrom === DEFAULT_CURRENCY) {
for (const date of dates) {
marketPriceBaseCurrencyFromCurrency[format(date, DATE_FORMAT)] = 1;
}
@ -422,7 +479,7 @@ export class ExchangeRateDataService {
assetProfileIdentifiers: [
{
dataSource,
symbol: `${DEFAULT_CURRENCY}${currencyFrom}`
symbol: `${DEFAULT_CURRENCY}${normalizedCurrencyFrom}`
}
],
dateQuery: { gte: startDate, lt: endDate }
@ -436,7 +493,7 @@ export class ExchangeRateDataService {
} catch {}
try {
if (currencyTo === DEFAULT_CURRENCY) {
if (normalizedCurrencyTo === DEFAULT_CURRENCY) {
for (const date of dates) {
marketPriceBaseCurrencyToCurrency[format(date, DATE_FORMAT)] = 1;
}
@ -445,7 +502,7 @@ export class ExchangeRateDataService {
assetProfileIdentifiers: [
{
dataSource,
symbol: `${DEFAULT_CURRENCY}${currencyTo}`
symbol: `${DEFAULT_CURRENCY}${normalizedCurrencyTo}`
}
],
dateQuery: {
@ -471,16 +528,17 @@ export class ExchangeRateDataService {
if (isNaN(factor)) {
throw new Error('Exchange rate is not a number');
} else {
factors[format(date, DATE_FORMAT)] = factor;
factors[format(date, DATE_FORMAT)] =
conversionFactorFrom * factor * conversionFactorTo;
}
} catch {
let errorMessage = `No exchange rate has been found for ${currencyFrom}${currencyTo} at ${format(
let errorMessage = `No exchange rate has been found for ${normalizedCurrencyFrom}${normalizedCurrencyTo} at ${format(
date,
DATE_FORMAT
)}. Please complement market data for ${DEFAULT_CURRENCY}${currencyFrom}`;
)}. Please complement market data for ${DEFAULT_CURRENCY}${normalizedCurrencyFrom}`;
if (DEFAULT_CURRENCY !== currencyTo) {
errorMessage = `${errorMessage} and ${DEFAULT_CURRENCY}${currencyTo}`;
if (DEFAULT_CURRENCY !== normalizedCurrencyTo) {
errorMessage = `${errorMessage} and ${DEFAULT_CURRENCY}${normalizedCurrencyTo}`;
}
Logger.error(`${errorMessage}.`, 'ExchangeRateDataService');

5
apps/api/src/services/market-data/market-data.service.ts

@ -35,8 +35,9 @@ export class MarketDataService {
where: {
dataSource,
symbol,
date: resetHours(date)
}
date: { lte: resetHours(date) }
},
orderBy: { date: 'desc' }
});
}

3
package.json

@ -72,7 +72,7 @@
"@date-fns/utc": "2.1.1",
"@internationalized/number": "3.6.6",
"@ionic/angular": "8.8.5",
"@keyv/redis": "4.4.0",
"@keyv/redis": "^5.1.6",
"@nestjs/bull": "11.0.4",
"@nestjs/cache-manager": "3.1.0",
"@nestjs/common": "11.1.19",
@ -118,6 +118,7 @@
"http-status-codes": "2.3.0",
"ionicons": "8.0.13",
"jsonpath": "1.3.0",
"keyv": "^5.6.0",
"lodash": "4.18.1",
"marked": "17.0.2",
"ms": "3.0.0-canary.1",

Loading…
Cancel
Save