/** * Creates a {@code Collector} that allows a {@code Map.Entry} of currency pair to rate * to be streamed and collected into a new {@code FxMatrix}. * * @return a collector for creating an {@code FxMatrix} from a stream */ public static Collector<? super Map.Entry<CurrencyPair, Double>, FxMatrixBuilder, FxMatrix> entriesToFxMatrix() { return collector((builder, entry) -> builder.addRate(entry.getKey(), entry.getValue())); }
public void canAddEntryWithNoCommonCurrencyIfSuppliedBySubsequentEntries() { FxMatrix.builder() .addRate(GBP, USD, 1.6) .addRate(CHF, AUD, 1.6) // Cannot be added as nothing to tie it to USD or GBP .addRate(EUR, CHF, 1.2) // Again cannot be added .addRate(EUR, USD, 1.4) // Now everything can be tied together .build(); }
/** * Creates a {@code Collector} that allows a collection of pairs each containing * a currency pair and a rate to be streamed and collected into a new {@code FxMatrix}. * * @return a collector for creating an {@code FxMatrix} from a stream */ public static Collector<? super Pair<CurrencyPair, Double>, FxMatrixBuilder, FxMatrix> pairsToFxMatrix() { return collector((builder, pair) -> builder.addRate(pair.getFirst(), pair.getSecond())); }
public void test_convertedTo() { FxMatrix fxMatrix = FxMatrix.builder() .addRate(GBP, CAD, 2) .addRate(USD, CAD, 1.3) .addRate(EUR, CAD, 1.4) .build(); CurrencyAmountArray convertedArray = VALUES_ARRAY.convertedTo(Currency.CAD, fxMatrix); DoubleArray expected = DoubleArray.of( 20 * 2 + 30 * 1.3 + 40 * 1.4, 21 * 2 + 32 * 1.3 + 43 * 1.4, 22 * 2 + 33 * 1.3 + 44 * 1.4); assertThat(convertedArray.getValues()).isEqualTo(expected); }
public void test_convertedTo_existingCurrency() { FxMatrix fxMatrix = FxMatrix.builder() .addRate(USD, GBP, 1 / 1.5) .addRate(EUR, GBP, 0.7) .build(); CurrencyAmountArray convertedArray = VALUES_ARRAY.convertedTo(Currency.GBP, fxMatrix); assertThat(convertedArray.getCurrency()).isEqualTo(Currency.GBP); double[] expected = new double[] { 20 + 30 / 1.5 + 40 * 0.7, 21 + 32 / 1.5 + 43 * 0.7, 22 + 33 / 1.5 + 44 * 0.7}; for (int i = 0; i < 3; i++) { assertThat(convertedArray.get(i).getAmount()).isEqualTo(expected[i], offset(1e-6)); } }
public void equalsBad() { FxMatrix test = FxMatrix.builder() .addRate(USD, GBP, 1.4) .build(); assertThat(test.equals(ANOTHER_TYPE)).isFalse(); assertThat(test.equals(null)).isFalse(); }
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 rateCanBeUpdatedInBuilder() { FxMatrix matrix = FxMatrix.builder() .addRate(GBP, USD, 1.5) .addRate(GBP, USD, 1.6) .build(); assertThat(matrix.getCurrencies()).containsOnly(GBP, USD); assertThat(matrix.fxRate(GBP, USD)).isEqualTo(1.6); assertThat(matrix.fxRate(USD, GBP)).isEqualTo(0.625); }
public void ratedCanBeUpdatedAndAddedViaBuilder() { FxMatrix matrix1 = FxMatrix.builder() .addRate(GBP, USD, 1.5) .build(); assertThat(matrix1.getCurrencies()).containsOnly(GBP, USD); assertThat(matrix1.fxRate(GBP, USD)).isEqualTo(1.5); FxMatrix matrix2 = matrix1.toBuilder() .addRate(GBP, USD, 1.6) .addRate(EUR, USD, 1.4) .build(); assertThat(matrix2.getCurrencies()).containsOnly(GBP, USD, EUR); assertThat(matrix2.fxRate(GBP, USD)).isEqualTo(1.6); assertThat(matrix2.fxRate(EUR, USD)).isEqualTo(1.4); }
public void singleRateMatrixCannotDoConversionForUnknownCurrency() { FxMatrix matrix = FxMatrix.builder() .addRate(GBP, USD, 1.6) .build(); assertThat(matrix.getCurrencies()).containsOnly(GBP, USD); assertThrowsIllegalArg(() -> matrix.fxRate(USD, EUR)); }
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); }
/** * Creates rates provider for EUR, USD with FX matrix. * * @param valuationDate the valuation date * @return the rates provider */ public static ImmutableRatesProvider createProviderEURUSD(LocalDate valuationDate) { FxMatrix fxMatrix = FxMatrix.builder().addRate(USD, EUR, 1.0d / EUR_USD).build(); return ImmutableRatesProvider.builder(valuationDate) .discountCurve(EUR, EUR_DSC) .discountCurve(USD, USD_DSC) .fxRateProvider(fxMatrix) .build(); }
public void test_currencyExposure() { for (ResolvedFxSingleBarrierOption option : OPTION_ALL) { CurrencyAmount pv = PRICER.presentValue(option, RATE_PROVIDER, VOLS_FLAT); MultiCurrencyAmount computed = PRICER.currencyExposure(option, RATE_PROVIDER, VOLS_FLAT); FxMatrix fxMatrix = FxMatrix.builder().addRate(EUR, USD, SPOT + FD_EPS).build(); ImmutableRatesProvider provBumped = RATE_PROVIDER.toBuilder().fxRateProvider(fxMatrix).build(); CurrencyAmount pvBumped = PRICER.presentValue(option, provBumped, VOLS_FLAT); double ceCounterFD = pvBumped.getAmount() - pv.getAmount(); double ceBaseFD = pvBumped.getAmount() / (SPOT + FD_EPS) - pv.getAmount() / SPOT; assertEquals(computed.getAmount(EUR).getAmount() * FD_EPS, ceCounterFD, NOTIONAL * TOL); assertEquals(computed.getAmount(USD).getAmount() * (1.0d / (SPOT + FD_EPS) - 1.0d / SPOT), ceBaseFD, NOTIONAL * TOL); } }
public void test_currencyExposure_atExpiry() { for (ResolvedFxSingleBarrierOption option : OPTION_ALL) { CurrencyAmount pv = PRICER.presentValue(option, RATE_PROVIDER_EXPIRY, VOLS_EXPIRY); MultiCurrencyAmount computed = PRICER.currencyExposure(option, RATE_PROVIDER_EXPIRY, VOLS_EXPIRY); FxMatrix fxMatrix = FxMatrix.builder().addRate(EUR, USD, SPOT + FD_EPS).build(); ImmutableRatesProvider provBumped = RATE_PROVIDER_EXPIRY.toBuilder().fxRateProvider(fxMatrix).build(); CurrencyAmount pvBumped = PRICER.presentValue(option, provBumped, VOLS_EXPIRY); double ceCounterFD = pvBumped.getAmount() - pv.getAmount(); double ceBaseFD = pvBumped.getAmount() / (SPOT + FD_EPS) - pv.getAmount() / SPOT; assertEquals(computed.getAmount(EUR).getAmount() * FD_EPS, ceCounterFD, NOTIONAL * TOL); assertEquals(computed.getAmount(USD).getAmount() * (1.0d / (SPOT + FD_EPS) - 1.0d / SPOT), ceBaseFD, NOTIONAL * TOL); } }
public void matrixCalculatesCrossRates() { FxMatrix matrix = FxMatrix.builder() .addRate(GBP, USD, 1.6) .addRate(EUR, USD, 1.4) .addRate(EUR, CHF, 1.2) .build(); assertThat(matrix.getCurrencies()).containsOnly(GBP, USD, EUR, CHF); 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); assertThat(matrix.fxRate(EUR, CHF)).isEqualTo(1.2); }
public void singleRateMatrixByBuilder() { FxMatrix matrix = FxMatrix.builder() .addRate(GBP, USD, 1.6) .build(); assertThat(matrix.getCurrencies()).containsOnly(GBP, USD); assertThat(matrix.fxRate(GBP, USD)).isEqualTo(1.6); assertThat(matrix.fxRate(USD, GBP)).isEqualTo(0.625); }
public void canAddRateUsingCurrencyPair() { FxMatrix matrix = FxMatrix.builder() .addRate(CurrencyPair.of(GBP, USD), 1.6) .build(); assertThat(matrix.getCurrencies()).containsOnly(GBP, USD); assertThat(matrix.fxRate(GBP, USD)).isEqualTo(1.6); assertThat(matrix.fxRate(USD, GBP)).isEqualTo(0.625); }