
It would be quite handy to know what is the true price of a european option given cash dividends. Without dividends we have the Black and Scholes analytical formula. With dividends, we can have a lower and a upper bound.
For the lower bound, we use the approach I called "Hull":
The stock $S$ is decomposed into a risky component $S^*$ and a certain component $D$ which is the present value of all dividends to be paid during the life of the option.
Since they will be paid before the option expired, the method prices the option using only $S^*$.
We argued that it was underestimating the price because the volatility is applied to $S^*$ until the dividends are paid and it can be quite smaller than $S$. The sooner the dividends are paid, the smaller the error though. Indeed if the dividends would be paid right now, it would be correct to price the option with $S^*$
For the upper bound, one can use the forward method:
If we had the dividend paid right at expiration of the option, payoff of the call would read 'max ((S-D)-K,0)' and the one of the put 'max((-(S-D)+K,0)'. In that case we could price the option using S and using a strike K+D instead of K.
The forward method extended this: all dividends are grown until expiration (if time of the dividend is $t_1$ and expiration $T$ we use $e^{r(T-t_1)}$ and added to the strike.
The volatility is here applied to the full stock $S$ even after dividend are paid. So it overestimate the price of an option.
There is some literature on how to correct the volatility we use with the Hull or the forward methods to get a good price but as soon as you have several dividends it becomes messy.
Find below the code for both adaptation of the BS formula for dividend options using the Hull and the forward method:
- def BlackScholes2b(option):
- [S0,K,sigma,T,r,divi,american]=[float(option.S0),float(option.K),option.sigma,float(option.T),option.r,option.divi,option.american]
- #Hull method, dividend are discounted and removed from the spot
- def phi(z):
- return np.exp(-.5 * z * z) / (np.sqrt( 2 * np.pi ))
- dividends=[[],[]]
- pvdividends=0
- if (np.size(divi)>0 and divi[0][0]<T) :
- lastdiv=np.nonzero(np.array(divi[0][:])<=T)[0][-1]
- dividends[0]=divi[0][:lastdiv+1]
- dividends[1]=divi[1][:lastdiv+1]
- if np.size(dividends)>0:
- for index,dv in enumerate(list(dividends[1])):
- pvdividends=pvdividends+dv*np.exp(-r*dividends[0][index])
- S0=S0-pvdividends
- td1=d1(S0, K, r, sigma, T)
- td2=d2(S0, K, r, sigma, T)
- option.call.price=S0 * ss.norm.cdf(td1) - K * np.exp(-r * T) * ss.norm.cdf(td2)
- option.put.price=K * np.exp(-r * T) * ss.norm.cdf(-td2) - S0 * ss.norm.cdf(-td1)
- option.call.delta=ss.norm.cdf(td1)
- option.put.delta=ss.norm.cdf(td1)-1
- NPrime=phi(td1)
- option.call.gamma=NPrime/(S0*sigma*np.sqrt(T))
- option.put.gamma=option.call.gamma
- option.call.theta=(NPrime)*(-S0*sigma*0.5/np.sqrt(T))-r*K * np.exp(-r * T) * ss.norm.cdf(td2)
- option.put.theta=(NPrime)*(-S0*sigma*0.5/np.sqrt(T))+r*K * np.exp(-r * T) * ss.norm.cdf(-td2)
- return option
- def BlackScholes2c(option):
- [S0,K,sigma,T,r,divi,american]=[float(option.S0),float(option.K),option.sigma,float(option.T),option.r,option.divi,option.american]
- #Forward method, dividends are grown and added to the strike
- def phi(z):
- return np.exp(-.5 * z * z) / (np.sqrt( 2 * np.pi ))
- dividends=[[],[]]
- pvdividends=0
- if (np.size(divi)>0 and divi[0][0]<T) :
- lastdiv=np.nonzero(np.array(divi[0][:])<=T)[0][-1]
- dividends[0]=divi[0][:lastdiv+1]
- dividends[1]=divi[1][:lastdiv+1]
- if np.size(dividends)>0:
- for index,dv in enumerate(list(dividends[1])):
- pvdividends=pvdividends+dv*np.exp(r*(T-dividends[0][index]))
- K=K+pvdividends
- td1=d1(S0, K, r, sigma, T)
- td2=d2(S0, K, r, sigma, T)
- option.call.price=S0 * ss.norm.cdf(td1) - K * np.exp(-r * T) * ss.norm.cdf(td2)
- option.put.price=K * np.exp(-r * T) * ss.norm.cdf(-td2) - S0 * ss.norm.cdf(-td1)
- option.call.delta=ss.norm.cdf(td1)
- option.put.delta=ss.norm.cdf(td1)-1
- NPrime=phi(td1)
- option.call.gamma=NPrime/(S0*sigma*np.sqrt(T))
- option.put.gamma=option.call.gamma
- option.call.theta=(NPrime)*(-S0*sigma*0.5/np.sqrt(T))-r*K * np.exp(-r * T) * ss.norm.cdf(td2)
- option.put.theta=(NPrime)*(-S0*sigma*0.5/np.sqrt(T))+r*K * np.exp(-r * T) * ss.norm.cdf(-td2)
- return option
Aucun commentaire:
Enregistrer un commentaire