Skip to main content

rcopula

Copula modelling in Python — a full-featured replication of R's copula package, verified against it numerically.

CI License: MIT

Status: pre-1.0, under active development. The API may change before 1.0.


Why this exists

R's copula package is the most complete copula toolkit in any language. Python's options are fragmented, and roughly 60–70% of R copula's statistical surface has no Python equivalent at all:

  • no multiplier-bootstrap goodness-of-fit anywhere;
  • no nested Archimedean copulas anywhere, because they need an exponentially tilted stable sampler that does not exist in NumPy, SciPy or any copula package;
  • no Khoudraji device, general rotation wrapper, or arbitrary-copula mixtures;
  • no Kendall distribution function K, no general Rosenblatt transform;
  • not one Python package returns standard errors for a fitted copula;
  • families missing under one API: Joe, AMH, Plackett, FGM, Marshall–Olkin, Galambos, Hüsler–Reiss, Tawn, t-EV, Fréchet bounds.

rcopula closes that gap, and proves it: every deterministic quantity is checked against fixtures generated by running the real R package — and separately against the definitions themselves, so agreeing with R cannot be mistaken for being right.

It also goes past R where the gap was worth closing:

  • time-varying copulas — Patton (2006) and score-driven (GAS) recursions, plus Engle's DCC for a correlation matrix that moves;
  • discrete and mixed margins — the exact inclusion-exclusion likelihood, with the identifiability caveat stated rather than buried;
  • vines — R/C/D, in pure NumPy;
  • automatic family selection, JSON serialization, and bootstrap confidence intervals with measured coverage.

What copulas are for

Sklar's theorem says any joint distribution splits cleanly into its margins and a copula that carries all the dependence. That separation is the whole point:

  • Model dependence and margins independently. Fit each margin however you like — a GARCH residual distribution, a kernel density, a fitted Gamma — then fit the dependence structure separately.
  • Dependence measures that don't lie. Kendall's τ and Spearman's ρ are invariant under monotone marginal transforms; Pearson correlation is not. Pearson also reports ~0 for strongly dependent pairs (e.g. y = x²).
  • Tail dependence. Gaussian dependence says extreme joint events are essentially impossible. Real markets disagree. A t or Clayton copula prices joint crashes correctly; a Gaussian one does not. This distinction is not cosmetic — it changes VaR materially.

Choosing a family

If your data look like… Use
Symmetric dependence, no joint extremes GaussianCopula
Symmetric dependence with joint extremes in both tails StudentCopula
Joint crashes but not joint booms (lower-tail dependence) ClaytonCopula
Joint booms but not joint crashes (upper-tail dependence) GumbelCopula, JoeCopula
Flexible middle, negative dependence allowed, no tail dependence FrankCopula
Weak dependence only (τ ∈ [−0.18, 0.33]) AMHCopula
Asymmetric tails KhoudrajiCopula, RotatedCopula
Block / hierarchical group structure NestedArchimedean
High-dimensional, pair-specific dependence VineCopula

Install

pip install rcopula

Quick start

import rcopula as rc
from scipy import stats

# Construct and sample
cop = rc.ClaytonCopula(theta=2.0, dim=3)
u = cop.rvs(1000, random_state=42)

cop.pdf(u)  # density
cop.cdf(u)  # distribution function
cop.tau()  # Kendall's tau  -> 0.5
cop.lambda_()  # TailDependence(lower=0.7071, upper=0.0)

# Calibrate from a target dependence
rc.GumbelCopula.from_tau(0.5)  # theta = 2.0

# Fit, with standard errors
res = rc.fit(rc.GumbelCopula(dim=2), u[:, :2], method="mpl")
print(res.summary())

# Attach margins (Sklar, second direction)
mv = rc.CopulaDistribution(
    cop, margins=[stats.norm(1, 2), stats.expon(scale=1 / 3), stats.gamma(2)]
)
x = mv.rvs(1000, random_state=0)

# Goodness of fit
rc.gof_test(rc.ClaytonCopula(dim=3), x, simulation="mult")

Datasets

Nothing is bundled: R copula's datasets are GPL-3 and this package is MIT, so copying them in would be a licence conflict. Instead the loader ships URLs, licences and SHA-256 digests, and fetches permissively-licensed sources on first use.

flood = rc.datasets.load("nwis_peaks")  # USGS, public domain
wine = rc.datasets.load("uci_wine_quality_red")  # UCI, CC BY 4.0
flood.attrs["citation"]

Five sources: USGS annual peak flows and NOAA GHCN-Daily (both live endpoints, so unpinnable), and three static UCI tables — abalone, red wine quality and NASA aerofoil self-noise — whose SHA-256 is checked on every fetch. A test asserts no data file is ever committed.

Examples

Twenty-seven scripts in examples/, each of which runs and asserts its own claims — so they cannot drift out of date without failing:

python examples/04_tail_dependence.py     # what tau does not tell you
python examples/13_hydrology_return_periods.py
pytest tests/test_examples.py             # run them all

They cover the R book chapters; applied finance (CDO tranches, basket and CMS spread options, pairs trading, copula-GARCH, operational risk); hydrology, climate compound extremes, structural reliability and survival analysis; the statistics and machine-learning uses (mutual information, robust covariance, synthetic data, conditional independence); vines; the nine diagnostic plots; time-varying dependence; count data; quasi-random sampling; Archimedean internals at d = 100; nested trees; and what rounding does to a rank statistic.

Coming from R?

The API is Pythonic (scipy/statsmodels verbs), but R's option strings are preserved so you can paste them across.

R rcopula
claytonCopula(2, dim = 3) rc.ClaytonCopula(theta=2, dim=3)
rCopula(n, cop) cop.rvs(n)
dCopula(u, cop) / pCopula(u, cop) cop.pdf(u) / cop.cdf(u)
tau(cop) / rho(cop) / lambda(cop) cop.tau() / cop.rho() / cop.lambda_()
iTau(claytonCopula(), 0.5) rc.ClaytonCopula.from_tau(0.5)
fitCopula(cop, u, method = "mpl") rc.fit(cop, u, method="mpl")
pobs(x) rc.pseudo_obs(x)
mvdc(cop, margins, paramMargins) rc.CopulaDistribution(cop, margins=[...])
fitMvdc(x, mvdc, start) rc.fit_joint(mv, x) — margins and copula together
cCopula(u, cop) rc.rosenblatt(cop, u)
gofCopula(cop, x, simulation = "mult") rc.gof_test(cop, x, simulation="mult")
gofT2stat(u1, u2) rc.gof_two_sample(x, y) — did the dependence change?
dependogram(x, d) rc.dependogram(x) — which subsets are dependent
rotCopula(cop, flip) rc.RotatedCopula(cop, flip) / rc.survival(cop)
khoudrajiCopula(c1, c2, shapes) rc.KhoudrajiCopula(c1, c2, shapes)
mixCopula(list(c1, c2), w) rc.MixtureCopula([c1, c2], w)
opower(cop, alpha) rc.opower(cop, alpha) — a second dial on the tails
margCopula(cop, keep) rc.marginal_copula(cop, [0, 3])
fitLambda(x) rc.fit_lambda(x) — tail dependence without a family
onacopula("G", C(1.5, , list(C(4, 1:3)))) rc.NestedArchimedean(rc.GumbelCopula(1.5), ...)
enacopula(u, cop, method = "etau") rc.fit_nested(structure, u)
(VineCopula::RVineStructureSelect) rc.fit_vine(u, structure="D")
retstable(n, V0, h, alpha) rcopula.special.stable.retstable(...)
pK(t, cop, d) / qK / dK / rK rc.kendall_cdf/ppf/pdf/rvs(cop, ...)
Kn(u, x) rc.kendall_empirical(x, u)
xvCopula(cop, x, k) rc.cross_validate(cop, x, k)
contour(cop, dCopula) / persp(...) rc.plots.contour(cop) / rc.plots.surface(cop)
pairsRosenblatt(...) rc.plots.pairs_rosenblatt(cop, u) — where a fit fails
(no equivalent) rc.select_copula(u) — rank every admissible family
(no equivalent) rc.plots.tail_concentration(u, [c1, c2]) — where families disagree
(no equivalent) rc.dynamic.fit_dynamic(u, cop) — Patton / GAS time-varying dependence
(no equivalent) rc.dynamic.fit_dcc(u) — Engle's dynamic conditional correlation
(no equivalent) rc.discrete.fit_discrete(x, cop, margins) — exact likelihood for counts
(no equivalent) rc.bootstrap.bootstrap_measure(u, "tau") — BCa intervals, n_jobs=
(no equivalent) rc.serialize.to_json(cop) — a model file you can read and diff
(no equivalent) rc.statarb.select_pairs(returns) — rank every pair, six criteria
(no equivalent) rc.statarb.select_partners(returns, "AAPL") — vine quadruples
rtrafo / inverse cCopula rc.inverse_rosenblatt(cop, z)
rAntitheticVariates rc.sampling.antithetic_rvs(cop, n)
rLatinHypercube rc.sampling.latin_hypercube_rvs(cop, n)
(qrng vignette) rc.sampling.quasi_rvs(cop, n) — Sobol/Halton through the copula
htrafo(u, cop) rc.htrafo(cop, u)

There is a vine copula tutorial that reproduces Aas et al. (2009) equation by equation — the D-vine and C-vine factorisations agree with the printed formulas to 2e-15, and the paper's count of "12 D-vines and 12 C-vines" in four dimensions is reproduced by enumeration.

The full translation table, an API reference, and the notes on where R is the less accurate side are in the documentation (make docs to read it locally).

How parity is verified

R's RNG cannot be matched bit-for-bit by NumPy, so verification splits in two:

  • Deterministic quantities — densities, CDFs, generators, Pickands functions, τ/ρ/λ, iTau/iRho, Rosenblatt transforms, the Kendall function, and every GoF statistic — must match R to ~1e-10.
  • RNG-dependent quantities — R's random draws are exported to CSV and fed into Python, making everything downstream deterministic. Fitted parameters must match to ~1e-6 and standard errors to ~1e-5. Only bootstrap p-values remain stochastic, and those are checked statistically.

Fixtures live in tests/golden/ and are committed, so CI needs no R. Regenerate with make golden. A published parity report lists every replicated function and its maximum observed deviation.

License and relationship to R copula

rcopula is MIT. R's copula is GPL-3. No R source code was translated into this project — every algorithm is implemented from its originating published paper, and the R package is used solely as a black-box test oracle. See NOTICE and CONTRIBUTING.md.

rcopula is not affiliated with or endorsed by the authors of the R copula package.

Metadata

Release files for rcopula 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for rcopula 0.1.0
File Size Uploaded Provenance
rcopula-0.1.0.tar.gz 1.6 MB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for rcopula 0.1.0
File Interpreter ABI Platform
rcopula-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 1.9 MB

Release files / rcopula-0.1.0.tar.gz

Download URL rcopula-0.1.0.tar.gz
Size 1.6 MB
Tags Source
SHA-256 checksum
How to use checksums
1d65f8640e7a3843b3d2c995fb119ce55119c9f9e39e234a3dad646c7d906031
BLAKE2b-256 checksum
How to use checksums
5c5fba2e7bb10eed7189bfeb03ab2773e6fba9b016faf7168e4fb4eebf091708
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.13

Release files / rcopula-0.1.0-py3-none-any.whl

Download URL rcopula-0.1.0-py3-none-any.whl
Size 297.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ebc2e8cb4854d496ad8c1a144ae946128486ae988046731e4d449d80fabf1993
BLAKE2b-256 checksum
How to use checksums
10df195c8f3080730a1cc8a1f840a592754e1b9d8bca4985e3e5229ea05f38db
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.13

Security for rcopula 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page