final double forward = underlyingSwap.accept(PRC, sabrData);
final double discountFactor = sabrData.getCurve(underlyingSwap.getFixedLeg().getNthPayment(0).getFundingCurveName()).getDiscountFactor(cmsCapFloor.getPaymentTime());
final double strike = cmsCapFloor.getStrike();
final double maturity = underlyingSwap.getFixedLeg().getNthPayment(underlyingSwap.getFixedLeg().getNumberOfPayments() - 1).getPaymentTime()
- cmsCapFloor.getSettlementTime();
final DoublesPair expiryMaturity = new DoublesPair(cmsCapFloor.getFixingTime(), maturity);
final double alpha = sabrParameter.getAlpha(expiryMaturity);
final double beta = sabrParameter.getBeta(expiryMaturity);
final double rho = sabrParameter.getRho(expiryMaturity);
final double nu = sabrParameter.getNu(expiryMaturity);
final SABRFormulaData sabrPoint = new SABRFormulaData(alpha, beta, rho, nu);
// Common
final CMSIntegrant integrantPrice = new CMSIntegrant(cmsCapFloor, sabrPoint, forward, _cutOffStrike, _mu);
final CMSDeltaIntegrant integrantDelta = new CMSDeltaIntegrant(cmsCapFloor, sabrPoint, forward, _cutOffStrike, _mu);
final double factor = discountFactor / integrantDelta.h(forward) * integrantDelta.g(forward);
final double absoluteTolerance = 1.0 / (factor * Math.abs(cmsCapFloor.getNotional()) * cmsCapFloor.getPaymentYearFraction());
final double relativeTolerance = 1E-10;
final RungeKuttaIntegrator1D integrator = new RungeKuttaIntegrator1D(absoluteTolerance, relativeTolerance, getNbIteration());
// Price
final double[] bs = integrantDelta.bsbsp(strike);
@SuppressWarnings("synthetic-access")
final double[] n = integrantDelta.nnp(forward);
final double strikePartPrice = discountFactor * integrantDelta.k(strike) * n[0] * bs[0];
double integralPartPrice;
try {
if (cmsCapFloor.isCap()) {
integralPartPrice = discountFactor * integrator.integrate(integrantPrice, strike, strike + getIntegrationInterval());
} else {
integralPartPrice = discountFactor * integrator.integrate(integrantPrice, 0.0, strike);
}
} catch (final Exception e) {
throw new RuntimeException(e);
}
final double price = (strikePartPrice + integralPartPrice) * cmsCapFloor.getNotional() * cmsCapFloor.getPaymentYearFraction();
// Delta
final double strikePart = discountFactor * integrantDelta.k(strike) * (n[1] * bs[0] + n[0] * bs[1]);
double integralPart;
try {
if (cmsCapFloor.isCap()) {
integralPart = discountFactor * integrator.integrate(integrantDelta, strike, strike + getIntegrationInterval());
} else {
integralPart = discountFactor * integrator.integrate(integrantDelta, 0.0, strike);
}
} catch (final Exception e) {
throw new RuntimeException(e);
}
final double deltaS0 = (strikePart + integralPart) * cmsCapFloor.getNotional() * cmsCapFloor.getPaymentYearFraction();
final double deltaPD = price / discountFactor;
final double sensiDF = -cmsCapFloor.getPaymentTime() * discountFactor * deltaPD;
final List<DoublesPair> list = new ArrayList<>();
list.add(new DoublesPair(cmsCapFloor.getPaymentTime(), sensiDF));
final Map<String, List<DoublesPair>> resultMap = new HashMap<>();
resultMap.put(cmsCapFloor.getUnderlyingSwap().getFixedLeg().getNthPayment(0).getFundingCurveName(), list);
InterestRateCurveSensitivity result = new InterestRateCurveSensitivity(resultMap);
final InterestRateCurveSensitivity forwardDr = new InterestRateCurveSensitivity(cmsCapFloor.getUnderlyingSwap().accept(PRSC, sabrData));
result = result.plus(forwardDr.multipliedBy(deltaS0));