Fast Implied Volatility Calculation in Python

14,692

Solution 1

If you change all calls to norm.cdf()-method into ndtr(), you will get a 2.4 time performance increase.

And if you change norm.pdf()-method into norm._pdf(), you will get another (huge) increase.

With both changes implemented, the example above dropped from 17.7 [s] down to 0.99 [s] on my machine.

You will loose error checking etc. but in this case you probably don't need all that.

See: https://github.com/scipy/scipy/issues/1914

ndtr() is in scipy.special

Solution 2

You have to realize that the implied volatility calculation is computationally expensive and if you want realtime numbers maybe python is not the best solution.

Here is an example of the functions you would need:

import numpy as np
from scipy.stats import norm
N = norm.cdf

def bs_call(S, K, T, r, vol):
    d1 = (np.log(S/K) + (r + 0.5*vol**2)*T) / (vol*np.sqrt(T))
    d2 = d1 - vol * np.sqrt(T)
    return S * norm.cdf(d1) - np.exp(-r * T) * K * norm.cdf(d2)

def bs_vega(S, K, T, r, sigma):
    d1 = (np.log(S / K) + (r + 0.5 * sigma ** 2) * T) / (sigma * np.sqrt(T))
    return S * norm.pdf(d1) * np.sqrt(T)

def find_vol(target_value, S, K, T, r, *args):
    MAX_ITERATIONS = 200
    PRECISION = 1.0e-5
    sigma = 0.5
    for i in range(0, MAX_ITERATIONS):
        price = bs_call(S, K, T, r, sigma)
        vega = bs_vega(S, K, T, r, sigma)
        diff = target_value - price  # our root
        if (abs(diff) < PRECISION):
            return sigma
        sigma = sigma + diff/vega # f(x) / f'(x)
    return sigma # value wasn't found, return best guess so far

Computing a single value is quick enough

S = 100
K = 100
T = 11
r = 0.01
vol = 0.25

V_market = bs_call(S, K, T, r, vol)
implied_vol = find_vol(V_market, S, K, T, r)

print ('Implied vol: %.2f%%' % (implied_vol * 100))
print ('Market price = %.2f' % V_market)
print ('Model price = %.2f' % bs_call(S, K, T, r, implied_vol))

Implied vol: 25.00%

Market price = 35.94

Model price = 35.94

But if you try to compute many, you will realize that it takes some time...

%%time
size = 10000
S = np.random.randint(100, 200, size)
K = S * 1.25
T = np.ones(size)
R = np.random.randint(0, 3, size) / 100
vols = np.random.randint(15, 50, size) / 100
prices = bs_call(S, K, T, R, vols)

params = np.vstack((prices, S, K, T, R, vols))
vols = list(map(find_vol, *params))

Wall time: 10.5 s

Solution 3

As of recent, there is a vectorized version of py_vollib available at py_vollib_vectorized, which is built on top of the py_vollib and makes pricing thousands of options contracts and calculating greeks much faster.

Share:
14,692
Admin
Author by

Admin

Updated on June 25, 2022

Comments

  • Admin
    Admin about 2 years

    I am looking for a library which i can use for faster way to calculate implied volatility in python. I have options data about 1+ million rows for which i want to calculate implied volatility. what would be the fastest way i can calculate IV's. I have tried using py_vollib but it doesnt support vectorization. It takes about 5 mins approx. to calculate. Are there any other libraries which can help in faster calculation. What do people use in real time volatility calculations where there are millions of rows coming in every second?