public static double sabrHaganLognormalBlackVolatilityApproximation(double alpha, double beta, double rho, double nu, double displacement, double underlying, double strike, double maturity)
	{

		if(alpha <= 0) {
			throw new IllegalArgumentException("&alpha; must be greater than 0.");
		}

		if(rho > 1 || rho < -1) {
			throw new IllegalArgumentException("&rho; must be between -1 and 1.");
		}

		if(nu <= 0) {
			throw new IllegalArgumentException("&nu; must be greater than 0.");
		}

		if(underlying <= 0) {
			throw new IllegalArgumentException("Approximation not definied for non-positive underlyings.");
		}

		// Apply displacement. Displaced model is just a shift on underlying and strike.
		underlying += displacement;
		strike += displacement;

		if(Math.abs(underlying - strike) < 0.0001 * (1+Math.abs(underlying))) {
			/*
			 * ATM case - we assume underlying = strike
			 */

			double term1 = alpha / (Math.pow(underlying,1-beta));

			double term2 = Math.pow(1-beta,2)/24 * Math.pow(alpha,2)/Math.pow(underlying,2*(1-beta))
					+ rho*beta*alpha*nu/(4*Math.pow(underlying,1-beta))
					+ (2-3*rho*rho)*nu*nu/24;
			return term1 * (1+ term2 * maturity);
		}
		else{
			/*
			 * General non-ATM case no prob with log(F/K)
			 */
			double forwardTimesStrike = underlying * strike;

			double z = nu/alpha * Math.pow(forwardTimesStrike, (1-beta)/2) * Math.log(underlying / strike);

			double x = Math.log((Math.sqrt(1- 2*rho * z + z*z) + z - rho)/(1 - rho));

			double term1 = alpha / Math.pow(forwardTimesStrike,(1-beta)/2)
					/ (1 + Math.pow(1-beta,2)/24*Math.pow(Math.log(underlying/strike),2)
							+ Math.pow(1-beta,4)/1920 * Math.pow(Math.log(underlying/strike),4));

			double term2 = (Math.abs(x-z) < 1E-10) ? 1 : z / x;

			double term3 = 1 + (Math.pow(1 - beta,2)/24 *Math.pow(alpha, 2)/Math.pow(forwardTimesStrike, 1-beta)
					+ rho*beta*nu*alpha / 4 / Math.pow(forwardTimesStrike, (1-beta)/2)
					+ (2-3*rho*rho)/24 * nu*nu) *maturity;


			return term1 * term2 * term3;
		}
	}
public static double sabrHaganLognormalBlackVolatilityApproximation ( double alpha , double beta , double rho , double nu , double displacement , double underlying , double strike , double maturity ) { if ( alpha <= 0 ) { throw new IllegalArgumentException ( "&alpha; must be greater than 0." ) ; } if ( rho > 1 || rho < - 1 ) { throw new IllegalArgumentException ( "&rho; must be between -1 and 1." ) ; } if ( nu <= 0 ) { throw new IllegalArgumentException ( "&nu; must be greater than 0." ) ; } if ( underlying <= 0 ) { throw new IllegalArgumentException ( "Approximation not definied for non-positive underlyings." ) ; } underlying += displacement ; strike += displacement ; if ( Math . abs ( underlying - strike ) < 0.0001 * ( 1 + Math . abs ( underlying ) ) ) { double term1 = alpha / ( Math . pow ( underlying , 1 - beta ) ) ; double term2 = Math . pow ( 1 - beta , 2 ) / 24 * Math . pow ( alpha , 2 ) / Math . pow ( underlying , 2 * ( 1 - beta ) ) + rho * beta * alpha * nu / ( 4 * Math . pow ( underlying , 1 - beta ) ) + ( 2 - 3 * rho * rho ) * nu * nu / 24 ; return term1 * ( 1 + term2 * maturity ) ; } else { double forwardTimesStrike = underlying * strike ; double z = nu / alpha * Math . pow ( forwardTimesStrike , ( 1 - beta ) / 2 ) * Math . log ( underlying / strike ) ; double x = Math . log ( ( Math . sqrt ( 1 - 2 * rho * z + z * z ) + z - rho ) / ( 1 - rho ) ) ; double term1 = alpha / Math . pow ( forwardTimesStrike , ( 1 - beta ) / 2 ) / ( 1 + Math . pow ( 1 - beta , 2 ) / 24 * Math . pow ( Math . log ( underlying / strike ) , 2 ) + Math . pow ( 1 - beta , 4 ) / 1920 * Math . pow ( Math . log ( underlying / strike ) , 4 ) ) ; double term2 = ( Math . abs ( x - z ) < 1E-10 ) ? 1 : z / x ; double term3 = 1 + ( Math . pow ( 1 - beta , 2 ) / 24 * Math . pow ( alpha , 2 ) / Math . pow ( forwardTimesStrike , 1 - beta ) + rho * beta * nu * alpha / 4 / Math . pow ( forwardTimesStrike , ( 1 - beta ) / 2 ) + ( 2 - 3 * rho * rho ) / 24 * nu * nu ) * maturity ; return term1 * term2 * term3 ; } }
Calculated the approximation to the lognormal Black volatility using the
standard SABR model and the standard Hagan approximation.

@param alpha initial value of the stochastic volatility process of the SABR model.
@param beta CEV parameter of the SABR model.
@param rho Correlation (leverages) of the stochastic volatility.
@param nu Volatility of the stochastic volatility (vol-of-vol).
@param displacement The displacement parameter d.
@param underlying Underlying (spot) value.
@param strike Strike.
@param maturity Maturity.
@return Implied lognormal Black volatility.