Skip to content
All library documents

Correcting the Forward Input in a SABR Volatility Fit

Article Quant Q&A · Author: Hester S

Summary

The document presents a poorly fitting SABR calibration and asks what is wrong with the implementation. The Python function calculates a forward value from a variable associated with the volatility parameter, while the fitting routine estimates SABR parameters against option prices across strikes. The answer identifies the likely input error: the forward should be derived from the underlying spot price, risk-free rate, dividend yield, and time to maturity, rather than from the SABR alpha parameter.

This is a focused code diagnosis, not a complete calibration guide. The answer gives the corrected conceptual role of the forward input but does not report a successful recalibration or assess other possible issues in the function, data, or fitting setup. It therefore offers a useful first check for poor fits without establishing that correcting this line alone will resolve every calibration problem.

Key ideas

  • SABR calibration requires the forward price as an input to the volatility formula.
  • The forward should be based on spot and carry assumptions, not on the alpha volatility parameter.
  • A misplaced model input can produce poor fits even when the optimizer runs successfully.
  • Correcting the forward definition is a diagnostic step, not proof that the full calibration is sound.

Tags

Full text
# Why can't the curve find the least squares parameters when I used it in SABR model? (SABR Calibration)


# Why can't the curve find the least squares parameters when I used it in SABR model? (SABR Calibration)












Follow is the SABR function part of my code in python:

```
def SABR_func( K, alp, bet, rho, nu ):
    "SABR"
    f = mV0*np.exp((0.02 - q)*tau)
    z = nu/alp*(f * K)**(0.5*(1 - bet)) * np.log(f / K)
    xz = np.log((np.sqrt(1 - 2*rho*z + z*z) + z - rho) / (1 - rho))
    zdivxz = z / xz
    zdivxz[np.isnan(zdivxz)] = 1.0
    result = ( alp*(f*K)**(0.5* (bet-1) )*
            (1 + ( ((1 - bet)*np.log(f/K))**2/24 + ((1 - bet)*np.log(f/K))**4/1920 ))**(-1.0)
            * zdivxz
            * ( 1 + ( ((1 - bet)*alp )**2 / (24*(f*K)**(1 - bet))
            + 0.25*alp*bet*rho*nu / ((f*K)**(0.5*(1-bet)))
            + ((2-3*rho**2)*nu**2)/24)*tau )
            )
    return result
```

And I use the function to fit the data in every time slice:

```
popt, pcov = curve_fit(SABR_func, cp[0, :], cp[1, :], p0 = init_guess,maxfev=10000)
#init_guess = [alp,bet,rho, nu] I have write before this
print(popt)
y1[it, :] = SABR_func(stkSet, *popt)
```

where:

mV0 is the Synthetic futures prices for atm options

cp[0,:] is the strike of option

cp[1,:] is the price of option

But I found that the model fitting is very poor,and be like this gif(pink points are true data)

Thanks for jChoi's help, I find I have some wrong with the f's formula,but when I using the right foluma, the result is same. Is there any other wrong I don't find ?

## Answer by jaehyukchoi49 (score 1)

https://quant.stackexchange.com/a/71283

`f` should be the forward rate. I have no idea where this line comes from?

```
f = alp*np.exp((0.02 - q)*tau)
```

It seems like that `alp` is playing the role of the spot price. You should take `spot` as an input and define

```
f = spot*np.exp((0.02 - q)*tau)
```

Shown in full with attribution under the source's licence. Licence: CC BY-SA 4.0 (Stack Exchange)

This summary was written by Stratmill's research agent from the original; it is not a copy of the source.