Class SabrModel

java.lang.Object
com.quantfinlib.pricing.SabrModel

public final class SabrModel extends Object
SABR stochastic volatility model: the Hagan, Kumar, Lesniewski and Woodward (2002) lognormal implied-vol expansion ("Managing smile risk", Wilmott, eq. 2.17a), and calibration of (α, ρ, ν) with β fixed.

Calibration is Levenberg-Marquardt (Marquardt 1963) on vol residuals, optionally weighted, in the unconstrained variables ln α, atanh ρ, ln ν, with a forward-difference Jacobian. calibrateToAtm(double, double, double, double, double[], double[], double[]) instead fixes the ATM vol exactly by solving α from West's (2005) cubic ("Calibration of the SABR model in illiquid markets", Applied Mathematical Finance 12) at every iteration and fits (ρ, ν) to the rest of the smile.

Hagan's expansion is not arbitrage-free: at low strikes and long expiries the implied density ∂²C/∂K² can go negative. Nothing here prevents that; minimumDensity(double, double, double, double, double, double, double, double, int) measures it on a strike grid so a caller can reject or flag a fit.

  • Nested Class Summary

    Nested Classes
    Modifier and Type
    Class
    Description
    static final record 
    Calibrated SABR parameters.
  • Method Summary

    Modifier and Type
    Method
    Description
    static double
    alphaFromAtmVol(double f, double t, double beta, double rho, double nu, double atmVol)
    α that reproduces an ATM vol exactly (West 2005, eq. 3): the smallest positive root of
    calibrate(double f, double t, double beta, double[] strikes, double[] marketVols)
    Unweighted calibration of (α, ρ, ν) with β fixed.
    calibrate(double f, double t, double beta, double[] strikes, double[] marketVols, double[] weights)
    Weighted least-squares calibration of (α, ρ, ν) with β fixed.
    calibrateToAtm(double f, double t, double beta, double atmVol, double[] strikes, double[] marketVols, double[] weights)
    Calibration that reprices the ATM vol exactly: α from alphaFromAtmVol(double, double, double, double, double, double) for each trial (ρ, ν), and (ρ, ν) fitted by Levenberg-Marquardt to the quotes.
    static double
    impliedVol(double f, double k, double t, double alpha, double beta, double rho, double nu)
    Hagan lognormal implied vol for forward f, strike k, expiry t.
    static double
    minimumDensity(double f, double t, double alpha, double beta, double rho, double nu, double kMin, double kMax, int n)
    Smallest risk-neutral density ∂²C/∂K² (undiscounted Black call on the SABR vol, central second difference) over n strikes evenly spaced on [kMin, kMax].

    Methods inherited from class Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Method Details

    • impliedVol

      public static double impliedVol(double f, double k, double t, double alpha, double beta, double rho, double nu)
      Hagan lognormal implied vol for forward f, strike k, expiry t.
    • alphaFromAtmVol

      public static double alphaFromAtmVol(double f, double t, double beta, double rho, double nu, double atmVol)
      α that reproduces an ATM vol exactly (West 2005, eq. 3): the smallest positive root of
        (1−β)²T/(24 f^{2−2β}) α³ + ρβνT/(4 f^{1−β}) α² + (1 + (2−3ρ²)ν²T/24) α − σ_ATM f^{1−β} = 0
    • calibrate

      public static SabrModel.Params calibrate(double f, double t, double beta, double[] strikes, double[] marketVols)
      Unweighted calibration of (α, ρ, ν) with β fixed.
    • calibrate

      public static SabrModel.Params calibrate(double f, double t, double beta, double[] strikes, double[] marketVols, double[] weights)
      Weighted least-squares calibration of (α, ρ, ν) with β fixed.
      Parameters:
      weights - per-quote weights (for example Black vegas, to fit prices rather than vols), or null for equal weights
    • calibrateToAtm

      public static SabrModel.Params calibrateToAtm(double f, double t, double beta, double atmVol, double[] strikes, double[] marketVols, double[] weights)
      Calibration that reprices the ATM vol exactly: α from alphaFromAtmVol(double, double, double, double, double, double) for each trial (ρ, ν), and (ρ, ν) fitted by Levenberg-Marquardt to the quotes.
    • minimumDensity

      public static double minimumDensity(double f, double t, double alpha, double beta, double rho, double nu, double kMin, double kMax, int n)
      Smallest risk-neutral density ∂²C/∂K² (undiscounted Black call on the SABR vol, central second difference) over n strikes evenly spaced on [kMin, kMax]. A negative value means the smile admits a butterfly arbitrage there.