Morten
Morten

Reputation: 1869

Scipy fsolve: No solution invalidates all valid solutions

I'm trying to back out Black-Scholes implied volatilities from financial options data. If the data contains options for which an implied volatility cannot be found, this will make all the results equal to the initial guess. See the following example

from scipy.optimize import fsolve
import numpy as np
from scipy.stats import norm

S = 1293.77
r = 0.05
K = np.array([1255, 1260, 1265, 1270, 1275])
T = 2./365
price = np.array([38.9, 34.35, 29.7, 25.35, 21.05])

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

volatility = lambda x: black_scholes(S, K, r, T, x) - price

print fsolve(volatility, np.repeat(0.1, len(K)))

gives

RuntimeWarning: The iteration is not making good progress, as measured by the 
  improvement from the last ten iterations.
  warnings.warn(msg, RuntimeWarning)
[ 0.1  0.1  0.1  0.1  0.1]

By doing the same operation with Matlab or Maple I know that no solution can be found for the first option. If I exclude that one, such that

K = np.array([1260, 1265, 1270, 1275])
price = np.array([34.35, 29.7, 25.35, 21.05])

I do get the right result

[ 0.19557092  0.20618568  0.2174149   0.21533821]

Therefore if a solution cannot be found I would expect fsolve to return NaN instead of my initial guess and not mess up the rest of the solutions.

Upvotes: 0

Views: 1847

Answers (1)

Warren Weckesser
Warren Weckesser

Reputation: 114976

Use the full_output argument to tell fsolve to return more information, and check the value of ier on return. For example,

sol, info, ier, msg = fsolve(volatility, np.repeat(0.1, len(K)), full_output=True)

if ier != 1:
    print "ier = %d" % (ier,)
    print msg
else:
    print "sol =", sol

You said:

...if a solution cannot be found I would expect fsolve to return NaN instead of my initial guess and not mess up the rest of the solutions.

fsolve has no way of knowing that the problem you are solving is actually a collection of decoupled problems. You've given it a single n-dimensional problem. Either it succeeds or it fails to find a solution to that problem.

Upvotes: 3

Related Questions