def test_mc_rn_measure(): kappa = 0.3 rate = 0.04 initial_curve = get_mock_yield_curve_const(rate=rate) linear_local = LinearLocalVolatility.from_const(30, 0.1, 0.1, 0.1) number_samples = 400 number_steps = 100 t_horizon = 5 dt = t_horizon / number_steps x_simulator = ProcessSimulator(number_samples, number_steps, dt) local_volatility = linear_local res = x_simulator.simulate_xy(kappa=kappa, local_volatility=local_volatility) interest_rate = res.x + initial_curve.get_inst_forward(res.time_grid) bond_mc = np.exp(-np.trapz(interest_rate, res.time_grid)) avg_bond = np.mean(bond_mc) std_mc = np.std(bond_mc) / np.sqrt(number_samples) upper_bound = avg_bond + 3 * std_mc lower_bound = avg_bond - 3 * std_mc assert np.exp(-rate * t_horizon) > lower_bound and np.exp( -rate * t_horizon) < upper_bound
def test_runge_kutta_approx(): kappa = 0.3 t = 10 initial_curve = LiborCurve.from_constant_rate(0.06) swap_pricer = SwapPricer(initial_curve, kappa=kappa) sigma_r = LinearLocalVolatility.from_const(t, 0.4, 0.1, 0) swap = Swap(4, 5, 0.5) swap0 = swap_pricer.price(swap, 0, 0, 0) integration_grid_size = 2*10 + 1 rk_approx = RungeKuttaApproxXY(integration_grid_size, swap_pricer, sigma_r, swap) res = rk_approx.calculate_xy() piterbarg_approx = PiterbargExpectationApproximator(sigma_r, swap_pricer) time_grid = res.t xbar = [] ybar = [] for t in time_grid: ybar.append(piterbarg_approx.ybar_formula(t)) xbar.append(piterbarg_approx.xbar_formula(t, ybar[-1], swap, swap0, 0)) print("As")
def simulate_process(self, kappa: float, local_volatility: LinearLocalVolatility, random_numbers, chunk_sim=0): number_samples, number_time_steps = random_numbers.shape x = np.zeros(shape=(number_samples, number_time_steps + 1)) y = np.zeros(shape=(number_samples, number_time_steps + 1)) for i in np.arange(0, number_samples): print("Simulation: " + str(i + chunk_sim)) for j in np.arange(0, number_time_steps): t = self.dt * j eta = local_volatility.calculate_vola(t, x[i][j], y[i][j]) # mu_x = y[i][j] - kappa * x[i][j] # x[i][j + 1] = x[i][j] + mu_x * self.dt + eta * random_numbers[i][j] * np.sqrt(self.dt) # y[i][j + 1] = y[i][j] + (np.power(eta, 2) - 2 * kappa * y[i][j]) * self.dt x[i][j + 1] = x[i][j] + self.get_drift_x(kappa, y[i][j], x[i][j], eta, t) * self.dt + eta * \ random_numbers[i][j] y[i][j + 1] = y[i][j] + self.get_drift_y(eta, kappa, y[i][j]) * self.dt return x, y
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 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 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 test_mc_swaption(): swap_T0 = 1 swap_TN = 2 coupon = 0.062 frequency = 0.5 swap = Swap(swap_T0, swap_TN, frequency) kappa = 0.3 rate = 0.06 initial_curve = get_mock_yield_curve_const(rate=rate) x = np.arange(0, 31) y = np.ones(31) * 0.1 lambda_t = interp1d(x, y, kind='previous') alpha_t = interp1d(x, y, kind='previous') b_t = interp1d(x, y * 0, kind='previous') linear_local = LinearLocalVolatility(lambda_t, alpha_t, b_t) #linear_vola = local_volatility #linear_local = LinearLocalVolatility.from_const(30, 0.1, 0.1, 0.1) number_samples = 100 number_steps = 10 swap_pricer = SwapPricer(initial_curve, kappa=kappa) t_horizon = swap_T0 dt = t_horizon / number_steps x_simulator = ProcessSimulator(number_samples, number_steps, dt) local_volatility = linear_local res = x_simulator.simulate_xy(kappa=kappa, local_volatility=local_volatility) interest_rate = res.x + initial_curve.get_inst_forward(res.time_grid) swaption = Swaption(swap_T0, coupon, swap) swaption_pricer = SwaptionPricer(swap_pricer) swaption_fair = swaption_pricer.maturity_price(swaption, res.x[:, -1], res.y[:, -1]) swaption_mc = np.exp( -np.trapz(interest_rate, res.time_grid)) * swaption_fair exp_swaption_mc = np.mean(swaption_mc) upper_value = exp_swaption_mc + 3 * np.std(swaption_mc) / np.sqrt( number_samples) lower_value = exp_swaption_mc - 3 * np.std(swaption_mc) / np.sqrt( number_samples) print("Swaption mean: {:.4f}, lower: {:.4f}, upper: {:.4f}".format( exp_swaption_mc, lower_value, upper_value))
def test_mc_swaption_annuity(): swap_T0 = 1 swap_TN = 2 coupon = 0.062 frequency = 0.5 swap = Swap(swap_T0, swap_TN, frequency) random_number_generator_type = "sobol" random_number_generator_type = "normal" kappa = 0.3 rate = 0.06 initial_curve = get_mock_yield_curve_const(rate=rate) x = np.arange(0, 31) y = np.ones(31) * 0.1 lambda_t = interp1d(x, y, kind='previous') alpha_t = interp1d(x, y, kind='previous') b_t = interp1d(x, y * 0, kind='previous') linear_local = LinearLocalVolatility(lambda_t, alpha_t, b_t) # linear_vola = local_volatility # linear_local = LinearLocalVolatility.from_const(30, 0.1, 0.1, 0.1) number_samples = np.power(2, 12) number_steps = np.power(2, 7) swap_pricer = SwapPricer(initial_curve, kappa=kappa) t_horizon = swap_T0 dt = t_horizon / number_steps annuity_pricer = AnnuityPricer(swap_pricer.bond_pricer) x_simulator = ProcessSimulator(number_samples, number_steps, dt, random_number_generator_type, annuity_pricer) local_volatility = linear_local annuity = Annuity(swap.bond_list, frequency) res = x_simulator.simulate_xy(kappa=kappa, local_volatility=local_volatility, annuity_measure=annuity) swaption_pricer = SwaptionPricer(swap_pricer) swaption = Swaption(swap_T0, coupon, swap) res = monte_carlo_pricer_annuity(res, swaption, swaption_pricer) exp_swaption_mc = np.mean(res) upper_value = exp_swaption_mc + 3 * np.std(res) / np.sqrt(number_samples) lower_value = exp_swaption_mc - 3 * np.std(res) / np.sqrt(number_samples) fd_price = 0.002313 print("Swaption mean: {:.6f}, lower: {:.6f}, upper: {:.6f}".format( exp_swaption_mc, lower_value, upper_value))
def calculate_x_boundaries(y, kappa, maturity, volatility: LinearLocalVolatility): eta_square = volatility.calculate_vola(0, 0, 0) exp_x = y / kappa * (1 - np.exp(-kappa * maturity)) var_x = eta_square / (2 * kappa) * (1 - np.exp(-2 * kappa * maturity)) x_max = exp_x + 3 * np.sqrt(var_x) x_min = exp_x - 3 * np.sqrt(var_x) return x_min, x_max
def test_adi_swaption(): swaption_expiry = 1 swaption_maturity = 2 freq = 0.5 coupon = 0.062 rate = 0.06 initial_curve = get_mock_yield_curve_const(rate=rate) kappa = 0.3 swap_pricer = SwapPricer(initial_curve, kappa) swap = Swap(swaption_expiry, swaption_maturity, freq) swaption_pricer = SwaptionPricer(swap_pricer) swaption = Swaption(swaption_expiry, coupon, swap) x = np.arange(0, 31) y = np.ones(31) * 0.1 lambda_t = interp1d(x, y, kind='previous') alpha_t = interp1d(x, y, kind='previous') b_t = interp1d(x, y * 0, kind='previous') local_volatility = LinearLocalVolatility(lambda_t, alpha_t, b_t) #local_volatility = LinearLocalVolatility.from_const(30, 0.1, 0.1, 0.1) t_min = 0 t_max = swaption_expiry t_grid_size = 100 x_grid_size = 401 y_grid_size = 20 x_min, x_max = calculate_x_boundaries2(t_max, local_volatility, alpha=3) y_min, y_max = calculate_u_boundaries(t_max, kappa, local_volatility, alpha=3) mesher = Mesher2d() mesher.create_mesher_2d(t_min, t_max, t_grid_size, x_min, x_max, x_grid_size, y_min, y_max, y_grid_size) theta = 0.5 adi_runner = AdiRunner(theta, kappa, initial_curve, local_volatility, mesher) swaption_value0 = adi_runner.run_adi(swaption, swaption_pricer) x0 = extract_x0_result(swaption_value0, mesher.xgrid, mesher.ugrid) print("Swaption value at 0: ", x0)
def __init__(self, x, y, time_grid, number_samples, number_time_steps, kappa, local_volatility: LinearLocalVolatility, measure, random_number_generator_type, nr_scrambles): self.x = x self.y = y self.time_grid = time_grid self.number_samples = number_samples self.number_time_steps = number_time_steps self.kappa = kappa self.local_volatility = local_volatility self.x_bar = x.mean(axis=0) self.y_bar = y.mean(axis=0) self.n_scrambles = nr_scrambles self.x_std, self.x_error = self.calculate_std_error( x, self.n_scrambles) self.y_std, self.y_error = self.calculate_std_error( y, self.n_scrambles) self.measure = measure self.random_number_generator_type = random_number_generator_type self.meta_data = { 'time grid': self.time_grid, "kappa": kappa, "lambda": float(local_volatility.lambda_t(0)), 'beta': float(local_volatility.b_t(0)), "alpha": float(local_volatility.alpha_t(0)), "random_number_generator_type": random_number_generator_type } self.res = pd.DataFrame({ 'time grid': self.time_grid, "x bar mc": self.x_bar, "y bar mc": self.y_bar, "x std mc": self.x_std, "y std mc": self.y_std })
def test_adi_swaption2(): swaption_expiry = 5 swaption_maturity = 10 freq = 0.5 rate = 0.06 initial_curve = get_mock_yield_curve_const(rate=rate) kappa = 0.3 swap_pricer = SwapPricer(initial_curve, kappa) swap = Swap(swaption_expiry, swaption_maturity, freq) swaption_pricer = SwaptionPricer(swap_pricer) coupon = swap_pricer.price(swap, 0, 0, 0) swaption = Swaption(swaption_expiry, coupon, swap) local_volatility = LinearLocalVolatility.from_const(30, 0.5, 0.1, 0.2) #local_volatility = LinearLocalVolatility.from_const(30, 0.1, 0.1, 0.1) t_min = 0 t_max = swaption_expiry t_grid_size = 100 x_grid_size = 401 y_grid_size = 20 x_min, x_max = calculate_x_boundaries2(t_max, local_volatility, alpha=3) y_min, y_max = calculate_u_boundaries(t_max, kappa, local_volatility, alpha=3) mesher = Mesher2d() mesher.create_mesher_2d(t_min, t_max, t_grid_size, x_min, x_max, x_grid_size, y_min, y_max, y_grid_size) theta = 0.5 adi_runner = AdiRunner(theta, kappa, initial_curve, local_volatility, mesher) swaption_value0 = adi_runner.run_adi(swaption, swaption_pricer) x0 = extract_x0_result(swaption_value0, mesher.xgrid, mesher.ugrid) implied_vola = find_implied_black_vola(x0, swaption, swap_pricer, swap_pricer.bond_pricer) print("Swaption value at 0: ", x0, implied_vola)
def test_piterbarg_y_bar(): kappa = 0.001 t = 15 initial_curve = LiborCurve.from_constant_rate(0.06) swap_pricer = SwapPricer(initial_curve, kappa=kappa) sigma_r = LinearLocalVolatility.from_const(t, 0.1, 0.1, 0) piterbarg_approx = PiterbargExpectationApproximator(sigma_r, swap_pricer) y_bar_actual = piterbarg_approx.calculate_ybar(t) y_bar_expected = np.exp(-2*kappa*t)*(np.exp(2*kappa*t) - 1)/(2*kappa)*0.0001 np.testing.assert_approx_equal(y_bar_actual, y_bar_expected)
def test_linear_local_volatility_approximation(): kappa = 0.001 t = 15 initial_curve = LiborCurve.from_constant_rate(0.06) swap_pricer = SwapPricer(initial_curve, kappa=kappa) sigma_r = LinearLocalVolatility.from_const(t, 0.1, 0.1, 0) piterbarg_approx = PiterbargExpectationApproximator(sigma_r, swap_pricer) swap = Swap(4, 5, 0.5) displaced_diffusion = DisplacedDiffusionParameterApproximator(sigma_r, swap_pricer, swap, piterbarg_approx) pass
def test_piterbarg_ksi(): kappa = 0.001 t = 15 initial_curve = LiborCurve.from_constant_rate(0.06) swap_pricer = SwapPricer(initial_curve, kappa=kappa) sigma_r = LinearLocalVolatility.from_const(t, 0.5, 0.5, 0.2) piterbarg_approx = PiterbargExpectationApproximator(sigma_r, swap_pricer) swap = Swap(4, 5, 0.5) swap_value = swap_pricer.price(swap, 0.01717964, 0.0025, 0.04) ksi = piterbarg_approx.calculate_ksi(0.04, swap_value, swap) np.testing.assert_approx_equal(ksi, 0.01717964, significant=4)
def test_adi_bond(): maturity = 10 linear_local_volatility = LinearLocalVolatility.from_const( 30, 0.1, 0.1, 0.1) #linear_local_volatility = LinearLocalVolatility.from_const(30, 0.1, 0.1, 0) theta = 0.5 kappa = 0.3 initial_curve = get_mock_yield_curve_const(rate=0.06) t_min = 0 t_max = maturity t_grid_size = 200 x_grid_size = 201 y_grid_size = 20 x_min, x_max = calculate_x_boundaries2(t_max, linear_local_volatility, alpha=2.5) y_min, y_max = calculate_u_boundaries(t_max, kappa, linear_local_volatility, alpha=2.5) mesher = Mesher2d() mesher.create_mesher_2d(t_min, t_max, t_grid_size, x_min, x_max, x_grid_size, y_min, y_max, y_grid_size) adi_runner = AdiRunner(theta, kappa, initial_curve, linear_local_volatility, mesher) bond = Bond(maturity) bond_pricer = BondPricer(initial_curve, kappa) bond_t0 = adi_runner.run_adi(bond, bond_pricer) bond_xyt0 = extract_x0_result(bond_t0, adi_runner.mesher.xgrid, adi_runner.mesher.ugrid) actual = bond_pricer.price(bond, 0, 0, 0) np.testing.assert_approx_equal(bond_xyt0, actual)
def test_mc_annuity_measure(): kappa = 0.001 rate = 0.06 initial_curve = get_mock_yield_curve_const(rate=rate) linear_local = LinearLocalVolatility.from_const(30, 0.1, 0.1, 0.1) number_samples = 200 number_steps = 50 local_volatility = linear_local swap_T0 = 4 swap_TN = 5 frequency = 0.5 t_horizon = swap_T0 dt = t_horizon / number_steps bond_pricer = BondPricer(initial_curve, kappa) annuity_pricer = AnnuityPricer(bond_pricer) swap = Swap(swap_T0, swap_TN, frequency) annuity = Annuity(swap.bond_list, frequency) x_simulator = ProcessSimulator(number_samples, number_steps, dt, annuity_pricer=annuity_pricer) res = x_simulator.simulate_xy(kappa=kappa, local_volatility=local_volatility, annuity_measure=annuity) mc_price = annuity_pricer.annuity_price( 0, 0, 0, annuity) * 1 / annuity_pricer.annuity_price( t_horizon, res.x[:, -1], res.y[:, -1], annuity) avg_bond = np.mean(mc_price) std_mc = np.std(mc_price) / np.sqrt(number_samples) actual_price = np.exp(-rate * t_horizon) assert actual_price > avg_bond - 3 * std_mc and actual_price < avg_bond + 3 * std_mc
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 mc_swaption_report(): output_path = os.path.join(output_data_raw_monte_carlo, date_timestamp) output_file = os.path.join(output_path, "swaption_price_mc.hdf") file_path = get_nonexistant_path(output_file) #random_number_generator_type = "sobol" random_number_generator_type = "normal" curve_rate = 0.06 kappa_grid = [0.03] initial_curve = get_mock_yield_curve_const(rate=curve_rate) vola_parameters = [(i, curve_rate, j) for i in [0.05, 0.2, 0.4, 0.5] for j in [0.05, 0.1, 0.3, 0.7]] vola_parameters = [(i, curve_rate, j) for i in [0.4] for j in [0.3]] vola_grid_df = pd.DataFrame(vola_parameters, columns=["lambda", "alpha", "beta"]) 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] #vola_grid_df = vola_grid_df.iloc[[10]] number_paths = np.power(2, 15) number_time_steps = np.power(2, 11) swap_ls = [(1, 6), (5, 10), (10, 20), (20, 30), (25, 30)] swap_ls = [(5, 10), (10, 20), (20, 30)] swap_ls = [(5, 10)] #swap_ls = [(1, 11)] for number_paths in [np.power(2,12), np.power(2, 13), np.power(2, 14), np.power(2, 15), np.power(2, 16), np.power(2, 17)]: for swap_exp_mat in swap_ls: print("swap: ", swap_exp_mat) expiry, maturity = swap_exp_mat for kappa in kappa_grid: swap_pricer = SwapPricer(initial_curve, kappa) swaption_pricer = SwaptionPricer(swap_pricer) swap = Swap(expiry, maturity, 0.5) atm_swap_price = swap_pricer.price(swap, 0, 0, 0) strike_grid = [atm_swap_price+coupon for coupon in coupon_grid] for index, vola_grid_row in vola_grid_df.iterrows(): loca_vola = LinearLocalVolatility.from_const(maturity, vola_grid_row["lambda"], vola_grid_row["alpha"], vola_grid_row["beta"]) bond_measure = swap.bond_T0 process_simulator = ProcessSimulatorTerminalMeasure(number_paths, number_time_steps, expiry / number_time_steps, random_number_generator_type, bond_measure, swap_pricer.bond_pricer, nr_processes=6, n_scrambles=64) result_obj = process_simulator.simulate_xy(kappa, loca_vola, parallel_simulation=True) for strike in strike_grid: swaption = Swaption(expiry, strike, swap) swaption_value_paths = monte_carlo_pricer_terminal_measure(result_obj, swaption, swaption_pricer) last_mc_time = result_obj.time_grid[-1] # swaption_value_paths_cv = apply_control_variate(last_mc_time, result_obj.x[:,-1], result_obj.y[:,-1], # swaption_value_paths, swap.bond_TN, swap_pricer.bond_pricer, swap_pricer.initial_curve) swaption_value_paths_cv2 = apply_control_variate_annuity(last_mc_time, result_obj.x[:, -1], result_obj.y[:, -1], swaption_value_paths, swap.annuity, swap_pricer.annuity_pricer, swap_pricer.annuity_pricer.bond_pricer.initial_curve) swaption_value_mean = swaption_value_paths.mean() std, swaption_value_error = result_obj.calculate_std_error(swaption_value_paths, result_obj.n_scrambles) # swaption_value_mean_cv = swaption_value_paths_cv.mean() # std, swaption_value_error_cv = result_obj.calculate_std_error(swaption_value_paths_cv, result_obj.n_scrambles) swaption_value_mean_cv = swaption_value_paths_cv2.mean() std, swaption_value_error_cv = result_obj.calculate_std_error(swaption_value_paths_cv2, result_obj.n_scrambles) bond_pricer = swap_pricer.bond_pricer output_data = {"number_paths": number_paths, "number_time_steps": number_time_steps, "random_number_generator_type": random_number_generator_type, "expiry": expiry, "maturity": maturity, "strike": strike, "atm strike": atm_swap_price, "moneyness": strike-atm_swap_price, "vola_lambda": vola_grid_row["lambda"], "vola_alpha": vola_grid_row["alpha"], "vola_beta": vola_grid_row["beta"], "curve_rate": curve_rate, "kappa": kappa, "swaption value": swaption_value_mean, "swaption value error": swaption_value_error, "swaption value cv": swaption_value_mean_cv, "swaption value error cv": swaption_value_error_cv, "implied_vola": find_implied_black_vola(swaption_value_mean, swaption, swap_pricer, bond_pricer), "implied_vola_max": find_implied_black_vola(swaption_value_mean+swaption_value_error, swaption, swap_pricer, bond_pricer), "implied_vola_min": find_implied_black_vola(swaption_value_mean-swaption_value_error, swaption, swap_pricer, bond_pricer), "implied_vola_cv": find_implied_black_vola(swaption_value_mean_cv, swaption, swap_pricer, bond_pricer), "implied_vola_cv_max": find_implied_black_vola(swaption_value_mean_cv + swaption_value_error_cv, swaption, swap_pricer, bond_pricer), "implied_vola_cv_min": find_implied_black_vola(swaption_value_mean_cv - swaption_value_error_cv, swaption, swap_pricer, bond_pricer)} output_df_new = pd.DataFrame(output_data, index=[0]) try: ouput_df_old = pd.read_hdf(file_path, key="output_data") except: ouput_df_old = pd.DataFrame() output_df_new = pd.concat([ouput_df_old, output_df_new]) output_df_new.to_hdf(file_path, key="output_data", complevel=9)
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)
return exp_u, var_u def calculate_u_boundaries(maturity, kappa, volatility: LocalVolatility, alpha=5): exp_u, var_u = calculate_u_moments(maturity, kappa, volatility) # y cannot be negative u_min = -alpha * np.sqrt(var_u) u_max = +alpha * np.sqrt(var_u) return u_min, u_max if __name__ == "__main__": y = 0.0005 kappa = 0.3 maturity = 1 eta_square = 0.01**2 print(np.sqrt(eta_square * maturity) * 5) linear_local_vola = LinearLocalVolatility() print(calculate_x_boundaries( y, kappa, maturity, ))
def adi_bond_report(): output_path = os.path.join(output_data_raw_finite_difference, date_timestamp) curve_rate = 0.01 maturity_grid = [30] kappa_grid = [0.03] theta = 1 / 2 initial_curve = get_mock_yield_curve_const(rate=curve_rate) vola_parameters = [(i, curve_rate, j) for i in [0.05, 0.1, 0.2, 0.4] for j in [0.1, 0.3, 0.5, 0.7, 0.9]] vola_grid_df = pd.DataFrame(vola_parameters, columns=["lambda", "alpha", "beta"]) finite_difference_parameter = [(100, 150, 20), (300, 400, 80)] #finite_difference_parameter = [(100, 150, 20)] finite_difference_grid_df = pd.DataFrame( finite_difference_parameter, columns=["t_grid_size", "x_grid_size", "y_grid_size"]) output_path = get_nonexistant_path(output_path) vola_grid_df = vola_grid_df.loc[(vola_grid_df["lambda"] == 0.4) & (vola_grid_df["beta"] == 0.35)] for maturity in maturity_grid: for kappa in kappa_grid: bond = Bond(maturity) bond_pricer = BondPricer(initial_curve, kappa) for index, vola_grid_row in vola_grid_df.iterrows(): loca_vola = LinearLocalVolatility.from_const( maturity, vola_grid_row["lambda"], vola_grid_row["alpha"], vola_grid_row["beta"]) for index, finite_difference_grid_row in finite_difference_grid_df.iterrows( ): x_grid_size = finite_difference_grid_row["x_grid_size"] y_grid_size = finite_difference_grid_row["y_grid_size"] t_grid_size = finite_difference_grid_row["t_grid_size"] t_min = 0 t_max = maturity x_min, x_max = calculate_x_boundaries2(t_max, loca_vola, alpha=3) x_min, x_max = calculate_x_boundaries3(t_max, kappa, loca_vola, alpha=3) u_min, u_max = calculate_u_boundaries(t_max, kappa, loca_vola, alpha=4) mesher = Mesher2d() mesher.create_mesher_2d(t_min, t_max, t_grid_size, x_min, x_max, x_grid_size, u_min, u_max, y_grid_size) adi_runner = AdiRunner(theta, kappa, initial_curve, loca_vola, mesher) bond_t0 = pd.DataFrame( adi_runner.run_adi(bond, bond_pricer)) output_file = os.path.join(output_path, "bond_price_fd.hdf") file_path = get_nonexistant_path(output_file) meta_data = { "x_grid_size": int(x_grid_size), "y_grid_size": int(y_grid_size), "maturity": maturity, "t_grid_size": int(t_grid_size), "vola_lambda": vola_grid_row["lambda"], "vola_alpha": vola_grid_row["alpha"], "vola_beta": vola_grid_row["beta"], "curve_rate": curve_rate, "kappa": kappa } meta_data = pd.DataFrame(meta_data, index=[0]) bond_t0.to_hdf(file_path, key="data", complevel=5) meta_data.to_hdf(file_path, key="metadata", complevel=5) pd.DataFrame(mesher.xmesh).to_hdf(file_path, key='xmesh', complevel=5) pd.DataFrame(mesher.umesh).to_hdf(file_path, key='ymesh', complevel=5) pd.DataFrame(mesher.xgrid).to_hdf(file_path, key='xgrid', complevel=5) pd.DataFrame(mesher.ugrid).to_hdf(file_path, key='ygrid', complevel=5)
def adi_swaption_report(): output_path = os.path.join(output_data_raw_finite_difference, date_timestamp) curve_rate = 0.06 kappa_grid = [0.03] theta = 1/2 initial_curve = get_mock_yield_curve_const(rate=curve_rate) finite_difference_parameter = [(100, 150, 10), (400, 800, 60)] finite_difference_parameter = [(150, 200, 80)] #finite_difference_parameter = [(400, 800, 60)] #finite_difference_parameter = [(800, 1000, 100)] finite_difference_parameter = [(50, 100, 10), (100, 150, 20), (150, 200, 40), (200, 300, 60), (300, 400, 80)] finite_difference_parameter = [(400, 600, 100)] #finite_difference_parameter = [(600, 800, 120)] #finite_difference_parameter = [(100, 150, 20), (150, 200, 40), (300, 400, 80), (400, 600, 100)] #finite_difference_parameter = [ (400, 600, 100)] finite_difference_parameter = [(100, 150, 20), (150, 200, 40), (300, 400, 80), (400, 600, 100)] #finite_difference_parameter = [ (400, 600, 100)] finite_difference_parameter = [(300, 400, 80)] #finite_difference_parameter = [(150, 200, 40)] finite_difference_grid_df = pd.DataFrame(finite_difference_parameter, columns=["t_grid_size", "x_grid_size", "y_grid_size"]) output_path = get_nonexistant_path(output_path) 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"]) #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] #swap_ls = [(1, 6), (5, 10), (10, 20), (20, 30), (25, 30)] #swap_ls = [(1,6), (5, 10), (10,20)] swap_ls = [(20, 21)] coupon_grid = [0, +0.005, -0.005, +0.01, -0.01, 0.015, -0.015] #coupon_grid = [0] #coupon_grid = [0] #swap_ls = [(5, 10)] #finite_difference_grid_df = finite_difference_grid_df[:-1] vola_grid_df = vola_grid_df.iloc[[0, 3]] for swap_exp_mat in swap_ls: expiry, maturity = swap_exp_mat for kappa in kappa_grid: swap_pricer = SwapPricer(initial_curve, kappa) swaption_pricer = SwaptionPricer(swap_pricer) swap = Swap(expiry, maturity, 0.5) 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] for strike in strike_grid: swaption = Swaption(expiry, strike, swap) for index, vola_grid_row in vola_grid_df.iterrows(): loca_vola = LinearLocalVolatility.from_const(maturity, vola_grid_row["lambda"], vola_grid_row["alpha"], vola_grid_row["beta"]) for index, finite_difference_grid_row in finite_difference_grid_df.iterrows(): x_grid_size = finite_difference_grid_row["x_grid_size"] y_grid_size = finite_difference_grid_row["y_grid_size"] t_grid_size = finite_difference_grid_row["t_grid_size"] t_min = 0 t_max = expiry x_min, x_max = calculate_x_boundaries2(t_max, loca_vola, alpha=3) x_min, x_max = calculate_x_boundaries3(expiry, kappa, loca_vola, alpha=4) y_min, y_max = calculate_u_boundaries(t_max, kappa, loca_vola, alpha=4) mesher = Mesher2d() mesher.create_mesher_2d(t_min, t_max, t_grid_size, x_min, x_max, x_grid_size, y_min, y_max, y_grid_size) adi_runner = AdiRunner(theta, kappa, initial_curve, loca_vola, mesher) swaption_t0 = pd.DataFrame(adi_runner.run_adi(swaption, swaption_pricer)) output_file = os.path.join(output_path, "swaption_price_fd.hdf") file_path = get_nonexistant_path(output_file) swaption_t0_x0_y0 = extract_x0_result(swaption_t0.values, mesher.xgrid, mesher.ugrid) implied_black_vola = find_implied_black_vola(swaption_t0_x0_y0, swaption, swap_pricer, swap_pricer.bond_pricer) meta_data = {"expiry": expiry, "maturity": maturity, "strike": strike, "atm strike": atm_swap_price, "moneyness": strike - atm_swap_price, "x_grid_size": int(x_grid_size), "y_grid_size": int(y_grid_size), "t_grid_size": int(t_grid_size), "vola_lambda": vola_grid_row["lambda"], "vola_alpha": vola_grid_row["alpha"], "vola_beta": vola_grid_row["beta"], "curve_rate": curve_rate, "kappa": kappa, "swaption_value": swaption_t0_x0_y0, "implied_black_vola": implied_black_vola} meta_data = pd.DataFrame(meta_data, index=[0]) swaption_t0.to_hdf(file_path, key="data", complevel=5) meta_data.to_hdf(file_path, key="metadata", complevel=5) print(meta_data) pd.DataFrame(mesher.xmesh).to_hdf(file_path, key='xmesh', complevel=5) pd.DataFrame(mesher.umesh).to_hdf(file_path, key='ymesh', complevel=5) pd.DataFrame(mesher.xgrid).to_hdf(file_path, key='xgrid', complevel=5) pd.DataFrame(mesher.ugrid).to_hdf(file_path, key='ygrid', complevel=5)