22# Copyright (C) 2018, 2019, 2020 Dominic O'Kane
33##############################################################################
44
5- from typing import Union
5+ from typing import Union , Any , Sequence , Optional , Tuple , List
66import matplotlib .pyplot as plt
77
88import numpy as np
5353
5454
5555@njit (fastmath = True , cache = True )
56- def _obj (params , * args ) :
56+ def _obj (params : np . ndarray , * args : Any ) -> float :
5757 """Return a value that is minimised when the ATM, MS and RR vols have
5858 been best fitted using the parametric volatility curve represented by
5959 params and specified by the vol_type_value. We fit at one time slice only.
@@ -89,17 +89,17 @@ def _obj(params, *args):
8989
9090
9191def _solve_to_horizon (
92- s ,
93- t ,
94- r ,
95- q ,
96- strikes ,
97- time_index ,
98- volatility_grid ,
99- vol_type_value ,
100- x_inits ,
101- fin_solver_type ,
102- ):
92+ s : float ,
93+ t : float ,
94+ r : float ,
95+ q : float ,
96+ strikes : Sequence [ float ] ,
97+ time_index : int ,
98+ volatility_grid : Union [ List [ Sequence [ float ]], np . ndarray ] ,
99+ vol_type_value : int ,
100+ x_inits : Sequence [ float ] ,
101+ fin_solver_type : Any ,
102+ ) -> np . ndarray :
103103
104104 ###########################################################################
105105 # Determine parameters of vol surface using minimisation
@@ -151,7 +151,13 @@ def _solve_to_horizon(
151151 cache = True ,
152152 fastmath = True ,
153153)
154- def vol_function (vol_function_type_value , params , f , k , t ):
154+ def vol_function (
155+ vol_function_type_value : int ,
156+ params : np .ndarray ,
157+ f : float ,
158+ k : float ,
159+ t : float
160+ ) -> float :
155161 """Return the volatility for a strike using a given polynomial
156162 interpolation following Section 3.9 of Iain Clark book."""
157163
@@ -187,7 +193,7 @@ def vol_function(vol_function_type_value, params, f, k, t):
187193
188194
189195@njit (cache = True , fastmath = True )
190- def _delta_fit (k , * args ) :
196+ def _delta_fit (k : float , * args : Any ) -> float :
191197 """This is the objective function used in the determination of the
192198 option implied strike which is computed in the class below. I map it into
193199 inverse normcdf space to avoid the flat slope of this function at low vol
@@ -220,16 +226,16 @@ def _delta_fit(k, *args):
220226# @njit(float64(float64, float64, float64, float64, int64, int64, float64,
221227# float64, float64[:]), fastmath=True)
222228def _solver_for_smile_strike (
223- s ,
224- t ,
225- r ,
226- q ,
227- opt_type_value ,
228- vol_type_value ,
229- delta_target ,
230- initial_guess ,
231- parameters ,
232- ):
229+ s : float ,
230+ t : float ,
231+ r : float ,
232+ q : float ,
233+ opt_type_value : int ,
234+ vol_type_value : int ,
235+ delta_target : float ,
236+ initial_guess : float ,
237+ parameters : np . ndarray ,
238+ ) -> float :
233239 """Solve for the strike that sets the delta of the option equal to the
234240 target value of delta allowing the volatility to be a function of the
235241 strike."""
@@ -269,12 +275,12 @@ def __init__(
269275 stock_price : float ,
270276 discount_curve : DiscountCurve ,
271277 dividend_curve : DiscountCurve ,
272- expiry_dts : list ,
273- strikes : Union [ list , np .ndarray ] ,
274- volatility_grid : Union [ list , np .ndarray ] ,
275- vol_func_type = VolFuncTypes .CLARK ,
276- fin_solver_type = FinSolverTypes .NELDER_MEAD ,
277- ):
278+ expiry_dts : List [ Date ] ,
279+ strikes : np .ndarray ,
280+ volatility_grid : np .ndarray ,
281+ vol_func_type : VolFuncTypes = VolFuncTypes .CLARK ,
282+ fin_solver_type : FinSolverTypes = FinSolverTypes .NELDER_MEAD ,
283+ ) -> None :
278284 """Create the EquitySurface object by passing in market vol data
279285 for a list of strikes and expiry dates."""
280286
@@ -310,7 +316,7 @@ def __init__(
310316
311317 ###########################################################################
312318
313- def vol_from_strike_dt (self , k , expiry_dt ) :
319+ def vol_from_strike_dt (self , k : float , expiry_dt : Date ) -> float :
314320 """Interpolates the Black-Scholes volatility from the volatility
315321 surface given call option strike and expiry date. Linear interpolation
316322 is done in variance space. The smile strikes at bracketed dates are
@@ -487,7 +493,12 @@ def vol_from_strike_dt(self, k, expiry_dt):
487493
488494 ####################################################################################
489495
490- def vol_from_delta_date (self , call_delta , expiry_dt , delta_method = None ):
496+ def vol_from_delta_date (
497+ self ,
498+ call_delta : float ,
499+ expiry_dt : Date ,
500+ delta_method = None ,
501+ ) -> Tuple [float , float ]:
491502 """Interpolates the Black-Scholes volatility from the volatility
492503 surface given a call option delta and expiry date. Linear interpolation
493504 is done in variance space. The smile strikes at bracketed dates are
@@ -600,7 +611,7 @@ def vol_from_delta_date(self, call_delta, expiry_dt, delta_method=None):
600611
601612 ####################################################################################
602613
603- def _build_vol_surface (self , fin_solver_type = FinSolverTypes .NELDER_MEAD ):
614+ def _build_vol_surface (self , fin_solver_type : Any = FinSolverTypes .NELDER_MEAD ) -> None :
604615 """Main function to construct the vol surface."""
605616
606617 s = self ._stock_price
@@ -702,7 +713,7 @@ def _build_vol_surface(self, fin_solver_type=FinSolverTypes.NELDER_MEAD):
702713
703714 ####################################################################################
704715
705- def check_calibration (self , verbose : bool ):
716+ def check_calibration (self , verbose : bool ) -> None :
706717 """Compare calibrated vol surface with market and output a report
707718 which sets out the quality of fit to the ATM and 10 and 25 delta market
708719 strangles and risk reversals."""
@@ -744,7 +755,12 @@ def check_calibration(self, verbose: bool):
744755
745756 ####################################################################################
746757
747- def implied_dbns (self , low_s , high_s , num_intervals ):
758+ def implied_dbns (
759+ self ,
760+ low_s : float ,
761+ high_s : float ,
762+ num_intervals : int
763+ ) -> List [FinDistribution ]:
748764 """Calculate the pdf for each tenor horizon. Returns a list of
749765 FinDistribution objects, one for each tenor horizon."""
750766
@@ -793,7 +809,7 @@ def implied_dbns(self, low_s, high_s, num_intervals):
793809
794810 ####################################################################################
795811
796- def plot_vol_curves (self ):
812+ def plot_vol_curves (self ) -> None :
797813 """Generates a plot of each of the vol discount implied by the market
798814 and fitted."""
799815
@@ -835,7 +851,7 @@ def plot_vol_curves(self):
835851
836852 ####################################################################################
837853
838- def __repr__ (self ):
854+ def __repr__ (self ) -> str :
839855 s = label_to_string ("OBJECT TYPE" , type (self ).__name__ )
840856 s += label_to_string ("VALUE DATE" , self .value_dt )
841857 s += label_to_string ("STOCK PRICE" , self ._stock_price )
@@ -853,7 +869,7 @@ def __repr__(self):
853869
854870 ####################################################################################
855871
856- def _print (self ):
872+ def _print (self ) -> None :
857873 """Print a list of the unadjusted coupon payment dates used in
858874 analytic calculations for the bond."""
859875 print (self )
0 commit comments