def plot_vars_and_means(asset, ax1, ax2): ''' Produces plots for upper left and upper right. ''' solver = option.SimpleLayeredMCOptionSolver(max_interval_length=.01, base_steps=10000, min_L=5) (price, means, variances, counts) = solver.solve_option_price(asset, True) for l, (m, v, c) in enumerate(zip(means, variances, counts)): print(l, m, v, c) # means and variances actually contain V(p(l) - p(l-1)) layer_means = np.array(means).cumsum() layer_vars = np.array(variances).cumsum() # take log of base 4, for plotting variances = [math.log(v, 4) for v in variances] layer_vars = [math.log(v, 4) for v in layer_vars] means = [math.log(abs(m), 4) for m in means] layer_means = [math.log(abs(m), 4) for m in layer_means] ax1.plot([1, 2, 3, 4, 5], layer_vars, marker='x', label="P_l") ax1.plot([2, 3, 4, 5], variances[1:], ls="--", marker='x', label="P_l - P_(l-1)") ax1.set_xlabel("l") ax1.set_ylabel("Log_M Variance") ax1.legend() ax2.plot([1, 2, 3, 4, 5], layer_means, marker='x', label="P_l") ax2.plot([2, 3, 4, 5], means[1:], ls="--", marker='x', label="P_l - P_(l-1)") ax2.set_xlabel("l") ax2.set_ylabel("Log_M |mean|") ax2.legend()
def create_hist(opt, n_trials=500, n_bins=20, interval=.005): exact_solver = option.AnalyticEuropeanStockOptionSolver() exact_sol = exact_solver.solve_option_price(opt) lower_bound = exact_sol - interval upper_bound = exact_sol + interval solver = option.SimpleLayeredMCOptionSolver(max_interval_length=interval, base_steps=1000) approx_sols = np.zeros((n_trials, 1)) in_bound_count = 0 for i in range(n_trials): approx_sol = solver.solve_option_price(opt, False) if lower_bound <= approx_sol <= upper_bound: in_bound_count += 1 approx_sols[i] = approx_sol mean, sigma = np.mean(approx_sols), np.std(approx_sols) conf_int = stats.norm.interval(.95, loc=mean, scale=sigma) fig, ax = plt.subplots() ax.hist(approx_sols, bins=50) ax.axvline(x=conf_int[0], color='r', ls='--', label='95% CI') ax.axvline(x=conf_int[1], color='r', ls='--') ax.axvline(x=lower_bound, color='g', ls='--', label='epsilon +/-%f' % interval) ax.axvline(x=upper_bound, color='g', ls='--') ax.set_xlabel("Option Price") ax.set_ylabel("Count") plt.legend(loc='upper right', bbox_to_anchor=(1.02, 1), borderaxespad=0) plt.title( "%i trials; Sample Empirical Var.%.2E\nNo. Samples in epsilon interval %i" % (n_trials, Decimal(np.var(approx_sols)), in_bound_count)) plt.show()
def plot_Npaths_for_epsilon(asset, ax3): epsilon_list = [.001, .0005, .0002, .0001] #epsilon_list = [.01, .005, .002, .001] def calc_comp_cost(counts, level_scaling_factor=4): C = counts[0] for l in range(1, len(counts)): C += counts[l] * (level_scaling_factor**l + level_scaling_factor**(l - 1)) return C cost_list = [] for i, e in enumerate(epsilon_list): print("NEW TRIAL") solver = option.SimpleLayeredMCOptionSolver(max_interval_length=e, base_steps=1000, min_L=3) (price, means, variances, counts) = solver.solve_option_price(asset, True) for l, (m, v, c) in enumerate(zip(means, variances, counts)): print(l, m, v, c) cost_list.append(calc_comp_cost(counts)) layers = [i for i in range(len(counts))] ax3.plot(layers, counts, ls="--", marker='x', label="e = %s" % e) ax3.set_yscale('log') ax3.set_xlabel("l") ax3.set_ylabel("N_l") ax3.legend(loc='upper right') ax4.plot(epsilon_list, cost_list, marker='x', label='MLMC') ax4.set_xlabel("epsilon") ax4.set_ylabel("Cost (total MC steps)") ax4.legend(loc='upper right')
def plot_numpaths(one_option, ax3, ax4, epsilon_list, str_solver_type): ''' Two lower graphs for simple layer solver or heuristic solver Args: str_solver_type (string): either "simple" or "heuristic" ''' # this is num steps * epsilon**2 ml_cost_list = [] naive_cost_list = [] for i, epsilon in enumerate(epsilon_list): print("NEW TRIAL") if str_solver_type == "simple": layer_solver = option.SimpleLayeredMCOptionSolver(epsilon) elif str_solver_type == "heuristic": layer_solver = option.HeuristicLayeredMCOptionSolver(epsilon) else: raise ValueError("type is 'simple' or 'heuristic'") (option_price, means, variances, counts) = layer_solver.solve_option_price(one_option, True) epsilon_scaled_cost = calc_total_numsteps(counts, layer_solver.level_scaling_factor) * epsilon**2 ml_cost_list.append(epsilon_scaled_cost) ax3.plot(range(len(counts)), counts, ls="--",marker='x',label="e = %s" % epsilon) naive_solver = option.NaiveMCOptionSolver(epsilon) option_value, pricer_stdev, n_paths, n_steps = naive_solver.solve_option_price(one_option, True) naive_cost_list.append(n_paths * n_steps * epsilon**2) ax3.set_yscale('log') ax3.set_xlabel("level") ax3.set_ylabel("N(l)") ax3.legend(loc='best') ax4.plot(epsilon_list, ml_cost_list, marker='x', label='MLMC') ax4.plot(epsilon_list, naive_cost_list, ls="--", marker='x', label='Std MC') ax4.set_xlabel("epsilon") ax4.set_ylabel("cost x square(epsilon)") ax4.legend(loc='best')
def main(): spot_1 = 100 vol_1 = 0.2 / (252**0.5) kappa_1 = 0.15 / (252**0.5) theta_1 = 0.25 / (252**0.5) gamma_1 = 0.1 / (252**0.5) spot_2 = 50 vol_2 = 0.4 / (252**0.5) kappa_2 = 0.35 / (252**0.5) theta_2 = 0.5 / (252**0.5) gamma_2 = 0.2 / (252**0.5) risk_free = 0.05 / 252 expiry = 100 is_call = True hvs_1 = stock.VariableVolatilityStock(spot_1, vol_1, kappa_1, theta_1, theta_1) hvs_2 = stock.VariableVolatilityStock(spot_2, vol_2, kappa_2, theta_2, theta_2) cvs_1 = stock.ConstantVolatilityStock(spot_1, vol_1) cvs_2 = stock.ConstantVolatilityStock(spot_2, vol_2) heston_swaption = option.EuropeanSwaption([hvs_1, hvs_2], risk_free, expiry, is_call) constvol_vanilla = option.EuropeanStockOption(cvs_1, risk_free, expiry, is_call, spot_1) heston_vanilla = option.EuropeanStockOption(hvs_1, risk_free, expiry, is_call, spot_1) ROOT_DIR = os.getcwd() # Case 1: simple layer solver, heston vol, swaption # filename = ROOT_DIR + '/figs/simple_layer_heston_swap' # fig, ((ax1,ax2), (ax3,ax4)) = plt.subplots(2,2) # epsilon = 2.0 # simple_layer_solver = option.SimpleLayeredMCOptionSolver(epsilon) # plot_log_var_mean(heston_swaption, simple_layer_solver, ax1, ax2) # epsilon_list = [5.0, 4.0, 3.0, 2.0, 1.0] # plot_numpaths(heston_swaption, ax3, ax4, epsilon_list, 'simple') # plt.tight_layout() # plt.savefig(filename) # Case 2: heuristic layer solver, heston vol, swaption # filename = ROOT_DIR + '/figs/heuristic_layer_heston_swap' # fig, ((ax1,ax2), (ax3,ax4)) = plt.subplots(2,2) # epsilon = 1.0 # heuristic_layer_solver = option.HeuristicLayeredMCOptionSolver(epsilon) # plot_log_var_mean(heston_swaption, heuristic_layer_solver, ax1, ax2) # epsilon_list = [4.0, 3.0, 2.0, 1.0, 0.5] # plot_numpaths(heston_swaption, ax3, ax4, epsilon_list, 'heuristic') # Case 3: simple layer solver, constant vol, vanilla call # filename = ROOT_DIR + '/figs/simple_layer_constvol_vanillacall' # fig, ((ax1,ax2), (ax3,ax4)) = plt.subplots(2,2) # epsilon = 0.1 # simple_layer_solver = option.SimpleLayeredMCOptionSolver(epsilon) # plot_log_var_mean(constvol_vanilla, simple_layer_solver, ax1, ax2) # epsilon_list = [0.5, 0.4, 0.3, 0.2, 0.1] # plot_numpaths(constvol_vanilla, ax3, ax4, epsilon_list, 'simple') # Case 4: simple layer solver, heston vol, vanilla call filename = ROOT_DIR + '/figs/simple_layer_heston_vanillacall' fig, ((ax1,ax2), (ax3,ax4)) = plt.subplots(2,2) epsilon = 0.5 simple_layer_solver = option.SimpleLayeredMCOptionSolver(epsilon) plot_log_var_mean(heston_vanilla, simple_layer_solver, ax1, ax2) epsilon_list = [2.5, 2.0, 1.5, 1.0, 0.5] plot_numpaths(heston_vanilla, ax3, ax4, epsilon_list, 'simple') plt.tight_layout() plt.savefig(filename) plt.show()