@Override public SwapTrade trade(LocalDate valuationDate, MarketData marketData) { double marketQuote = marketData.getValue(spreadKey) + additionalSpread; FxRate fxRate = marketData.getValue(fxKey()); double rate = fxRate.fxRate(template.getCurrencyPair()); return template.toTrade(valuationDate, BuySell.BUY, 1, rate, marketQuote); }
public void convertCurrencyAmount() { List<FxRate> rates = ImmutableList.of( FxRate.of(Currency.GBP, Currency.USD, 1.61), FxRate.of(Currency.GBP, Currency.USD, 1.62), FxRate.of(Currency.GBP, Currency.USD, 1.63)); CalculationEnvironment marketData = MarketEnvironment.builder() .valuationDate(date(2011, 3, 8)) .addValue(FxRateId.of(Currency.GBP, Currency.USD), rates) .build(); MarketDataMappings mappings = MarketDataMappings.of(MarketDataFeed.NONE); DefaultCalculationMarketData calculationMarketData = DefaultCalculationMarketData.of(marketData, mappings); SingleScenarioResult<CurrencyAmount> test = SingleScenarioResult.of(3, CurrencyAmount.of(Currency.GBP, 2)); ScenarioResult<?> convertedList = test.convertedTo(Currency.USD, calculationMarketData); List<CurrencyAmount> expectedValues = ImmutableList.of( CurrencyAmount.of(Currency.USD, 2 * 1.61), CurrencyAmount.of(Currency.USD, 2 * 1.62), CurrencyAmount.of(Currency.USD, 2 * 1.63)); DefaultScenarioResult<CurrencyAmount> expectedList = DefaultScenarioResult.of(expectedValues); assertThat(convertedList).isEqualTo(expectedList); }
// ------------------------------------------------------------------------- public void coverage() { DiscountFxForwardRates test1 = DiscountFxForwardRates.of(CURRENCY_PAIR, FX_RATE, DFCURVE_GBP, DFCURVE_USD); coverImmutableBean(test1); DiscountFxForwardRates test2 = DiscountFxForwardRates.of(CURRENCY_PAIR, FX_RATE.inverse(), DFCURVE_GBP2, DFCURVE_USD2); coverBeanEquals(test1, test2); DiscountFxForwardRates test3 = DiscountFxForwardRates.of( CurrencyPair.of(USD, EUR), FxRate.of(EUR, USD, 1.2d), DFCURVE_USD, ZeroRateDiscountFactors.of(EUR, DATE_VAL, CURVE2)); coverBeanEquals(test1, test3); }
// ------------------------------------------------------------------------- public void test_rate() { DiscountFxForwardRates test = DiscountFxForwardRates.of(CURRENCY_PAIR, FX_RATE, DFCURVE_GBP, DFCURVE_USD); double dfCcyBaseAtMaturity = DFCURVE_GBP.discountFactor(DATE_REF); double dfCcyCounterAtMaturity = DFCURVE_USD.discountFactor(DATE_REF); double expected = FX_RATE.fxRate(GBP, USD) * (dfCcyBaseAtMaturity / dfCcyCounterAtMaturity); assertEquals(test.rate(GBP, DATE_REF), expected, 1e-12); assertEquals(test.rate(USD, DATE_REF), 1d / expected, 1e-12); }
/** Test a failure is returned for a convertible value if there is no reporting currency. */ public void convertResultCurrencyNoReportingCurrency() { DoubleArray values = DoubleArray.of(1, 2, 3); List<FxRate> rates = ImmutableList.of(1.61, 1.62, 1.63) .stream() .map(rate -> FxRate.of(Currency.GBP, Currency.USD, rate)) .collect(toImmutableList()); CurrencyValuesArray list = CurrencyValuesArray.of(Currency.GBP, values); CalculationEnvironment marketData = CalculationEnvironment.builder() .valuationDate(date(2011, 3, 8)) .addValue(FxRateId.of(Currency.GBP, Currency.USD), rates) .build(); ConvertibleFunction fn = ConvertibleFunction.of(() -> list); ReportingRules reportingRules = ReportingRules.empty(); CalculationTask task = new CalculationTask(TARGET, 0, 0, fn, MAPPINGS, reportingRules); CalculationResult calculationResult = task.execute(marketData); Result<?> result = calculationResult.getResult(); assertThat(result).hasFailureMessageMatching("No reporting currency available.*"); }
public void coverage_functions() { Currency ccy1 = TRADE.getProduct().getNonDeliverableCurrency(); Currency ccy2 = TRADE.getProduct().getSettlementCurrency(); LocalDate valDate = TRADE.getProduct().getPaymentDate().plusDays(7); Curve df = ConstantNodalCurve.of(Curves.discountFactors("Test", ACT_360), 0.99); FxRate fxRate = FxRate.of(ccy1, ccy2, 1.6d); TestMarketDataMap md = new TestMarketDataMap( valDate, ImmutableMap.of( DiscountCurveKey.of(ccy1), df, DiscountCurveKey.of(ccy2), df, FxRateKey.of(ccy1, ccy2), fxRate), ImmutableMap.of( IndexRateKey.of(GBP_USD_WM), LocalDateDoubleTimeSeries.of(date(2015, 3, 17), 1.45d))); assertNotNull(new FxNdfBucketedPv01Function().execute(TRADE, md)); assertNotNull(new FxNdfCurrencyExposureFunction().execute(TRADE, md)); assertNotNull(new FxNdfForwardFxRateFunction().execute(TRADE, md)); assertNotNull(new FxNdfPv01Function().execute(TRADE, md)); assertNotNull(new FxNdfPvFunction().execute(TRADE, md)); }
/** * Test that the result is converted to the reporting currency if it implements * CurrencyConvertible and the FX rates are available in the market data. The reporting currency * is taken from the reporting rules. */ public void convertResultCurrencyUsingReportingRules() { DoubleArray values = DoubleArray.of(1, 2, 3); List<FxRate> rates = ImmutableList.of(1.61, 1.62, 1.63) .stream() .map(rate -> FxRate.of(Currency.GBP, Currency.USD, rate)) .collect(toImmutableList()); CurrencyValuesArray list = CurrencyValuesArray.of(Currency.GBP, values); CalculationEnvironment marketData = CalculationEnvironment.builder() .valuationDate(date(2011, 3, 8)) .addValue(FxRateId.of(Currency.GBP, Currency.USD), rates) .build(); ConvertibleFunction fn = ConvertibleFunction.of(() -> list); CalculationTask task = new CalculationTask(TARGET, 0, 0, fn, MAPPINGS, REPORTING_RULES); DoubleArray expectedValues = DoubleArray.of(1 * 1.61, 2 * 1.62, 3 * 1.63); CurrencyValuesArray expectedArray = CurrencyValuesArray.of(Currency.USD, expectedValues); CalculationResult calculationResult = task.execute(marketData); Result<?> result = calculationResult.getResult(); assertThat(result).hasValue(expectedArray); }
/** Test {@link FxNdfFunctionGroups}. */ @Test public class FxNdfFunctionGroupsTest { private static final FxRate FX_RATE = FxRate.of(GBP, USD, 1.5d); private static final CurrencyAmount NOTIONAL = CurrencyAmount.of(GBP, (double) 100_000_000); private static final FxNdf PRODUCT = FxNdf.builder() .agreedFxRate(FX_RATE) .settlementCurrencyNotional(NOTIONAL) .index(GBP_USD_WM) .paymentDate(date(2015, 3, 19)) .build(); public static final FxNdfTrade TRADE = FxNdfTrade.builder() .tradeInfo(TradeInfo.builder().tradeDate(date(2015, 6, 1)).build()) .product(PRODUCT) .build(); public void test_discounting() { FunctionGroup<FxNdfTrade> test = FxNdfFunctionGroups.discounting(); assertThat(test.configuredMeasures(TRADE)) .contains( Measure.PRESENT_VALUE, Measure.PV01, Measure.BUCKETED_PV01, Measure.CURRENCY_EXPOSURE, Measure.FORWARD_FX_RATE); } public void test_presentValue() { Currency ccy1 = TRADE.getProduct().getNonDeliverableCurrency(); Currency ccy2 = TRADE.getProduct().getSettlementCurrency(); LocalDate valDate = TRADE.getProduct().getPaymentDate().plusDays(7); FunctionConfig<FxNdfTrade> config = FxNdfFunctionGroups.discounting().functionConfig(TRADE, Measure.PRESENT_VALUE).get(); CalculationSingleFunction<FxNdfTrade, ?> function = config.createFunction(); FunctionRequirements reqs = function.requirements(TRADE); assertThat(reqs.getOutputCurrencies()).containsOnly(ccy1, ccy2); assertThat(reqs.getSingleValueRequirements()) .isEqualTo(ImmutableSet.of(DiscountCurveKey.of(ccy1), DiscountCurveKey.of(ccy2))); assertThat(reqs.getTimeSeriesRequirements()).isEqualTo(ImmutableSet.of()); assertThat(function.defaultReportingCurrency(TRADE)).hasValue(GBP); DiscountFactors df1 = SimpleDiscountFactors.of( ccy1, valDate, ConstantNodalCurve.of(Curves.discountFactors("Test", ACT_360), 0.99)); DiscountFactors df2 = SimpleDiscountFactors.of( ccy2, valDate, ConstantNodalCurve.of(Curves.discountFactors("Test", ACT_360), 0.99)); TestMarketDataMap md = new TestMarketDataMap( valDate, ImmutableMap.of(DiscountCurveKey.of(ccy1), df1, DiscountCurveKey.of(ccy2), df2), ImmutableMap.of()); assertThat(function.execute(TRADE, md)) .isEqualTo(FxConvertibleList.of(ImmutableList.of(CurrencyAmount.zero(GBP)))); } // ------------------------------------------------------------------------- public void coverage() { coverPrivateConstructor(FxNdfFunctionGroups.class); } public void coverage_functions() { Currency ccy1 = TRADE.getProduct().getNonDeliverableCurrency(); Currency ccy2 = TRADE.getProduct().getSettlementCurrency(); LocalDate valDate = TRADE.getProduct().getPaymentDate().plusDays(7); Curve df = ConstantNodalCurve.of(Curves.discountFactors("Test", ACT_360), 0.99); FxRate fxRate = FxRate.of(ccy1, ccy2, 1.6d); TestMarketDataMap md = new TestMarketDataMap( valDate, ImmutableMap.of( DiscountCurveKey.of(ccy1), df, DiscountCurveKey.of(ccy2), df, FxRateKey.of(ccy1, ccy2), fxRate), ImmutableMap.of( IndexRateKey.of(GBP_USD_WM), LocalDateDoubleTimeSeries.of(date(2015, 3, 17), 1.45d))); assertNotNull(new FxNdfBucketedPv01Function().execute(TRADE, md)); assertNotNull(new FxNdfCurrencyExposureFunction().execute(TRADE, md)); assertNotNull(new FxNdfForwardFxRateFunction().execute(TRADE, md)); assertNotNull(new FxNdfPv01Function().execute(TRADE, md)); assertNotNull(new FxNdfPvFunction().execute(TRADE, md)); } }
/** Test {@link DiscountFxForwardRates}. */ @Test public class DiscountFxForwardRatesTest { private static final LocalDate DATE_VAL = date(2015, 6, 4); private static final LocalDate DATE_REF = date(2015, 7, 30); private static final FxRate FX_RATE = FxRate.of(GBP, USD, 1.5d); private static final CurrencyPair CURRENCY_PAIR = CurrencyPair.of(GBP, USD); private static final CurveInterpolator INTERPOLATOR = CurveInterpolators.LINEAR; private static final CurveMetadata METADATA1 = Curves.zeroRates("TestCurve", ACT_365F); private static final CurveMetadata METADATA2 = Curves.zeroRates("TestCurveUSD", ACT_365F); private static final InterpolatedNodalCurve CURVE1 = InterpolatedNodalCurve.of( METADATA1, DoubleArray.of(0, 10), DoubleArray.of(0.01, 0.02), INTERPOLATOR); private static final InterpolatedNodalCurve CURVE2 = InterpolatedNodalCurve.of( METADATA2, DoubleArray.of(0, 10), DoubleArray.of(0.015, 0.025), INTERPOLATOR); private static final ZeroRateDiscountFactors DFCURVE_GBP = ZeroRateDiscountFactors.of(GBP, DATE_VAL, CURVE1); private static final ZeroRateDiscountFactors DFCURVE_GBP2 = ZeroRateDiscountFactors.of(GBP, DATE_VAL, CURVE2); private static final ZeroRateDiscountFactors DFCURVE_USD = ZeroRateDiscountFactors.of(USD, DATE_VAL, CURVE2); private static final ZeroRateDiscountFactors DFCURVE_USD2 = ZeroRateDiscountFactors.of(USD, DATE_VAL, CURVE1); // ------------------------------------------------------------------------- public void test_of() { DiscountFxForwardRates test = DiscountFxForwardRates.of(CURRENCY_PAIR, FX_RATE, DFCURVE_GBP, DFCURVE_USD); assertEquals(test.getCurrencyPair(), CURRENCY_PAIR); assertEquals(test.getValuationDate(), DATE_VAL); assertEquals(test.getBaseCurrencyDiscountFactors(), DFCURVE_GBP); assertEquals(test.getCounterCurrencyDiscountFactors(), DFCURVE_USD); assertEquals(test.getFxRateProvider(), FX_RATE); assertEquals(test.findData(CURVE1.getName()), Optional.of(CURVE1)); assertEquals(test.findData(CURVE2.getName()), Optional.of(CURVE2)); assertEquals(test.findData(CurveName.of("Rubbish")), Optional.empty()); int baseSize = DFCURVE_USD.getParameterCount(); assertEquals(test.getParameterCount(), DFCURVE_GBP.getParameterCount() + baseSize); assertEquals(test.getParameter(0), DFCURVE_GBP.getParameter(0)); assertEquals(test.getParameter(baseSize), DFCURVE_USD.getParameter(0)); assertEquals(test.getParameterMetadata(0), DFCURVE_GBP.getParameterMetadata(0)); assertEquals(test.getParameterMetadata(baseSize), DFCURVE_USD.getParameterMetadata(0)); assertEquals( test.withParameter(0, 1d).getBaseCurrencyDiscountFactors(), DFCURVE_GBP.withParameter(0, 1d)); assertEquals(test.withParameter(0, 1d).getCounterCurrencyDiscountFactors(), DFCURVE_USD); assertEquals(test.withParameter(baseSize, 1d).getBaseCurrencyDiscountFactors(), DFCURVE_GBP); assertEquals( test.withParameter(baseSize, 1d).getCounterCurrencyDiscountFactors(), DFCURVE_USD.withParameter(0, 1d)); assertEquals( test.withPerturbation((i, v, m) -> v + 1d).getBaseCurrencyDiscountFactors(), DFCURVE_GBP.withPerturbation((i, v, m) -> v + 1d)); assertEquals( test.withPerturbation((i, v, m) -> v + 1d).getCounterCurrencyDiscountFactors(), DFCURVE_USD.withPerturbation((i, v, m) -> v + 1d)); } public void test_of_nonMatchingCurrency() { assertThrowsIllegalArg( () -> DiscountFxForwardRates.of(CURRENCY_PAIR, FX_RATE, DFCURVE_GBP, DFCURVE_GBP)); assertThrowsIllegalArg( () -> DiscountFxForwardRates.of(CURRENCY_PAIR, FX_RATE, DFCURVE_USD, DFCURVE_USD)); } public void test_of_nonMatchingValuationDates() { DiscountFactors curve2 = ZeroRateDiscountFactors.of(USD, DATE_REF, CURVE2); assertThrowsIllegalArg( () -> DiscountFxForwardRates.of(CURRENCY_PAIR, FX_RATE, DFCURVE_GBP, curve2)); } public void test_builder() { assertThrowsIllegalArg( () -> DiscountFxForwardRates.meta() .builder() .setString(DiscountFxForwardRates.meta().currencyPair(), "GBP/USD") .build()); assertThrowsIllegalArg( () -> DiscountFxForwardRates.meta() .builder() .setString(DiscountFxForwardRates.meta().currencyPair().name(), "GBP/USD") .build()); } // ------------------------------------------------------------------------- public void test_withDiscountFactors() { DiscountFxForwardRates test = DiscountFxForwardRates.of(CURRENCY_PAIR, FX_RATE, DFCURVE_GBP, DFCURVE_USD); test = test.withDiscountFactors(DFCURVE_GBP2, DFCURVE_USD2); assertEquals(test.getCurrencyPair(), CURRENCY_PAIR); assertEquals(test.getValuationDate(), DATE_VAL); assertEquals(test.getBaseCurrencyDiscountFactors(), DFCURVE_GBP2); assertEquals(test.getCounterCurrencyDiscountFactors(), DFCURVE_USD2); assertEquals(test.getFxRateProvider(), FX_RATE); } // ------------------------------------------------------------------------- public void test_rate() { DiscountFxForwardRates test = DiscountFxForwardRates.of(CURRENCY_PAIR, FX_RATE, DFCURVE_GBP, DFCURVE_USD); double dfCcyBaseAtMaturity = DFCURVE_GBP.discountFactor(DATE_REF); double dfCcyCounterAtMaturity = DFCURVE_USD.discountFactor(DATE_REF); double expected = FX_RATE.fxRate(GBP, USD) * (dfCcyBaseAtMaturity / dfCcyCounterAtMaturity); assertEquals(test.rate(GBP, DATE_REF), expected, 1e-12); assertEquals(test.rate(USD, DATE_REF), 1d / expected, 1e-12); } public void test_rate_nonMatchingCurrency() { DiscountFxForwardRates test = DiscountFxForwardRates.of(CURRENCY_PAIR, FX_RATE, DFCURVE_GBP, DFCURVE_USD); assertThrowsIllegalArg(() -> test.rate(EUR, DATE_VAL)); } // ------------------------------------------------------------------------- public void test_ratePointSensitivity() { DiscountFxForwardRates test = DiscountFxForwardRates.of(CURRENCY_PAIR, FX_RATE, DFCURVE_GBP, DFCURVE_USD); assertEquals( test.ratePointSensitivity(GBP, DATE_REF), FxForwardSensitivity.of(CURRENCY_PAIR, GBP, DATE_REF, 1d)); assertEquals( test.ratePointSensitivity(USD, DATE_REF), FxForwardSensitivity.of(CURRENCY_PAIR, USD, DATE_REF, 1d)); } public void test_ratePointSensitivity_nonMatchingCurrency() { DiscountFxForwardRates test = DiscountFxForwardRates.of(CURRENCY_PAIR, FX_RATE, DFCURVE_GBP, DFCURVE_USD); assertThrowsIllegalArg(() -> test.ratePointSensitivity(EUR, DATE_VAL)); } // ------------------------------------------------------------------------- public void test_rateFxSpotSensitivity() { DiscountFxForwardRates test = DiscountFxForwardRates.of(CURRENCY_PAIR, FX_RATE, DFCURVE_GBP, DFCURVE_USD); double dfCcyBaseAtMaturity = DFCURVE_GBP.discountFactor(DATE_REF); double dfCcyCounterAtMaturity = DFCURVE_USD.discountFactor(DATE_REF); double expected = dfCcyBaseAtMaturity / dfCcyCounterAtMaturity; assertEquals(test.rateFxSpotSensitivity(GBP, DATE_REF), expected, 1e-12); assertEquals(test.rateFxSpotSensitivity(USD, DATE_REF), 1d / expected, 1e-12); } public void test_rateFxSpotSensitivity_nonMatchingCurrency() { DiscountFxForwardRates test = DiscountFxForwardRates.of(CURRENCY_PAIR, FX_RATE, DFCURVE_GBP, DFCURVE_USD); assertThrowsIllegalArg(() -> test.rateFxSpotSensitivity(EUR, DATE_VAL)); } // ------------------------------------------------------------------------- // proper end-to-end tests are elsewhere public void test_parameterSensitivity() { DiscountFxForwardRates test = DiscountFxForwardRates.of(CURRENCY_PAIR, FX_RATE, DFCURVE_GBP, DFCURVE_USD); FxForwardSensitivity point = FxForwardSensitivity.of(CURRENCY_PAIR, GBP, DATE_VAL, 1d); assertEquals(test.parameterSensitivity(point).size(), 2); FxForwardSensitivity point2 = FxForwardSensitivity.of(CURRENCY_PAIR, USD, DATE_VAL, 1d); assertEquals(test.parameterSensitivity(point2).size(), 2); } // ------------------------------------------------------------------------- public void coverage() { DiscountFxForwardRates test1 = DiscountFxForwardRates.of(CURRENCY_PAIR, FX_RATE, DFCURVE_GBP, DFCURVE_USD); coverImmutableBean(test1); DiscountFxForwardRates test2 = DiscountFxForwardRates.of(CURRENCY_PAIR, FX_RATE.inverse(), DFCURVE_GBP2, DFCURVE_USD2); coverBeanEquals(test1, test2); DiscountFxForwardRates test3 = DiscountFxForwardRates.of( CurrencyPair.of(USD, EUR), FxRate.of(EUR, USD, 1.2d), DFCURVE_USD, ZeroRateDiscountFactors.of(EUR, DATE_VAL, CURVE2)); coverBeanEquals(test1, test3); } }
/** * Test for curve calibration in USD and EUR. The USD curve is obtained by OIS and the EUR one by FX * Swaps from USD. */ @Test public class CalibrationZeroRateUsdEur2OisFxTest { private static final LocalDate VAL_DATE = LocalDate.of(2015, 11, 2); private static final CurveInterpolator INTERPOLATOR_LINEAR = CurveInterpolators.LINEAR; private static final CurveExtrapolator EXTRAPOLATOR_FLAT = CurveExtrapolators.FLAT; private static final DayCount CURVE_DC = ACT_365F; private static final String SCHEME = "CALIBRATION"; /** Curve names */ private static final String USD_DSCON_STR = "USD-DSCON-OIS"; private static final CurveName USD_DSCON_CURVE_NAME = CurveName.of(USD_DSCON_STR); private static final String EUR_DSC_STR = "EUR-DSC-FX"; private static final CurveName EUR_DSC_CURVE_NAME = CurveName.of(EUR_DSC_STR); /** Curves associations to currencies and indices. */ private static final Map<CurveName, Currency> DSC_NAMES = new HashMap<>(); private static final Map<CurveName, Set<Index>> IDX_NAMES = new HashMap<>(); private static final Map<Index, LocalDateDoubleTimeSeries> TS = new HashMap<>(); static { DSC_NAMES.put(USD_DSCON_CURVE_NAME, USD); Set<Index> usdFedFundSet = new HashSet<>(); usdFedFundSet.add(USD_FED_FUND); IDX_NAMES.put(USD_DSCON_CURVE_NAME, usdFedFundSet); } /** Data FX * */ private static final FxRate FX_RATE_EUR_USD = FxRate.of(EUR, USD, 1.10); /** Data for USD-DSCON curve */ /* Market values */ private static final double[] USD_DSC_MARKET_QUOTES = new double[] { 0.0016, 0.0022, 0.0013, 0.0016, 0.0020, 0.0026, 0.0033, 0.0039, 0.0053, 0.0066, 0.0090, 0.0111 }; private static final int USD_DSC_NB_NODES = USD_DSC_MARKET_QUOTES.length; private static final String[] USD_DSC_ID_VALUE = new String[] { "USD-ON", "USD-TN", "USD-OIS-1M", "USD-OIS-2M", "USD-OIS-3M", "USD-OIS-6M", "USD-OIS-9M", "USD-OIS-1Y", "USD-OIS-18M", "USD-OIS-2Y", "USD-OIS-3Y", "USD-OIS-4Y" }; /* Nodes */ private static final CurveNode[] USD_DSC_NODES = new CurveNode[USD_DSC_NB_NODES]; /* Tenors */ private static final int[] USD_DSC_DEPO_OFFSET = new int[] {0, 1}; private static final int USD_DSC_NB_DEPO_NODES = USD_DSC_DEPO_OFFSET.length; private static final Period[] USD_DSC_OIS_TENORS = new Period[] { Period.ofMonths(1), Period.ofMonths(2), Period.ofMonths(3), Period.ofMonths(6), Period.ofMonths(9), Period.ofYears(1), Period.ofMonths(18), Period.ofYears(2), Period.ofYears(3), Period.ofYears(4) }; private static final int USD_DSC_NB_OIS_NODES = USD_DSC_OIS_TENORS.length; static { USD_DSC_NODES[0] = TermDepositCurveNode.of( TermDepositTemplate.of(Period.ofDays(1), USD_DEPOSIT_T0), QuoteKey.of(StandardId.of(SCHEME, USD_DSC_ID_VALUE[0]))); USD_DSC_NODES[1] = TermDepositCurveNode.of( TermDepositTemplate.of(Period.ofDays(1), USD_DEPOSIT_T1), QuoteKey.of(StandardId.of(SCHEME, USD_DSC_ID_VALUE[1]))); for (int i = 0; i < USD_DSC_NB_OIS_NODES; i++) { USD_DSC_NODES[USD_DSC_NB_DEPO_NODES + i] = FixedOvernightSwapCurveNode.of( FixedOvernightSwapTemplate.of( Period.ZERO, Tenor.of(USD_DSC_OIS_TENORS[i]), USD_FIXED_1Y_FED_FUND_OIS), QuoteKey.of(StandardId.of(SCHEME, USD_DSC_ID_VALUE[USD_DSC_NB_DEPO_NODES + i]))); } } /** Data for EUR-DSC curve */ /* Market values */ private static final double[] EUR_DSC_MARKET_QUOTES = new double[] { 0.0004, 0.0012, 0.0019, 0.0043, 0.0074, 0.0109, 0.0193, 0.0294, 0.0519, 0.0757 }; private static final int EUR_DSC_NB_NODES = EUR_DSC_MARKET_QUOTES.length; private static final String[] EUR_DSC_ID_VALUE = new String[] { "EUR-USD-FX-1M", "EUR-USD-FX-2M", "EUR-USD-FX-3M", "EUR-USD-FX-6M", "EUR-USD-FX-9M", "EUR-USD-FX-1Y", "EUR-USD-FX-18M", "EUR-USD-FX-2Y", "EUR-USD-FX-3Y", "EUR-USD-FX-4Y" }; /* Nodes */ private static final CurveNode[] EUR_DSC_NODES = new CurveNode[EUR_DSC_NB_NODES]; /* Tenors */ private static final Period[] EUR_DSC_FX_TENORS = new Period[] { Period.ofMonths(1), Period.ofMonths(2), Period.ofMonths(3), Period.ofMonths(6), Period.ofMonths(9), Period.ofYears(1), Period.ofMonths(18), Period.ofYears(2), Period.ofYears(3), Period.ofYears(4) }; private static final int EUR_DSC_NB_FX_NODES = EUR_DSC_FX_TENORS.length; static { for (int i = 0; i < EUR_DSC_NB_FX_NODES; i++) { EUR_DSC_NODES[i] = FxSwapCurveNode.of( FxSwapTemplate.of(EUR_DSC_FX_TENORS[i], EUR_USD), QuoteKey.of(StandardId.of(SCHEME, EUR_DSC_ID_VALUE[i]))); } } /** All quotes for the curve calibration */ private static final ImmutableMarketData ALL_QUOTES; static { Map<MarketDataKey<?>, Object> map = new HashMap<>(); for (int i = 0; i < USD_DSC_NB_NODES; i++) { map.put(QuoteKey.of(StandardId.of(SCHEME, USD_DSC_ID_VALUE[i])), USD_DSC_MARKET_QUOTES[i]); } for (int i = 0; i < EUR_DSC_NB_NODES; i++) { map.put(QuoteKey.of(StandardId.of(SCHEME, EUR_DSC_ID_VALUE[i])), EUR_DSC_MARKET_QUOTES[i]); } map.put(FxRateKey.of(EUR, USD), FX_RATE_EUR_USD); ALL_QUOTES = ImmutableMarketData.of(map); } private static final DiscountingSwapProductPricer SWAP_PRICER = DiscountingSwapProductPricer.DEFAULT; private static final DiscountingTermDepositProductPricer DEPO_PRICER = DiscountingTermDepositProductPricer.DEFAULT; private static final DiscountingFxSwapProductPricer FX_PRICER = DiscountingFxSwapProductPricer.DEFAULT; private static final MarketQuoteSensitivityCalculator MQC = MarketQuoteSensitivityCalculator.DEFAULT; private static final CalibrationMeasures CALIBRATION_MEASURES = CalibrationMeasures.DEFAULT; private static final CurveCalibrator CALIBRATOR = CurveCalibrator.of(1e-9, 1e-9, 100, CALIBRATION_MEASURES); // Constants private static final double TOLERANCE_PV = 1.0E-6; private static final double TOLERANCE_PV_DELTA = 1.0E+3; private static final CurveGroupName CURVE_GROUP_NAME = CurveGroupName.of("USD-DSCON-EUR-DSC"); private static final InterpolatedNodalCurveDefinition USD_DSC_CURVE_DEFN = InterpolatedNodalCurveDefinition.builder() .name(USD_DSCON_CURVE_NAME) .xValueType(ValueType.YEAR_FRACTION) .yValueType(ValueType.ZERO_RATE) .dayCount(CURVE_DC) .interpolator(INTERPOLATOR_LINEAR) .extrapolatorLeft(EXTRAPOLATOR_FLAT) .extrapolatorRight(EXTRAPOLATOR_FLAT) .nodes(USD_DSC_NODES) .build(); private static final InterpolatedNodalCurveDefinition EUR_DSC_CURVE_DEFN = InterpolatedNodalCurveDefinition.builder() .name(EUR_DSC_CURVE_NAME) .xValueType(ValueType.YEAR_FRACTION) .yValueType(ValueType.ZERO_RATE) .dayCount(CURVE_DC) .interpolator(INTERPOLATOR_LINEAR) .extrapolatorLeft(EXTRAPOLATOR_FLAT) .extrapolatorRight(EXTRAPOLATOR_FLAT) .nodes(EUR_DSC_NODES) .build(); private static final CurveGroupDefinition CURVE_GROUP_CONFIG = CurveGroupDefinition.builder() .name(CURVE_GROUP_NAME) .addCurve(USD_DSC_CURVE_DEFN, USD, USD_FED_FUND) .addDiscountCurve(EUR_DSC_CURVE_DEFN, EUR) .build(); // ------------------------------------------------------------------------- public void calibration_present_value_oneGroup() { ImmutableRatesProvider result = CALIBRATOR.calibrate(CURVE_GROUP_CONFIG, VAL_DATE, ALL_QUOTES, TS); assertPresentValue(result); } private void assertPresentValue(ImmutableRatesProvider result) { // Test PV USD; List<Trade> usdTrades = new ArrayList<>(); for (int i = 0; i < USD_DSC_NODES.length; i++) { usdTrades.add(USD_DSC_NODES[i].trade(VAL_DATE, ALL_QUOTES)); } // Depo for (int i = 0; i < USD_DSC_NB_DEPO_NODES; i++) { CurrencyAmount pvDep = DEPO_PRICER.presentValue(((TermDepositTrade) usdTrades.get(i)).getProduct(), result); assertEquals(pvDep.getAmount(), 0.0, TOLERANCE_PV); } // OIS for (int i = 0; i < USD_DSC_NB_OIS_NODES; i++) { MultiCurrencyAmount pvOis = SWAP_PRICER.presentValue( ((SwapTrade) usdTrades.get(USD_DSC_NB_DEPO_NODES + i)).getProduct(), result); assertEquals(pvOis.getAmount(USD).getAmount(), 0.0, TOLERANCE_PV); } // Test PV EUR; List<Trade> eurTrades = new ArrayList<>(); for (int i = 0; i < EUR_DSC_NODES.length; i++) { eurTrades.add(EUR_DSC_NODES[i].trade(VAL_DATE, ALL_QUOTES)); } // Depo for (int i = 0; i < EUR_DSC_NB_FX_NODES; i++) { MultiCurrencyAmount pvFx = FX_PRICER.presentValue(((FxSwapTrade) eurTrades.get(i)).getProduct(), result); assertEquals(pvFx.convertedTo(USD, result).getAmount(), 0.0, TOLERANCE_PV); } } public void calibration_market_quote_sensitivity_one_group() { double shift = 1.0E-6; Function<MarketData, ImmutableRatesProvider> f = ov -> CALIBRATOR.calibrate(CURVE_GROUP_CONFIG, VAL_DATE, ov, TS); calibration_market_quote_sensitivity_check(f, shift); } private void calibration_market_quote_sensitivity_check( Function<MarketData, ImmutableRatesProvider> calibrator, double shift) { double notional = 100_000_000.0; double fx = 1.1111; double fxPts = 0.0012; FxSwapTrade trade = EUR_USD.toTrade( VAL_DATE, Period.ofWeeks(6), Period.ofMonths(5), BuySell.BUY, notional, fx, fxPts); ImmutableRatesProvider result = CALIBRATOR.calibrate(CURVE_GROUP_CONFIG, VAL_DATE, ALL_QUOTES, TS); PointSensitivities pts = FX_PRICER.presentValueSensitivity(trade.getProduct(), result); CurveCurrencyParameterSensitivities ps = result.curveParameterSensitivity(pts); CurveCurrencyParameterSensitivities mqs = MQC.sensitivity(ps, result); double pvUsd = FX_PRICER.presentValue(trade.getProduct(), result).getAmount(USD).getAmount(); double pvEur = FX_PRICER.presentValue(trade.getProduct(), result).getAmount(EUR).getAmount(); double[] mqsUsd1Computed = mqs.getSensitivity(USD_DSCON_CURVE_NAME, USD).getSensitivity().toArray(); for (int i = 0; i < USD_DSC_NB_NODES; i++) { Map<MarketDataKey<?>, Object> map = new HashMap<>(ALL_QUOTES.getValues()); map.put( QuoteKey.of(StandardId.of(SCHEME, USD_DSC_ID_VALUE[i])), USD_DSC_MARKET_QUOTES[i] + shift); ImmutableMarketData marketData = ImmutableMarketData.of(map); ImmutableRatesProvider rpShifted = calibrator.apply(marketData); double pvS = FX_PRICER.presentValue(trade.getProduct(), rpShifted).getAmount(USD).getAmount(); assertEquals(mqsUsd1Computed[i], (pvS - pvUsd) / shift, TOLERANCE_PV_DELTA); } double[] mqsUsd2Computed = mqs.getSensitivity(USD_DSCON_CURVE_NAME, EUR).getSensitivity().toArray(); for (int i = 0; i < USD_DSC_NB_NODES; i++) { Map<MarketDataKey<?>, Object> map = new HashMap<>(ALL_QUOTES.getValues()); map.put( QuoteKey.of(StandardId.of(SCHEME, USD_DSC_ID_VALUE[i])), USD_DSC_MARKET_QUOTES[i] + shift); ImmutableMarketData ov = ImmutableMarketData.of(map); ImmutableRatesProvider rpShifted = calibrator.apply(ov); double pvS = FX_PRICER.presentValue(trade.getProduct(), rpShifted).getAmount(EUR).getAmount(); assertEquals(mqsUsd2Computed[i], (pvS - pvEur) / shift, TOLERANCE_PV_DELTA); } double[] mqsEur1Computed = mqs.getSensitivity(EUR_DSC_CURVE_NAME, USD).getSensitivity().toArray(); for (int i = 0; i < EUR_DSC_NB_NODES; i++) { assertEquals(mqsEur1Computed[i], 0.0, TOLERANCE_PV_DELTA); } double[] mqsEur2Computed = mqs.getSensitivity(EUR_DSC_CURVE_NAME, EUR).getSensitivity().toArray(); for (int i = 0; i < EUR_DSC_NB_NODES; i++) { Map<MarketDataKey<?>, Object> map = new HashMap<>(ALL_QUOTES.getValues()); map.put( QuoteKey.of(StandardId.of(SCHEME, EUR_DSC_ID_VALUE[i])), EUR_DSC_MARKET_QUOTES[i] + shift); ImmutableMarketData marketData = ImmutableMarketData.of(map); ImmutableRatesProvider rpShifted = calibrator.apply(marketData); double pvS = FX_PRICER.presentValue(trade.getProduct(), rpShifted).getAmount(EUR).getAmount(); assertEquals(mqsEur2Computed[i], (pvS - pvEur) / shift, TOLERANCE_PV_DELTA, "Node " + i); } } }