public BigDecimal getLatestFromDB(CurrencyType currencyType) throws RateNotFoundException { Optional<ExchangeAggregateRate> exchangeAggregateRate = exchangeAggregateRateRepository.findFirstOptionalByOrderByCreationDateDesc(); return exchangeAggregateRate.flatMap((aggregateRate) -> aggregateRate.getExchangeAggregateCurrencyRates(currencyType)) .map((aggCurrencyRate) -> aggCurrencyRate.getAggregateExchangeRate()) .orElseThrow(() -> new RateNotFoundException(String.format("No rate aggregation found for %s-%s.", ratesAppConfigHolder.getBaseFiatCurrency(), currencyType))); }
public BigDecimal getRate(CurrencyType currencyType, Instant timestamp) throws RateNotFoundException { // fetch rates between the startDate and endDate Instant startRange = calculateRangeStartDate(timestamp); Instant endRange = calculateRangeEndDate(timestamp); List<ExchangeAggregateRate> rates = exchangeAggregateRateRepository .findAllByCreationDateBetweenOrderByCreationDateDesc(Date.from(startRange), Date.from(endRange)); // get the closest rate to the specified timestamp Optional<ExchangeAggregateRate> closestRateToTimestamp = getClosestRateToTimestamp(timestamp, rates); return closestRateToTimestamp // obtaining the rate from the DB for the specified currency type .flatMap((aggregateRate) -> aggregateRate.getExchangeAggregateCurrencyRates(currencyType)) .map((aggCurrencyRate) -> aggCurrencyRate.getAggregateExchangeRate()) .map(Optional::of) // if it was not found, try to get from the historical provider .orElseGet(() -> getRateFromHistoricalProviderAndSaveToDB(currencyType, timestamp)) // if not found, then throw an exception .orElseThrow(() -> new RateNotFoundException( String.format("Rate for currency %s with timestamp %s was not found either in the DB " + "or fetching from the historical provider API.", currencyType, timestamp.getEpochSecond()))); }
protected Optional<BigDecimal> getRateFromHistoricalProviderAndSaveToDB(CurrencyType currencyType, Instant timestamp) { ExchangeEntryRate exchangeEntryRate = getRateFromHistoricalProviderFromAllSupportedCurrencies(timestamp); // create the aggregation object ExchangeAggregateRate aggregateRate = new ExchangeAggregateRate(Date.from(Instant.now()), blockNrProviderService.getCurrentBlockNrEthereum(), blockNrProviderService.getCurrentBlockNrBitcoin()); aggregateRate.addExchangeEntry(exchangeEntryRate); if (exchangeEntryRate.getExchangeCurrencyRates() != null && !exchangeEntryRate.getExchangeCurrencyRates().isEmpty()) { exchangeEntryRate.getExchangeCurrencyRates().stream() .filter(distinctByKey(ExchangeCurrencyRate::getCurrencyType)) .forEach((entry) -> { // get all "ExchangeCurrencyRate" objects of distinct crypto currencies List<ExchangeCurrencyRate> allExchangeCurrencyRates = aggregateRate.getAllExchangeCurrencyRates(entry.getCurrencyType()); // remove outliers and get the mean BigDecimal mean = aggregationService.removeOutliersAndGetMean(allExchangeCurrencyRates); // create a new aggregate currency ExchangeAggregateCurrencyRate aggCurrencyRate = new ExchangeAggregateCurrencyRate(entry.getCurrencyType(), mean); // add to the top-level "ExchangeAggregateRate" aggregateRate.addExchangeAggregateCurrencyRate(aggCurrencyRate); }); // save to DB exchangeAggregateRateRepository.save(aggregateRate); } return aggregateRate.getExchangeAggregateCurrencyRates(currencyType) .map((aggregateObj) -> aggregateObj.getAggregateExchangeRate()); }