Coverage for rivapy/pricing/analytics.py: 95%

19 statements  

« prev     ^ index     » next       coverage.py v7.8.2, created at 2025-06-05 14:27 +0000

1import math 

2from scipy.optimize import brentq 

3from scipy.stats import norm 

4from scipy.special import ndtr 

5import numpy as np 

6 

7 

8def compute_european_price_Buehler(strike:float, maturity:float, volatility:float, is_call: bool=True)->float: 

9 """Compute a call/put option price for the Buehler model (w.r.t. x-process), i.e. no dividends, rates etc. 

10 Args: 

11 strike (float): strike 

12 maturity (float): maturity 

13 volatility (float): volatility 

14 is_call (bool): if option is call or put 

15 Returns: 

16 float: Black-Scholes call price 

17 """ 

18 if maturity < 1E-12: 

19 return np.maximum(1.0 - strike, 0) 

20 sqrt_mat = math.sqrt(maturity) 

21 d1 = ( math.log( 1.0 / strike ) + 0.5*volatility*volatility*maturity ) / ( volatility * sqrt_mat) 

22 d2 = d1 - volatility * sqrt_mat 

23 #print(d1,d2) 

24 if is_call: 

25 return ndtr(d1) - strike * ndtr(d2) 

26 return -ndtr(-d1) + strike*ndtr(-d2) 

27 

28def compute_implied_vol_Buehler(strike: float, maturity:float, price:float, 

29 min_vol = 0.05, max_vol = 2.0, is_call=True, **kwargs)->float: 

30 """Computes the implied volatility for a given cal/putl price using brentq from scipy. It throws an exception if no implied vol can be determined. 

31 

32 Args: 

33 strike (float): [description] 

34 maturity (float): [description] 

35 price (float): [description] 

36 min_vol (float, optional): [description]. Defaults to 0.05. 

37 max_vol (float, optional): [description]. Defaults to 2.0. 

38 is_call (bool): if option is call or put 

39 

40 Returns: 

41 float: [description] 

42 """ 

43 def error(vol:float): 

44 result = price - compute_european_price_Buehler(strike, maturity, vol, is_call= is_call) 

45 return result 

46 return brentq(error,a=min_vol, b=max_vol, **kwargs)