@ImmutableDefaults private static void applyDefaults(Builder builder) { builder.fxRateProvider = FxMatrix.empty(); }
/** * Obtains an instance containing a single FX rate. * <p> * This is most likely to be used in testing. * <p> * An invocation of the method with {@code FxMatrix.of(CurrencyPair.of(GBP, USD), 1.6)} * indicates that 1 pound sterling is worth 1.6 US dollars. * The matrix can also be queried for the reverse rate, from USD to GBP. * * @param currencyPair the currency pair to be added * @param rate the FX rate between the base currency of the pair and the * counter currency. The rate indicates the value of one unit of the base * currency in terms of the counter currency. * @return a matrix containing the single FX rate */ public static FxMatrix of(CurrencyPair currencyPair, double rate) { return FxMatrix.of(currencyPair.getBase(), currencyPair.getCounter(), rate); }
public void emptyMatrixCannotDoConversion() { FxMatrix matrix = FxMatrix.builder().build(); assertThat(matrix.getCurrencies()).isEmpty(); assertThrowsIllegalArg(() -> matrix.fxRate(USD, EUR)); }
public void emptyMatrixCanHandleTrivialRate() { FxMatrix matrix = FxMatrix.empty(); assertThat(matrix.getCurrencies()).isEmpty(); assertThat(matrix.fxRate(USD, USD)).isEqualTo(1.0); assertThat(matrix.toString()).isEqualTo("FxMatrix[ : ]"); }
public void rateCanBeUpdatedWithDirectionSwitched() { FxMatrix matrix1 = FxMatrix.builder() .addRate(GBP, USD, 1.6) .build(); assertThat(matrix1.getCurrencies()).hasSize(2); assertThat(matrix1.fxRate(GBP, USD)).isEqualTo(1.6); FxMatrix matrix2 = matrix1.toBuilder() .addRate(USD, GBP, 0.625) .build(); assertThat(matrix2.getCurrencies()).hasSize(2); assertThat(matrix2.fxRate(GBP, USD)).isEqualTo(1.6); }
public void singleRateMatrixByOfCurrencyPairFactory() { FxMatrix matrix = FxMatrix.of(CurrencyPair.of(GBP, USD), 1.6); assertThat(matrix.getCurrencies()).containsOnly(GBP, USD); assertThat(matrix.fxRate(GBP, USD)).isEqualTo(1.6); assertThat(matrix.fxRate(USD, GBP)).isEqualTo(0.625); assertThat(matrix.toString()).isEqualTo("FxMatrix[GBP, USD : [1.0, 1.6],[0.625, 1.0]]"); }
public void singleRateMatrixByOfCurrenciesFactory() { FxMatrix matrix = FxMatrix.of(GBP, USD, 1.6); assertThat(matrix.getCurrencies()).containsOnly(GBP, USD); assertThat(matrix.fxRate(GBP, USD)).isEqualTo(1.6); assertThat(matrix.fxRate(USD, GBP)).isEqualTo(0.625); }
public void convertCurrencyAmount() { FxMatrix matrix = FxMatrix.builder() .addRate(GBP, EUR, 1.4) .addRate(GBP, USD, 1.6) .build(); CurrencyAmount amount = CurrencyAmount.of(GBP, 1600); assertThat(matrix.convert(amount, GBP)).isEqualTo(amount); assertThat(matrix.convert(amount, USD)) .hasCurrency(USD) .hasAmount(2560); assertThat(matrix.convert(amount, EUR)) .hasCurrency(EUR) .hasAmount(2240); }
public void mergeAddsInAdditionalCurrencies() { FxMatrix matrix1 = FxMatrix.builder() .addRate(GBP, USD, 1.6) .addRate(EUR, USD, 1.4) .build(); FxMatrix matrix2 = FxMatrix.builder() .addRate(EUR, CHF, 1.2) .addRate(CHF, AUD, 1.2) .build(); FxMatrix result = matrix1.merge(matrix2); assertThat(result.getCurrencies()).contains(USD, GBP, EUR, CHF, AUD); assertThat(result.fxRate(GBP, USD)).isEqualTo(1.6); assertThat(result.fxRate(GBP, EUR)).isEqualTo(1.6 / 1.4, TOL); assertThat(result.fxRate(EUR, CHF)).isEqualTo(1.2); assertThat(result.fxRate(CHF, AUD)).isEqualTo(1.2); assertThat(result.fxRate(GBP, CHF)).isEqualTo((1.6 / 1.4) * 1.2, TOL); assertThat(result.fxRate(GBP, AUD)).isEqualTo((1.6 / 1.4) * 1.2 * 1.2, TOL); }
public void addSimpleMultipleRates() { // Use linked to force the order of evaluation // want to see that builder recovers when // encountering a currency pair for 2 unknown // currencies but which will appear later LinkedHashMap<CurrencyPair, Double> rates = new LinkedHashMap<>(); rates.put(CurrencyPair.of(GBP, USD), 1.6); rates.put(CurrencyPair.of(EUR, USD), 1.4); FxMatrix matrix = FxMatrix.builder() .addRates(rates) .build(); assertThat(matrix.fxRate(GBP, USD)).isEqualTo(1.6); assertThat(matrix.fxRate(USD, GBP)).isEqualTo(1 / 1.6); assertThat(matrix.fxRate(EUR, USD)).isEqualTo(1.4); assertThat(matrix.fxRate(USD, EUR)).isEqualTo(1 / 1.4); assertThat(matrix.fxRate(EUR, GBP)).isEqualTo(1.4 / 1.6, TOL); assertThat(matrix.fxRate(GBP, EUR)).isEqualTo(1.6 / 1.4, TOL); }
public void addMultipleRatesContainingEntryWithNoCommonCurrency() { LinkedHashMap<CurrencyPair, Double> rates = new LinkedHashMap<>(); rates.put(CurrencyPair.of(GBP, USD), 1.6); rates.put(CurrencyPair.of(EUR, USD), 1.4); rates.put(CurrencyPair.of(JPY, CAD), 0.01); // Neither currency linked to one of the others assertThrows( () -> FxMatrix.builder().addRates(rates).build(), IllegalStateException.class); }
public void test_presentValueVsForex() { CurrencyAmount pvNDF = PRICER.presentValue(NDF, PROVIDER); MultiCurrencyAmount pvFX = PRICER_FX.presentValue(FOREX, PROVIDER); assertEquals( pvNDF.getAmount(), pvFX.getAmount(USD).getAmount() + pvFX.getAmount(KRW).getAmount() * FX_MATRIX.fxRate(KRW, USD), NOMINAL_USD * TOL); }
public void hashCodeCoverage() { FxMatrix m1 = FxMatrix.builder() .addRate(GBP, USD, 1.4) .build(); FxMatrix m2 = FxMatrix.builder() .addRate(GBP, USD, 1.39) .build(); FxMatrix m3 = FxMatrix.builder() .addRate(GBP, USD, 1.39) .build(); assertThat(m1.hashCode()).isNotEqualTo(m2.hashCode()); assertThat(m2.hashCode()).isEqualTo(m3.hashCode()); }
public void streamEntriesToMatrix() { // If we obtain a stream of rates we can collect to an fx matrix Map<CurrencyPair, Double> rates = ImmutableMap.<CurrencyPair, Double>builder() .put(CurrencyPair.of(GBP, USD), 1.6) .put(CurrencyPair.of(EUR, USD), 1.4) .put(CurrencyPair.of(CHF, AUD), 1.2) // Neither currency seen before .put(CurrencyPair.of(SEK, AUD), 0.1) // AUD seen before but not added yet .put(CurrencyPair.of(JPY, CAD), 0.0) // Neither currency seen before .put(CurrencyPair.of(EUR, CHF), 1.2) .put(CurrencyPair.of(JPY, USD), 0.008) .build(); FxMatrix matrix = rates.entrySet() .stream() .collect(entriesToFxMatrix()); assertThat(matrix.fxRate(GBP, USD)).isEqualTo(1.6); assertThat(matrix.fxRate(EUR, USD)).isEqualTo(1.4); }
public void streamPairsToMatrix() { // If we obtain a stream of pairs with rates we can stream them // This could happen if an entry set undergoes a map operation Map<CurrencyPair, Double> rates = ImmutableMap.<CurrencyPair, Double>builder() .put(CurrencyPair.of(GBP, USD), 1.6) .put(CurrencyPair.of(EUR, USD), 1.4) .put(CurrencyPair.of(CHF, AUD), 1.2) // Neither currency seen before .put(CurrencyPair.of(SEK, AUD), 0.1) // AUD seen before but not added yet .put(CurrencyPair.of(JPY, CAD), 0.0) // Neither currency seen before .put(CurrencyPair.of(EUR, CHF), 1.2) .put(CurrencyPair.of(JPY, USD), 0.008) .build(); FxMatrix matrix = rates.entrySet() .stream() .map(e -> Pair.of(e.getKey(), e.getValue() * 1.01)) // Apply some shift .collect(pairsToFxMatrix()); assertThat(matrix.fxRate(GBP, USD)).isEqualTo(1.616); assertThat(matrix.fxRate(EUR, USD)).isEqualTo(1.414); }
/** * Converts a {@code MultipleCurrencyAmount} into an amount in the * specified currency using the rates in this matrix. * * @param amount the {@code MultipleCurrencyAmount} to be converted * @param targetCurrency the currency to convert all entries to * @return the total amount in the requested currency */ public CurrencyAmount convert(MultiCurrencyAmount amount, Currency targetCurrency) { ArgChecker.notNull(amount, "amount"); ArgChecker.notNull(targetCurrency, "targetCurrency"); // We could do this using the currency amounts but to // avoid creating extra objects we'll use doubles double total = amount.getAmounts() .stream() .mapToDouble(ca -> convert(ca.getAmount(), ca.getCurrency(), targetCurrency)) .sum(); return CurrencyAmount.of(targetCurrency, total); }
@Override public String toString() { return "FxMatrix[" + Joiner.on(", ").join(getCurrencies()) + " : " + Stream.of(rates.toArrayUnsafe()).map(Arrays::toString).collect(Collectors.joining(",")) + "]"; }