def test_value_at_risk_lognormal(self): mu, sigma = 0, 1 def f(x): return np.exp(x).T def VaR(p): return np.exp(mu + sigma * np.sqrt(2) * erfinv(2 * p - 1)) mean = np.exp(mu + sigma**2 / 2) def CVaR(p): return mean * stats.norm.cdf( (mu + sigma**2 - np.log(VaR(p))) / sigma) / (1 - p) weights = None alpha = 0.8 num_samples = int(1e6) samples = f(np.random.normal(0, 1, num_samples)) xx = np.sort(samples) empirical_VaR, __ = value_at_risk(xx, alpha, weights, samples_sorted=True) # print(VaR(alpha),empirical_VaR) assert np.allclose(VaR(alpha), empirical_VaR, 1e-2)
def conditional_value_at_risk_subgradient(samples, alpha, weights=None, samples_sorted=False): assert samples.ndim == 1 or samples.shape[1] == 1 samples = samples.squeeze() num_samples = samples.shape[0] if weights is None: weights = np.ones(num_samples) / num_samples assert np.allclose(weights.sum(), 1) assert weights.ndim == 1 or weights.shape[1] == 1 if not samples_sorted: II = np.argsort(samples) xx, ww = samples[II], weights[II] else: xx, ww = samples, weights VaR, index = value_at_risk(xx, alpha, ww, samples_sorted=True) grad = np.empty(num_samples) grad[:index] = 0 grad[index] = 1 / (1 - alpha) * (weights[:index + 1].sum() - alpha) grad[index + 1:] = 1 / (1 - alpha) * weights[index + 1:] if not samples_sorted: # grad is for sorted samples so revert to original ordering grad = grad[np.argsort(II)] return grad
def test_weighted_value_at_risk_normal(self): mu, sigma = 1, 1 # bias_mu,bias_sigma=1.0,1 bias_mu, bias_sigma = mu, sigma from scipy.special import erf def VaR(alpha): return stats.norm.ppf(alpha, loc=mu, scale=sigma) def CVaR(alpha): vals = 0.5 * mu vals -= 0.5*mu*erf((VaR(alpha)-mu)/(np.sqrt(2)*sigma)) -\ sigma*np.exp(-(mu-VaR(alpha))**2/(2*sigma**2))/np.sqrt(2*np.pi) vals /= (1 - alpha) return vals alpha = 0.8 print(CVaR(alpha), cvar_gaussian_variable(stats.norm(loc=mu, scale=sigma), alpha)) assert np.allclose( CVaR(alpha), cvar_gaussian_variable(stats.norm(loc=mu, scale=sigma), alpha)) num_samples = int(1e5) samples = np.random.normal(bias_mu, bias_sigma, num_samples) target_pdf_vals = stats.norm.pdf(samples, loc=mu, scale=sigma) bias_pdf_vals = stats.norm.pdf(samples, loc=bias_mu, scale=bias_sigma) II = np.where(bias_pdf_vals < np.finfo(float).eps)[0] assert np.all(target_pdf_vals[II] < np.finfo(float).eps) J = np.where(bias_pdf_vals >= np.finfo(float).eps)[0] weights = np.zeros_like(target_pdf_vals) weights[J] = target_pdf_vals[J] / bias_pdf_vals[J] weights /= weights.sum() empirical_VaR, __ = value_at_risk(samples, alpha, weights, samples_sorted=False) # print('VaR',VaR(alpha),empirical_VaR) assert np.allclose(VaR(alpha), empirical_VaR, rtol=1e-2) empirical_CVaR = conditional_value_at_risk(samples, alpha, weights) # print('CVaR',CVaR(alpha),empirical_CVaR) assert np.allclose(CVaR(alpha), empirical_CVaR, rtol=1e-2)
def test_value_at_risk_normal(self): weights = None alpha = 0.8 num_samples = int(1e2) samples = np.random.normal(0, 1, num_samples) # [np.random.permutation(num_samples)] samples = np.arange(1, num_samples + 1) # xx = np.sort(samples) # VaR,VaR_index = value_at_risk(xx,alpha,weights,samples_sorted=True) xx = samples VaR, VaR_index = value_at_risk(xx, alpha, weights, samples_sorted=False) sorted_index = int(np.ceil(alpha * num_samples) - 1) II = np.argsort(samples) index = II[sorted_index] print(index, VaR_index) assert np.allclose(VaR_index, index) assert np.allclose(VaR, xx[index])
def help_check_smooth_conditional_value_at_risk(self, smoother_type, eps, alpha): samples = np.linspace(-1, 1, 11) t = value_at_risk(samples, alpha)[0] x0 = np.hstack((samples, t))[:, None] errors = check_gradients( lambda xx: smooth_conditional_value_at_risk( smoother_type, eps, alpha, xx), lambda xx: smooth_conditional_value_at_risk_gradient( smoother_type, eps, alpha, xx), x0) assert errors.min() < 1e-6 weights = np.random.uniform(1, 2, samples.shape[0]) weights /= weights.sum() errors = check_gradients( lambda xx: smooth_conditional_value_at_risk( smoother_type, eps, alpha, xx, weights), lambda xx: smooth_conditional_value_at_risk_gradient( smoother_type, eps, alpha, xx, weights), x0) assert errors.min() < 1e-6
def plot_lognormal_example_exact_quantities( num_samples=int(2e5), plot=False, mu=0, sigma=1): num_vars = 1 if plot: assert num_samples <= 1e5 else: assert num_samples >= 1e4 f, f_cdf, f_pdf, VaR, CVaR, ssd, ssd_disutil = \ get_lognormal_example_exact_quantities(mu, sigma) from pyapprox.low_discrepancy_sequences import transformed_halton_sequence # samples = np.random.normal(mu,sigma,(num_vars,num_samples)) # values = f(samples)[:,0] samples = transformed_halton_sequence( [partial(stats.norm.ppf, loc=mu, scale=sigma)], num_vars, num_samples) values = f(samples)[:, 0] if plot: import matplotlib.pyplot as plt fig, axs = plt.subplots(1, 6, sharey=False, figsize=(16, 6)) # from pyapprox.density import EmpiricalCDF ygrid = np.linspace(-1, 5, 100) # ecdf = EmpiricalCDF(values) # axs[0].plot(ygrid,ecdf(ygrid),'-') axs[0].plot(ygrid, f_cdf(ygrid), '--') # axs[0].set_xlim(ygrid.min(),ygrid.max()) axs[0].set_title('CDF') # ecdf = EmpiricalCDF(-values) # axs[0].plot(-ygrid,ecdf(-ygrid),'-') ygrid = np.linspace(-1, 20, 100) # axs[1].hist(values,bins='auto',density=True) axs[1].plot(ygrid, f_pdf(ygrid), '--') axs[1].set_xlim(ygrid.min(), ygrid.max()) axs[1].set_title('PDF') pgrid = np.linspace(1e-2, 1 - 1e-2, 100) evar = np.array([value_at_risk(values, p)[0] for p in pgrid]) # print(np.linalg.norm(evar.squeeze()-VaR(pgrid),ord=np.inf)) if plot: axs[2].plot(pgrid, evar, '-') axs[2].plot(pgrid, VaR(pgrid), '--') axs[2].set_title('VaR') else: assert np.allclose(evar.squeeze(), VaR(pgrid), atol=2e-1) pgrid = np.linspace(1e-2, 1 - 1e-2, 100) ecvar = np.array([conditional_value_at_risk(values, y) for y in pgrid]) # print(np.linalg.norm(ecvar.squeeze()-CVaR(pgrid).squeeze(),ord=np.inf)) print(CVaR(0.8)) if plot: axs[3].plot(pgrid, ecvar, '-') axs[3].plot(pgrid, CVaR(pgrid), '--') axs[3].set_xlim(pgrid.min(), pgrid.max()) axs[3].set_title('CVaR') else: assert np.allclose(ecvar.squeeze(), CVaR(pgrid).squeeze(), rtol=4e-2) # ygrid = np.linspace(-1,10,100) ygrid = np.linspace(stats.lognorm.ppf(0.0, np.exp(mu), sigma), stats.lognorm.ppf(0.9, np.exp(mu), sigma), 101) essd = compute_conditional_expectations(ygrid, values, False) # print(np.linalg.norm(essd.squeeze()-ssd(ygrid),ord=np.inf)) if plot: axs[4].plot(ygrid, essd, '-') axs[4].plot(ygrid, ssd(ygrid), '--') axs[4].set_xlim(ygrid.min(), ygrid.max()) axs[4].set_title(r'$E[(\eta-Y)^+]$') axs[4].set_xlabel(r'$\eta$') else: assert np.allclose(essd.squeeze(), ssd(ygrid), atol=1e-3) # zoom into ygrid over high probability region of -Y ygrid = -ygrid[::-1] disutil_essd = compute_conditional_expectations(ygrid, values, True) assert np.allclose(disutil_essd, compute_conditional_expectations(ygrid, -values, False)) # print(np.linalg.norm(disutil_essd.squeeze()-ssd_disutil(ygrid),ord=np.inf)) if plot: axs[5].plot(ygrid, disutil_essd, '-', label='Empirical') axs[5].plot(ygrid, ssd_disutil(ygrid), '--', label='Exact') axs[5].set_xlim((ygrid).min(), (ygrid).max()) axs[5].set_title(r'$E[(\eta-(-Y))^+]$') axs[5].set_xlabel(r'$\eta$') axs[5].plot([0], [np.exp(mu + sigma**2 / 2)], 'o') axs[5].legend() plt.show() else: assert np.allclose(disutil_essd.squeeze(), ssd_disutil(ygrid), atol=1e-3)
def plot_truncated_lognormal_example_exact_quantities(num_samples=int(1e5), plot=False, mu=0, sigma=1): if plot: assert num_samples <= 1e5 lb, ub = -1, 3 f, f_cdf, f_pdf, VaR, CVaR, ssd, ssd_disutil = \ get_truncated_lognormal_example_exact_quantities(lb, ub, mu, sigma) # lb,ub passed to stats.truncnorm are defined for standard normal. # Adjust for mu and sigma using alpha, beta = (lb - mu) / sigma, (ub - mu) / sigma samples = stats.truncnorm.rvs(alpha, beta, mu, sigma, size=num_samples)[np.newaxis, :] values = f(samples)[:, 0] ygrid = np.linspace(np.exp(lb) - 1, np.exp(ub) * 1.1, 100) if plot: import matplotlib.pyplot as plt fig, axs = plt.subplots(1, 6, sharey=False, figsize=(16, 6)) from pyapprox.density import EmpiricalCDF ecdf = EmpiricalCDF(values) axs[0].plot(ygrid, ecdf(ygrid), '-') axs[0].plot(ygrid, f_cdf(ygrid), '--') axs[0].set_xlim(ygrid.min(), ygrid.max()) axs[0].set_title('CDF') if plot: ygrid = np.linspace(np.exp(lb) - 1, np.exp(ub) * 1.1, 100) axs[1].hist(values, bins='auto', density=True) axs[1].plot(ygrid, f_pdf(ygrid), '--') axs[1].set_xlim(ygrid.min(), ygrid.max()) axs[1].set_title('PDF') pgrid = np.linspace(0.01, 1 - 1e-2, 10) evar = np.array([value_at_risk(values, p)[0] for p in pgrid]).squeeze() if plot: axs[2].plot(pgrid, evar, '-') axs[2].plot(pgrid, VaR(pgrid), '--') axs[2].set_title('VaR') else: assert np.allclose(evar, VaR(pgrid), rtol=2e-2) pgrid = np.linspace(0, 1 - 1e-2, 100) ecvar = np.array([conditional_value_at_risk(values, p) for p in pgrid]) # CVaR for alpha=0 should be the mean assert np.allclose(ecvar[0], values.mean()) if plot: axs[3].plot(pgrid, ecvar, '-') axs[3].plot(pgrid, CVaR(pgrid), '--') axs[3].set_xlim(pgrid.min(), pgrid.max()) axs[3].set_title('CVaR') else: assert np.allclose(ecvar.squeeze(), CVaR(pgrid).squeeze(), rtol=1e-2) ygrid = np.linspace(np.exp(lb) - 10, np.exp(ub) + 1, 100) essd = compute_conditional_expectations(ygrid, values, False) if plot: axs[4].plot(ygrid, essd, '-') axs[4].plot(ygrid, ssd(ygrid), '--') axs[4].set_xlim(ygrid.min(), ygrid.max()) axs[4].set_title(r'$E[(\eta-Y)^+]$') axs[5].set_xlabel(r'$\eta$') else: assert np.allclose(essd.squeeze(), ssd(ygrid), rtol=2e-2) # zoom into ygrid over high probability region of -Y ygrid = -ygrid[::-1] disutil_essd = compute_conditional_expectations(ygrid, values, True) assert np.allclose(disutil_essd, compute_conditional_expectations(ygrid, -values, False)) # print(np.linalg.norm(disutil_essd.squeeze()-ssd_disutil(ygrid),ord=np.inf)) if plot: axs[5].plot(ygrid, disutil_essd, '-', label='Empirical') axs[5].plot(ygrid, ssd_disutil(ygrid), '--', label='Exact') axs[5].set_xlim(ygrid.min(), ygrid.max()) axs[5].set_title(r'$E[(\eta-(-Y))^+]$') axs[5].set_xlabel(r'$\eta$') axs[5].legend() plt.show()