Black-Scholes Model in Python

Previously, I gave a brief introduction to Derivates – my favourite concept in Finance. To continue this topic, I present a step-by-step tutorial on how to set up the calculation in Python.

Essentially, the code is a set of formulas wrapped in a Python function which takes the same parameters.

Here is the formula refresher:

Black Scholes model formula

Prior to coding the function, we need to import two libraries into the editor, i.e., numpy (general module for calculation) and norm from scipy.stats (a statistical module that we use to calculate normal distribution).

import numpy as np
from scipy.stats import norm

Step 1: Define a function and its parameters

Breaking down the formula, we can see that it takes only five essential parameters, i.e., S0, K, r, T and sigma. Hence, the first step is to define a function with these parameters. Additionally, we add a parameter option_type to distinguish which type (call or put) we want to calculate.

def black_scholes_calc(S0, K, r, T, sigma, option_type):
'''This function calculates the value of the European option based on Black-Scholes formula'''

Step 2: Determine d1 and d2

Stepping back from the original formula, we notice that prior to call or put calculation, we have to define d1 an d2 parameters. Please refer to the previous post for any further explanation of the meaning of the parameters.

The standard Python operators in combination with the numpy module are used for this operation.

d1 = 1/(sigma*np.sqrt(T)) * (np.log(S0/K) + (r+sigma**2/2)*T)
d2 = d1 - sigma*np.sqrt(T)

Next, we make use of the cumulation distribution function (CDF) from the norm module to obtain the distribution number for both d1 and d2. Consequently, we apply the function on the opposite values, i.e., -d1 and -d2.

nd1 = norm.cdf(d1)
nd2 = norm.cdf(d2)

n_d1 = norm.cdf(-d1)
n_d2 = norm.cdf(-d2)

Step 3: Define put and call formulas

Now that we have defined the missing input parameters, we can get back to the initial call and put formulas. 

c = nd1*S0 - nd2*K*np.exp(-r*T)
p = K*np.exp(-r*T)*n_d2 - S0*n_d1

Step 4: Finalize the function

To finalize the function, we add a functionality of verifying which option type the user intends to calculate using an if-statement. We return the corresponding variable, i.e., c or p which are defined in the previous step.

# 4) define which value to return based on the option_type parameter
if option_type=='call':
return c
elif option_type=='put':
return p
else:
print('Wrong option type specified')

Step 5: Test the function

To test the function, we can plug in some arbitrary numbers and verify if the returned result is in line with the expectations.

The final function should look as follows:

def black_scholes_calc(S0, K, r, T, sigma, option_type):
'''This function calculates the value of the European option based on Black-Scholes formula'''
# 1) determine N(d1) and N(d2)
d1 = 1/(sigma*np.sqrt(T)) * (np.log(S0/K) + (r+sigma**2/2)*T)
d2 = d1 - sigma*np.sqrt(T)
nd1 = norm.cdf(d1)
nd2 = norm.cdf(d2)
   n_d1 = norm.cdf(-d1)
n_d2 = norm.cdf(-d2)
# 2) determine call value
c = nd1*S0 - nd2*K*np.exp(-r*T
# 3) determine put value
p = K*np.exp(-r*T)*n_d2 - S0*n_d1
# 4) define which value to return based on the option_type parameter
if option_type=='call':
return c
elif option_type=='put':
return p
else:
print('Wrong option type specified')

Let’s define the numbers separately and then calculate the price of the put function!

S0=8.; K=9.; T=3/12.; r=.01; sigma=.2
black_scholes_calc(S0, K, r, T, sigma, 'put')

Running the function gives the result of 1.0298. Recall that holding a put option means that the asset holder has a right to sell the underlying asset at the predefined price (9 in our scenario) at the specified time (in 3 months in our scenario). It is likely that the asset holder expects the price of the asset to decrease. By entering into the put option contract, she secures the opportunity to sell the asset at the price of 9, and pays 1.0298 for the contract itself. 

To make the profit, the asset price at the option expiry should correspond the following rule:

9 – 1.0298 – Price > 0, i.e., Price < 7.97

Leave a Reply

Your email address will not be published. Required fields are marked *