final double rho = -0.4;
final double nu = 0.4;
final SABRFormulaData sabrData = new SABRFormulaData(alpha, beta, rho, nu);
final SABRHaganVolatilityFunction sabr = new SABRHaganVolatilityFunction();
final double[] vol = sabr.getVolatilityAdjoint(new EuropeanVanillaOption(k, t, true), f, sabrData);
final double bsDelta = BlackFormulaRepository.delta(f, k, t, vol[0], true);
final double bsVega = BlackFormulaRepository.vega(f, k, t, vol[0]);
final double volForwardSense = vol[1];
final double delta = bsDelta + bsVega * volForwardSense;
final double volUp = sabr.getVolatility(f + eps, k, t, alpha, beta, rho, nu);
final double volDown = sabr.getVolatility(f - eps, k, t, alpha, beta, rho, nu);
final double priceUp = BlackFormulaRepository.price(f + eps, k, t, volUp, true);
final double price = BlackFormulaRepository.price(f, k, t, vol[0], true);
final double priceDown = BlackFormulaRepository.price(f - eps, k, t, volDown, true);
final double fdDelta = (priceUp - priceDown) / 2 / eps;
assertEquals(fdDelta, delta, 1e-6);
final double bsVanna = BlackFormulaRepository.vanna(f, k, t, vol[0]);
final double bsGamma = BlackFormulaRepository.gamma(f, k, t, vol[0]);
final double[] volD1 = new double[5];
final double[][] volD2 = new double[2][2];
sabr.getVolatilityAdjoint2(new EuropeanVanillaOption(k, t, true), f, sabrData, volD1, volD2);
final double d2Sigmad2Fwd = volD2[0][0];
final double gamma = bsGamma + 2 * bsVanna * vol[1] + bsVega * d2Sigmad2Fwd;
final double fdGamma = (priceUp + priceDown - 2 * price) / eps / eps;
final double d2Sigmad2FwdFD = (volUp + volDown - 2 * vol[0]) / eps / eps;