Brenner and Subrahmanyam (1988) provided a closed form estimate of IV, you can use it as the initial estimate:
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
Note that \begin{align*} (K-S_T)^+ \ge K-S_T. \end{align*} Then \begin{align*} p &\equiv E\Big(e^{-rT} (K-S_T)^+ \Big)\\ &\ge E\Big(e^{-rT} (K-S_T) \Big)\\ &=K\, e^{-rT} - S_0\\ &= 670 \times e^{-0.05 \times 55/365} - 563.48\\ &=102.49. \end{align*} However, the option price is 101.375, which is smaller. This is the reason that you have difficulty to obtain an implied volatility.