diff --git a/pysabr/examples/discount_factors.csv b/pysabr/examples/discount_factors.csv deleted file mode 100755 index 80d21bb..0000000 --- a/pysabr/examples/discount_factors.csv +++ /dev/null @@ -1,18 +0,0 @@ -Option_expiry,Discount_factor -1D,0.999960557 -1W,0.999684723 -1M,0.998778948 -2M,0.997527403 -3M,0.996476323 -6M,0.992450051 -9M,0.988086652 -1Y,0.983539026 -1Y6M,0.974038489 -2Y,0.964215632 -3Y,0.94423346 -5Y,0.904792378 -7Y,0.865728899 -10Y,0.807429493 -15Y,0.716771459 -20Y,0.637459484 -30Y,0.509615334 diff --git a/pysabr/examples/option_expiries.csv b/pysabr/examples/option_expiries.csv new file mode 100755 index 0000000..f0323f9 --- /dev/null +++ b/pysabr/examples/option_expiries.csv @@ -0,0 +1,18 @@ +Option_expiry,Year_frac +1D,0.002739726 +1W,0.021917808 +1M,0.084931507 +2M,0.17260274 +3M,0.246575342 +6M,0.498630137 +9M,0.750684932 +1Y,1 +1Y6M,1.498630137 +2Y,2 +3Y,3.008219178 +5Y,5.002739726 +7Y,7.005479452 +10Y,10.00821918 +15Y,15.01369863 +20Y,20.01917808 +30Y,30.01917808 diff --git a/pysabr/tests/hagan_2002_lognormal_sabr/conftest.py b/pysabr/tests/hagan_2002_lognormal_sabr/conftest.py index 998a7ef..48d055b 100644 --- a/pysabr/tests/hagan_2002_lognormal_sabr/conftest.py +++ b/pysabr/tests/hagan_2002_lognormal_sabr/conftest.py @@ -1,7 +1,6 @@ import pytest import itertools import pandas as pd -from pysabr.helpers import year_frac_from_maturity_label # Path to vols, premiums and discount factors data @@ -19,13 +18,13 @@ df_premiums.sort_index(inplace=True) # Load discount factors -df_discount = pd.read_csv(PATH + 'discount_factors.csv') +df_option_expiries = pd.read_csv(PATH + 'option_expiries.csv') # Cartesian product of all expiries and tenors expiries = df_vols.index.levels[1] tenors = df_vols.columns all_points = list(itertools.product(*[expiries, tenors])) -# all_points = [('1Y', '10Y')] # for debugging +# all_points = [('1Y', '10Y'), ('1Y', '30Y'), ('9M', '10Y')] # for debugging all_points_ids = ["{} into {}".format(e, t) for e, t in all_points] @@ -41,12 +40,13 @@ def vol_cube(request): df_vols.loc[idx[:, option_expiry], swap_tenor]. reset_index(level=1, drop=True) ) - expiry_year_frac = year_frac_from_maturity_label(option_expiry) + # Option expiry year fraction + i = df_option_expiries.Option_expiry == option_expiry + expiry_year_frac = df_option_expiries.loc[i].Year_frac.values[0] + # expiry_year_frac = year_frac_from_maturity_label(option_expiry) vol_input = (p['Forward'], p['Shift'], expiry_year_frac, p['Normal_ATM_vol'], p['Beta'], p['Rho'], p['Volvol']) - # Discount factor - df = df_discount[ - df_discount['Option_expiry'] == '10Y'].Discount_factor.values[0] + # Target vols vols_target = df_premiums.loc[ idx['SLN_vol', option_expiry, :], swap_tenor @@ -56,4 +56,4 @@ def vol_cube(request): idx['Call', option_expiry, :], swap_tenor ].reset_index(level=[0, 1], drop=True) # Yields the tuple - yield (vol_input, df, vols_target, premiums_target) + yield (vol_input, vols_target, premiums_target) diff --git a/pysabr/tests/hagan_2002_lognormal_sabr/test_cube.py b/pysabr/tests/hagan_2002_lognormal_sabr/test_cube.py index 4f7e90b..666ce96 100644 --- a/pysabr/tests/hagan_2002_lognormal_sabr/test_cube.py +++ b/pysabr/tests/hagan_2002_lognormal_sabr/test_cube.py @@ -4,14 +4,14 @@ N = 1e9 # We assume BPV = $100,000 (= 1e9 / 1e4) -MAX_ABS_ERROR_PREMIUM = 0.1 # Max absolute error on premium is $0.1 +MAX_ABS_ERROR_PREMIUM = 10.0 # Max absolute error on premium is $10.0 MAX_ERROR_VOL = 0.0005 # Max error is 0.05% def test_vols(vol_cube): """Test the full ATM SABR vol chain for Hagan's 2002 Lognormal model.""" logging.debug(vol_cube) - (f, s, t, v_atm_n, beta, rho, volvol), _, vols_target, _ = vol_cube + (f, s, t, v_atm_n, beta, rho, volvol), vols_target, _ = vol_cube sabr = Hagan2002LognormalSABR(f/100, t, s/100, v_atm_n/1e4, beta, rho, volvol) strikes = vols_target.index @@ -21,7 +21,7 @@ def test_vols(vol_cube): def test_premiums(vol_cube): """Test the premiums.""" - (f, s, t, v_atm_n, beta, rho, volvol), df, _, premiums_target = vol_cube + (f, s, t, v_atm_n, beta, rho, volvol), _, premiums_target = vol_cube sabr = Hagan2002LognormalSABR(f/100, t, s/100, v_atm_n/1e4, beta, rho, volvol) strikes = premiums_target.index[premiums_target.index + s > 0.]