tests/testthat/test-model-covariance.R

# tests/testthat/test-model-covariance.R

# Helper: create a simple AR(1) model and solve it
# y_t = rho * y_{t-1} + e_t, implemented as obs(y ~ lead(y) + u) with state(u ~ rho * u)
make_ar1_solution <- function(rho = 0.5, sigma = 0.1) {
  m <- dsge_model(
    obs(y ~ lead(y) + u),
    state(u ~ rho_u * u),
    fixed = list(),
    start = list(rho_u = rho)
  )
  solve_dsge(m, params = c(rho_u = rho), shock_sd = c(u = sigma))
}

test_that("model_covariance works on dsge_solution", {
  sol <- make_ar1_solution(0.5, 0.1)
  mc <- model_covariance(sol)

  expect_s3_class(mc, "dsge_covariance")
  expect_true(is.matrix(mc$covariance))
  expect_true(is.matrix(mc$correlation))

  # Symmetric
  expect_equal(mc$covariance, t(mc$covariance))
  expect_equal(mc$correlation, t(mc$correlation))

  # Positive diagonal
  expect_true(all(diag(mc$covariance) >= 0))

  # Correlation diagonal = 1
  expect_equal(unname(diag(mc$correlation)), rep(1, length(mc$variables)))

  # Standard deviations consistent
  expect_equal(mc$std_dev^2, diag(mc$covariance), tolerance = 1e-10)
})

test_that("model_covariance with autocovariances", {
  sol <- make_ar1_solution(0.5, 0.1)
  mc <- model_covariance(sol, n_lags = 3)

  expect_equal(mc$n_lags, 3)
  expect_length(mc$autocovariances, 3)
  expect_true("lag_1" %in% names(mc$autocovariances))
  expect_true("lag_3" %in% names(mc$autocovariances))

  # Autocovariances should decay (AR(1) model)
  acov1 <- abs(mc$autocovariances$lag_1[1, 1])
  acov3 <- abs(mc$autocovariances$lag_3[1, 1])
  expect_true(acov1 >= acov3)
})

test_that("model_covariance AR(1) analytical check", {
  # State u follows AR(1): u_{t+1} = 0.9*u_t + e_t, var(e)=0.01
  # y_t = G * u_t where G is the policy coefficient
  # Var(u) = 0.01 / (1 - 0.81), Var(y) = G^2 * Var(u)
  # Gamma_y(k) = G^2 * 0.9^k * Var(u)
  sol <- make_ar1_solution(0.9, 0.1)
  mc <- model_covariance(sol)

  G_val <- sol$G[1, 1]
  var_u <- 0.01 / (1 - 0.81)
  expected_var <- G_val^2 * var_u
  expect_equal(mc$covariance[1, 1], expected_var, tolerance = 1e-4)

  # Autocovariance at lag k: Gamma_y(k) = rho^k * Gamma_y(0)
  mc2 <- model_covariance(sol, n_lags = 2)
  expect_equal(mc2$autocovariances$lag_1[1, 1],
               0.9 * mc2$covariance[1, 1], tolerance = 1e-4)
  expect_equal(mc2$autocovariances$lag_2[1, 1],
               0.81 * mc2$covariance[1, 1], tolerance = 1e-4)
})

test_that("model_covariance print method works", {
  sol <- make_ar1_solution(0.5, 0.1)
  mc <- model_covariance(sol)

  expect_output(print(mc), "Model-Implied Covariance Matrix")
  expect_output(print(mc), "Covariance")
  expect_output(print(mc), "Correlation")
})

test_that("model_covariance works on dsge_fit", {
  m <- dsge_model(
    obs(y ~ lead(y) + u),
    state(u ~ rho_u * u),
    fixed = list(),
    start = list(rho_u = 0.5)
  )

  # Simulate data
  set.seed(42)
  n <- 100
  u <- numeric(n)
  for (t in 2:n) u[t] <- 0.5 * u[t - 1] + rnorm(1, sd = 0.1)
  dat <- data.frame(y = u)

  fit <- estimate(m, data = dat)
  mc <- model_covariance(fit)

  expect_s3_class(mc, "dsge_covariance")
  expect_true(mc$covariance[1, 1] > 0)
})

test_that("model_covariance multi-variable NK model", {
  m <- dsge_model(
    obs(p ~ beta * lead(p) + kappa * x),
    unobs(x ~ lead(x) - (r - lead(p) - g)),
    obs(r ~ psi * p + u),
    state(u ~ rhou * u),
    state(g ~ rhog * g),
    fixed = list(beta = 0.96, kappa = 0.1),
    start = list(psi = 1.5, rhou = 0.7, rhog = 0.9)
  )

  sol <- solve_dsge(m,
    params = c(beta = 0.96, kappa = 0.1, psi = 1.5, rhou = 0.7, rhog = 0.9),
    shock_sd = c(u = 0.01, g = 0.01))

  mc <- model_covariance(sol)

  # Should have 2 observables (p, r)
  expect_equal(length(mc$variables), 2)
  expect_true(all(c("p", "r") %in% mc$variables))

  # 2x2 covariance matrix
  expect_equal(dim(mc$covariance), c(2, 2))

  # Symmetric and positive diagonal
  expect_equal(mc$covariance, t(mc$covariance), tolerance = 1e-12)
  expect_true(all(diag(mc$covariance) > 0))

  # Correlations between -1 and 1
  expect_true(all(mc$correlation >= -1 - 1e-10))
  expect_true(all(mc$correlation <= 1 + 1e-10))
})

Try the dsge package in your browser

Any scripts or data that you put into this service are public.

dsge documentation built on Sept. 25, 2026, 5:08 p.m.