public SABR(double t, double forward, double alpha, double beta, double nu, double rho, bool alphaIsFixed, bool betaIsFixed, bool nuIsFixed, bool rhoIsFixed, bool vegaWeighted = false, EndCriteria endCriteria = null, OptimizationMethod optMethod = null, double errorAccept = 0.0020, bool useMaxError = false, int maxGuesses = 50, double shift = 0.0, VolatilityType volatilityType = VolatilityType.ShiftedLognormal, SabrApproximationModel approximationModel = SabrApproximationModel.Hagan2002) { t_ = t; forward_ = forward; alpha_ = alpha; beta_ = beta; nu_ = nu; rho_ = rho; alphaIsFixed_ = alphaIsFixed; betaIsFixed_ = betaIsFixed; nuIsFixed_ = nuIsFixed; rhoIsFixed_ = rhoIsFixed; vegaWeighted_ = vegaWeighted; endCriteria_ = endCriteria; optMethod_ = optMethod; errorAccept_ = errorAccept; useMaxError_ = useMaxError; maxGuesses_ = maxGuesses; shift_ = shift; volatilityType_ = volatilityType; approximationModel_ = approximationModel; }
public static double sabrVolatility(double strike, double forward, double expiryTime, double alpha, double beta, double nu, double rho, SabrApproximationModel approximationModel = SabrApproximationModel.Hagan2002) { QL_REQUIRE(strike > 0.0, () => "strike must be positive: " + strike + " not allowed"); QL_REQUIRE(forward > 0.0, () => "at the money forward rate must be: " + forward + " not allowed"); QL_REQUIRE(expiryTime >= 0.0, () => "expiry time must be non-negative: " + expiryTime + " not allowed"); validateSabrParameters(alpha, beta, nu, rho); return(unsafeSabrVolatility(strike, forward, expiryTime, alpha, beta, nu, rho, approximationModel)); }
public static double unsafeShiftedSabrVolatility(double strike, double forward, double expiryTime, double alpha, double beta, double nu, double rho, double shift, SabrApproximationModel approximationModel = SabrApproximationModel.Hagan2002) { return(unsafeSabrVolatility(strike + shift, forward + shift, expiryTime, alpha, beta, nu, rho, approximationModel)); }
public SABRInterpolation(List <double> xBegin, // x = strikes int xEnd, List <double> yBegin, // y = volatilities double t, // option expiry double forward, double?alpha, double?beta, double?nu, double?rho, bool alphaIsFixed, bool betaIsFixed, bool nuIsFixed, bool rhoIsFixed, bool vegaWeighted = true, EndCriteria endCriteria = null, OptimizationMethod optMethod = null, double errorAccept = 0.0020, bool useMaxError = false, int maxGuesses = 50, double shift = 0.0, VolatilityType volatilityType = VolatilityType.ShiftedLognormal, SabrApproximationModel approximationModel = SabrApproximationModel.Hagan2002) { List <double?> addParams = new List <double?>(); addParams.Add(shift); addParams.Add(volatilityType == VolatilityType.ShiftedLognormal ? 0.0 : 1.0); addParams.Add((double?)approximationModel); impl_ = new XABRInterpolationImpl <SABRSpecs>( xBegin, xEnd, yBegin, t, forward, new List <double?>() { alpha, beta, nu, rho }, //boost::assign::list_of(alpha)(beta)(nu)(rho), new List <bool>() { alphaIsFixed, betaIsFixed, nuIsFixed, rhoIsFixed }, //boost::assign::list_of(alphaIsFixed)(betaIsFixed)(nuIsFixed)(rhoIsFixed), vegaWeighted, endCriteria, optMethod, errorAccept, useMaxError, maxGuesses, addParams); coeffs_ = (impl_ as XABRInterpolationImpl <SABRSpecs>).coeff_; }
public static double unsafeSabrVolatility(double strike, double forward, double expiryTime, double alpha, double beta, double nu, double rho, SabrApproximationModel approximationModel = SabrApproximationModel.Hagan2002) { if (approximationModel == SabrApproximationModel.Hagan2002) { double oneMinusBeta = 1.0 - beta; double A = Math.Pow(forward * strike, oneMinusBeta); double sqrtA = Math.Sqrt(A); double logM; if (!close(forward, strike)) { logM = Math.Log(forward / strike); } else { double epsilon = (forward - strike) / strike; logM = epsilon - .5 * epsilon * epsilon; } double z = (nu / alpha) * sqrtA * logM; double B = 1.0 - 2.0 * rho * z + z * z; double C = oneMinusBeta * oneMinusBeta * logM * logM; double tmp = (Math.Sqrt(B) + z - rho) / (1.0 - rho); double xx = Math.Log(tmp); double D = sqrtA * (1.0 + C / 24.0 + C * C / 1920.0); double d = 1.0 + expiryTime * (oneMinusBeta * oneMinusBeta * alpha * alpha / (24.0 * A) + 0.25 * rho * beta * nu * alpha / sqrtA + (2.0 - 3.0 * rho * rho) * (nu * nu / 24.0)); double multiplier; // computations become precise enough if the square of z worth slightly more than the precision machine (hence the m) const double m = 10; if (Math.Abs(z * z) > Const.QL_EPSILON * m) { multiplier = z / xx; } else { multiplier = 1.0 - 0.5 * rho * z - (3.0 * rho * rho - 2.0) * z * z / 12.0; } return((alpha / D) * multiplier * d); } else if (approximationModel == SabrApproximationModel.Obloj2008) { double oneMinusBeta = 1.0 - beta; double Fmid = Math.Sqrt(forward * strike); double gamma1 = beta / Fmid; double gamma2 = -beta * oneMinusBeta / (Fmid * Fmid); double zeta = alpha / (nu * oneMinusBeta) * (Math.Pow(forward, oneMinusBeta) - Math.Pow(strike, oneMinusBeta)); double D = Math.Log((Math.Sqrt(1.0 - 2.0 * rho * zeta + zeta * zeta) + zeta - rho) / (1.0 - rho)); double epsilon = alpha * alpha * expiryTime; double logM; if (!close(forward, strike)) { logM = Math.Log(forward / strike); } else { double eps = (forward - strike) / strike; logM = eps - .5 * eps * eps; } double a = nu * Math.Pow(Fmid, beta) / alpha; double b = Math.Pow(a, 2.0); double d = 1.0 + ((2.0 * gamma2 - gamma1 * gamma1 + 1 / (Fmid * Fmid)) / 24.0 * b + rho * gamma1 / 4.0 * a + (2.0 - 3.0 * rho * rho) / 24.0) * epsilon; return(alpha * logM / D * d); } else { QL_FAIL("Unknown approximation model."); return(0.0); } }