All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.objectlab.kit.fxcalc.FxRateCalculatorImpl Maven / Gradle / Ivy

package net.objectlab.kit.fxcalc;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * Main implementation, uses the ratesSnapshot or BaseFxRateProvider to find the FX Rate, if not present then
 * try via a cross currency in the order specified in orderedCurrenciesForCross.
 *
 * Uses the {@link CrossRateCalculator}
 *
 * @author Benoit Xhenseval
 *
 */
public class FxRateCalculatorImpl implements FxRateCalculator {
    private final Map rates = new HashMap<>();
    private final BaseFxRateProvider baseFxRateProvider;
    private final MajorCurrencyRanking majorCurrencyRanking;
    private final List orderedCurrenciesForCross;
    private final int precisionForFxRate;
    private final int precisionForInverseFxRate;
    private final boolean cacheResults;
    private final boolean cacheBaseRates;

    public FxRateCalculatorImpl(final FxRateCalculatorBuilder builder) {
        builder.checkValid();

        rates.putAll(builder.getRatesSnapshot());
        this.baseFxRateProvider = builder.getBaseFxRateProvider();
        this.majorCurrencyRanking = builder.getMajorCurrencyRanking();
        this.orderedCurrenciesForCross = builder.getOrderedCurrenciesForCross();
        this.precisionForFxRate = builder.getPrecisionForFxRate();
        this.precisionForInverseFxRate = builder.getPrecisionForInverseFxRate();
        this.cacheBaseRates = builder.isCacheBaseRates();
        this.cacheResults = builder.isCacheResults();
    }

    private FxRate getBaseRate(final CurrencyPair ccyPair) {
        FxRate fxRate = rates.get(ccyPair);

        if (fxRate == null && baseFxRateProvider != null) {
            final Optional latetsRate = baseFxRateProvider.getLatestRate(ccyPair);
            if (latetsRate.isPresent()) {
                fxRate = latetsRate.get();
                if (cacheBaseRates) {
                    rates.put(ccyPair, fxRate);
                }
            }
        }
        return fxRate;
    }

    @Override
    public Optional findFx(final CurrencyPair ccyPair) {
        FxRate fxRate = getBaseRate(ccyPair);
        if (fxRate == null) {
            // try inverse
            final FxRate inverse = getBaseRate(ccyPair.createInverse());

            if (inverse != null) {
                fxRate = inverse.createInverse(precisionForInverseFxRate);
                if (cacheResults) {
                    rates.put(ccyPair, fxRate);
                }
            } else {
                for (final String crossCcy : orderedCurrenciesForCross) {
                    fxRate = findViaCrossCcy(ccyPair, crossCcy);
                    if (fxRate != null) {
                        if (cacheResults) {
                            rates.put(ccyPair, fxRate);
                        }
                        break;
                    }
                }
            }
        }

        return Optional.ofNullable(fxRate);
    }

    private FxRate findViaCrossCcy(final CurrencyPair ccyPair, final String crossCcy) {
        final CurrencyPair xCcyPair = CurrencyPair.of(crossCcy, ccyPair.getCcy1());
        FxRate xCcy1 = getBaseRate(xCcyPair);
        if (xCcy1 == null) {
            // try inverse
            final FxRate inverse = getBaseRate(xCcyPair.createInverse());
            if (inverse != null) {
                xCcy1 = inverse.createInverse(precisionForInverseFxRate);
            }
        }

        if (xCcy1 != null) {
            final CurrencyPair xCcy2Pair = CurrencyPair.of(crossCcy, ccyPair.getCcy2());
            FxRate xCcy2 = getBaseRate(xCcy2Pair);
            if (xCcy2 == null) {
                // try inverse
                final FxRate inverse = getBaseRate(xCcy2Pair.createInverse());
                if (inverse != null) {
                    xCcy2 = inverse.createInverse(precisionForInverseFxRate);
                }
            }
            if (xCcy2 != null) {
                return CrossRateCalculator.calculateCross(ccyPair, xCcy1, xCcy2, precisionForFxRate, majorCurrencyRanking);
            }
        }
        return null;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy