def min_call(S1, S2, K, r, delta1, delta2, sigma1, sigma2, t, T, rho): tau = T - t sigma = sqrt(sigma1**2 + sigma2**2 - 2 * rho * sigma1 * sigma2) d = (log(S1 / S2) + (delta2 - delta1 + 0.5 * sigma**2) * tau) / (sigma * sqrt(tau)) y1 = D(S1, K, r, delta1, sigma1, t, T) y2 = D(S2, K, r, delta2, sigma2, t, T) rho1 = (sigma1 - sigma2 * rho) / sigma rho2 = (sigma2 - sigma1 * rho) / sigma mean1 = np.zeros(2) cov1 = np.array([[1, -rho1], [-rho1, 1]]) x1 = [y1, -d] N1 = multivariate_normal.cdf(x1, mean=mean1, cov=cov1) B1 = S1 * exp(-delta1 * tau) * N1 cov2 = np.array([[1, -rho2], [-rho2, 1]]) x2 = [y2, d - sigma * sqrt(tau)] N2 = multivariate_normal.cdf(x2, mean=mean1, cov=cov2) B2 = S2 * exp(-delta2 * tau) * N2 cov3 = np.array([[1, rho], [rho, 1]]) x3 = [y1 - sigma1 * sqrt(tau), y2 - sigma2 * sqrt(tau)] N3 = multivariate_normal.cdf(x3, mean=mean1, cov=cov3) B3 = K * exp(-r * tau) * N3 return B1 + B2 - B3
def RSO_call(S, H, K, r, delta, sigma, t, T1, T2): tau1 = T1 - t tau2 = T2 - t tau12 = T2 - T1 B1 = S * exp( -delta * tau1) * norm.cdf(-D(S, H, r, delta, sigma, t, T1)) * A( r, delta, sigma, tau12) tau2 = T2 - t rho = sqrt(tau1 / tau2) cov1 = np.array([[1, rho], [rho, 1]]) mean1 = np.array([0, 0]) x = np.array( [D(S, H, r, delta, sigma, t, T1), D(S, K, r, delta, sigma, t, T2)]) N2 = multivariate_normal.cdf(x, mean=mean1, cov=cov1) B2 = S * exp(-delta * tau2) * N2 y = np.array([ D(S, H, r, delta, sigma, t, T1) - sigma * sqrt(tau1), D(S, K, r, delta, sigma, t, T2) - sigma * sqrt(tau2) ]) N3 = multivariate_normal.cdf(y, mean=mean1, cov=cov1) B3 = K * exp(-r * tau2) * N3 return B1 + B2 - B3
def callMin2NoStrike(S0, S1, r, T, vol1, vol2, vol3): vol = [vol1, vol2, vol3] S = [S0, S1] cmin = 0 cmin += S[0] * multivariate_normal.cdf(x=d2Prime(1, 0, S, vol)) cmin += S[1] * multivariate_normal.cdf(x=d2Prime(0, 1, S, vol)) return cmin
def PP(S, K1, K2, r, delta, sigma, t, T1, T2, a, b, epsilon): S_star = reverse_BS_put(a, b, K2, r, delta, sigma, T1, T2, K1, epsilon) tau1 = T1 - t tau2 = T2 - t mean1 = np.array([0, 0]) rho = sqrt(tau1 / tau2) cov1 = np.array([[1, -rho], [-rho, 1]]) B1 = K1 * exp(-r * tau1) * norm.cdf( D(S, S_star, r, delta, sigma, t, T1) - sigma * sqrt(tau1)) x = [ D(S, S_star, r, delta, sigma, t, T1) - sigma * sqrt(tau1), -D(S, K2, r, delta, sigma, t, T2) + sigma * sqrt(tau2) ] N1 = multivariate_normal.cdf(x, mean=mean1, cov=cov1) B2 = K2 * exp(-r * tau2) * N1 y = [ D(S, S_star, r, delta, sigma, t, T1), -D(S, K2, r, delta, sigma, t, T2) ] N2 = multivariate_normal.cdf(y, mean=mean1, cov=cov1) B3 = S * exp(-delta * tau2) * N2 return B1 - B2 + B3
def CC(S, K1, K2, r, delta, sigma, t, T1, T2, a, b, epsilon): S_star = reverse_BS_call(a, b, K2, r, delta, sigma, T1, T2, K1, epsilon) print(S_star) tau1 = T1 - t tau2 = T2 - t tau12 = T2 - T1 mean1 = np.array([0, 0]) rho = sqrt(tau1 / tau2) cov1 = np.array([[1, rho], [rho, 1]]) x = [ D(S, S_star, r, delta, sigma, t, T1), D(S, K2, r, delta, sigma, t, T2) ] N1 = multivariate_normal.cdf(x, mean=mean1, cov=cov1) B1 = S * exp(-delta * tau2) * N1 y = [ D(S, S_star, r, delta, sigma, t, T1) - sigma * sqrt(tau1), D(S, K2, r, delta, sigma, t, T2) - sigma * sqrt(tau2) ] N2 = multivariate_normal.cdf(y, mean=mean1, cov=cov1) B2 = K2 * exp(-r * tau2) * N2 B3 = K1 * exp(-r * tau1) * norm.cdf( D(S, S_star, r, delta, sigma, t, T1) - sigma * sqrt(tau1)) return B1 - B2 - B3
def callMin2(S, K, r, T, corr1, corr2, corr3): cmin = 0 cmin += S[0] * multivariate_normal.cdf( x=np.array([d2Prime(1, 0), d1(0)]), cov=corr1) cmin += S[1] * multivariate_normal.cdf( x=np.array([d2Prime(0, 1), d1(1)]), cov=corr2) cmin -= K * np.exp(-r * T) * (multivariate_normal.cdf( x=np.array([d2(0), d2(1)]), cov=corr3)) return cmin
def callMax2(S, K, r, T, corr1, corr2, corr3): cmax = 0 cmax += S[0] * multivariate_normal.cdf( x=np.array([-d2Prime(1, 0), d1(0)]), cov=corr1) cmax += S[1] * multivariate_normal.cdf( x=np.array([-d2Prime(0, 1), d1(1)]), cov=corr2) cmax -= K * np.exp(-r * T) * ( 1 - multivariate_normal.cdf(x=np.array([-d2(0), -d2(1)]), cov=corr3)) return cmax
def __init__(self, prior, clutter, Dy, sy, alpha=1): # prior: mixed gaussian prior object # clutter: mixed gaussian prior object (models noise) # Dy: input diagram, given as an np.array where each entry are points in a PD # sy: covariance magnitude of stochastic kernel, given as a numeric # wscalars: components of w^y, given as a list # Qs: Q values from paper, given as a list # pmeans: posterior means, given as an np.array # psigmas: posterior sigmas, given as a list # alpha: alpha parameter from paper, given as a numeric self.prior = prior self.clutter = clutter self.Dy = np.array(Dy) self.sy = sy self.wscalars = [ self.prior.weights[i] * mvn.pdf(x=self.Dy[j], mean=self.prior.mus[i], cov=self.prior.sigmas[i] + self.sy) for i in range(len(self.prior.weights)) for j in range(len(self.Dy)) ] self.pmeans = [(self.prior.sigmas[i] * np.array(Dy[j]) + self.sy * np.array(self.prior.mus[i])) / (self.prior.sigmas[i] + self.sy) for i in range(len(self.prior.mus)) for j in range(len(self.Dy))] self.psigmas = [ (self.prior.sigmas[i] * self.sy) / (self.prior.sigmas[i] + self.sy) for i in range(len(self.prior.sigmas)) for j in range(len(self.Dy)) ] self.Qs = [ 1 - (mvn.cdf( [float('inf'), 0], mean=self.pmeans[i], cov=self.psigmas[i]) - mvn.cdf( [0, float('inf')], mean=self.pmeans[i], cov=self.psigmas[i])) + mvn.cdf([0, 0], mean=self.pmeans[i], cov=self.psigmas[i]) for i in range(len(self.pmeans)) ] self.alpha = alpha self.cluts = [self.clutter.eval(y) for y in self.Dy] * len(self.prior.mus) self.wQs = list(np.multiply(self.wscalars, self.Qs)) self.Csums = [ sum(self.wQs[i::(len(self.Dy))]) for i in range(0, len(self.Dy)) ] * len(self.prior.mus) # sum every len(prior.mus) entry self.Cs = [ w / (c + s) for w, c, s in zip(self.wscalars, self.cluts, self.Csums) ]
def cdf(self, X, Y): """ Predicts the conditional cumulative probability p(Y<=y|X=x). Requires the model to be fitted. Args: X: numpy array to be conditioned on - shape: (n_samples, n_dim_x) Y: numpy array of y targets - shape: (n_samples, n_dim_y) Returns: conditional cumulative probability p(Y<=y|X=x) - numpy array of shape (n_query_samples, ) """ assert self.fitted, "model must be fitted to compute likelihood score" assert hasattr( self, '_get_mixture_components' ), "cdf computation requires _get_mixture_components method" X, Y = self._handle_input_dimensionality(X, Y, fitting=False) weights, locs, scales = self._get_mixture_components(X) P = np.zeros(X.shape[0]) for i in range(X.shape[0]): for j in range(self.n_centers): P[i] += weights[i, j] * multivariate_normal.cdf( Y[i], mean=locs[i, j, :], cov=np.diag(scales[i, j, :])) return P
def func(correlation, x, target_probability): """The objective function to minimise.""" correlation_matrix = [[1, correlation], [correlation, 1]] probability = multivariate_normal.cdf(x, mean=[0, 0], cov=correlation_matrix) return abs(probability - target_probability)
def callMax2(S0, S1, K, r, T, corr, vol1, vol2, vol3): vol = [vol1, vol2, vol3] S = [S0, S1] corr1 = np.array([[1, rho(1, 2, 0, vol)], [rho(1, 2, 0, vol), 1]]) corr2 = np.array([[1, rho(0, 2, 1, vol)], [rho(0, 2, 1, vol), 1]]) corr3 = np.array([[1, corr], [corr, 1]]) cmax = 0 cmax += S[0] * multivariate_normal.cdf(x=np.array( [-d2Prime(1, 0, S, vol), d1(0, S, vol)]), cov=corr1) cmax += S[1] * multivariate_normal.cdf(x=np.array( [-d2Prime(0, 1, S, vol), d1(1, S, vol)]), cov=corr2) cmax -= K * np.exp(-r * T) * (1 - multivariate_normal.cdf( x=np.array([-d2(0, S, vol), -d2(1, S, vol)]), cov=corr3)) return cmax
def Gaussian( r=0, steps=200 ): # -1 <= r <=1 ; -1 for opposite, 1 for indep and 1 for perfect if r is 0: C = pi() return Copula(C.cdf, Gau, 0) if r is -1: C = W() return Copula(C.cdf, Gau, -1) if r is 1: C = M() return Copula(C.cdf, Gau, 1) x = np.linspace(0, 1, num=steps) xx, yy = np.meshgrid(x, x, indexing='ij') X = np.array([xx.flatten(), yy.flatten()]) cdf = mvn.cdf(norm.ppf(X.transpose()), mean=[0, 0], cov=[[1, r], [r, 1]]) cdf = cdf.reshape(steps, steps) cdf[0, ] = 0 cdf[:, 0] = 0 # Grounds C return Copula(cdf, Gau, r)
def EBV_reduction(cMu, newMvar, cMvar): cov_red = np.zeros(cMu.shape) for i in range(cov_red.shape[0]): cov_red[i] = mvn.cdf([l, l], mean=[cMu[i], cMu[i]], cov=np.array([[cMvar[i], cMvar[i] - newMvar[i]], [cMvar[i] - newMvar[i], cMvar[i]]])) return (cov_red)
def cdf(self, d): """ returns the cumulative distribution d = (U1, ..., Un) """ y = norm.ppf(d, 0, 1) return multivariate_normal.cdf(y, mean=None, cov=self.corrMatrix)
def CH(S, Kc, Kp, r, delta, sigma, t, T1, Tc, Tp, a, b, epsilon): S_star = reverse_call_put(a, b, Kc, Kp, r, delta, sigma, T1, Tc, Tp, epsilon) tauc = Tc - t taup = Tp - t tau1 = T1 - t mean1 = np.zeros(2) rhoc = sqrt(tau1 / tauc) rhop = sqrt(tau1 / taup) covc = np.array([[1, rhoc], [rhoc, 1]]) covp = np.array([[1, rhop], [rhop, 1]]) x = [ D(S, S_star, r, delta, sigma, t, T1), D(S, Kc, r, delta, sigma, t, Tc) ] N1 = multivariate_normal.cdf(x, mean=mean1, cov=covc) B1 = S * exp(-delta * tauc) * N1 y = [ D(S, S_star, r, delta, sigma, t, T1) - sigma * sqrt(tau1), D(S, Kc, r, delta, sigma, t, Tc) - sigma * sqrt(tauc) ] N2 = multivariate_normal.cdf(y, mean=mean1, cov=covc) B2 = Kc * exp(-r * tauc) * N2 z = [ -D(S, S_star, r, delta, sigma, t, T1) + sigma * sqrt(tau1), -D(S, Kp, r, delta, sigma, t, Tp) + sigma * sqrt(taup) ] N3 = multivariate_normal.cdf(z, mean=mean1, cov=covp) B3 = Kp * exp(-r * taup) * N3 m = [ -D(S, S_star, r, delta, sigma, t, T1), -D(S, Kp, r, delta, sigma, t, Tp) ] N4 = multivariate_normal.cdf(m, mean=mean1, cov=covp) B4 = S * exp(-delta * taup) * N4 return B1 - B2 + B3 - B4
def acquire(self, X: NDArray, surrogate: object, f_hat: float) -> NDArray: # Turn 1d vector into 1 x d vector if X.ndim < 2: X = X[np.newaxis, :] mu, std = surrogate.predict(X, return_std=True) if mu.ndim > 1: mu = mu[:, 0] # Avoid divide by zero error std += self.epsilon return multivariate_normal.cdf((mu - f_hat) / std)
def cdf(self, u, v, rho): """ returns the cumulative distribution d = (U1, ..., Un) """ y1 = norm.ppf(u, 0, 1) y2 = norm.ppf(v, 0, 1) return multivariate_normal.cdf((y1, y2), mean=None, cov=[[1, rho], [rho, 1]])
def cifar_10_classify_mvn(f, train_data, train_labels, ms, cov_matrices, p): #test = cifar_10_features(f) prob = [] for i in range(0, 10): mus = ms[i] idx = np.where(train_labels == i) cov_mat = cov_matrices[i] mv = mvn.cdf(f, mus, cov_mat) * (1 / 10) prob.append(mv) mx = max(prob) idx = prob.index(mx) return idx
def joint_cdf(self, data, mu=None): # The entire CDF is zero if at least one coordinate is 0 if self.family.lower() == "gaussian": if mu is None or mu.size == 0: raise ValueError( "You must provide a non-empty NumPy array for mu") dim = data.shape[1] num_dim = data.shape[0] cov = self.cov if cov is None: cov = skd.make_spd_matrix(dim) second_arr = [] for i in range(num_dim): second_arr.append(norm.ppf(self.cdf(data[i], mu[i]))) cdfs = np.array(second_arr) arr = multivariate_normal.cdf(cdfs.T, mean=mu, cov=cov) return arr elif self.family.lower() == "clayton": if mu is None or mu.size == 0: raise ValueError( "You must provide a non-empty NumPy array for mu") dim = data.shape[1] num_dim = data.shape[0] arr = np.zeros(dim) gau = 1e-3 for j in range(data.shape[0]): cdf = self.cdf(data[j], mu[j]) raised_to_power = [ np.maximum(x, gau)**-self.alpha for x in cdf ] # TODO: fix the zero-raised-to-negative-power issue arr = np.add(arr, raised_to_power) arr = 1 - num_dim + arr arr = np.maximum(arr, gau) # get rid of all the zero values pow = np.power(arr, (-1 / self.alpha)) neg_alpha = -1 / self.alpha return np.array([y**neg_alpha for y in arr]) elif self.family.lower() == "gumbel": dim = data.shape[1] num_dim = data.shape[0] arr = np.zeros(dim) for i in range(num_dim): cdf = self.cdf(data[i], mu[i]) u = [-np.log(u_i)**self.alpha for u_i in cdf] # log_u = np.array([(- np.log(x)) ** self.alpha for x in cdf]) arr = np.add(arr, u) arr = -(arr**(1 / self.alpha)) arr = np.exp(arr) return arr
def exceedance_probability(distribution: rv_continuous, n_samples: Optional[int] = None): """ Calculates the exceedance probability of a random variable following a continuous multivariate distribution. Exceedance probability: φ_i = p(∀j != i: x_i > x_j | x ~ ``distribution``). :param distribution: the continuous multivariate distribution. :param n_samples: the number of realization sampled from the distribution to approximate the exceedance probability. Default to ``None`` and numerical integration is used instead of Monte Carlo simulation. :return: the exceedance probability of a random variable following the continuous multivariate distribution. """ if n_samples is None: # Numerical integration from scipy.stats._multivariate import dirichlet_frozen, multivariate_normal_frozen if type(distribution) is multivariate_normal_frozen: # Speekenbrink, M., & Konstantinidis, E. (2015). Uncertainty and exploration in a restless bandit problem. # https://onlinelibrary.wiley.com/doi/pdf/10.1111/tops.12145: p. 4. distribution: multivariate_normal_frozen μ, Σ = distribution.mean, distribution.cov n = len(μ) φ = np.zeros(n) I = -np.eye(n - 1) for i in range(n): A = np.insert(I, i, 1, axis=1) φ[i] = (mvn.cdf(A @ μ, cov=A @ Σ @ A.T)) elif type(distribution) is dirichlet_frozen: # Soch, J. & Allefeld, C. (2016). Exceedance Probabilities for the Dirichlet Distribution. # https://arxiv.org/pdf/1611.01439.pdf: p. 361. distribution: dirichlet_frozen α = distribution.alpha n = len(α) γ = [gammaln(α[i]) for i in range(n)] def f(x, i): φ_i = 1 for j in range(n): if i != j: φ_i *= gammainc(α[j], x) return φ_i * exp((α[i] - 1) * log(x) - x - γ[i]) φ = [ integrate.quad(lambda x: f(x, i), 0, np.inf)[0] for i in range(n) ] else: raise NotImplementedError( 'Numerical integration not implemented for this distribution!') φ = np.array(φ) else: # Monte Carlo simulation samples = distribution.rvs(size=n_samples) φ = (samples == np.amax(samples, axis=1, keepdims=True)).sum(axis=0) return φ / φ.sum()
def get_bivargauss_cdf(vals, corr_coef): """ Computes cdf of a bivariate Gaussian distribution with mean zero, variance 1 and input correlation. Inputs: :param vals: arguments for bivariate cdf (μi, μj). :param corr_coef: correlation coefficient of biavariate Gaussian (Λij). Returns: :return: Φ2([μi, μj], Λij) """ cov = np.eye(2) cov[1, 0], cov[0, 1] = corr_coef, corr_coef cdf = mnorm.cdf(vals, mean=[0., 0.], cov=cov) return cdf
def RSO_put(S, H, K, r, delta, sigma, t, T1, T2): tau1 = T1 - t tau2 = T2 - t tau12 = T2 - T1 mean1 = np.zeros(2) rho = sqrt(tau1 / tau2) cov1 = np.array([[1, rho], [rho, 1]]) A_ptau12 = A_p(r, delta, sigma, tau12) B1 = S * exp(-delta * tau1) * norm.cdf(D(S, K, r, delta, sigma, t, T1)) * A_ptau12 x = [ -D(S, H, r, delta, sigma, t, T1) + sigma * sqrt(tau1), -D(S, K, r, delta, sigma, t, T2) + sigma * sqrt(tau2) ] N2 = multivariate_normal.cdf(x, mean=mean1, cov=cov1) B2 = K * exp(-r * tau2) * N2 y = [-D(S, H, r, delta, sigma, t, T1), -D(S, K, r, delta, sigma, t, T2)] N3 = multivariate_normal.cdf(y, mean=mean1, cov=cov1) B3 = S * exp(-delta * tau1) * N3 return B1 + B2 - B3
def prob_dg(self, vs, g_idx, xs, pdf_on=False, cdf_on=False, **kargs): ''' Args: vs: 2D array (num_vs, ndim) g_idx: integer index of an axis xs: scalar or 1D array(num_vs) or 2D array (num_xs, num_vs) Returns: pd: None or scalar or 1D array (num_xs), p(dg(v) = x(vi)) prob: None or scalar or 1D array (num_xs), P(dg(v) < x(vi)) ''' vs = np.atleast_2d(vs) dg_mean, dg_cov = self.posterior_dg(vs, g_idx) pd = mvnnorm.pdf(xs, dg_mean, dg_cov) if pdf_on else None prob = mvnnorm.cdf(xs, dg_mean, dg_cov) if pdf_on else None return pd, prob
def dV(x, eta, x0, y0, theta, periodic=False): """ x must be 1-d array (single point) or array of length d x0 must be k-d array y0 must be k-1 array or array of length k returns : vector of length d """ if len(x.shape) == 1: x = x.reshape((1, -1)) if len(y0.shape) == 1: y0 = y0.reshape((-1, 1)) assert len(x.shape) == 2 and x.shape[0] == 1 assert len(x0.shape) == 2 and x0.shape[1] == x.shape[1] assert len(y0.shape) == 2 and y0.shape[0] == x0.shape[0] and y0.shape[1] == 1 sigma = theta[5] if len(theta) == 6 else 0.0 E0 = np.eye(x0.shape[0]) x = x.reshape((1, -1)) # x is a single sample mu0 = theta[4] * np.ones(y0.shape) mi, Ci = get_moments(x, x0, y0, theta) # Kx0K00Inv = kernel(x, x0, theta).dot(np.linalg.inv(kernel(x0, x0, theta) + sigma ** 2 * E0)) K00Inv = np.linalg.inv(kernel(x0, x0, theta, periodic) + sigma ** 2 * E0) Kx0Grad = d_kernel(x, x0, theta, periodic) dCi = -2 * Kx0Grad.dot(K00Inv).dot(kernel(x0, x, theta, periodic)) dmi = Kx0Grad.dot(K00Inv).dot(y0 - mu0) # Ci must be positive semidefinite Ci = np.maximum(Ci, 0) # Phi = multivariate_normal.cdf(eta, mean=mi, cov=Ci, allow_singular=True) # N = multivariate_normal.pdf(eta, mean=mi, cov=Ci, allow_singular=True) out = dmi * multivariate_normal.cdf( eta, mi, Ci, allow_singular=True ) - 0.5 * dCi * multivariate_normal.pdf(eta, mi, Ci, allow_singular=True) assert len(out.shape) == 2 and out.shape[0] == x.shape[1] and out.shape[1] == 1 return out.flatten()
def V(x, eta, x0, y0, theta): """ Eq. (8) x must be 1-d array x0 must be k-d array y0 must be k-1 array rho must be an array of length S theta must be an array of length >= 4 """ x = x.reshape((1, -1)) # x is a single sample mi, Ci = get_moments(x, x0, y0, theta) Phi = multivariate_normal.cdf(eta, mean=mi, cov=Ci, allow_singular=True) N = multivariate_normal.pdf(eta, mean=mi, cov=Ci, allow_singular=True) return eta + (mi - eta) * Phi - Ci * N
def mvstdnormcdf(lower, cov): """integrate a multivariate gaussian on rectangular domain Parameters ---------- lower: array the lower bound of the rectangular region, vector of length d upper: array the upper bound of the rectangular region, vector of length d mu: array the average of the multivariate gaussian, vector of length d cov: array the covariance matrix, matrix of shape (d, d) """ n = len(lower) if n == 1: return 1 - multivariate_normal.cdf(lower, cov=cov) upper = [np.inf] * n lowinf = np.isneginf(lower) uppinf = np.isposinf(upper) infin = 2.0 * np.ones(n) np.putmask(infin, lowinf, 0) np.putmask(infin, uppinf, 1) np.putmask(infin, lowinf * uppinf, -1) correl = cov[np.tril_indices(n, -1)] options = {'abseps': 1e-20, 'maxpts': 6000 * n} error, cdfvalue, inform = kde.mvn.mvndst(lower, upper, infin, correl, **options) if inform: print('something wrong', inform, error) return cdfvalue
def __sample_gamma_hyperparameters(self): # Initial Condition X = np.array([self.a0, self.b0]) # Proposal Distribution Sigma sigma2_a = (self.prop_scale)**2 sigma2_b = (self.prop_scale)**2 # Proposal Distribution logQ = lambda z, mu, Sig: np.log( multivariate_normal.pdf(z, mean=mu, cov=Sig)) - np.log( multivariate_normal.cdf([0, 0], mean=-mu, cov=Sig)) # Target Distribution logP = lambda z, x: (z[0] - 1) * np.sum(np.log(x)) - z[1] * np.sum( x) - x.size * (np.log(gamma(z[0])) - z[0] * np.log(z[1])) # Step step_fail = True reject = True for ii in range(10): a0_prop = np.random.normal(self.a0, sigma2_a) b0_prop = np.random.normal(self.b0, sigma2_b) if (a0_prop >= 0) & (b0_prop >= 0): Y = np.array([a0_prop, b0_prop]) step_fail = False break if step_fail == False: Sigma = np.array([[sigma2_a, 0], [0, sigma2_b]]) ratio = np.exp( logP(Y, self.lambdas) - logP(X, self.lambdas) + logQ(X, Y, Sigma) - logQ(Y, X, Sigma)) A = min(1, ratio) if np.random.uniform() <= A: self.a0 = a0_prop self.b0 = b0_prop reject = False return reject, ratio
def _get_prob(rho, threshold1, threshold2): # 计算列联表的二元正态分布累计概率 len1 = len(threshold1) len2 = len(threshold2) p1 = norm.cdf(threshold1) p2 = norm.cdf(threshold2) threshold_pd = np.array(list(product(threshold1, threshold2))) bi = multivariate_normal.cdf(threshold_pd, cov=np.array([[1, rho], [rho, 1]])) if isinstance(bi, float): bi = np.array([[bi]]) else: bi.shape = len1, len2 bi = np.column_stack((np.zeros(len1), bi, p1)) temp = np.zeros(bi.shape[1]) temp[-1] = 1 temp[1:-1] = p2 bi = np.row_stack((np.zeros(bi.shape[1]), bi, temp)) pi = bi[1:, 1:] - bi[1:, :-1] - bi[:-1, 1:] + bi[:-1, :-1] pi[pi <= 0] = 1e-200 return pi
def sample_trunc(self): sigma = scpla.cho_solve(scpla.cho_factor(self.sigma_inv), np.eye(self.mean.shape[0])) # sigma = np.diag(np.diag(sigma)) rejection_sampling = False if self.use_rejection_sampling: cdf_u = multivariate_normal.cdf(self.bounds[1], self.mean, sigma, allow_singular=True) ### THIS IS NOT WORKING ### cdf_l = [ multivariate_normal.cdf(self.bounds[0], self.mean, sigma, allow_singular=True) ] # As long as there is a 5 percent chance that a sample from a regular normal is in the bounds, 200 rejection # sampling iterations have only a chance of 0.003% of failing if cdf_u - sum(cdf_l) >= 0.05: rejection_sampling = True if rejection_sampling: if LOG_LEVEL == "all": print("Rejection sampling") samples = self.sample_rejection(self.mean, sigma, self.bounds, self.min_mcmc_steps * self.ensemble_size, rejection_iters=200) self.act = None self.context_samples = np.reshape( samples, (self.min_mcmc_steps, self.ensemble_size, -1)) else: if LOG_LEVEL == "all": print("Sampling with MCMC") burn_in = 500 n_step = 100000 if self.act is not None: burn_in = 0 n_step = max(self.min_mcmc_steps + 1, 200 * self.act) chain, self.act = self.sample_mcmc( self.unnormalized_log_pdf, self.bounds, mcmc_burn_in=burn_in, mcmc_n_steps=n_step, ensemble_size=self.ensemble_size) self.context_samples = chain[ min(-self.min_mcmc_steps, int(-2 * self.act)):, :, :] self.context_samples_torch = torch.from_numpy(self.context_samples) # Generate a random permutation for sampling self.idxs = np.random.permutation( np.arange(np.prod(self.context_samples.shape[0:2]))) self.sample_count = 0
df2['loss'] = df2['portfolio'] - portfolio_init VaR = -df2['loss'].quantile(0.05) # VaR is positive # ==== Q3 ===== """ Yes, for the analytical solution of Q2-1, we have the joint distribution, so Prob = F(S1<log(S1*0.95/S), S2<log(S2*0.95<S2)). Likewise, we have the covariance matrix of log return and the weight of portfolio, so we can calculate analytical VaR. """ mu = -0.5 * T * np.array([sigma_S1**2, sigma_S2**2]) cov_matrix = T * np.array([ sigma_S1**2, rho * sigma_S1 * sigma_S2, rho * sigma_S1 * sigma_S2, sigma_S2 **2 ]).reshape(2, 2) Prob_analytical = multivariate_normal.cdf( [np.log(0.95), np.log(0.95)], mu, cov_matrix) # log(0.95 * S/ S) = log(0.95) S1_frac = S1_init / portfolio_init S2_frac = 10 * S2_init / portfolio_init frac_vec = np.array([S1_frac, S2_frac]) x = np.dot(cov_matrix, frac_vec.T) x = np.dot(frac_vec, x) log_ret_VaR = np.sqrt(x) * norm.ppf(0.05) VaR_analytical = -(np.exp(log_ret_VaR) * portfolio_init - portfolio_init ) # restore from return_VaR to price_VaR # ==== summarize solutions =====