Source code for copul.family.frechet.rho_d_upper_boundary

# upper_boundary.py
import sympy

from copul.family.frechet.frechet import Frechet


[docs] class RhoDUpperBoundary(Frechet): r""" One-parameter family attaining the *upper* boundary of the (rho, D) region: C = alpha * M + (1 - alpha) * W, with alpha = (1 + rho)/2. Hence the independence weight is zero and beta = 1 - alpha = (1 - rho)/2. This family satisfies Spearman's rho(C) = rho. Parameters ---------- rho : sympy symbol or float in [-1, 1] Target Spearman's rho. Notes ----- We implement this as a Frechet subclass but expose only the single parameter 'rho'. Internally: alpha(rho) = (1 + rho)/2, beta(rho) = (1 - rho)/2. """ _rho = sympy.symbols("rho", real=True) params = [_rho] intervals = { "rho": sympy.Interval(-1, 1, left_open=False, right_open=False), } def __init__(self, *args, **kwargs): # Allow positional or keyword initialization: RhoDUpperBoundary(rho=0.2) or (0.2) if args and len(args) == 1: kwargs["rho"] = args[0] if "rho" in kwargs: self._rho = kwargs["rho"] # Remove to avoid Frechet.__init__ trying to treat it as alpha/beta del kwargs["rho"] super().__init__(**kwargs) def __call__(self, *args, **kwargs): # Functional style: obj(rho=...) returns a cloned instance with the new parameter if args and len(args) == 1: kwargs["rho"] = args[0] if "rho" in kwargs: new = sympy.deepcopy(self) if hasattr(sympy, "deepcopy") else None if new is None: import copy as _copy new = _copy.deepcopy(self) new._rho = kwargs["rho"] del kwargs["rho"] return new.__call__(**kwargs) return super().__call__(**kwargs) @property def rho(self): return self._rho @property def alpha(self): # alpha = (1 + rho)/2 return (1 + self._rho) / 2 @property def beta(self): # beta = (1 - rho)/2 return (1 - self._rho) / 2 @property def cdf(self): r""" C(u,v) = alpha * min(u,v) + (1 - alpha - beta) * u v + beta * max(u+v-1, 0) = alpha * M + beta * W (since 1 - alpha - beta = 0 in this family). """ frechet_upper = sympy.Min(self.u, self.v) frechet_lower = sympy.Max(self.u + self.v - 1, 0) a = self.alpha b = self.beta # Independence weight is identically zero. return self.CDFWrapper(a * frechet_upper + b * frechet_lower)
if __name__ == "__main__": copula = RhoDUpperBoundary()