Nothing
# Tests for smooth_states(), smooth_shocks(), shock_decomposition()
test_that("smooth_states works on ML fit", {
# Simple AR(1) model
m <- dsge_model(
obs(y ~ z),
state(z ~ rho * z),
start = list(rho = 0.5)
)
set.seed(42)
e <- rnorm(100)
z <- numeric(100)
for (i in 2:100) z[i] <- 0.8 * z[i - 1] + e[i]
fit <- estimate(m, data = data.frame(y = z))
sm <- smooth_states(fit)
expect_s3_class(sm, "dsge_smoothed")
expect_equal(nrow(sm$smoothed_states), 100)
expect_equal(ncol(sm$smoothed_states), 1) # 1 state
expect_equal(nrow(sm$smoothed_obs), 100)
expect_equal(ncol(sm$smoothed_obs), 1) # 1 observable
expect_equal(nrow(sm$residuals), 100)
# Smoothed obs should approximate the data
expect_true(cor(sm$smoothed_obs[, 1], z) > 0.95)
})
test_that("smooth_states dimensions match for multi-state model", {
m <- dsge_model(
obs(y1 ~ a),
obs(y2 ~ b),
state(a ~ rho_a * a),
state(b ~ rho_b * b),
start = list(rho_a = 0.5, rho_b = 0.3)
)
set.seed(42)
e1 <- rnorm(80)
e2 <- rnorm(80)
a <- numeric(80); b <- numeric(80)
for (i in 2:80) {
a[i] <- 0.8 * a[i-1] + e1[i]
b[i] <- 0.5 * b[i-1] + e2[i]
}
fit <- estimate(m, data = data.frame(y1 = a, y2 = b))
sm <- smooth_states(fit)
expect_equal(nrow(sm$smoothed_states), 80)
expect_equal(ncol(sm$smoothed_states), 2) # 2 states
expect_equal(ncol(sm$smoothed_obs), 2) # 2 observables
})
test_that("smooth_shocks works on ML fit", {
m <- dsge_model(
obs(y ~ z),
state(z ~ rho * z),
start = list(rho = 0.5)
)
set.seed(42)
e <- rnorm(100)
z <- numeric(100)
for (i in 2:100) z[i] <- 0.8 * z[i - 1] + e[i]
fit <- estimate(m, data = data.frame(y = z))
sh <- smooth_shocks(fit)
expect_s3_class(sh, "dsge_smoothed_shocks")
expect_equal(nrow(sh$shocks), 99) # T-1 shocks
expect_equal(ncol(sh$shocks), 1) # 1 shock
expect_equal(length(sh$shock_names), 1)
# Shock SD should be approximately 1 (or close to estimated sd)
expect_true(sd(sh$shocks[, 1]) > 0.5 && sd(sh$shocks[, 1]) < 2.0)
})
test_that("shock_decomposition sums to observed data", {
m <- dsge_model(
obs(y ~ z),
state(z ~ rho * z),
start = list(rho = 0.5)
)
set.seed(42)
e <- rnorm(100)
z <- numeric(100)
for (i in 2:100) z[i] <- 0.8 * z[i - 1] + e[i]
fit <- estimate(m, data = data.frame(y = z))
hd <- shock_decomposition(fit)
expect_s3_class(hd, "dsge_decomposition")
expect_equal(dim(hd$decomposition)[1], 100) # T
expect_equal(dim(hd$decomposition)[2], 1) # n_obs
expect_equal(dim(hd$decomposition)[3], 2) # 1 shock + initial
# Key test: sum of contributions = smoothed observables
recon <- apply(hd$decomposition, c(1, 2), sum)
# Should match the smoothed observables (from smooth_states)
sm <- smooth_states(fit)
# Decomposition sums to smoothed obs
expect_true(max(abs(recon[, 1] - sm$smoothed_obs[, 1])) < 1e-6)
})
test_that("shock_decomposition with multiple shocks", {
m <- dsge_model(
obs(y1 ~ a),
obs(y2 ~ b),
state(a ~ rho_a * a),
state(b ~ rho_b * b),
start = list(rho_a = 0.5, rho_b = 0.3)
)
set.seed(42)
e1 <- rnorm(80)
e2 <- rnorm(80)
a <- numeric(80); b <- numeric(80)
for (i in 2:80) {
a[i] <- 0.8 * a[i-1] + e1[i]
b[i] <- 0.5 * b[i-1] + e2[i]
}
fit <- estimate(m, data = data.frame(y1 = a, y2 = b))
hd <- shock_decomposition(fit)
expect_equal(dim(hd$decomposition)[3], 3) # 2 shocks + initial
# Reconstruction test for both observables
recon <- apply(hd$decomposition, c(1, 2), sum)
sm <- smooth_states(fit)
expect_true(max(abs(recon - sm$smoothed_obs)) < 1e-6)
})
test_that("print methods work", {
m <- dsge_model(
obs(y ~ z),
state(z ~ rho * z),
start = list(rho = 0.5)
)
set.seed(42)
e <- rnorm(50)
z <- numeric(50)
for (i in 2:50) z[i] <- 0.8 * z[i - 1] + e[i]
fit <- estimate(m, data = data.frame(y = z))
expect_output(print(smooth_states(fit)), "DSGE Smoothed States")
expect_output(print(smooth_shocks(fit)), "DSGE Smoothed Structural Shocks")
expect_output(print(shock_decomposition(fit)), "DSGE Historical Shock Decomposition")
})
test_that("plot methods execute without error", {
m <- dsge_model(
obs(y ~ z),
state(z ~ rho * z),
start = list(rho = 0.5)
)
set.seed(42)
e <- rnorm(50)
z <- numeric(50)
for (i in 2:50) z[i] <- 0.8 * z[i - 1] + e[i]
fit <- estimate(m, data = data.frame(y = z))
sm <- smooth_states(fit)
hd <- shock_decomposition(fit)
# Plot should not error
pdf(NULL)
expect_no_error(plot(sm, type = "states"))
expect_no_error(plot(sm, type = "fit"))
expect_no_error(plot(hd))
dev.off()
})
test_that("analytical check: AR(1) smoothed states match true states", {
# For a simple AR(1) with known rho, the Kalman smoother should
# recover the true states well
set.seed(123)
rho_true <- 0.9
sd_true <- 1.0
n <- 200
z_true <- numeric(n)
for (i in 2:n) z_true[i] <- rho_true * z_true[i-1] + rnorm(1, sd = sd_true)
m <- dsge_model(
obs(y ~ z),
state(z ~ rho * z),
start = list(rho = 0.5)
)
fit <- estimate(m, data = data.frame(y = z_true))
sm <- smooth_states(fit)
# Smoothed states should correlate strongly with true states
r <- cor(sm$smoothed_states[, 1], z_true)
expect_true(r > 0.95)
})
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.