In [148]:
import numpy as np
import matplotlib.pyplot as plt
In the below formula, $K$ is the option strike, and $T$ its maturity (in years). $df$ and $F$ are the discount factor to maturity and the forward at maturity respectively (in absence of dividends / foreign interest $df\times F$ equals the spot price), and $\sigma$ is the annualised volatility (eg 0.2 for 20%)
$$ \begin{eqnarray} \mathrm{Call}(K,T; df,F,\sigma) &=& df \times (F N(d_1) - K N(d_2)) \\ d_1 &=& \frac{\ln (F/K) + 0.5 \sigma^2 T}{\sigma \sqrt{T}} \\ d_2 &=& \frac{\ln (F/K) - 0.5 \sigma^2 T}{\sigma \sqrt{T}} \end{eqnarray} $$
In [149]:
from scipy.stats import norm
def bscall(strike=100,mat=1,fwd=100,sig=0.1,df=1):
lnfs = log(1.0*fwd/strike)
sig2t = sig*sig*mat
sigsqrt = sig*sqrt(mat)
d1 = (lnfs + 0.5 * sig2t) / sigsqrt
d2 = (lnfs - 0.5 * sig2t) / sigsqrt
fv = fwd * norm.cdf (d1) - strike * norm.cdf (d2)
return df * fv
bscall(fwd=100, strike=100, sig=0.1, mat=1, df=1)
Out[149]:
In the below formula, $K$ is the option strike, and $T$ its maturity (in years). $df$ and $F$ are the discount factor to maturity and the forward at maturity respectively (in absence of dividends / foreign interest $df\times F$ equals the spot price), and $\sigma$ is the annualised volatility (eg 0.2 for 20%)
$$ \begin{eqnarray} \mathrm{Put}(K,T; df,F,\sigma) &=& df \times (K N(-d_2) - F N(-d_1)) \\ d_1 &=& \frac{\ln (F/K) + 0.5 \sigma^2 T}{\sigma \sqrt{T}} \\ d_2 &=& \frac{\ln (F/K) - 0.5 \sigma^2 T}{\sigma \sqrt{T}} \end{eqnarray} $$
In [150]:
from scipy.stats import norm
def bsput(strike=100,mat=1,fwd=100,sig=0.1,df=1):
lnfs = log(1.0*fwd/strike)
sig2t = sig*sig*mat
sigsqrt = sig*sqrt(mat)
d1 = (lnfs + 0.5 * sig2t) / sigsqrt
d2 = (lnfs - 0.5 * sig2t) / sigsqrt
fv = strike * norm.cdf (-d2) - fwd * norm.cdf (-d1)
return df * fv
bsput(fwd=100, strike=100, sig=0.1, mat=1, df=1)
Out[150]:
The standard European digital call option pays one unit of the currency if and only if the spot price at expiry as above the strike $K$, ie the payoff is a step function. The price is given by the following formula ($d_2$ is defined as above) $$ \mathrm{DCall}(K,T;df,F,\sigma)=df\times N(d_2) $$ The price for a digitial put is $df\times(1-N(d_2))$
In [151]:
from scipy.stats import norm
def bsdcall(strike=100,mat=1,fwd=100,sig=0.1,df=1):
lnfs = log(1.0*fwd/strike)
sig2t = sig*sig*mat
sigsqrt = sig*sqrt(mat)
d2 = (lnfs - 0.5 * sig2t) / sigsqrt
fv = norm.cdf(d2)
return df * fv
def bsdput(strike=100,mat=1,fwd=100,sig=0.1,df=1):
lnfs = log(1.0*fwd/strike)
sig2t = sig*sig*mat
sigsqrt = sig*sqrt(mat)
d2 = (lnfs - 0.5 * sig2t) / sigsqrt
fv = 1.0 - norm.cdf(d2)
return df * fv
bsdcall(fwd=100, strike=100, sig=0.1, mat=1, df=1), bsdput(fwd=100, strike=100, sig=0.1, mat=1, df=1)
Out[151]:
The reverse European digital call option pays one unit of the underlying asset if and only if the spot price at expiry as above the strike $K$. The price is given by the following formula ($d_1$ is defined as above) $$ \mathrm{RDCall}(K,T;df,F,\sigma)=df\times F \times N(d_1) $$ The price for the corresponding put is as above. Note that in the absence of dividends / foreign interest $df\times F=S$
In [152]:
from scipy.stats import norm
def bsdrcall(strike=100,mat=1,fwd=100,sig=0.1,df=1):
lnfs = log(1.0*fwd/strike)
sig2t = sig*sig*mat
sigsqrt = sig*sqrt(mat)
d1 = (lnfs + 0.5 * sig2t) / sigsqrt
fv = fwd * norm.cdf (d1)
return df * fv
def bsdrput(strike=100,mat=1,fwd=100,sig=0.1,df=1):
lnfs = log(1.0*fwd/strike)
sig2t = sig*sig*mat
sigsqrt = sig*sqrt(mat)
d1 = (lnfs + 0.5 * sig2t) / sigsqrt
fv = fwd * (1.0 - norm.cdf (d1))
return df * fv
bsdrcall(fwd=100, strike=100, sig=0.1, mat=1, df=1), bsdrput(fwd=100, strike=100, sig=0.1, mat=1, df=1)
Out[152]:
In [160]:
import sys
print(sys.version)
In [160]: