Based on this topic: How to derive the implied probability distribution from B-S volatilities?
I am trying to implement the Breeden-Litzenberger formula to compute the market implied risk-neutral densities for the S&P 500 for some quoting dates. The steps that I take are as follows:
Step 1: Extract the call_strikes c_strikes
for a given maturity T and the
corresponding market prices css
.
Step 2: Once I have the strikes and market prices, I compute the implied volatilities via the function ImplieVolatilities.m
I'm 100% sure that this function works.
Step 3: Next, I interpolate the implied volatility curve by making use of the Matlab command interp1
. Now, the vector xq
is the strikes grid and the vector vq
the corresponding interpolated implied volatilities.
Step 4: Since I have to volatility curve, I can compute the market implied density: \begin{align} f(K) &= e^{rT} \frac{\partial^2 C(K,T)}{\partial K^2} \\ &\approx e^{rT} \frac{C(K+\Delta_K,T)-2C(K,T)+C(K-\Delta_K, T)}{(\Delta_K)^2} \end{align} where $\Delta_K = 0.2$ is the strike grid size. I only show the core part of the Matlab program:
c_strikes = Call_r_strikes(find(imp_vols > 0));
css = Call_r_prices(find(imp_vols > 0));
impvolss = ImpliedVolatilities(S,c_strikes,r,q,Time,0,css); %implied volatilities
xq = (min(c_strikes):0.2:max(c_strikes)); %grid of strikes
vq = interp1(c_strikes,impvolss,xq); %interpolatd values %interpolated implied volatilities
f = zeros(1,length(xq)); %risk-neutral density
function [f] = secondDerivativeNonUniformMesh(x, y)
dx = diff(x); %grid size (uniform)
dxp = dx(2:end);
d2k = dxp.^2; %squared grid size
f = (1./d2k).*(y(1:end-2)-2*y(2:end-1)+y(3:end));
end
figure(2)
plot(xq,f);
Note: blsprice
is an intern Matlab function so that one should definitely work.
This is the risk-neutral pdf for the interior points:
The data The following table shows the option data (left column: strikes, middle: market prices and right column: implied volatilities):
650 387.5 0.337024
700 346.45 0.325662
750 306.8 0.313846
800 268.95 0.302428
850 232.85 0.290759
900 199.15 0.279979
950 168.1 0.270041
975 153.7 0.265506
1000 139.9 0.260885
1025 126.15 0.255063
1050 112.9 0.248928
1075 100.7 0.243514
1100 89.45 0.238585
1125 79.25 0.234326
1150 69.7 0.229944
1175 60.8 0.22543
1200 52.8 0.221322
1225 45.8 0.21791
1250 39.6 0.21486
1275 33.9 0.21154
1300 28.85 0.208372
1325 24.4 0.205328
1350 20.6 0.202698
1375 17.3 0.200198
1400 13.35 0.193611
1450 9.25 0.190194
1500 6.55 0.188604
1550 4.2 0.184105
1600 2.65 0.180255
1650 1.675 0.177356
1700 1.125 0.176491
1800 0.575 0.177828
$T = 1.6329$ is the time to maturity, $r = 0.009779$ the risk-free rate and $q = 0.02208$ the dividend yield. The spot price $S = 1036.2$.
Computation of the risk-free rate and dividend yield via Put-Call parity $r$ is the risk-free rate corresponding to maturity $T$ and $q$ is the dividend yield. In the numerical implementation, we derive $r$ and $q$ by again making use of the Put-Call parity. To that end, we assume the following linear relationship: $$f(K) = \alpha K-\beta,$$ where $\alpha = e^{-rT}$ and $-e^{-qT}S(0) = \beta$, and $f(K) = P(K,T)-C(K,T)$. The constants $\alpha$ and $\beta$ are then computed by carrying out a linear regression. Consequently, the risk-free rate $r$ and dividend yield $q$ are then given by \begin{align} r &= \frac{1}{T}\ln\left(\frac{1}{\alpha}\right), \nonumber \\ q &= \frac{1}{T} \ln \left(\frac{-S(0)}{\beta}\right). \nonumber \end{align}