def CIR_call(t, S, T, K, **params): s = S - t U = T - S beta1 = beta_fun(**params) beta2 = (params['alpha'] + beta1) / params['sigma']**2 beta3 = 2 * beta1 / (np.exp(beta1*s) - 1) / params['sigma']**2 AU = A_func(U, beta1, **params) BU = B_func(U, beta1, **params) term = (AU - np.log(K)) / BU v1 = 2 * (beta2 + beta3 + BU) * term v2 = 2 * (beta2 + beta3) * term df = 4*params['alpha']*params['theta']/params['sigma']**2 nc_nominator = 2 * beta3**2 * params['X_0'] * np.exp(beta1*s) nc1 = nc_nominator / (beta2 + beta3 + BU) nc2 = nc_nominator / (beta2 + beta3) pi1 = ncx2.cdf(v1, df=df, nc=nc1) pi2 = ncx2.cdf(v2, df=df, nc=nc2) bond1 = simple_bond_pricer(t, T, **params) bond2 = simple_bond_pricer(t, S, **params) return pi1, pi2, (bond1 * pi1) - (K * bond2 * pi2)
def C(t, K): kappa = 2 * r / (sigma**2 * (1 - gamma) * (np.exp(2 * r * (1 - gamma) * t) - 1)) x = kappa * S0**(2 * (1 - gamma)) * np.exp(2 * r * (1 - gamma) * t) y = kappa * K**(2 * (1 - gamma)) return S0 * (1 - ncx2.cdf(y, z, x)) - K * np.exp(-r * t) * ncx2.cdf( x, z - 2, y)
def CEV_call(S0, t, K): kappa2 = 2 * annualized_rates[-1] / (sigma**2 * (1 - gamma) * (np.exp(2 * annualized_rates[-1] * (1 - gamma) * t) - 1)) x = kappa2 * S0**(2 * (1 - gamma)) * np.exp(2 * annualized_rates[-1] * (1 - gamma) * t) y = kappa2 * K**(2 * (1 - gamma)) return S0 * (1 - ncx2.cdf(y, z, x)) - K * np.exp( -annualized_rates[-1] * t) * ncx2.cdf(x, z - 2, y)
def calculate_option_value(V0, kappa, theta, sigma, zeta, T, r, K): ''' Calculation of European call option price in GL96 model. Parameters ========== V0 : float current volatility level kappa : float mean reversion factor theta : float long-run mean of volatility sigma : float volatility of volatility zeta : volatility risk premium T : float time-to-maturity r : float risk-free short rate K : float strike price of the option Returns ======= value : float net present value of volatility call option ''' D = np.exp(-r * T) # discount factor # variables alpha = kappa * theta beta = kappa + zeta gamma = 4 * beta / (sigma ** 2 * (1 - np.exp(-beta * T))) nu = 4 * alpha / sigma ** 2 lamb = gamma * np.exp(-beta * T) * V0 cx1 = 1 - ncx2.cdf(gamma * K, nu + 4, lamb) cx2 = 1 - ncx2.cdf(gamma * K, nu + 2, lamb) cx3 = 1 - ncx2.cdf(gamma * K, nu, lamb) # formula for European call price value = (D * np.exp(-beta * T) * V0 * cx1 + D * (alpha / beta) * (1 - np.exp(-beta * T)) * cx2 - D * K * cx3) return value
def getChiSq2(self, t, T,S, K): theta = np.sqrt(self.__kappa ** 2 + 2 * (self._sigma ** 2)) phi = 2 * theta / (self._sigma ** 2 * (np.exp(theta * (T - t)) - 1)) psi = (self.__kappa + theta) / (self._sigma ** 2) A, B = self.getA_B(T, S) r_star = np.log(A / K) / B x = 2 * r_star*(phi + psi) p = 4 * self.__kappa * self.__rbar / (self._sigma ** 2) q = 2 * (phi ** 2) * self._r0 * (np.exp(theta * (T - t))) / (phi + psi ) return ncx2.cdf(x, p, q)
def getChiSq2(self, t, T, S, K): theta = np.sqrt(self.__kappa**2 + 2 * (self._sigma**2)) phi = 2 * theta / (self._sigma**2 * (np.exp(theta * (T - t)) - 1)) psi = (self.__kappa + theta) / (self._sigma**2) A, B = self.getA_B(T, S) r_star = np.log(A / K) / B x = 2 * r_star * (phi + psi) p = 4 * self.__kappa * self.__rbar / (self._sigma**2) q = 2 * (phi**2) * self._r0 * (np.exp(theta * (T - t))) / (phi + psi) return ncx2.cdf(x, p, q)
def pchisq(q,df,ncp=0): """ Calculates the cumulative of the chi-square distribution """ from scipy.stats import chi2,ncx2 if ncp==0: result=chi2.cdf(x=q,df=df,loc=0,scale=1) else: result=ncx2.cdf(x=q,df=df,nc=ncp,loc=0,scale=1) return result
def calculate_option_value(V0, kappa, theta, sigma, zeta, T, r, K): ''' Calculation of European call option price in GL96 model. Parameters ========== V0 : float current volatility level kappa : float mean reversion factor theta : float long-run mean of volatility sigma : float volatility of volatility zeta : volatility risk premium T : float time-to-maturity r : float risk-free short rate K : float strike price of the option Returns ======= value : float net present value of volatility call option ''' D = np.exp(-r * T) # discount factor # variables alpha = kappa * theta beta = kappa + zeta gamma = 4 * beta / (sigma**2 * (1 - np.exp(-beta * T))) nu = 4 * alpha / sigma**2 lamb = gamma * np.exp(-beta * T) * V0 cx1 = 1 - ncx2.cdf(gamma * K, nu + 4, lamb) cx2 = 1 - ncx2.cdf(gamma * K, nu + 2, lamb) cx3 = 1 - ncx2.cdf(gamma * K, nu, lamb) # formula for European call price value = (D * np.exp(-beta * T) * V0 * cx1 + D * (alpha / beta) * (1 - np.exp(-beta * T)) * cx2 - D * K * cx3) return value
def logrank_test_power(arms, alpha, meds, N, T): K = arms hs = math.log(2) / meds lhs = np.log(hs) psi_2 = 0 for k in range(0, K): psi_2 = psi_2 + (N * (1 - math.exp(-hs[0, k] * T)) * (lhs[0, k] - np.mean(lhs))**2) chisq_cut = chi2.ppf(1 - alpha, K - 1) power = 1 - ncx2.cdf(chisq_cut, K - 1, psi_2) return power
def upper_tail_probability_noncentral_chisquare(mvn, A, t, **kwargs): """ Approximate the upper tail probability using the noncentral chi square approximation. Use the scipy implementation of ncx2. This is the method of liu tang zhang. https://doi.org/10.1016/j.csda.2009.11.025 """ tspecial, dof, noncentrality = compute_ncx2_params( t, mvn.mean, mvn.covariance, A) if noncentrality == 0.0: # If non-centrality is zero, we can just use the standard chi2 distribution. return 1.0 - chi2.cdf(tspecial, dof, loc=0, scale=1) else: return 1.0 - ncx2.cdf(tspecial, dof, noncentrality)
def predict_proba(self, X): X = torch.FloatTensor(X) if self.gpu: X = X.cuda() # Calculate the distances in a memory-efficient way. B = 10 all_dists = [] for i in range(0, len(X), B): all_dists.append((X[i:i + B].unsqueeze(1) - self.train_X).norm(dim=2).cpu().numpy()) all_dists = np.concatenate(all_dists, axis=0)**2 preds = [] for dists in all_dists: F_mat = ncx2.cdf(self.buckets[None] / self.sigma2, self.Xdim, dists[:, None] / self.sigma2) p_mat = np.concatenate( (F_mat[:, 1:] - F_mat[:, :-1], 1 - F_mat[:, -1:]), axis=1) psum = np.cumsum(p_mat[:, ::-1], axis=1)[:, ::-1] logpprod = np.cumsum(np.log(psum), axis=0) logpprod = np.maximum(logpprod, -999999) logpprod[np.isnan(logpprod)] = -999999 #Test cur_pred = np.zeros(2) knn_ps = [] for i, yi in enumerate(self.train_y): p = 0.0 for l in range(self.N_bucket): if (i == 0): term1 = 0.0 elif (l == self.N_bucket - 1): term1 = -999999 else: term1 = logpprod[i - 1, l + 1] term2 = logpprod[len(self.train_y) - 1, l] - logpprod[i, l] p_cur = p_mat[i, l] * np.exp(term1 + term2) p += p_cur knn_ps.append(p) cur_pred[yi] += p preds.append(cur_pred / sum(cur_pred)) # Normalize, due to numerical error return np.array(preds)
def prob_no_alarm_simple(self, d, astrat=None): """ Probability of no alarm under simple likelihood. Given by P(chi2_nk(mu) < -2(ln(d) + nk/2 ln(2pi) + k \sum_J ln(\sigma_j))) where mu is given by \sum_IJ (aij/sigma_j)^2 """ muhat = 0 param_contribution = -2 * (d + self.tau * len(self.positive_edges)/2.*np.log(2*np.pi) + self.tau*self.sumlogsigma ) for edge in self.positive_edges: muhat += np.sum(astrat[edge]**2) / float(self.sigmamat[edge])**2 if muhat > 0: p_no_alarm = ncx2.cdf(param_contribution, self.tau * len(self.positive_edges), muhat) if muhat ==0: p_no_alarm = chi2.cdf(param_contribution, self.tau * len(self.positive_edges)) return p_no_alarm
def chisq_test_power(alpha, pi_1, N): R = pi_1.shape[0] C = pi_1.shape[1] pi_0 = np.zeros((R, C)) w = 0 for r in range(0, R): for c in range(0, C): pi_0[r][c] = np.sum(pi_1[r]) * np.sum(pi_1[:, c]) w = w + (pi_1[r][c] - pi_0[r][c]) * (pi_1[r][c] - pi_0[r][c]) / pi_0[r][c] w = w * N chisq_cut = chi2.ppf(1 - alpha, (R - 1) * (C - 1)) power = 1 - ncx2.cdf(chisq_cut, (R - 1) * (C - 1), w) return power
def _compute_ppvals_33(self, pcurvetype="full"): family = self._df_results["family"].values df1, df2, stat, pvals, ncp33 = self._df_results[[ "df1", "df2", "stat", "p", "ncp33" ]].to_numpy().T if pcurvetype == "full": pthresh = .05 # Only keep p-values smaller than .05 propsig = 1 / 3 # Under 33% power, 1/3 of p-values should be lower than .05 else: pthresh = .025 # Only keep p-values smaller than .025 # We don't know which prop of p-values should be smaller than .025 under 33% power, so compute it propsig = 3 * self._compute_prop_lower_33(.025, family, df1, df2, pvals, ncp33) # We then stretch the ppval on the [0, 1] interval. pp_33_f = (1 / propsig) * (ncf.cdf(stat, df1, df2, ncp33) - (1 - propsig)) pp_33_chi = (1 / propsig) * (ncx2.cdf(stat, df1, ncp33) - (1 - propsig)) pp_33 = np.where(family == "F", pp_33_f, pp_33_chi) return np.array([ self._bound_pvals(pp) if p < pthresh else np.nan for (p, pp) in zip(pvals, pp_33) ])
#!usr/bin/python # -*- coding:utf-8 -*- # draw ROC curve and SNR \sim P_D for random phase detection case, signal detection plotting routine # Apache License: Version 2.0 # implementation of Marcum function : scipy.stats.ncx2 # Q(a,b)=1-ncx2.cdf(b^2,df=2,nc=a^2) from scipy.stats import ncx2 import numpy as np import matplotlib.pyplot as plt alpha = np.linspace(0.01, 0.99, 100) # a^2=r # r=1 P_D_1 = 1 - ncx2.cdf(-2 * np.log(alpha), df=2, nc=1) # r=1.5 P_D_2 = 1 - ncx2.cdf(-2 * np.log(alpha), df=2, nc=1.5) plt.plot(alpha, P_D_1, 'r', linewidth=3) plt.plot(alpha, P_D_2, 'b', linewidth=3) plt.xlabel('$\\alpha$') plt.ylabel('$P_D$', rotation='horizontal') plt.title('ROC curve') plt.savefig('ROC_random_phase.eps') plt.show() # next fix alpha draw r(dB) \sim P_D r = np.logspace(0.5, 1.9, 100)
def to_minimize(ncp): return math.fabs(beta - ncx2.cdf(x, df, ncp))
def equation(c, a, b, u): return 1 - ncx2.cdf(a, b, c) - u # page 13 step 7
def C_h(t,K): kappa = 2*r/(sigma**2*(2-beta)*(np.exp(r*(2-beta)*t)-1)) x = kappa*S0**(2-beta)*np.exp(r*(2-beta)*t) y = kappa*K**(2-beta) return S0*(1-(ncx2.cdf(2*y,zb,2*x)))-K*(1-(1-ncx2.cdf(2*x,zb-2,2*y)))*np.exp(-r*t)
def _chi2_approximation(df1, fcrit, noncen): prob = ncx2.cdf(x=fcrit, df=df1, nc=noncen) fmethod = Constants.FMETHOD_CHI2 return prob, fmethod
def calculate_rician_outage_probability(h, sigma_sqr, sigma_n_sqr, gamma_th, p_sig, antnum): lambda1 = np.square(np.linalg.norm(h)) / sigma_sqr a_sqr = 2 * lambda1 b_sqr = 2 * sigma_n_sqr * gamma_th / (sigma_sqr * p_sig) return ncx2.cdf(b_sqr, 2 * antnum, a_sqr)
def closed_form_call_price(t): '''Call option price under CEV with maturity t''' kappa = 2*risk_free_rate/(sigma_CEV**2*(1-gamma)*(np.exp(2*risk_free_rate*(1-gamma)*t)-1)) x = kappa*S0**(2*(1-gamma))*np.exp(2*risk_free_rate*(1-gamma)*t) y = kappa*K**(2*(1-gamma)) return S0*(1-ncx2.cdf(y,z,x))-K*np.exp(-risk_free_rate*t)*ncx2.cdf(x,z-2,y)
# Display the probability density function (``pdf``): x = np.linspace(ncx2.ppf(0.01, df, nc), ncx2.ppf(0.99, df, nc), 100) ax.plot(x, ncx2.pdf(x, df, nc), 'r-', lw=5, alpha=0.6, label='ncx2 pdf') # Alternatively, the distribution object can be called (as a function) # to fix the shape, location and scale parameters. This returns a "frozen" # RV object holding the given parameters fixed. # Freeze the distribution and display the frozen ``pdf``: rv = ncx2(df, nc) ax.plot(x, rv.pdf(x), 'k-', lw=2, label='frozen pdf') # Check accuracy of ``cdf`` and ``ppf``: vals = ncx2.ppf([0.001, 0.5, 0.999], df, nc) np.allclose([0.001, 0.5, 0.999], ncx2.cdf(vals, df, nc)) # True # Generate random numbers: r = ncx2.rvs(df, nc, size=1000) # And compare the histogram: ax.hist(r, density=True, histtype='stepfilled', alpha=0.2) ax.legend(loc='best', frameon=False) plt.show()
def Marcum_Q(a, b, order=1): k = 2 * order return 1 - ncx2.cdf(b**2, k, a**2)
def chisq(x, p, q): return ncx2.cdf(x, p, q)
def DistributionFunction(q, lambdaValues, mult=None, delta=None): """ Implements methods to compute the distribution function of a linear combination of quadratic forms in normal variables. This can be used if e.g. we have a test statistic which has distribution as a mixture of chi square distributions. Computes the probability of the distribution function to have a value greater than the given values i.e. the p-value of the distribution. We will use the approximation proposed by Liu et al. This approximate method which expresses the distribution function as a standard chi-square distribution function and then computes the p-value accordingly. Parameters ---------- q : Value at which the distribution function is to be evaluated. lambdaValues : A numpy array of the coefficients of the quadratic forms. mult : A numpy array of the multiplicities of the lambdaValues. Default is an array of ones. delta : A numpy array of non-centrality parameters. Default is an array of zeros. Returns ------- pval : numeric value of the Prob(Q > q). Example -------- >>> import numpy as np >>> from QuadFormsDistribution.quadforms import DistributionFun >>> q = 2 >>> lambdaValues = np.array([0.5,0.4,0.1]) >>> mult = np.array([1,2,1]) >>> delta = np.array([1,0.6,0.8]) >>> X = DistributionFun(q,lambdaValues, mult, delta) References ---------- [1] P. Duchesne, P. Lafaye de Micheaux, Computing the distribution of quadratic form : Further comparisons between the Liu-Tang-Zhanf approximation and exact methods, Computational Statistics and Data Analysis, Volume 54,(2010), 858-862. [2] H.Liu, Y.Tang, H.H. Zhang, A new chi-square approximation to the distribution of non-negative definite quadratic forms in non-certral normal variables. Computational Statistics and Data Analysis, Volume 53,(2009), 853-856. """ n = len(lambdaValues) if (mult == None): mult = np.ones(n) if (delta == None): delta = np.ones(n) if (len(mult) != n): print "Error : lambdaValues and mult should have same length." if (len(delta) != n): print "Error : lambdaValues and delta should have same length." # Compute Liu parameters. param1 = np.sum(lambdaValues.dot(mult)) + np.sum(lambdaValues.dot(delta)) param2 = np.sum((lambdaValues**2).dot(mult)) + 2*np.sum((lambdaValues**2).dot(delta)) param3 = np.sum((lambdaValues**3).dot(mult)) + 3*np.sum((lambdaValues**3).dot(delta)) param4 = np.sum((lambdaValues**4).dot(mult)) + 4*np.sum((lambdaValues**4).dot(delta)) alpha = param2**(1.5) s1 = float(param3)/alpha s2 = float(param4)/(param2**2) # mean and sd of the distribution. meanQ = param1 sigmaQ = math.sqrt(2*param2) # t-statistic tStar = float(q - meanQ)/sigmaQ if ((s1**2) > s2): a = 1/float(s1 - math.sqrt(s1**2 - s2)) delta = s1*(a**3) - (a**2) l = (a**2) - 2*delta else: a = 1/float(s1) delta = 0 l = (param2**3)/(param3**2) # mean and sd of the chi-square distribution. meanX = l + delta sigmaX = math.sqrt(2)*a # p-value approxChi2 = tStar*sigmaX + meanX if (delta != 0): pval = 1 - ncx2.cdf(approxChi2,l,delta) else: pval = 1 - chi2.cdf(approxChi2,l) return pval
F'fit, $df={df_fit:1.2f} \pm {df_err:1.2f}, nc={nc_fit:1.2f} \pm {nc_err:1.2f}$', linewidth=0.8) ax_cdf = ax.twinx() ax_cdf.set_ylabel('cdf') ax.set_xlim((0, 40)) ax.xaxis.set_major_locator(MultipleLocator(5)) ax.xaxis.set_minor_locator(MultipleLocator(1)) xlim = ax.get_xlim() ax_cdf.hist(random, density=True, bins=cum_bins, cumulative=True, histtype='step', color='black', linewidth=0.6) ax_cdf.plot(x, ncx2.cdf(x, df, nc), c='red', linewidth=0.8) cl_95 = ncx2.ppf(0.954, df, nc) cl_99 = ncx2.ppf(0.997, df, nc) ax_cdf.plot((cl_95, cl_95), (0, 1), c='black', linestyle='-.', linewidth=0.5) ax_cdf.plot((cl_99, cl_99), (0, 1), c='black', linestyle='--', linewidth=0.5) ax_cdf.set_ylim((0, 1)) ax_cdf.text(cl_95, 0.5, '$2\sigma$', rotation=90) ax_cdf.text(cl_99, 0.5, '$3\sigma$', rotation=90) # convert the actual data/random numbers into a pdf and cfd! # n, bins is the data and bin boundaries, respectively # works, but does not look so good! need improvement on optics data_rv = rv_histogram((n, bins)) fig_2 = plt.figure(2, dpi=150) ax_2 = fig_2.add_subplot(111) ax_2.xaxis.set_major_locator(MultipleLocator(5))