#!/usr/bin/env python # coding: utf-8 # #iPython Cookbook - Analytic Pricing # >A collection of various analytic pricing formulas, to be added to as and when needed # In[148]: import numpy as np import matplotlib.pyplot as plt # ## Black Scholes Pricing - Simple # ### European Call Option # 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) # ### European Put Option # 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) # ### European Digital # 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) # 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) # ## Licence and version # *Copyright Stefan Loesch / oditorium 2014; all rights reserved* # # License: [AGPL v3.0](https://github.com/oditorium/blog/blob/master/LICENSE) # In[160]: import sys print(sys.version) # In[160]: