Last Updated on April 30, 2022 by Jay

This tutorial covers two methods on how to calculate option implied volatility using Python: brute force and Newton Raphson Method.

A single option chain contains thousands of values for different options. If we want to calculate the implied volatilities for all options, we have to use something fast. For practical reasons, we would prefer Newton’s method, and brute force is just for comparison.

In reality, option prices are determined by demand and supply. For a given option, when:

- More buyers than sellers, the price goes up
- More seller than buyers, the price goes down

The Black Scholes formula gives a framework to model the option prices and risks associated with an option. All the input values are readily observable except for one – the **implied volatility**. As its name suggests – it is implied and not explicitly known.

## Black Scholes Option Pricing Formula In Python

In this tutorial, we implemented the BS formula in Python to calculate options prices. Below is the code:

```
import scipy.stats
from numpy import sqrt, log, exp, pi
N = scipy.stats.norm.cdf
d1 = (log(S/K) + (r+sigma**2/2)*t) / (sigma*sqrt(t))
d2 = d1 - sigma * sqrt(t)
def bs_price(c_p, S, K, r, t, sigma):
if c_p == 'c':
return N(d1) * S - N(d2) * K * exp(-r*t)
elif c_p == 'p':
return N(-d2) * K * exp(-r*t) - N(-d1) * S
else:
return "Please specify call or put options."
```

The BS pricing formula sort of has what we need but does not exactly solve our problem.

- Instead of calculating an option price, we already know it
- The volatility (sigma) is unknown and we need to calculate it

## Calculating Implied Volatility In Python Brute Force Method

A “brute force” method basically attempts to use many different sigma (volatility) values to calculate the option price. When a calculated price is close enough to the observed price, the corresponding sigma is considered to be the “root”.

This method will perform many calculations since we don’t know when there will be a match. Usually, brute force is the last resort when everything else fails. Luckily, for our problem, there’s a more efficient solution. If you don’t want to read about the brute force method, skip ahead to the next section to learn how to implement the more efficient method – The Newton Rasphon Method.

To start the brute force calculation, we need a starting sigma value. There’s no right or wrong number for this starting value, but I chose to use 0.5, or 50% volatility. Note that many stocks can have volatility well over 100% so the 0.5 isn’t really the midpoint. The process goes like this:

- Define a threshold
**ONE_CENT**on when to accept the solution, e.g. when the calculated price and the actual market price are within 1 cent. - Define a
**step**variable to adjust the sigma values. - Use an initial guess (
**_sigma**) to calculate the Black Scholes option price - Calculate the difference (
**diff**) between the BS price and the actual market price - If the
**diff**is larger than the threshold**ONE_CENT**, adjust the sigma value and re-calculate the difference - Repeat #4-5 until the
**diff**is less than or equal to the threshold

To avoid an infinite loop, let’s also set a limit on the max number of calculations to perform.

```
ONE_CENT = 0.01
step = 0.0001
def brute_force(c_p, S, K, r, t, market_price):
_sigma = 0.5
for i in range(10000): #max number of calculations is 10000
bs_price = bs_price(c_p, S, K, r, t, sigma = _sigma)
diff = market_price - bs_price
if diff > ONE_CENT:
_sigma = _sigma + step
elif diff < 0 and abs(diff) > ONE_CENT:
_sigma = _sigma - step
elif abs(diff) < ONE_CENT:
return _sigma
return _sigma
```

## Calculate Option Implied Volatility In Python – Newton Raphson Method

The Newton Raphson Method is a very fast root-finding approximation method. The math is beyond the scope of this tutorial, feel free to Google it if interested.

At a high level, we repeat the following calculation until reaching a threshold (similar to brute force).

In this context:

- x is
- f(x) is a function that is the theoretical (BS) option price – the actual option price. In other words, we want f(x) = BS_price – market_price = 0
- The derivative of f(x), or f'(σ) is actually known as Vega, or the option price sensitivity to implied volatility. We can calculate Vega easily using the below formula. Note the notation N'() is the standard normal probability density function.

```
N_price = scipy.stats.norm.pdf
vega = S*N_prime(d1)*sqrt(t)
```

Then, use the Newton Raphson Method to calculate implied volatility.

**diff**is essentially f(x) = bs_price – market_price**vega**is f'(x)- We use a MAX_TRY = 1000 loops to help avoid an infinite loop
- Assume the starting sigma to be 0.5, which is just an arbitrary number

```
MAX_TRY = 1000
def find_iv_newton(c_p, S, K, r, t, market_price):
_sigma = 0.5
for i in range(MAX_TRY):
_bs_price = bs_price(c_p,S, K, r, t, sigma=_sigma)
diff = market_price - _bs_price
vega = S*N_prime(d1)*sqrt(t)
if abs(diff) < ONE_CENT:
return _sigma
_sigma += diff/vega
return _sigma
```

Let’s use the following example to test the performance of the two different methods:

- Stock price S = 100
- Strike price K = 120
- Call option
- risk free rate r = 0.02
- Time to expiration t = 30 days or 30/365
- A market price of $5.67

```
import time
start = time.time()
sigma = brute_force('c',100,120,0.02,30/365, 5.67)
print(sigma)
print(f'finished in {time.time() - start} seconds')
1.063399999999938
finished in 0.53448486328125 seconds
start = time.time()
sigma2 = find_iv_newton('c',100,120,0.02,30/365, 5.67)
print(sigma2)
print(f'finished in {time.time() - start} seconds')
1.064303827083575
finished in 0.001001119613647461 seconds
```

The brute force method took 0.53 seconds, pretty fast. However, the Newton Rasphon method took 0.001 seconds which is 500 times faster!! The two calculated numbers are not exactly the same due to in the **brute_force() **method we either increment or decrement the **sigma** values by 0.0001 each time, so that’s the best it can achieve. On the other hand, Newton’s Method is probably more accurate.

You can also add a **print(i)** in each of the **brute_force()** or **find_iv_newton()** functions and observe:

- Brute force method took 5633 attempts before finding the simga
- Newton’s method took 3 attempts

Hello,

Sometimes I get “RuntimeWarning: invalid value encountered in double_scalars” for the d1 calculation. From what I’ve read it’s caused by operations with extremely small or extremely large numbers. Any suggestions for handling?

Example Input Causing the Error:

c_p = ‘p’

S = 143.0

K = 147.0

r = 0.0281

t = 0.0136986301369863

market_price = 3.8

Hi Dave,

Thanks for dropping by and very interesting question!

From coding perspective, yes you are exactly right it’s because the values are extremely small and close to 0 is the reason for the warning message. We should definitely have some error handling here. However, let’s take a look at the option first…

Assumine the t is 5 days (based on 365 days/year).

S = 143, K = 147 -> implies the put option is currently ITM, with an intrinsic value of $4.

With still 5 days left to expiration, I’d assume there are still some (although very little) extrinsic value in the option, meaning the given option should be traded > $4.

Let’s do a quick test by using your given input, and a sigma value of 0:

bs_price(c_p, S, K, r, t, 0) = $3.94. Very close to the intrinsic value of $4, kinda weird but it’s a theoretical equation and very close to $4, so I’m okay with it. In fact, if we plug t=0 in to the equation, we get exactly $4. By settingsigma = 0(i.e. the minimal possible value for IV), we set the minimum value of the option, which should be at least 3.94 (based on the BS equation).However, the market price is only $3.8…. This is some serious mis-price according to BSM framework. However, BSM is only theoretical, the option prices are determined by the buyers and sellers in reality. For this reason, I’d suggest using BSM as a guide/reference point instead of relying it on everything.

Another possibility for this “misprice” is that you might be using end of day data, which could be inaccurate (e.g. stock price moved after market close, but the last option price didn’t change, etc.)

Going back to the coding side with the handling, we can probably do something like this (pseudocode):

if intrinsic value < market pricethen return a warning message : "mispricing detected: market value is less than intrinsic value"Hope that helps, and happy to discuss more!