final CMSStrikeIntegrant integrant = new CMSStrikeIntegrant(cmsCapFloor, sabrParameter, forward);
final double factor = discountFactor * integrant.g(forward) / integrant.h(forward);
final double absoluteTolerance = 1.0E-9;
final double relativeTolerance = 1.0E-5;
final RungeKuttaIntegrator1D integrator = new RungeKuttaIntegrator1D(absoluteTolerance, relativeTolerance, getNbIteration());
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);
final EuropeanVanillaOption option = new EuropeanVanillaOption(strike, cmsCapFloor.getFixingTime(), cmsCapFloor.isCap());
final Function1D<SABRFormulaData, double[]> sabrFunctionAdjoint = sabrParameter.getSabrFunction().getVolatilityAdjointFunction(option, forward);
final double[] volA = sabrFunctionAdjoint.evaluate(sabrPoint);
final BlackFunctionData dataBlack = new BlackFunctionData(forward, 1.0, volA[0]);
final BlackPriceFunction blackFunction = new BlackPriceFunction();
final double[] bsA = blackFunction.getPriceAdjoint(option, dataBlack);
final double[] kpkpp = integrant.kpkpp(strike);
double firstPart;
double thirdPart;
if (cmsCapFloor.isCap()) {
firstPart = -kpkpp[0] * integrant.bs(strike);
thirdPart = integrator.integrate(integrant, strike, strike + getIntegrationInterval());
} else {
firstPart = 3 * kpkpp[0] * integrant.bs(strike);
thirdPart = integrator.integrate(integrant, 0.0, strike);
}
final double secondPart = integrant.k(strike) * (bsA[3] + bsA[2] * volA[2]);
return cmsCapFloor.getNotional() * cmsCapFloor.getPaymentYearFraction() * factor * (firstPart + secondPart + thirdPart);
}