// -------------------------------------------------------------------------
 public void test_priceSensitivity() {
   PointSensitivities point =
       OPTION_PRICER.priceSensitivityStickyStrike(
           FUTURE_OPTION_PRODUCT, RATE_PROVIDER, VOL_PROVIDER);
   CurveCurrencyParameterSensitivities computed = RATE_PROVIDER.curveParameterSensitivity(point);
   CurveCurrencyParameterSensitivities expected =
       FD_CAL.sensitivity(
           RATE_PROVIDER,
           (p) ->
               CurrencyAmount.of(
                   EUR, OPTION_PRICER.price(FUTURE_OPTION_PRODUCT, (p), VOL_PROVIDER)));
   double futurePrice = FUTURE_PRICER.price(FUTURE_OPTION_PRODUCT.getUnderlying(), RATE_PROVIDER);
   double strike = FUTURE_OPTION_PRODUCT.getStrikePrice();
   double expiryTime =
       ACT_365F.relativeYearFraction(VALUATION_DATE, FUTURE_OPTION_PRODUCT.getExpiryDate());
   double logMoneyness = Math.log(strike / futurePrice);
   double logMoneynessUp = Math.log(strike / (futurePrice + EPS));
   double logMoneynessDw = Math.log(strike / (futurePrice - EPS));
   double vol = SURFACE.zValue(expiryTime, logMoneyness);
   double volUp = SURFACE.zValue(expiryTime, logMoneynessUp);
   double volDw = SURFACE.zValue(expiryTime, logMoneynessDw);
   double volSensi = 0.5 * (volUp - volDw) / EPS;
   double vega = BlackFormulaRepository.vega(futurePrice, strike, expiryTime, vol);
   CurveCurrencyParameterSensitivities sensiVol =
       RATE_PROVIDER
           .curveParameterSensitivity(
               FUTURE_PRICER.priceSensitivity(
                   FUTURE_OPTION_PRODUCT.getUnderlying(), RATE_PROVIDER))
           .multipliedBy(-vega * volSensi);
   expected = expected.combinedWith(sensiVol);
   assertTrue(computed.equalWithTolerance(expected, 30d * EPS));
 }
 public void test_theta() {
   double computed = OPTION_PRICER.theta(FUTURE_OPTION_PRODUCT, RATE_PROVIDER, VOL_PROVIDER);
   double futurePrice = FUTURE_PRICER.price(FUTURE_OPTION_PRODUCT.getUnderlying(), RATE_PROVIDER);
   double strike = FUTURE_OPTION_PRODUCT.getStrikePrice();
   double expiryTime =
       ACT_365F.relativeYearFraction(VALUATION_DATE, FUTURE_OPTION_PRODUCT.getExpiryDate());
   double logMoneyness = Math.log(strike / futurePrice);
   double vol = SURFACE.zValue(expiryTime, logMoneyness);
   double expected = BlackFormulaRepository.driftlessTheta(futurePrice, strike, expiryTime, vol);
   assertEquals(computed, expected, TOL);
 }
 public void test_gamma_from_future_price() {
   double futurePrice = 1.1d;
   double computed =
       OPTION_PRICER.gammaStickyStrike(
           FUTURE_OPTION_PRODUCT, RATE_PROVIDER, VOL_PROVIDER, futurePrice);
   double strike = FUTURE_OPTION_PRODUCT.getStrikePrice();
   double expiryTime =
       ACT_365F.relativeYearFraction(VALUATION_DATE, FUTURE_OPTION_PRODUCT.getExpiryDate());
   double logMoneyness = Math.log(strike / futurePrice);
   double vol = SURFACE.zValue(expiryTime, logMoneyness);
   double expected = BlackFormulaRepository.gamma(futurePrice, strike, expiryTime, vol);
   assertEquals(computed, expected, TOL);
 }
  /** Calculate the true SABR delta and gamma and compare with that found by finite difference */
  @Test(enabled = false)
  public void testGreeks() {
    double eps = 1e-3;
    double f = 1.2;
    double k = 1.4;
    double t = 5.0;
    double alpha = 0.3;
    double beta = 0.6;
    double rho = -0.4;
    double nu = 0.4;
    SabrFormulaData sabrData = SabrFormulaData.of(alpha, beta, rho, nu);
    ValueDerivatives adj = FUNCTION.getVolatilityAdjoint(f, k, t, sabrData);
    double bsDelta = BlackFormulaRepository.delta(f, k, t, adj.getValue(), true);
    double bsVega = BlackFormulaRepository.vega(f, k, t, adj.getValue());
    double volForwardSense = adj.getDerivative(1);
    double delta = bsDelta + bsVega * volForwardSense;

    SabrFormulaData data = SabrFormulaData.of(alpha, beta, rho, nu);
    double volUp = FUNCTION.getVolatility(f + eps, k, t, data);
    double volDown = FUNCTION.getVolatility(f - eps, k, t, data);
    double priceUp = BlackFormulaRepository.price(f + eps, k, t, volUp, true);
    double price = BlackFormulaRepository.price(f, k, t, adj.getValue(), true);
    double priceDown = BlackFormulaRepository.price(f - eps, k, t, volDown, true);
    double fdDelta = (priceUp - priceDown) / 2 / eps;
    assertEquals(fdDelta, delta, 1e-6);

    double bsVanna = BlackFormulaRepository.vanna(f, k, t, adj.getValue());
    double bsGamma = BlackFormulaRepository.gamma(f, k, t, adj.getValue());

    double[] volD1 = new double[5];
    double[][] volD2 = new double[2][2];
    FUNCTION.getVolatilityAdjoint2(f, k, t, sabrData, volD1, volD2);
    double d2Sigmad2Fwd = volD2[0][0];
    double gamma = bsGamma + 2 * bsVanna * adj.getDerivative(1) + bsVega * d2Sigmad2Fwd;
    double fdGamma = (priceUp + priceDown - 2 * price) / eps / eps;

    double d2Sigmad2FwdFD = (volUp + volDown - 2 * adj.getValue()) / eps / eps;
    assertEquals(d2Sigmad2FwdFD, d2Sigmad2Fwd, 1e-4);

    assertEquals(fdGamma, gamma, 1e-2);
  }