Package: jetblack-options
jetblack-optionsThis repository contains reference implementations of option pricing formulae
implemented in Python.It has no dependencies.There is an online demonstration of some of the valuationshere(source codehere).StatusThis is currently considered alpha.UsageThe library can be installed as a package.pipinstalljetblack-optionsAn obvious place to start would be with Black-Scholes.fromjetblack_options.european.black_scholes_mertonimport(price,delta)is_call=TrueS=110# Asset price.K=100# Strike price.r=0.1# 10% risk free rate.q=0.08# 8% dividend.T=6/12# Half a year till expiry.v=0.125# 12.5% volatility.b=r-q# Cost of carry for generalized Black-Scholes.p=price(is_call,S,K,T,r,b,v)d=delta(is_call,S,K,T,r,b,v)# Calculate the delta by bumping the price.fromjetblack_options.numeric_greeks.with_carryimportNumericGreeksng=NumericGreeks(price)d1=ng.delta(is_call,S,K,T,r,b,v)Typically each module has a function calledpricewhich calculates the price
of the model. Where closed form solutions are available, they have their
canonical name (e.g.delta). In this case a general numeric class was also
available.A tree solution only provides a price. However the numeric class can provide
support for the greeks.fromjetblack_options.trees.cox_ross_rubinsteinimportgreeksfromjetblack_options.numeric_greeksimportNumericGreeksis_european=Trueis_call=TrueS=110# Stock price.K=100# Strike price.r=0.1# 10% risk free rate.q=0.08# 8% dividend.T=6/12# Half a year till expiry.v=0.125# 12,5% volatility.b=r-qvalue,delta,gamma,theta=greeks(is_european,is_call,S,K,T,r,b,v,200)# Make a lambda to handle is_european.ng=NumericGreeks(lambdais_call,S,K,T,r,b,v:greeks(is_european,is_call,S,K,T,r,b,v,100)[0])# The numeric delta should be close to the analytic.numeric_delta=ng.delta(is_call,S,K,T,r,b,v)PandasThe code has been written without dependencies to keep the implementation clean.It is fairly simple to support vectors. The following is the generalised
Black Scholes price function using scipy, numpy and pandas.importnumpyasnpimportpandasaspdfromscipy.statsimportnormdefprice(is_call,S,K,T,r,b,v):d1=(np.log(S/K)+T*(b+v**2/2))/(v*np.sqrt(T))d2=d1-v*np.sqrt(T)ifis_call:returnS*np.exp((b-r)*T)*norm.cdf(d1)-K*np.exp(-r*T)*norm.cdf(d2)else:returnK*np.exp(-r*T)*norm.cdf(-d2)-S*np.exp((b-r)*T)*norm.cdf(-d1)df=pd.DataFrame([{'S':110,'K':100,'r':0.1,'q':0.08,'T':6/12,'v':0.125},{'S':100,'K':100,'r':0.1,'q':0.08,'T':6/12,'v':0.125},{'S':100,'K':110,'r':0.1,'q':0.08,'T':6/12,'v':0.125},])price(True,df['S'],df['K'],df['T'],df['r'],df['r']-df['q'],df['v'])Here's another implementation using a single data frame.importnumpyasnpimportpandasaspdfromscipy.statsimportnormdata=pd.DataFrame([{'is_call':True,'S':110,'K':100,'r':0.1,'q':0.08,'T':6/12,'v':0.125},{'is_call':False,'S':110,'K':100,'r':0.1,'q':0.08,'T':6/12,'v':0.125},{'is_call':True,'S':100,'K':100,'r':0.1,'q':0.08,'T':6/12,'v':0.125},{'is_call':False,'S':100,'K':100,'r':0.1,'q':0.08,'T':6/12,'v':0.125},{'is_call':True,'S':100,'K':110,'r':0.1,'q':0.08,'T':6/12,'v':0.125},{'is_call':False,'S':100,'K':110,'r':0.1,'q':0.08,'T':6/12,'v':0.125},])defprice(df):d1=(np.log(df['S']/df['K'])+df['T']*(df['b']+df['v']**2/2))/(df['v']*np.sqrt(df['T']))d2=d1-df['v']*np.sqrt(df['T'])returnpd.Series(np.where(df['is_call'],df['S']*np.exp((df['b']-df['r'])*df['T'])*norm.cdf(d1)-df['K']*np.exp(-df['r']*df['T'])*norm.cdf(d2),df['K']*np.exp(-df['r']*df['T'])*norm.cdf(-d2)-df['S']*np.exp((df['b']-df['r'])*df['T'])*norm.cdf(-d1)),name='price')data['b']=data['r']-data['q']x=price(data)ContributionsContributions are welcome!The goals of the project are centred on clarity and accuracy.Valuable contributions include:More tests. Note that tests are code too, and have to be maintained. We should
aim for the smallest complete set possible. Requests to delete are as
relevant as those to add.More implementations. Pricing models should come with tests, and a numerical
bumping framework.The code is formatted with autopep8, and linted with pylint and mypy. Typing is
used throughout to help the reader.Optimisations or integrations with other packages should be included as
examples only.