# time to expiry (in years) tau = (t_end - t_now) / 252 # compute induced m-moneyness m_sandp = np.log(v_sandp_grid / k_strk) / np.sqrt(tau) # transition from delta-moneyness to m-moneyness parametrization sigma_tnow_m_tau, m_grid = implvol_delta2m_moneyness( np.array([sigma_delta_tnow.T]), tau_grid, delta_grid, y, tau, 13) # interpolate impied volatility surface sigma = interpolate.interp2d( m_grid, tau_grid, sigma_tnow_m_tau.reshape(tau_grid.shape[0], m_grid.shape[0])) sigma_tnow_m_sandp_tau = sigma(m_sandp, tau) #current Black-Scholes values of call option as the function of the underlying v_call_bsm_tnow_kstrk_tend = bsm_function(v_sandp_grid, y, sigma_tnow_m_sandp_tau, m_sandp, tau) # payoff of call option as the function of the underlying values v_call_tend_kstrk_tend = np.maximum(v_sandp_grid - k_strk, 0) # returns r_call_bsm_tnow = v_call_bsm_tnow_kstrk_tend / v_call_tnow_kstrk_tend - 1 r_call_tend = v_call_tend_kstrk_tend / v_call_tnow_kstrk_tend - 1 # - # ## Plots: # + # colors teal = [0.2344, 0.582, 0.5664] light_green_1 = [0.8398, 0.9141, 0.8125] light_green_2 = [0.4781, 0.6406, 0.4031] light_grey = [0.6, 0.6, 0.6]
zip(*[grid.flatten() for grid in np.meshgrid(*[tau_implvol, m_moneyness])])) # known values values = implvol_m_moneyness_3d[-1, :, :].flatten('F') # implied volatility (interpolated) impl_vol_tnow = \ interpolate.LinearNDInterpolator(points, values)(*np.r_[tau_option_tnow, moneyness_tnow]) impl_vol_tinit = \ interpolate.LinearNDInterpolator(points, values)(*np.r_[tau_option_tinit, moneyness_tinit]) # compute call option value by means of Black-Scholes-Merton formula v_call_tnow = bsm_function(s_tnow, y, impl_vol_tnow, moneyness_tnow, tau_option_tnow) v_call_tinit = bsm_function(s_tinit, y, impl_vol_tinit, moneyness_tinit, tau_option_tinit) # compute put option value by means of the put-call parity v_zcb_tnow = np.exp(-y * tau_option_tnow) v_put_tnow = v_call_tnow - s_tnow + k_strk * v_zcb_tnow v_zcb_tinit = np.exp(-y * tau_option_tinit) v_put_tinit = v_call_tinit - s_tinit + k_strk * v_zcb_tinit # store data d_implvol = log_implvol_m_moneyness_2d.shape[1] for d in np.arange(d_implvol): db_risk_drivers[d_ + d] = log_implvol_m_moneyness_2d[:, d] risk_drivers_names[d_ + d] = 'option_spx_logimplvol_mtau_' + str(d + 1)
r_bms = r_call[:, -1] - beta_bms * r_stock[:, -index] # FOD return of hedged portfolio r_fod = r_call[:, -1] - beta_fod * r_stock[:, -index] # ## [Step 5](https://www.arpm.co/lab/redirect.php?permalink=s_attribution_hedging-implementation-step05): Compute the Black-Scholes-Merton curve and payoff # + s = np.arange(600, 1801) # range of values for underlying l_ = len(s) bs_curve = np.zeros(l_) bs_payoff = np.zeros(l_) for l in range(l_): m = np.log(s[l] / k_strike) / np.sqrt(tau) # range of call option values bs_curve[l] = bsm_function(s[l], 0, sigma, m, tau) # range of the payoff values bs_payoff[l] = (s[l] - k_strike)*int(k_strike <= s[l]) +\ 0*int(k_strike >= s[l]) # current value of the call option m = np.log(v_stock_u[0, 0] / k_strike) / np.sqrt(tau) bs_curve_current = bsm_function(v_stock_u[0, 0], 0, sigma, m, tau) # - # ## Plots # + plt.style.use('arpm') lgray = [0.8, 0.8, 0.8] # light grey
values_oneday = logsigma_oneday[j, :, :].flatten('F') # interpolation moneyness_thor = min(max(mon_thor[j], min(m_moneyness)), max(m_moneyness)) moneyness_oneday = min(max(mon_oneday[j], min(m_moneyness)), max(m_moneyness)) # log-implied volatility at the horizon logsigma_interp[j] =\ interpolate.LinearNDInterpolator(points, values)(*np.r_[tau_opt_thor, moneyness_thor]) # log-implied volatility after one day logsigma_interp_oneday[j] =\ interpolate.LinearNDInterpolator(points, values_oneday)(*np.r_[tau_opt_oneday, moneyness_oneday]) # compute call option value by means of Black-Scholes-Merton formula v_call_thor = bsm_function(s_thor, y, np.exp(logsigma_interp), moneyness_thor, tau_opt_thor) v_call_oneday = bsm_function(s_oneday, y, np.exp(logsigma_interp_oneday), moneyness_oneday, tau_opt_oneday) # compute put option value using put-call parity v_zcb_thor = np.exp(-y * tau_opt_thor) v_put_thor = v_call_thor - s_thor + k_strk * v_zcb_thor v_zcb_oneday = np.exp(-y * tau_opt_oneday) v_put_oneday = v_call_oneday - s_oneday + k_strk * v_zcb_oneday # compute P&L of the call option pi_tnow_thor[:, n_stocks + 1] = v_call_thor - v_tnow[n_stocks + 1] pi_oneday[:, n_stocks + 1] = v_call_oneday - v_tnow[n_stocks + 1] # compute P&L of the put option pi_tnow_thor[:, n_stocks + 2] = v_put_thor - v_tnow[n_stocks + 2] pi_oneday[:, n_stocks + 2] = v_put_oneday - v_tnow[n_stocks + 2]