def test_swaption_price(): kappa = 0.03 swaption_expiry = 4 swap_maturity = 5 swap_freq = 0.5 initial_curve = LiborCurve.from_constant_rate(0.06) swap_pricer = SwapPricer(initial_curve, kappa=kappa) sigma_r = LinearLocalVolatility.from_const(swap_maturity, 0.4, 0.1, 0) piterbarg_approx = PiterbargExpectationApproximator(sigma_r, swap_pricer) swap = Swap(swaption_expiry, swap_maturity, swap_freq) displaced_diffusion = DisplacedDiffusionParameterApproximator(sigma_r, swap_pricer, swap, piterbarg_approx) coupon = swap_pricer.price(swap, 0, 0, 0) swaption = Swaption(swaption_expiry, coupon, swap) b_s = displaced_diffusion.calculate_bs lambda_s_bar, b_bar = calculate_vola_skew(swaption.expiry, displaced_diffusion.calculate_lambda_square, b_s) swaption_value, black_implied_vola = lognormalimpliedvola(swaption, swap_pricer, lambda_s_bar, b_bar) print(lambda_s_bar, b_bar) print(swaption_value, black_implied_vola)
def test_approx(): kappa = 0.03 initial_curve = LiborCurve.from_constant_rate(0.06) swap_pricer = SwapPricer(initial_curve, kappa=kappa) sigma_r = LinearLocalVolatility.from_const(15, 0.4, 0.06, 0.2) swaption_expiry = 4 swap = Swap(swaption_expiry, 5, 0.5) coupon = swap_pricer.price(swap, 0, 0, 0) swaption = Swaption(swaption_expiry, coupon, swap) xyapproximator = RungeKuttaApproxXY #xyapproximator = PitergargDiscreteXY for xyapproximator in [RungeKuttaApproxXY, PitergargDiscreteXY]: for k in [16]: grid_size = 2**k + 1 #xy_calculator = PitergargDiscreteXY(grid_size, swap_pricer, sigma_r, swap) xy_calculator = xyapproximator(grid_size, swap_pricer, sigma_r, swap) integration_approx = DiscreteParameterAveraging(grid_size, swap_pricer, sigma_r, swap, xy_calculator) lambda_avg, beta_avg = integration_approx.calculate_average_param() swaption_value, black_implied_vola = lognormalimpliedvola(swaption, swap_pricer, lambda_avg, beta_avg) print(lambda_avg, beta_avg) print(swaption_value, black_implied_vola)
def plot_model_vs_market_data(market_data, res, approximator): expiry = market_data["Expiry"].iloc[0] tenor = market_data["Tenor"].iloc[0] curve_rate = market_data["Rate"].iloc[0] kappa = 0.03 initial_curve = get_mock_yield_curve_const(rate=curve_rate) swap_pricer = SwapPricer(initial_curve, kappa) swaption_pricer = SwaptionPricer(swap_pricer) swap = Swap(expiry, expiry + tenor, frequency=0.5) atm_swap_price = swap_pricer.price(swap, 0, 0, 0) sigma_r = LinearLocalVolatility.from_const(int(swap.TN), res.x[0], curve_rate, res.x[1]) xy_calculator = approximator(grid_size, swap_pricer, sigma_r, swap) aprox_type = str(xy_calculator) integration_approx = DiscreteParameterAveraging(grid_size, swap_pricer, sigma_r, swap, xy_calculator) lambda_avg, beta_avg = integration_approx.calculate_average_param() moneyness_ls = [] market_implied_vola_ls = [] black_implied_vola_ls = [] swaption_value_fd_ls = [] for row_id, inp_data in market_data.iterrows(): expiry = inp_data["Expiry"] coupon = inp_data["moneyness"] + atm_swap_price if coupon < 0: continue swaption = Swaption(expiry, coupon, swap) market_implied_vola_ls.append(inp_data["implied black vola"]) swaption_value_fd = price_fd(swaption_pricer, sigma_r, swaption) swaption_value_fd_ls.append(swaption_value_fd) swaption_value, black_implied_vola = lognormalimpliedvola( swaption, swap_pricer, lambda_avg, beta_avg) black_implied_vola_ls.append(black_implied_vola) print(swaption_value_fd_ls) moneyness_ls.append(inp_data["moneyness"]) fig = plt.figure() plt.plot(moneyness_ls, market_implied_vola_ls, "g-x", label="Market data") plt.plot(moneyness_ls, black_implied_vola_ls, "r-x", label="Approximate solution") plt.plot(moneyness_ls, swaption_value_fd_ls, "b-x", label="Finite Difference repricing") plt.legend() return fig
def minimize_func(x): print("run minimize") lambda_param = x[0] beta_param = x[1] sigma_r = LinearLocalVolatility.from_const(int(swap.TN), lambda_param, curve_rate, beta_param) xy_calculator = XYApproximator(grid_size, swap_pricer, sigma_r, swap) integration_approx = DiscreteParameterAveraging( grid_size, swap_pricer, sigma_r, swap, xy_calculator) lambda_avg, beta_avg = integration_approx.calculate_average_param() error = 0 for row_id, inp_data in market_data.iterrows(): expiry = inp_data["Expiry"] coupon = inp_data["moneyness"] + atm_swap_price swaption = Swaption(expiry, coupon, swap) market_implied_vola = inp_data["implied black vola"] swaption_value, black_implied_vola = lognormalimpliedvola( swaption, swap_pricer, lambda_avg, beta_avg) error += (black_implied_vola - market_implied_vola)**2 return error
def calculate_swaption_prices(): output_path = os.path.join(output_data_raw_approx, date_timestamp, "result") output_file = os.path.join(output_path, "swaption_approximation.hdf") file_path = get_nonexistant_path(output_file) grid_size = 2**12 + 1 swap_freq = 0.5 curve_rate = 0.06 initial_curve = LiborCurve.from_constant_rate(curve_rate) kappa_grid = [0.03] vola_parameters = [(i, curve_rate, j) for i in [0.6, 0.8] for j in [0.05, 0.2]] vola_grid_df = pd.DataFrame(vola_parameters, columns=["lambda", "alpha", "beta"]) vola_grid_df = vola_grid_df.iloc[[0, 3]] #coupon_grid = [0, +0.0025, -0.0025, +0.005, -0.005, +0.01, -0.01, 0.015, -0.015, 0.02, -0.02, 0.025, -0.025] XYApproximator = PitergargDiscreteXY XYApproximator = RungeKuttaApproxXY swap_ls = [(20, 21)] coupon_grid = [0, +0.005, -0.005, +0.01, -0.01, 0.015, -0.015] #vola_grid_df = vola_grid_df.iloc[9:10] for swap_T0_TN in swap_ls: print(swap_T0_TN) T0, TN = swap_T0_TN for kappa in kappa_grid: swap_pricer = SwapPricer(initial_curve, kappa) swap = Swap(T0, TN, 1 / 2) for index, vola_grid_row in vola_grid_df.iterrows(): sigma_r = LinearLocalVolatility.from_const( swap.TN, vola_grid_row["lambda"], vola_grid_row["alpha"], vola_grid_row["beta"]) swap = Swap(T0, TN, swap_freq) atm_swap_price = swap_pricer.price(swap, 0, 0, 0) strike_grid = [ atm_swap_price + coupon for coupon in coupon_grid ] #strike_grid = [0.01, 0.015, 0.02, 0.025, 0.03] xy_calculator = XYApproximator(grid_size, swap_pricer, sigma_r, swap) integration_approx = DiscreteParameterAveraging( grid_size, swap_pricer, sigma_r, swap, xy_calculator) lambda_avg, beta_avg = integration_approx.calculate_average_param( ) for strike in strike_grid: swaption = Swaption(T0, strike, swap) swaption_value, black_implied_vola = lognormalimpliedvola( swaption, swap_pricer, lambda_avg, beta_avg) output_data = pd.DataFrame({ 'expiry': [T0], "maturity": [TN], "atm strike": atm_swap_price, "swaption_value": [swaption_value], "kappa": [kappa], "vola_lambda": [vola_grid_row["lambda"]], "vola_alpha": [vola_grid_row["alpha"]], "vola_beta": [vola_grid_row['beta']], "strike": [strike], 'moneyness': [strike - atm_swap_price], "curve_rate": [curve_rate], "implied_black_vola": [black_implied_vola], 'integration_grid': [grid_size], "xy_approximation": [str(xy_calculator)] }) try: all_output_data = pd.read_hdf(file_path, key="data") except: all_output_data = pd.DataFrame() all_output_data = pd.concat([all_output_data, output_data]) all_output_data.to_hdf(file_path, key="data", complevel=9)