SABRExtrapolationRightFunction extends SABRExtrapolationLeftRightFunction { public double priceDerivativeForward(final EuropeanVanillaOption option) { double[] pA; double priceDerivative; final double k = option.getStrike(); if (k <= _cutOffStrike) { final double[] volatilityA = getVolatilityAdjoint(option, _forward, _sabrData); final BlackFunctionData dataBlack = new BlackFunctionData(_forward, 1.0, volatilityA[0]); pA = BLACK_FUNCTION.getPriceAdjoint(option, dataBlack); priceDerivative = pA[1] + pA[2] * volatilityA[1]; } else { if (!_parameterDerivativeForwardComputed) { _parameterDerivativeForward = computesParametersDerivativeForward(); _parameterDerivativeForwardComputed = true; } final double f = extrapolation(k); final double fDa = f; final double fDb = f / k; final double fDc = fDb / k; priceDerivative = fDa * _parameterDerivativeForward[0] + fDb * _parameterDerivativeForward[1] + fDc * _parameterDerivativeForward[2]; if (!option.isCall()) { priceDerivative -= 1; } } return priceDerivative; } SABRExtrapolationRightFunction(final double forward, final SABRFormulaData sabrData, final double cutOffStrike, final double timeToExpiry, final double mu);  SABRExtrapolationRightFunction(final double forward, final SABRFormulaData sabrData, final double cutOffStrike, final double timeToExpiry, final double mu,
      final VolatilityFunctionProvider<SABRFormulaData> volatilityFunction); double price(final EuropeanVanillaOption option); double priceDerivativeStrike(final EuropeanVanillaOption option); double priceDerivativeForward(final EuropeanVanillaOption option); double priceAdjointSABR(final EuropeanVanillaOption option, final double[] priceDerivativeSABR); SABRFormulaData getSabrData(); double getCutOffStrike(); double getMu(); double getTimeToExpiry(); double[] getParameter(); double[] getParameterDerivativeForward(); double[][] getParameterDerivativeSABR();  }
@Test public void priceDerivativeForward() { double strikeIn = 0.08; double strikeAt = CUT_OFF_STRIKE; double strikeOut = 0.12; EuropeanVanillaOption optionIn = new EuropeanVanillaOption(strikeIn, TIME_TO_EXPIRY, true); EuropeanVanillaOption optionAt = new EuropeanVanillaOption(strikeAt, TIME_TO_EXPIRY, true); EuropeanVanillaOption optionOut = new EuropeanVanillaOption(strikeOut, TIME_TO_EXPIRY, true); double shiftF = 0.000001; SABRFormulaData sabrDataFP = new SABRFormulaData(ALPHA, BETA, RHO, NU); SABRExtrapolationRightFunction sabrExtrapolationFP = new SABRExtrapolationRightFunction(FORWARD + shiftF, sabrDataFP, CUT_OFF_STRIKE, TIME_TO_EXPIRY, MU); double priceIn = SABR_EXTRAPOLATION.price(optionIn); double priceInFP = sabrExtrapolationFP.price(optionIn); double priceInDF = SABR_EXTRAPOLATION.priceDerivativeForward(optionIn); double priceInDFExpected = (priceInFP - priceIn) / shiftF; assertEquals("SABR extrapolation: derivative with respect to forward, below cut-off", priceInDFExpected, priceInDF, 1E-5); double priceAt = SABR_EXTRAPOLATION.price(optionAt); double priceAtFP = sabrExtrapolationFP.price(optionAt); double priceAtDF = SABR_EXTRAPOLATION.priceDerivativeForward(optionAt); double priceAtDFExpected = (priceAtFP - priceAt) / shiftF; assertEquals("SABR extrapolation: derivative with respect to forward, at cut-off", priceAtDFExpected, priceAtDF, 1E-6); double[] abc = SABR_EXTRAPOLATION.getParameter(); double[] abcDF = SABR_EXTRAPOLATION.getParameterDerivativeForward(); double[] abcFP = sabrExtrapolationFP.getParameter(); double[] abcDFExpected = new double[3]; for (int loopparam = 0; loopparam < 3; loopparam++) { abcDFExpected[loopparam] = (abcFP[loopparam] - abc[loopparam]) / shiftF; assertEquals("SABR extrapolation: parameters derivative " + loopparam, 1.0, abcDFExpected[loopparam] / abcDF[loopparam], 5E-2); } double priceOut = SABR_EXTRAPOLATION.price(optionOut); double priceOutFP = sabrExtrapolationFP.price(optionOut); double priceOutDF = SABR_EXTRAPOLATION.priceDerivativeForward(optionOut); double priceOutDFExpected = (priceOutFP - priceOut) / shiftF; assertEquals("SABR extrapolation: derivative with respect to forward, above cut-off", priceOutDFExpected, priceOutDF, 1E-5); }