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); } }
/** Test par spread sensitivity for ISDA FRA Discounting method. */ public void test_parSpreadSensitivity_ISDA() { PointSensitivities sensi = DEFAULT_PRICER.parSpreadSensitivity(FRA, IMM_PROV); CurveCurrencyParameterSensitivities sensiComputed = IMM_PROV.curveParameterSensitivity(sensi); CurveCurrencyParameterSensitivities sensiExpected = CAL_FD.sensitivity( IMM_PROV, (p) -> CurrencyAmount.of(FRA.getCurrency(), DEFAULT_PRICER.parSpread(FRA, (p)))); assertTrue(sensiComputed.equalWithTolerance(sensiExpected, EPS_FD)); }
// ------------------------------------------------------------------------- public void test_cashFlowEquivalentAndSensitivity() { Swap swap = Swap.builder().legs(IBOR_LEG, FIXED_LEG).build(); ImmutableMap<NotionalExchange, PointSensitivityBuilder> computedFull = CashFlowEquivalentCalculator.cashFlowEquivalentAndSensitivitySwap(swap.expand(), PROVIDER); ImmutableList<NotionalExchange> keyComputedFull = computedFull.keySet().asList(); ImmutableList<PointSensitivityBuilder> valueComputedFull = computedFull.values().asList(); ImmutableMap<NotionalExchange, PointSensitivityBuilder> computedIborLeg = CashFlowEquivalentCalculator.cashFlowEquivalentAndSensitivityIborLeg( IBOR_LEG.expand(), PROVIDER); ImmutableMap<NotionalExchange, PointSensitivityBuilder> computedFixedLeg = CashFlowEquivalentCalculator.cashFlowEquivalentAndSensitivityFixedLeg( FIXED_LEG.expand(), PROVIDER); assertEquals(computedFixedLeg.keySet().asList(), keyComputedFull.subList(0, 2)); assertEquals(computedIborLeg.keySet().asList(), keyComputedFull.subList(2, 6)); assertEquals(computedFixedLeg.values().asList(), valueComputedFull.subList(0, 2)); assertEquals(computedIborLeg.values().asList(), valueComputedFull.subList(2, 6)); double eps = 1.0e-7; RatesFiniteDifferenceSensitivityCalculator calc = new RatesFiniteDifferenceSensitivityCalculator(eps); int size = keyComputedFull.size(); for (int i = 0; i < size; ++i) { final int index = i; CurveCurrencyParameterSensitivities expected = calc.sensitivity( PROVIDER, p -> ((NotionalExchange) CashFlowEquivalentCalculator.cashFlowEquivalentSwap(swap.expand(), p) .getPaymentEvents() .get(index)) .getPaymentAmount()); PointSensitivityBuilder point = computedFull.get( CashFlowEquivalentCalculator.cashFlowEquivalentSwap(swap.expand(), PROVIDER) .getPaymentEvents() .get(index)); CurveCurrencyParameterSensitivities computed = PROVIDER.curveParameterSensitivity(point.build()); assertTrue(computed.equalWithTolerance(expected, eps * NOTIONAL)); } }
/** Test parameter sensitivity with finite difference sensitivity calculator. No cutoff period. */ public void rateChfNoCutOffParameterSensitivity() { LocalDate[] valuationDate = {date(2015, 1, 1), date(2015, 1, 8)}; double[] time = new double[] {0.0, 0.5, 1.0, 2.0, 5.0, 10.0}; double[] rate = new double[] {0.0100, 0.0110, 0.0115, 0.0130, 0.0135, 0.0135}; for (int loopvaldate = 0; loopvaldate < 2; loopvaldate++) { Curve onCurve = InterpolatedNodalCurve.of(Curves.zeroRates("ON", ACT_ACT_ISDA), time, rate, INTERPOLATOR); ImmutableRatesProvider prov = ImmutableRatesProvider.builder() .valuationDate(valuationDate[loopvaldate]) .indexCurves(ImmutableMap.of(CHF_TOIS, onCurve)) .timeSeries(ImmutableMap.of(CHF_TOIS, TIME_SERIES_BUILDER.build())) .build(); OvernightAveragedRateObservation ro = OvernightAveragedRateObservation.of(CHF_TOIS, FIXING_START_DATE, FIXING_END_DATE, 0); ForwardOvernightAveragedRateObservationFn obsFn = ForwardOvernightAveragedRateObservationFn.DEFAULT; PointSensitivityBuilder sensitivityBuilderComputed = obsFn.rateSensitivity(ro, DUMMY_ACCRUAL_START_DATE, DUMMY_ACCRUAL_END_DATE, prov); CurveCurrencyParameterSensitivities parameterSensitivityComputed = prov.curveParameterSensitivity(sensitivityBuilderComputed.build()); CurveCurrencyParameterSensitivities parameterSensitivityExpected = CAL_FD.sensitivity( prov, (p) -> CurrencyAmount.of( CHF_TOIS.getCurrency(), obsFn.rate(ro, DUMMY_ACCRUAL_START_DATE, DUMMY_ACCRUAL_END_DATE, (p)))); assertTrue( parameterSensitivityComputed.equalWithTolerance( parameterSensitivityExpected, EPS_FD * 10.0)); } }