SABRHaganVolatilityFunction extends VolatilityFunctionProvider<SABRFormulaData> { @Override public Function1D<SABRFormulaData, Double> getVolatilityFunction(final EuropeanVanillaOption option, final double forward) { Validate.notNull(option, "option"); Validate.isTrue(forward >= 0.0, "forward must be greater than zero"); return new Function1D<SABRFormulaData, Double>() { @Override public final Double evaluate(final SABRFormulaData data) { Validate.notNull(data, "data"); return getVolatility(option, forward, data); } }; }  @Override Function1D<SABRFormulaData, Double> getVolatilityFunction(final EuropeanVanillaOption option, final double forward); @Override Function1D<SABRFormulaData, double[]> getVolatilityAdjointFunction(final EuropeanVanillaOption option, final double forward); @Override Function1D<SABRFormulaData, double[][]> getVolatilityAdjointFunction(final double forward, final double[] strikes, final double timeToExpiry); @Override Function1D<SABRFormulaData, double[]> getModelAdjointFunction(final EuropeanVanillaOption option, final double forward); @Override Function1D<SABRFormulaData, double[][]> getModelAdjointFunction(final double forward, final double[] strikes, final double timeToExpiry); double getVolatility(final EuropeanVanillaOption option, final double forward, final SABRFormulaData data); @ExternalFunction double getVolatility(final double forward, final double strike, final double timeToExpiry, final double alpha, final double beta, final double rho, final double nu); double[] getVolatilityModelAdjoint(final EuropeanVanillaOption option, final double forward, final SABRFormulaData data); double[] getVolatilityAdjoint(final EuropeanVanillaOption option, final double forward, final SABRFormulaData data); double getVolatilityAdjoint2(final EuropeanVanillaOption option, final double forward, final SABRFormulaData data, final double[] volatilityD, final double[][] volatilityD2); @Override int hashCode(); @Override boolean equals(final Object obj); @Override String toString();  }
@Test public void testATMSmoothness() { final double timeToExpiry = 1; final boolean isCall = true; EuropeanVanillaOption option; final double alpha = 0.05; final double beta = 0.5; final double nu = 0.50; final double rho = -0.25; final int nbPoints = 100; final double forward = 0.05; final double[] sabrVolatilty = new double[2 * nbPoints + 1]; final double range = 5E-9; final double strike[] = new double[2 * nbPoints + 1]; for (int looppts = -nbPoints; looppts <= nbPoints; looppts++) { strike[looppts + nbPoints] = forward + ((double) looppts) / nbPoints * range; option = new EuropeanVanillaOption(strike[looppts + nbPoints], timeToExpiry, isCall); final SABRFormulaData SabrData = new SABRFormulaData(alpha, beta, rho, nu); sabrVolatilty[looppts + nbPoints] = FUNCTION.getVolatilityFunction(option, forward).evaluate(SabrData); } for (int looppts = -nbPoints; looppts < nbPoints; looppts++) { assertTrue(Math.abs(sabrVolatilty[looppts + nbPoints + 1] - sabrVolatilty[looppts + nbPoints]) / (strike[looppts + nbPoints + 1] - strike[looppts + nbPoints]) < 20.0); } }
@Test(enabled = false) public void smile() { final double alpha = 0.04079820992199477; final double beta = 0.5; final double rho = 0.12483799350466732; final double nu = 1.1156276403408933; final double timeToExpiry = 5.0; final double forward = 0.03189998273775524; final int nbpoints = 20; final double startStrike = 0.0001; final double endStrike = 0.2500; final SABRFormulaData SabrData = new SABRFormulaData(alpha, beta, rho, nu); final double[] strikes = new double[nbpoints + 1]; final double[] sabrVolatilty = new double[nbpoints + 1]; EuropeanVanillaOption option; for (int loopstrike = 0; loopstrike <= nbpoints; loopstrike++) { strikes[loopstrike] = startStrike + loopstrike * (endStrike - startStrike) / nbpoints; option = new EuropeanVanillaOption(strikes[loopstrike], timeToExpiry, true); sabrVolatilty[loopstrike] = FUNCTION.getVolatilityFunction(option, forward).evaluate(SabrData); } }