The hardware and bandwidth for this mirror is donated by METANET, the Webhosting and Full Service-Cloud Provider.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]metanet.ch.

Comparing Copula VAR Models

Overview

The dcvar package provides three copula VAR models:

  1. DC-VAR (dcvar()): Time-varying correlation via a random walk on the Fisher-z scale. Best for smooth, gradual changes.

  2. HMM Copula (dcvar_hmm()): Discrete regime-switching with K hidden states. Best for abrupt changes between distinct coupling regimes.

  3. Constant Copula (dcvar_constant()): Single time-invariant correlation. Serves as a null/baseline model.

Mathematical Background

For normal-margin fits, all three models share a common decomposition of the bivariate likelihood into marginal and copula components. The package also supports exponential, gamma, and skew-normal margins for these three models, but the copula structure below is the common part. All three single-level models additionally support per-variable margins, where each variable can use a different marginal family (see the mixed-margins section below).

VAR(1) Marginals

Each variable follows a VAR(1) process with innovations:

\[y_t = \mu + \Phi \, (y_{t-1} - \mu) + \varepsilon_t, \qquad \varepsilon_t \sim N(0, \text{diag}(\sigma_{\varepsilon}^2))\]

The normal marginal densities provide the per-variable likelihoods in this special case. For non-normal margins, dcvar uses the same VAR recursion and Gaussian copula but swaps in the corresponding marginal likelihood and transform.

Gaussian Copula

The dependence between variables is captured by a Gaussian copula with time-varying correlation \(\rho_t\). The log-likelihood contribution of the copula at time \(t\) is:

\[\log c(u_{1t}, u_{2t}; \rho_t) = -\frac{1}{2}\log(1 - \rho_t^2) - \frac{\rho_t^2 \, (z_{1t}^2 + z_{2t}^2) - 2\rho_t \, z_{1t} z_{2t}}{2(1 - \rho_t^2)}\]

where \(z_{it} = \Phi^{-1}(u_{it})\) and \(u_{it} = \Phi(\varepsilon_{it} / \sigma_{\varepsilon,i})\).

How the Models Differ

Per-variable (mixed) margins

A copula separates the marginal distributions from the dependence structure, so each variable is free to follow its own marginal family. dcvar_constant(), dcvar(), and dcvar_hmm() expose this by accepting a length-2 margins vector. For example, a roughly-symmetric first series paired with a positively-skewed second series can be modelled as normal and exponential margins under a single Gaussian copula:

library(dcvar)

sim_mix <- simulate_dcvar(
  n_time = 200,
  rho_trajectory = rho_constant(200, rho = 0.6),
  margins = c("normal", "exponential"),
  skew_direction = c(1, 1),
  seed = 11
)

fit_mix <- dcvar_constant(
  sim_mix$Y_df,
  vars = c("y1", "y2"),
  margins = c("normal", "exponential"),
  skew_direction = c(1, 1),
  seed = 11
)

# Each dimension is reported under its own family: sigma_eps for the normal
# variable, sigma_exp for the exponential variable.
coef(fit_mix)[c("sigma_eps", "sigma_exp")]

skew_direction is required whenever any dimension uses an exponential or gamma margin, and only those dimensions consult it. A single margins string still applies the same family to both variables, and an all-identical vector such as c("normal", "normal") is treated exactly like the scalar form (it reuses the specialised single-family model), so existing code is unaffected. Mixed margins currently require the Gaussian copula and are available for the three single-level models (dcvar_constant(), dcvar(), dcvar_hmm()).

Time-varying coefficients and scales

In dcvar() the copula correlation always evolves over time. The autoregressive dynamics and the residual scales can be allowed to evolve as well, each as a random walk around a constant baseline. Two flags turn these on:

With both flags off, dcvar() is the usual dynamic copula model with constant coefficients and scales. Smaller models are nested in larger ones, which suggests fitting a short ladder and comparing the fits.

library(dcvar)

# A series with declining coupling to illustrate the time-varying fits
sim_tv <- simulate_dcvar(
  n_time = 150,
  rho_trajectory = rho_decreasing(150, rho_start = 0.7, rho_end = 0.3),
  seed = 3
)

# Only the autoregressive coefficients evolve over time
fit_ar <- dcvar(
  sim_tv$Y_df,
  vars = c("y1", "y2"),
  tv_phi = "ar",
  seed = 4
)

# Time-varying coefficients and time-varying scales together, with a
# right-skewed second margin (the exponential dimension uses the soft barrier)
fit_full <- dcvar(
  sim_tv$Y_df,
  vars = c("y1", "y2"),
  margins = c("normal", "exponential"),
  skew_direction = c(1, 1),
  tv_phi = TRUE,
  tv_sigma = TRUE,
  seed = 5
)

The coefficient and scale paths come back as posterior summaries, in the same shape as the correlation trajectory, and have their own plotting helpers.

# Posterior summaries of phi11(t), phi12(t), phi21(t), phi22(t)
head(phi_trajectory(fit_ar))

# Per-variable residual-scale paths
head(sigma_trajectory(fit_full))

# Facetted trajectory plots
plot_phi_trajectory(fit_ar)
plot_sigma_trajectory(fit_full)

Fitting All Three Models

library(dcvar)

# Simulate data with a step-function trajectory
sim <- simulate_dcvar(
  n_time = 200,
  rho_trajectory = rho_step(200, rho_before = 0.7, rho_after = 0.3),
  seed = 42
)

# Fit all three models on the same data
fit_dc  <- dcvar(sim$Y_df, vars = c("y1", "y2"), seed = 1)
fit_hmm <- dcvar_hmm(sim$Y_df, vars = c("y1", "y2"), K = 2, seed = 2)
fit_con <- dcvar_constant(sim$Y_df, vars = c("y1", "y2"), seed = 3)

LOO-CV Comparison

dcvar_compare(dcvar = fit_dc, hmm = fit_hmm, constant = fit_con)

Extracting Tidy Summaries

All fit objects support as.data.frame() for exporting tidy parameter summaries. All five fit families also support fitted()/predict() for one-step-ahead values (for SEM and multilevel fits as well). Prediction intervals are restricted to normal margins for single-level, multilevel, and naive-SEM fits; indicator-SEM predictions are available for all supported SEM margins:

# Full parameter summary as a data frame
param_df <- as.data.frame(fit_dc)
head(param_df)

# Predictions with marginal intervals
pred_df <- predict(fit_hmm)
head(pred_df)

HMM-Specific Outputs

The HMM model provides additional outputs related to state inference:

# State posteriors, Viterbi path, transition matrix
states <- hmm_states(fit_hmm)

# State-specific rho values
states$rho_state

# Transition matrix
states$A

# Visualise state posteriors
plot(fit_hmm, type = "states")

# Transition matrix heatmap
plot(fit_hmm, type = "transition")

Clinical Interpretation

interpret_rho_trajectory() provides a model-aware narrative:

interpret_rho_trajectory(fit_dc)
interpret_rho_trajectory(fit_hmm)
interpret_rho_trajectory(fit_con)

When to Use Which Model

These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.