@ -30,6 +30,7 @@ import ms from 'ms';
export class ExchangeRateDataService {
private currencies : string [ ] = [ ] ;
private currencyPairs : DataGatheringItem [ ] = [ ] ;
private derivedCurrencyFactors : { [ currencyPair : string ] : number } = { } ;
private exchangeRates : { [ currencyPair : string ] : number } = { } ;
public constructor (
@ -135,8 +136,14 @@ export class ExchangeRateDataService {
public async initialize() {
this . currencies = await this . prepareCurrencies ( ) ;
this . currencyPairs = [ ] ;
this . derivedCurrencyFactors = { } ;
this . exchangeRates = { } ;
for ( const { currency , factor , rootCurrency } of DERIVED_CURRENCIES ) {
this . derivedCurrencyFactors [ ` ${ currency } ${ rootCurrency } ` ] = 1 / factor ;
this . derivedCurrencyFactors [ ` ${ rootCurrency } ${ currency } ` ] = factor ;
}
for ( const {
currency1 ,
currency2 ,
@ -266,10 +273,14 @@ export class ExchangeRateDataService {
return this . toCurrency ( aValue , aFromCurrency , aToCurrency ) ;
}
const derivedCurrencyFactor =
this . derivedCurrencyFactors [ ` ${ aFromCurrency } ${ aToCurrency } ` ] ;
let factor : number ;
if ( aFromCurrency === aToCurrency ) {
factor = 1 ;
} else if ( derivedCurrencyFactor ) {
factor = derivedCurrencyFactor ;
} else {
const dataSource =
this . dataProviderService . getDataSourceForExchangeRates ( ) ;
@ -357,111 +368,120 @@ export class ExchangeRateDataService {
for ( const date of dates ) {
factors [ format ( date , DATE_FORMAT ) ] = 1 ;
}
} else {
const dataSource =
this . dataProviderService . getDataSourceForExchangeRates ( ) ;
const symbol = ` ${ currencyFrom } ${ currencyTo } ` ;
const marketData = await this . marketDataService . getRange ( {
assetProfileIdentifiers : [
{
dataSource ,
symbol
}
] ,
dateQuery : { gte : startDate , lt : endDate }
} ) ;
return factors ;
}
const derivedCurrencyFactor =
this . derivedCurrencyFactors [ ` ${ currencyFrom } ${ currencyTo } ` ] ;
if ( derivedCurrencyFactor ) {
for ( const date of dates ) {
factors [ format ( date , DATE_FORMAT ) ] = derivedCurrencyFactor ;
}
if ( marketData ? . length > 0 ) {
for ( const { date , marketPrice } of marketData ) {
factors [ format ( date , DATE_FORMAT ) ] = marketPrice ;
return factors ;
}
const dataSource = this . dataProviderService . getDataSourceForExchangeRates ( ) ;
const symbol = ` ${ currencyFrom } ${ currencyTo } ` ;
const marketData = await this . marketDataService . getRange ( {
assetProfileIdentifiers : [
{
dataSource ,
symbol
}
} else {
// Calculate indirectly via base currency
] ,
dateQuery : { gte : startDate , lt : endDate }
} ) ;
const marketPriceBaseCurrencyFromCurrency : {
[ dateString : string ] : number ;
} = { } ;
const marketPriceBaseCurrencyToCurrency : {
[ dateString : string ] : number ;
} = { } ;
if ( marketData ? . length > 0 ) {
for ( const { date , marketPrice } of marketData ) {
factors [ format ( date , DATE_FORMAT ) ] = marketPrice ;
}
} else {
// Calculate indirectly via base currency
const marketPriceBaseCurrencyFromCurrency : {
[ dateString : string ] : number ;
} = { } ;
const marketPriceBaseCurrencyToCurrency : {
[ dateString : string ] : number ;
} = { } ;
try {
if ( currencyFrom === DEFAULT_CURRENCY ) {
for ( const date of dates ) {
marketPriceBaseCurrencyFromCurrency [ format ( date , DATE_FORMAT ) ] = 1 ;
}
} else {
const marketData = await this . marketDataService . getRange ( {
assetProfileIdentifiers : [
{
dataSource ,
symbol : ` ${ DEFAULT_CURRENCY } ${ currencyFrom } `
}
] ,
dateQuery : { gte : startDate , lt : endDate }
} ) ;
try {
if ( currencyFrom === DEFAULT_CURRENCY ) {
for ( const date of dates ) {
marketPriceBaseCurrencyFromCurrency [ format ( date , DATE_FORMAT ) ] =
1 ;
}
} else {
const marketData = await this . marketDataService . getRange ( {
assetProfileIdentifiers : [
{
dataSource ,
symbol : ` ${ DEFAULT_CURRENCY } ${ currencyFrom } `
}
] ,
dateQuery : { gte : startDate , lt : endDate }
} ) ;
for ( const { date , marketPrice } of marketData ) {
marketPriceBaseCurrencyFromCurrency [ format ( date , DATE_FORMAT ) ] =
marketPrice ;
}
for ( const { date , marketPrice } of marketData ) {
marketPriceBaseCurrencyFromCurrency [ format ( date , DATE_FORMAT ) ] =
marketPrice ;
}
} catch { }
}
} catch { }
try {
if ( currencyTo === DEFAULT_CURRENCY ) {
for ( const date of dates ) {
marketPriceBaseCurrencyToCurrency [ format ( date , DATE_FORMAT ) ] = 1 ;
}
} else {
const marketData = await this . marketDataService . getRange ( {
assetProfileIdentifiers : [
{
dataSource ,
symbol : ` ${ DEFAULT_CURRENCY } ${ currencyTo } `
}
] ,
dateQuery : {
gte : startDate ,
lt : endDate
try {
if ( currencyTo === DEFAULT_CURRENCY ) {
for ( const date of dates ) {
marketPriceBaseCurrencyToCurrency [ format ( date , DATE_FORMAT ) ] = 1 ;
}
} else {
const marketData = await this . marketDataService . getRange ( {
assetProfileIdentifiers : [
{
dataSource ,
symbol : ` ${ DEFAULT_CURRENCY } ${ currencyTo } `
}
} ) ;
for ( const { date , marketPrice } of marketData ) {
marketPriceBaseCurrencyToCurrency [ format ( date , DATE_FORMAT ) ] =
marketPrice ;
] ,
dateQuery : {
gte : startDate ,
lt : endDate
}
} ) ;
for ( const { date , marketPrice } of marketData ) {
marketPriceBaseCurrencyToCurrency [ format ( date , DATE_FORMAT ) ] =
marketPrice ;
}
} catch { }
}
} catch { }
for ( const date of dates ) {
try {
const factor =
( 1 /
marketPriceBaseCurrencyFromCurrency [
format ( date , DATE_FORMAT )
] ) *
marketPriceBaseCurrencyToCurrency [ format ( date , DATE_FORMAT ) ] ;
if ( isNaN ( factor ) ) {
throw new Error ( 'Exchange rate is not a number' ) ;
} else {
factors [ format ( date , DATE_FORMAT ) ] = factor ;
}
} catch {
let errorMessage = ` No exchange rate has been found for ${ currencyFrom } ${ currencyTo } at ${ format (
date ,
DATE_FORMAT
) } . Please complement market data for $ { DEFAULT_CURRENCY } $ { currencyFrom } ` ;
if ( DEFAULT_CURRENCY !== currencyTo ) {
errorMessage = ` ${ errorMessage } and ${ DEFAULT_CURRENCY } ${ currencyTo } ` ;
}
for ( const date of dates ) {
try {
const factor =
( 1 /
marketPriceBaseCurrencyFromCurrency [ format ( date , DATE_FORMAT ) ] ) *
marketPriceBaseCurrencyToCurrency [ format ( date , DATE_FORMAT ) ] ;
Logger . error ( ` ${ errorMessage } . ` , 'ExchangeRateDataService' ) ;
if ( isNaN ( factor ) ) {
throw new Error ( 'Exchange rate is not a number' ) ;
} else {
factors [ format ( date , DATE_FORMAT ) ] = factor ;
}
} catch {
let errorMessage = ` No exchange rate has been found for ${ currencyFrom } ${ currencyTo } at ${ format (
date ,
DATE_FORMAT
) } . Please complement market data for $ { DEFAULT_CURRENCY } $ { currencyFrom } ` ;
if ( DEFAULT_CURRENCY !== currencyTo ) {
errorMessage = ` ${ errorMessage } and ${ DEFAULT_CURRENCY } ${ currencyTo } ` ;
}
Logger . error ( ` ${ errorMessage } . ` , 'ExchangeRateDataService' ) ;
}
}
}