Correcting the Forward Input in a SABR Volatility Fit
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.