# Gaussian and Student t Copula Time Series Models for Count Data

The `gctsc` package provides fast and scalable tools for fitting Gaussian and Student t copula models for count time series, supporting a wide range of discrete marginals:

- Poisson
- Negative Binomial
- Binomial
- Beta Binomial
- Zero-Inflated Poisson (ZIP)
- Zero-Inflated Binomial (ZIB)
- Zero-Inflated Beta-Binomial (ZIBB)

These models are constructed from a latent ARMA process combined with a discrete marginal distribution. Likelihood evaluation requires computing multivariate probabilities under Gaussian or Student–t dependence structures.

The package provides several likelihood approximation methods:

- TMET — Time Series Minimax Exponential Tilting
- GHK — Geweke–Hajivassiliou–Keane simulator
- CE — Continuous Extension approximation

In addition, the package offers:

- Simulation of count time series with ARMA latent structure
- Maximum likelihood estimation using the above likelihoods
- Residual diagnostic tools
- One-step-ahead prediction

A key feature of the package is the TMET method, which exploits the conditional structure of ARMA processes to compute likelihood approximations efficiently even for long time series. The package also includes the classical GHK simulator and the Continuous Extension approximation for comparison.

This vignette illustrates the main functionality of the `gctsc` package, including simulation, likelihood approximation, model fitting, diagnostics, and prediction for copula-based count time series models.

## Installation

The package can be installed from CRAN using

    install.packages("gctsc")

The development version is available at

    remotes::install_github("QNNHU/gctsc")

## Package overview

The package provides tools for simulation, likelihood evaluation, estimation, diagnostics, and prediction for copula-based count time series models with Gaussian or Student–t copula dependence.

The package implements several likelihood approximation methods, including Time Series Minimax Exponential Tilting (TMET), the classical Geweke–Hajivassiliou–Keane (GHK) simulator, and the Continuous Extension (CE) approximation.

### Main functions

Function | Description
--- | ---
`sim_*()` | Simulate copula count time series with latent ARMA dependence
`pmvn*()` / `pmvt*()` | Compute multivariate rectangle probabilities for Gaussian and Student–t copulas
`gctsc()` | Fit Gaussian or Student–t copula count time series models
`predict()` | Compute one-step-ahead predictive distributions and moments
`plot()` | Produce residual diagnostic plots
`summary()` | Display parameter estimates and model fit statistics

The following sections illustrate the main functionality of the package, including simulation, likelihood approximation, model estimation, diagnostics, and prediction.

### Example 1: Simulating Poisson AR(1) counts under a Gaussian copula

    n  <- 300
    mu <- 10
    phi <- 0.2
    arma_order <- c(1, 0)
    tau <- c(phi)

    sim_data <- sim_poisson(
      mu = mu,
      tau = tau,
      arma_order = arma_order,
      nsim = n,
      family = "gaussian",
      seed = 7
    )

    y <- sim_data$y
    plot(y, type = "l", main = "Simulated Poisson AR(1) Counts: Gaussian Copula")

### Example 2: Simulating Poisson AR(1) counts under a Student–t copula

    n  <- 300
    mu <- 10
    phi <- 0.2
    arma_order <- c(1, 0)
    tau <- c(phi)

    sim_data <- sim_poisson(
      mu = mu,
      tau = tau,
      arma_order = arma_order,
      nsim = n,
      family  = "t",
      df = 5,
      seed = 7
    )

    y <- sim_data$y
    plot(y, type = "l", main = "Simulated Poisson AR(1) Counts: t Copula")

### Example 3: Simulating Zero–Inflated Beta–Binomial (ZIBB) AR(1) Count Time Series

    n <- 300
    phi <- 0.5
    tau <- c(phi)

    beta_0 <- 1.2
    prob   <- plogis(beta_0)
    rho    <- 0.1
    pi0    <- 0.8
    size   <- 24

    set.seed(7)
    sim_data <- sim_zibb(prob = prob,
                         rho = rho, pi0 = pi0,
                         size = size, tau = tau,
                         arma_order = c(1,0),
                         family = "gaussian",
                         nsim = n)
    y <- sim_data$y

    plot(y, type = "l", main = "Simulated ZIBB AR(1) Counts: gaussian Copula")

### Example 4: Likelihood approximation (TMET vs GHK vs CE)

    n <- 300
    mu <- 10
    phi <- 0.5
    theta <- 0.2
    arma_order <- c(1,1)
    tau <- c(phi, theta)

    # Simulate Poisson count data
    sim_data <- sim_poisson(mu, tau, arma_order, nsim = n, family = "gaussian",
                            seed = 1)
    y <- sim_data$y

    # Compute bounds for truncated MVN using marginal object
    marg <- poisson.marg(link = "identity")
    lower <- qnorm(ppois(y - 1, lambda = mu))
    upper <- qnorm(ppois(y, lambda = mu))

    # Likelihood approximation
    llk_tmet <- pmvn(lower, upper, tau, od = arma_order, method ="TMET",
                     pm = 30, QMC = TRUE)
    llk_ghk  <- pmvn(lower, upper, tau, od = arma_order, method = "GHK",
                     QMC = TRUE)
    llk_ce  <-  pmvn(lower, upper, tau, od = arma_order, method ="CE")

    c(TMET = llk_tmet, GHK = llk_ghk, CE = llk_ce)
    #>      TMET       GHK        CE
    #> -704.8721 -704.8980 -704.8964

### Example 4: Fitting a Gaussian Copula Count Model

    n <- 1000
    mu <- 10
    phi <- 0.5
    theta <- 0.2
    arma_order <- c(1,1)
    tau <- c(phi, theta)

    # Simulate Poisson count data
    sim_data <- sim_poisson(mu, tau, arma_order, nsim = n, seed = 1, family ="gaussian")
    y <- sim_data$y

    fit <- gctsc(
      formula  = y ~ 1, data= data.frame(y),
      marginal = poisson.marg(link = "log"),
      cormat   = arma.cormat(p = 1, q = 1),
      method   = "CE", family ="gaussian"
    )

    summary(fit)
    #>
    #> --- Summary of Copula Time Series Model ---
    #> Call:
    #>  gctsc(formula = y ~ 1, data = data.frame(y), marginal = poisson.marg(link = "log"),      cormat = arma.cormat(p = 1, q = 1), method = "CE", family = "gaussian")
    #>
    #> Marginal Model Coefficients:
    #>              Estimate Std. Error z value Pr(>|z|)
    #> mu_intercept  2.29551    0.01899   120.9   <2e-16 ***
    #>
    #> Copula (Dependence) Coefficients:
    #>     Estimate Std. Error z value Pr(>|z|)
    #> ar1  0.55001    0.03535  15.557   <2e-16 ***
    #> ma1  0.12135    0.04818   2.519   0.0118 *
    #> ---
    #> Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
    #>
    #> Model Fit Statistics:
    #>   Log-likelihood: -2342.0674
    #>   AIC:             4690.1347
    #>   BIC:             4704.8580

### Example 5: Residual diagnostics

    oldpar <- par(no.readonly = TRUE)

    par(mfrow = c(2,3))
    plot(fit)

    par(oldpar)

### Example 6: One-step-ahead prediction

    prediction <- predict(
      fit,
      newdata   = data.frame(y = 10)
    )

    prediction
    #> $mean
    #> [1] 8.372438
    #>
    #> $median
    #> [1] 8
    #>
    #> $mode
    #> [1] 8
    #>
    #> $variance
    #> [1] 5.500032
    #>
    #> $p_y
    #>  [1] 6.809085e-06 1.832308e-04 1.718838e-03 8.675613e-03 2.814967e-02
    #>  [6] 6.475353e-02 1.123689e-01 1.535627e-01 1.705589e-01 1.577208e-01
    #> [11] 1.237677e-01 8.370201e-02 4.941055e-02 2.573476e-02 1.193470e-02
    #> [16] 4.967316e-03 1.868272e-03 6.388433e-04 1.996706e-04 5.731634e-05
    #> [21] 1.517591e-05 3.720737e-06 8.476796e-07 1.800355e-07 3.575082e-08
    #> [26] 6.655623e-09 1.164525e-09 1.919412e-10 2.986591e-11 4.395801e-12
    #> [31] 6.131322e-13 8.117491e-14 1.507927e-14 1.507927e-14 1.507927e-14
    #> [36] 1.507927e-14
    #>
    #> $y_grid
    #>  [1]  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
    #> [26] 25 26 27 28 29 30 31 32 33 34 35
    #>
    #> $lower
    #> [1] 4
    #>
    #> $upper
    #> [1] 13
    #>
    #> $CRPS
    #> [1] 1.017137
    #>
    #> $LOGS
    #> [1] 2.089349
    #>
    #> $y_true
    #> [1] 10

### Example 7: Fitting a t Copula Count Model

    n <- 1000
    mu <- 10
    phi <- 0.5
    theta <- 0.2
    arma_order <- c(1,1)
    tau <- c(phi, theta)

    # Simulate Poisson count data
    sim_data <- sim_poisson(mu, tau, arma_order, nsim = n, family = "t", df= 15, seed = 1)
    y <- sim_data$y

    fit <- gctsc(
      formula  = y ~ 1, data = data.frame(y),
      marginal = poisson.marg(),
      cormat   = arma.cormat(p = 1, q = 1),
      method   = "CE", family ="t", df= 15
    )

    summary(fit)
    #>
    #> --- Summary of Copula Time Series Model ---
    #> Call:
    #>  gctsc(formula = y ~ 1, data = data.frame(y), marginal = poisson.marg(),      cormat = arma.cormat(p = 1, q = 1), method = "CE", family = "t",      df = 15)
    #>
    #> Marginal Model Coefficients:
    #>              Estimate Std. Error z value Pr(>|z|)
    #> mu_intercept  2.29377    0.01794   127.9   <2e-16 ***
    #>
    #> Copula (Dependence) Coefficients:
    #>     Estimate Std. Error z value Pr(>|z|)
    #> ar1  0.49380    0.03825  12.908  < 2e-16 ***
    #> ma1  0.12949    0.04897   2.644  0.00818 **
    #> ---
    #> Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
    #>
    #> Model Fit Statistics:
    #>   Log-likelihood: -2535.3621
    #>   AIC:             5076.7242
    #>   BIC:             5091.4474

### Example 7: Real Data Analysis — Campylobacter Time Series

    ## Load weekly Campylobacter incidence data
    data("campyl", package = "gctsc")
    y <- campyl[,"X1"]
    n <- length(y)

    ## Plot the time series
    ts_y <- ts(y, start = c(2001, 1), frequency = 52)
    plot(ts_y, main = "Weekly Campylobacter Incidence",
         ylab = "Cases", xlab = "Year")

    ## ---------------------------------------------------------------
    ## Construct seasonal covariates
    ## ---------------------------------------------------------------
    ## Seasonal structure appears to have yearly periodicity,
    ## so we include sine/cosine terms with period = 52 weeks.

    time <- 1:n
    X <- data.frame(
      intercept = 1,
      sin52 = sin(2 * pi * time / 52),
      cos52 = cos(2 * pi * time / 52)
    )

    ## Combine response and covariates
    data_df <- data.frame(Y = y, X)

    ## Use the first 800 observations for model fitting
    train_end <- 1000
    data_train <- data_df[1:train_end, ]

    ## ---------------------------------------------------------------
    ## Fit a Negative Binomial Gaussian Copula model
    ## ---------------------------------------------------------------
    ## We use:
    ##   - Negative Binomial marginal (log link)
    ##   - ARMA(1,1) latent correlation structure
    ##   - GHK likelihood approximation
    ##
    ## The model is:
    ##     E[Y_t] = exp(β0 + β1 sin + β2 cos)
    ##
    ## Covariates enter only through the marginal mean.

    fit <- gctsc(
      formula  = Y ~ sin52 + cos52,
      data     = data_train,
      marginal = negbin.marg(link = "log"),
      cormat   = arma.cormat(p = 1, q = 1),
      method   = "CE", family ="gaussian",
      options  = gctsc.opts(seed = 1)   # fixed seed for reproducibility
    )

    summary(fit)
    #>
    #> --- Summary of Copula Time Series Model ---
    #> Call:
    #>  gctsc(formula = Y ~ sin52 + cos52, data = data_train, marginal = negbin.marg(link = "log"),      cormat = arma.cormat(p = 1, q = 1), method = "CE", family = "gaussian",      options = gctsc.opts(seed = 1))
    #>
    #> Marginal Model Coefficients:
    #>              Estimate Std. Error z value Pr(>|z|)
    #> mu_intercept  1.57385    0.08006  19.660  < 2e-16 ***
    #> mu_sin52     -0.31857    0.02952 -10.793  < 2e-16 ***
    #> mu_cos52     -0.30412    0.02866 -10.612  < 2e-16 ***
    #> dispersion    0.13623    0.03383   4.027 5.66e-05 ***
    #>
    #> Copula (Dependence) Coefficients:
    #>      Estimate Std. Error z value Pr(>|z|)
    #> ar1  0.988033   0.007675  128.73   <2e-16 ***
    #> ma1 -0.914750   0.021974  -41.63   <2e-16 ***
    #> ---
    #> Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
    #>
    #> Model Fit Statistics:
    #>   Log-likelihood: -2318.2763
    #>   AIC:             4648.5526
    #>   BIC:             4677.9992

    ## ---------------------------------------------------------------
    ## Residual diagnostics
    ## ---------------------------------------------------------------
    oldpar <- par(no.readonly = TRUE)
    on.exit(par(oldpar))   # restore user settings

    par(mfrow=c(2,3))
    plot(fit)

    ## ---------------------------------------------------------------
    ## One-step-ahead prediction
    ## ---------------------------------------------------------------
    ## Predict Y_{801} using fitted model
    new_obs_index <- train_end + 1
    pred <- predict(
      fit,
      newdata = data_df[new_obs_index, ]
    )

    pred
    #> $mean
    #> [1] 4.021819
    #>
    #> $median
    #> [1] 4
    #>
    #> $mode
    #> [1] 3
    #>
    #> $variance
    #> [1] 4.854918
    #>
    #> $p_y
    #>  [1] 2.135069e-02 8.595747e-02 1.559186e-01 1.894055e-01 1.784984e-01
    #>  [6] 1.407531e-01 9.714828e-02 6.044059e-02 3.459288e-02 1.848521e-02
    #> [11] 9.325158e-03 4.479150e-03 2.062393e-03 9.152446e-04 3.932009e-04
    #> [16] 1.641321e-04 6.677378e-05 2.654475e-05 1.033412e-05 3.947480e-06
    #> [21] 1.481958e-06 5.475826e-07 1.993941e-07 7.163264e-08 2.541431e-08
    #> [26] 8.912518e-09 3.005135e-09 3.005135e-09 3.005135e-09 3.005135e-09
    #> [31] 3.005135e-09
    #>
    #> $y_grid
    #>  [1]  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
    #> [26] 25 26 27 28 29 30
    #>
    #> $lower
    #> [1] 1
    #>
    #> $upper
    #> [1] 9
    #>
    #> $CRPS
    #> [1] 1.066323
    #>
    #> $LOGS
    #> [1] 1.858421
    #>
    #> $y_true
    #> [1] 2

Further examples (Negative Binomial, Binomial,Beta-Binomial, ZIP, ZIB, ZIBB, including cases with covariates) and another real data analysis are available in the `inst/examples/` directory of the package source.