Skip to content

Equicorrelation Gaussian API

Equicorrelation Gaussian Copula

The equicorrelation model, its parameter range, and selection guidance are described in the Multivariate Models guide.

Usage

from pyscarcopula.copula.multivariate import EquicorrGaussianCopula

cop = EquicorrGaussianCopula(d=6)

# MLE (constant rho)
cop.fit(u, method='mle')

# SCAR (time-varying rho)
cop.fit(u, method='scar-tm-ou')

# GAS (observation-driven rho)
cop.fit(u, method='gas')

High-dimensional preparation

For data that is already expressed as pseudo-observations, prepare the two equicorrelation sufficient statistics without materializing a dense correlation matrix:

from pyscarcopula import EquicorrGaussianCopula

cop = EquicorrGaussianCopula(d=100_000)
prepared = cop.prepare_sufficient_statistics(
    u_batches,                 # ndarray, memmap, or iterable of 2D blocks
    batch_rows=256,
    dimension_tile=16_384,
    n_threads=4,               # omit for the unconditional one-thread default
)

prepared.save_npz("equicorr-statistics.npz")
prepared.save_mmap("equicorr-statistics-mmap")

mle_result = cop.fit(prepared, method="MLE")
gas_result = cop.fit(prepared, method="GAS")
scar_result = cop.fit(prepared, method="scar-tm-ou")

prepared is an immutable EquicorrPreparedData object containing only sum_z and sum_z2, two float64 vectors of length T. It does not retain the input matrix. The native reduction clips values with the library's pseudo-observation policy, evaluates each normal quantile once, and merges fixed dimension tiles in deterministic order. Results are therefore identical across supported thread counts for a fixed dimension_tile.

The mmap directory format stores each vector as a read-only .npy mapping; the .npz format is the compact portable option. Diagnostics report clipping, block/tile counts, the selected parallel axes, and peak temporary scalar storage.

This preparation API expects pseudo-observations and does not perform global ranking. MLE, GAS, and SCAR-TM-OU consume the prepared vectors directly; static row likelihood and emission-grid methods do the same. Existing ndarray inputs remain supported. Every Equicorr MLE result represents correlation by its scalar equicorrelation_rho and leaves correlation_matrix=None, avoiding an otherwise prohibitive d * d result allocation for both dense and prepared inputs.

Grid output can also be bounded explicitly. Both the density and gradient arrays count toward memory_budget_bytes:

for pdf_block, grad_block in cop.pdf_and_grad_on_grid_batches(
    prepared,
    x_grid,
    batch_rows=64,
    memory_budget_bytes=2 * 64 * len(x_grid) * 8,
    n_threads=4,
):
    consume(pdf_block, grad_block)

Goodness of fit

from pyscarcopula.stattests import gof_test
gof = gof_test(cop, u, to_pobs=False)

gof_bootstrap = gof_test(
    cop,
    u,
    to_pobs=False,
    bootstrap=True,
    n_bootstrap=499,
    n_jobs=-1,
    rng=20260730,
)

Parametric-bootstrap calibration is supported for static GaussianCopula and StudentCopula (dense and factor correlation representations), EquicorrGaussianCopula, and StochasticStudentCopula. Dynamic models retain their fitted MLE/GAS/SCAR-TM-OU strategy settings and correlation policy. Stochastic Student supports fixed, shrinkage, Cholesky, and two-stage factor correlation. Its factor Rosenblatt transform uses compact rank-dimensional conditioning for MLE, GAS, and SCAR-TM-OU without materializing a dense correlation matrix. Replicas use independent process-owned models and deterministic per-replication random streams. GAS/SCAR stochastic Student results with estimated correlation must be paired with their fitted model, because the result object alone does not store the full fitted correlation.

Sampling

samples = cop.predict(n=10000)
samples = cop.sample(n=10000)
parameter_samples = cop.sample_at_parameter(n=10000, r=0.5)

# Bounded-memory unconditional generation, including negative rho:
for block in cop.sample_at_parameter_batches(
    n=1_000_000, r=-1e-6, batch_rows=128
):
    consume(block)

# Bounded output from a fitted MLE, GAS, or SCAR-TM-OU model:
for block in cop.sample_batches(
    n=1_000_000,
    batch_rows=128,
    memory_budget_bytes=128 * cop.d * 8,
):
    consume(block)

for block in cop.predict_batches(
    n=1_000_000,
    batch_rows=128,
    memory_budget_bytes=128 * cop.d * 8,
):
    consume(block)

The structural sampler costs O(n*d) and does not construct a dense correlation matrix. It supports the full admissible open interval -1/(d-1) < rho < 1. Fitted batching preserves model semantics: GAS updates its state after every generated row, while SCAR uses one OU path for unconditional sampling and one frozen posterior state for prediction. Monolithic sample, predict, sample_conditional, and sample_at_parameter also accept memory_budget_bytes and fail before allocating an oversized output.

All Equicorr sampling and prediction methods shown above, including their batch variants and sample_conditional, accept keyword-only n_threads=1. The requested count reaches the native observation sampler for explicit parameters and fitted MLE/GAS/SCAR predictions. Thread counts must be integers in [1, 256], including when all coordinates are fixed or the output is empty. Small blocks and the one-observation-at-a-time GAS model trajectory retain their sequential execution policy.

SCAR sample_batches generates OU states one block at a time, with dt=1/(n-1) based on the full requested length (dt=1 for a single row). Its temporary path storage is O(batch_rows), not O(n). Observation draws are interleaved with OU blocks, so reproduce a draw sequence with the same seed and batch_rows; changing the block size may change the sequence.

For both EquicorrGaussianCopula and StochasticStudentCopula, omitting r in log_likelihood(u) evaluates the fitted MLE/GAS/SCAR strategy. An explicit r requests a static emission likelihood. Omitting r in sample_conditional(n, given=...) with fixed coordinates uses the next predictive distribution. Pass r to condition at a fixed parameter, or use sample_batches(..., given=...) for a conditional model trajectory.

API

pyscarcopula.copula.multivariate.equicorr.EquicorrGaussianCopula

Bases: MultivariateCopula

Gaussian copula controlled by one equicorrelation parameter.

Row emission methods accept t_index as a compatibility offset: it must be None or a non-negative integer. Pass already-sliced u and r; the offset does not select or shift their rows.

fit(data, method='scar-tm-ou', to_pobs=False, config=None, **kwargs)

prepare_sufficient_statistics(u_batches, *, dimension=None, batch_rows=256, dimension_tile=16384, n_threads=1)

Prepare O(T) emission statistics from dense or streamed blocks.

u_batches may be a 2D ndarray/memmap or a repeatable or one-shot iterable yielding 2D blocks of pseudo-observations. The default is unconditionally single-threaded.

sample(n, u=None, rng=None, *, n_threads=1, memory_budget_bytes=None)

Generate observations reproducing the fitted model.

sample_batches(n, u=None, rng=None, *, batch_rows=128, given=None, n_threads=1, memory_budget_bytes=None)

Yield fitted-model samples in bounded row blocks.

GAS is advanced one generated observation at a time. MLE and SCAR use their constant or OU model parameter paths respectively.

sample_conditional(n, r=None, given=None, rng=None, *, n_threads=1, memory_budget_bytes=None)

predict(n, u=None, rng=None, given=None, horizon='next', predictive_r_mode=None, predict_config=None, memory_budget_bytes=None, *, n_threads=1)

predict_batches(n, u=None, rng=None, *, batch_rows=128, given=None, horizon='next', predictive_r_mode=None, predict_config=None, n_threads=1, memory_budget_bytes=None)

Yield fitted predictive samples from one frozen predictive state.

predictive_mean(u)

Return the predictive parameter path for the fitted strategy.

xT_distribution(u, K=None, grid_range=None)

Return the fitted OU state distribution at the last observation.

Omitted grid settings inherit the fit; explicit K/grid_range override them. MLE and GAS fits do not define an OU state distribution.

log_likelihood(u, r=None, *, n_threads=1)

Evaluate the fitted strategy, or a static density at explicit r.

log_pdf_rows(u, r, t_index=None, *, n_threads=1)

dlog_pdf_dr_rows(u, r, t_index=None, *, n_threads=1)

log_pdf_and_dlog_dr_rows(u, r, t_index=None, *, n_threads=1)

pdf_on_grid(u_row, z_grid, *, n_threads=1)

pdf_and_grad_on_grid(u_row, z_grid, *, n_threads=1)

pdf_and_grad_on_grid_batch(u, x_grid, *, n_threads=1, memory_budget_bytes=None)

Evaluate a grid batch, optionally enforcing an output budget.

pdf_and_grad_on_grid_batches(u, x_grid, *, batch_rows=128, n_threads=1, memory_budget_bytes=None)

Yield bounded row blocks of the two (T,K) grid outputs.

sample_at_parameter(n, r, rng=None, *, n_threads=1, memory_budget_bytes=None)

sample_at_parameter_batches(n, r, *, batch_rows=128, rng=None, n_threads=1, memory_budget_bytes=None)

Yield unconditional samples without allocating the full (n,d).

The returned iterator owns no model state. Each yielded array has at most batch_rows rows and uses the structural equicorrelation sampler for both positive and negative correlation.

transform(x)

inv_transform(r)

dtransform(x)