CapFloorCMSSABRReplicationMethod extends CapFloorCMSSABRReplicationAbstractMethod { @Override public PresentValueSABRSensitivityDataBundle presentValueSABRSensitivity(final CapFloorCMS cmsCapFloor, final SABRSwaptionProviderInterface sabrData) { ArgumentChecker.notNull(cmsCapFloor, "CMA cap/floor"); ArgumentChecker.notNull(sabrData, "SABR swaption provider"); final Currency ccy = cmsCapFloor.getCurrency(); final SABRInterestRateParameters sabrParameter = sabrData.getSABRParameter(); final SwapFixedCoupon<? extends Payment> underlyingSwap = cmsCapFloor.getUnderlyingSwap(); final double forward = underlyingSwap.accept(PRDC, sabrData.getMulticurveProvider()); final double discountFactor = sabrData.getMulticurveProvider().getDiscountFactor(ccy, cmsCapFloor.getPaymentTime()); final double strike = cmsCapFloor.getStrike(); final double maturity = underlyingSwap.getFixedLeg().getNthPayment(underlyingSwap.getFixedLeg().getNumberOfPayments() - 1).getPaymentTime() - cmsCapFloor.getSettlementTime(); final CMSVegaIntegrant integrantVega = new CMSVegaIntegrant(cmsCapFloor, sabrParameter, forward); final double factor = discountFactor / integrantVega.h(forward) * integrantVega.g(forward); final double absoluteTolerance = 1.0 / (factor * Math.abs(cmsCapFloor.getNotional()) * cmsCapFloor.getPaymentYearFraction()); final double relativeTolerance = 1E-3; final RungeKuttaIntegrator1D integrator = new RungeKuttaIntegrator1D(absoluteTolerance, relativeTolerance, getNbIteration()); final double factor2 = factor * integrantVega.k(strike) * integrantVega.bs(strike); final double[] strikePartPrice = new double[4]; final double[] volatilityAdjoint = sabrData.getSABRParameter().getVolatilityAdjoint(cmsCapFloor.getFixingTime(), maturity, strike, forward); strikePartPrice[0] = factor2 * volatilityAdjoint[3]; strikePartPrice[1] = factor2 * volatilityAdjoint[4]; strikePartPrice[2] = factor2 * volatilityAdjoint[5]; strikePartPrice[3] = factor2 * volatilityAdjoint[6]; final double[] integralPart = new double[4]; final double[] totalSensi = new double[4]; for (int loopparameter = 0; loopparameter < 4; loopparameter++) { integrantVega.setParameterIndex(loopparameter); try { if (cmsCapFloor.isCap()) { integralPart[loopparameter] = discountFactor * integrator.integrate(integrantVega, strike, strike + getIntegrationInterval()); } else { integralPart[loopparameter] = discountFactor * integrator.integrate(integrantVega, 0.0, strike); } } catch (final Exception e) { throw new RuntimeException(e); } totalSensi[loopparameter] = (strikePartPrice[loopparameter] + integralPart[loopparameter]) * cmsCapFloor.getNotional() * cmsCapFloor.getPaymentYearFraction(); } final PresentValueSABRSensitivityDataBundle sensi = new PresentValueSABRSensitivityDataBundle(); final DoublesPair expiryMaturity = DoublesPair.of(cmsCapFloor.getFixingTime(), maturity); sensi.addAlpha(expiryMaturity, totalSensi[0]); sensi.addBeta(expiryMaturity, totalSensi[1]); sensi.addRho(expiryMaturity, totalSensi[2]); sensi.addNu(expiryMaturity, totalSensi[3]); return sensi; } private  CapFloorCMSSABRReplicationMethod();  CapFloorCMSSABRReplicationMethod(final double integrationInterval); static CapFloorCMSSABRReplicationMethod getDefaultInstance(); @Override MultipleCurrencyAmount presentValue(final CapFloorCMS cmsCapFloor, final SABRSwaptionProviderInterface sabrData); @Override @SuppressWarnings("synthetic-access") MultipleCurrencyMulticurveSensitivity presentValueCurveSensitivity(final CapFloorCMS cmsCapFloor, final SABRSwaptionProviderInterface sabrData); @Override PresentValueSABRSensitivityDataBundle presentValueSABRSensitivity(final CapFloorCMS cmsCapFloor, final SABRSwaptionProviderInterface sabrData); @Override double presentValueStrikeSensitivity(final CapFloorCMS cmsCapFloor, final SABRSwaptionProviderInterface sabrData);  }
@Test public void presentValueSABRSensitivity() { final double pv = METHOD_CAP_CMS_SABR.presentValue(CMS_CAP, SABR_MULTICURVES).getAmount(EUR); final PresentValueSABRSensitivityDataBundle pvsCapLong = METHOD_CAP_CMS_SABR.presentValueSABRSensitivity(CMS_CAP, SABR_MULTICURVES); final double shift = 0.0001; final double shiftAlpha = 0.00001; final double maturity = CMS_CAP.getUnderlyingSwap().getFixedLeg().getNthPayment(CMS_CAP.getUnderlyingSwap().getFixedLeg().getNumberOfPayments() - 1).getPaymentTime() - CMS_CAP.getSettlementTime(); final DoublesPair expectedExpiryTenor = DoublesPair.of(CMS_CAP.getFixingTime(), maturity); final SABRInterestRateParameters sabrParameterAlphaBumped = SABRDataSets.createSABR1AlphaBumped(shiftAlpha); final SABRSwaptionProviderDiscount sabrBundleAlphaBumped = new SABRSwaptionProviderDiscount(MULTICURVES, sabrParameterAlphaBumped, EUR1YEURIBOR6M); final double pvLongPayerAlphaBumped = METHOD_CAP_CMS_SABR.presentValue(CMS_CAP, sabrBundleAlphaBumped).getAmount(EUR); final double expectedAlphaSensi = (pvLongPayerAlphaBumped - pv) / shiftAlpha; assertEquals("Number of alpha sensitivity", pvsCapLong.getAlpha().getMap().keySet().size(), 1); assertEquals("Alpha sensitivity expiry/tenor", pvsCapLong.getAlpha().getMap().keySet().contains(expectedExpiryTenor), true); assertEquals("Alpha sensitivity value", expectedAlphaSensi, pvsCapLong.getAlpha().getMap().get(expectedExpiryTenor), 3.0E+1); final SABRInterestRateParameters sabrParameterRhoBumped = SABRDataSets.createSABR1RhoBumped(); final SABRSwaptionProviderDiscount sabrBundleRhoBumped = new SABRSwaptionProviderDiscount(MULTICURVES, sabrParameterRhoBumped, EUR1YEURIBOR6M); final double pvLongPayerRhoBumped = METHOD_CAP_CMS_SABR.presentValue(CMS_CAP, sabrBundleRhoBumped).getAmount(EUR); final double expectedRhoSensi = (pvLongPayerRhoBumped - pv) / shift; assertEquals("Number of rho sensitivity", pvsCapLong.getRho().getMap().keySet().size(), 1); assertEquals("Rho sensitivity expiry/tenor", pvsCapLong.getRho().getMap().keySet().contains(expectedExpiryTenor), true); assertEquals("Rho sensitivity value", expectedRhoSensi, pvsCapLong.getRho().getMap().get(expectedExpiryTenor), 1.0E+0); final SABRInterestRateParameters sabrParameterNuBumped = SABRDataSets.createSABR1NuBumped(); final SABRSwaptionProviderDiscount sabrBundleNuBumped = new SABRSwaptionProviderDiscount(MULTICURVES, sabrParameterNuBumped, EUR1YEURIBOR6M); final double pvLongPayerNuBumped = METHOD_CAP_CMS_SABR.presentValue(CMS_CAP, sabrBundleNuBumped).getAmount(EUR); final double expectedNuSensi = (pvLongPayerNuBumped - pv) / shift; assertEquals("Number of nu sensitivity", pvsCapLong.getNu().getMap().keySet().size(), 1); assertTrue("Nu sensitivity expiry/tenor", pvsCapLong.getNu().getMap().keySet().contains(expectedExpiryTenor)); assertEquals("Nu sensitivity value", expectedNuSensi, pvsCapLong.getNu().getMap().get(expectedExpiryTenor), 2.0E+0); }
@Test public void presentValueSABRSensitivityMethodVsCalculator() { final PresentValueSABRSensitivityDataBundle pvssMethod = METHOD_CAP_CMS_SABR.presentValueSABRSensitivity(CMS_CAP, SABR_MULTICURVES); final PresentValueSABRSensitivityDataBundle pvssCalculator = PVSSSSC.visit(CMS_CAP, SABR_MULTICURVES); assertEquals("CMS cap/floor SABR: Present value SABR sensitivity: method vs calculator", pvssMethod, pvssCalculator); }