I am implementing my local volatility pricer using the finite difference method in MATLAB. I parametrise the implied volatility surface using the SSVI parametrisation (Gatheral & Jacquier), which allows me to obtain a pretty smooth local volatility surface:
I use Dupire's formula in terms of total implied variance $w(k,T)$, where $k=\log(K/F_{0,T})$ and interpSsviStineman
is responsible for interpolating the ATMF total variance curve and return the implied total variance level for any arbitrary $k$ and $T$:
delta_k = 0.0001;
delta_t = 1e-6;
w_k_t = interpSsviStineman(k, t_, ssvi_param_);
w_k_tm = interpSsviStineman(k, t_-delta_t, ssvi_param_);
w_k_tp = interpSsviStineman(k, t_+delta_t, ssvi_param_);
dwdt = (w_k_tp-w_k_tm)/(2*delta_t);
w_km_t = interpSsviStineman(k-delta_k, t_, ssvi_param_);
w_kp_t = interpSsviStineman(k+delta_k, t_, ssvi_param_);
dwdk = (w_kp_t-w_km_t)/(2*delta_k);
d2wdk2 = (w_kp_t+w_km_t-2*w_k_t)/(delta_k^2);
[kg, ~] = ndgrid(k, t_);
local_var = dwdt./(1-kg./w_k_t.*dwdk+1/4*(-1/4-1./w_k_t+...
kg.^2./w_k_t.^2).*(dwdk).^2 + 1/2*d2wdk2);
local_vol = sqrt(local_var);
To validate my implementation I am repricing the vanilla options that I used to calibrate the volatility surface in the first place. If my implementation were to be correct, I would expect to be able to back out the same implied volatilities used to generate the local volatility surface. This is not the case and I seem to be able to match only the prices of AMTF options while my implementation is overpricing the options in the wings:
I would be grateful for any suggestion that can point me to the mistake.
Cheers!