// ------------------------------------------------------------------------- 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)); }
/** 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); }