def bsimpvol(callput, S0, K, r, T, price, sigma, q=0, priceTolerance=0.01, method='bisect', reportCalls=False): def targetfunction(x): return bsformula(callput, S0, K, r, T, x, q)[0] def getReturnData(_impVol, _calls): if (reportCalls): return (_impVol, _calls) else: return _impVol if (isNoVolatilityCanBeFound(callput, price, S0, K, T)): return getReturnData(float('NaN'), 0) impvol = float('NaN') calls = 0 if (method=="bisect"): start = 0.50 result = bisect(price, targetfunction, start, None, [priceTolerance, priceTolerance]) impvol = result[-1] calls = len(result) elif (method=="newton"): result = newtonsMethod(callput, S0, K, r, T, q, price, sigma, priceTolerance) impvol = result[0] calls = result[1] else: result = secantMethodBS(price, targetfunction, callput, S0, K, r, T, q, priceTolerance) impvol = result[0] calls = result[1] return getReturnData(impvol, calls)
def bsimpvol(callput, S0, K, r, T, price, q=0., priceTolerance=0.01, method='bisect', reportCalls=False): ''' :param callput: Callput is 1 for a call and -1 for a put :param S0: The stock price at time zero :param K: The strike price :param r: Risk-free interest rate :param T: The maturity time :param price: The price of the option :param q: A continuous return rate on the underlying :param priceTolerance: :param method: The method used to calculate sigma :param reportCalls: The record of call bsformula :return: sigma, numbers of calling bsformula ''' y = lambda sigma: bsformula(callput, S0, K, r, T, sigma)[0] dy = lambda sigma: bsformula(callput, S0, K, r, T, sigma)[2] if method == 'bisect': if bisect(price, y, bounds=[0.01, 1])[0] == None: return None item = bisect(price, y, bounds=[0.01, 1])[0] elif method == 'newton': if newton(price, y, dy, start=1, bounds=[0.01, 1])[0] == None: return None item = newton(price, y, dy, start=1, bounds=[0.01, 1])[0] if item != None: sigma = item[-1] else: sigma = item return None if reportCalls == True: return (sigma, len(item)) else: return sigma
def bsimpvol(callput, S0, K, r, T, price, q=0.0, priceTollerance=0.01, method='bisect', reportCalls=False): #judge which method to use 'return NaN' # no input value input_Value = [callput, S0, K, r, T] if all(input_Value) is False: return 'NaN' # price is less than intrinsic value if callput == 1: if price < max(0, S0 - K): return 'NaN' if callput == -1: if price < max(0, K - S0): return 'NaN' # call bsformula # create f function and df for methods def optionValue(x): return bsformula(callput, S0, K, r, T, x, q)[0] def optVega(x): return bsformula(callput, S0, K, r, T, x, q)[2] # use bisection method if method == 'bisect': (volatility, callsTimes) = bisect(price, optionValue, 0.001, [-0.001, 15], [0.001, priceTollerance], 1000) #if reportCalls is true if reportCalls == True: return (volatility[callsTimes - 1], callsTimes) else: return volatility[callsTimes - 1] # use newton method elif method == 'newton': (volatility, callsTimes) = newton_Method(price, optionValue, optVega, 0.8, [0.001, priceTollerance], 1000) #if reportCalls is true if reportCalls == True: return (volatility, callsTimes) else: return volatility else: print("please input 'bisect' or 'newton' in method")
def bsimpvol(callput, S0, K, r, T, price, q=0., priceTolerance=0.01, method='bisect', reportCalls=False): if price != 'NaN' and price >= callput * (S0 - K): def bsmvsact(sigma, callput, S0, K, r, T, price): return bsformula(callput, S0, K, r, T, sigma, q=0.)[0] - price def vega(sigma, callput, S0, K, r, T): return bsformula(callput, S0, K, r, T, sigma, q=0.)[2] partial_bsmvsact = partial(bsmvsact, callput=callput, S0=S0, K=K, r=r, T=T, price=price) partial_vega = partial(vega, callput=callput, S0=S0, K=K, r=r, T=T) if method == 'bisect': root, diff, iterations = bisect(0, partial_bsmvsact, None, [0, 2], [0.00001, 0.0001], 1000) n_calls = iterations elif method == 'newton': root, diff, iterations = newton(0, partial_bsmvsact, partial_vega, 1.0, 0, [0.00001, 0.0001], 1000) n_calls = 2 * iterations if root: if reportCalls: return root[-1], n_calls else: return root[-1] else: if reportCalls: return 'NaN', n_calls else: return 'NaN' else: return 'NaN'
def impliedVol(callput, price, S0, T, K, r, tolerence): def obejctFunc(x): return BS(callput, S0, K, T, r, x) if callput == "call" and (price > S0 or price < positivePart(S0 - K * np.exp(-r * T))): print "invalid call price" return float('nan') elif callput == "put" and (price < positivePart(K * np.exp(-r * T) - S0) or price > K * np.exp(-r * T)): print "invalid put price" print T, K, price return float('nan') start = 0.30 result = bisect(price, obejctFunc, start, None, tolerence) impVol = result[-1] return impVol
def bsimpvol(callput, S0, K, r, T, price, sigma, q=0, priceTolerance=0.01, method='bisect', reportCalls=False): def targetfunction(x): return bsformula(callput, S0, K, r, T, x, q)[0] def getReturnData(_impVol, _calls): if (reportCalls): return (_impVol, _calls) else: return _impVol if (isNoVolatilityCanBeFound(callput, price, S0, K, T)): return getReturnData(float('NaN'), 0) impvol = float('NaN') calls = 0 if (method == "bisect"): start = 0.50 result = bisect(price, targetfunction, start, None, [priceTolerance, priceTolerance]) impvol = result[-1] calls = len(result) elif (method == "newton"): result = newtonsMethod(callput, S0, K, r, T, q, price, sigma, priceTolerance) impvol = result[0] calls = result[1] else: result = secantMethodBS(price, targetfunction, callput, S0, K, r, T, q, priceTolerance) impvol = result[0] calls = result[1] return getReturnData(impvol, calls)
def bsimpvol(callput, S0, K, r, T, price, q=0., priceTolerance=0.01, method='bisect'): """ :param callput: Indicates if the option is a Call or Put option :param S0: Stock price :param K: Strike price :param r: Risk-free rate :param T: Time to expiration :param price: Price of option :param q: Dividend rate :param priceTolerance: The precision of the solution :param method: Specifies if Bisection method or Newton's method is to be used :return: Implied Volatility """ sigma = 0.5 def targetfunction(x): return bsformula(callput, S0, K, r, T, x, q)[0] if (isnan(S0) or isnan(K) or isnan(r) or isnan(T) or isnan(price)): return float('NaN') if ((callput == 1 and price < (S0 - K)) or (callput == -1 and price < (K - S0))): return float('NaN') if method == 'newton': sigma_est = newton(callput, S0, K, r, T, q, price, sigma, priceTolerance) if method == 'bisect': sigma_est = (bisect(price, targetfunction, start=0.5, tols=[priceTolerance, priceTolerance]))[0] return sigma_est
def bsimpvol(callput, S0, K, r, T, price, q=0, priceTolerance=0.01, init=0, max_iter=100, method='bisect'): ''' :param callput:judgement for option :param S0:intial value of the underlying :param K:the strike price :param r:interest rate :param T:time to maturity :param price:theoretical price under BS formula :param q:continuous return rate on the underlying :param priceTolerance:criterion to stop the process :param method:judgement to use bisect method or newton method :return:implied volatility and iteration ''' sigma = init #np.random.random() results = [] def f(x): return bsformula(callput, S0, K, r, T, x, q)[0] - price if method == 'bisect': results = bisect(0, f, None, [0.001, 1.0], [priceTolerance, priceTolerance], max_iter) else: def f_prime(x): return bsformula(callput, S0, K, r, T, x, q)[2] results = newton(f, f_prime, sigma, priceTolerance, max_iter) return results