# =========================================================================== # # Tests for forecasting # =========================================================================== # test_that("filter_svp CKF runs and returns expected components", { set.seed(42) y <- sim_svp(500, phi = 0.95, sigy = 1, sigv = 0.3)$y mdl <- svp(y, p = 1) filt <- filter_svp(mdl) expect_s3_class(filt, "svp_filter") expect_true("w_filtered" %in% names(filt)) expect_true("w_smoothed" %in% names(filt)) expect_true("P_filtered" %in% names(filt)) expect_true("loglik" %in% names(filt)) expect_true("P_filt_T" %in% names(filt)) }) test_that("forecast_svp accepts model object and produces h-step forecasts", { set.seed(42) sim <- sim_svp(500, phi = 0.95, sigy = 1, sigv = 0.3, leverage = TRUE, rho = -0.3) fit <- svp(sim$y, p = 1, leverage = TRUE) fc <- forecast_svp(fit, H = 5) expect_s3_class(fc, "svp_forecast") expect_true("w_forecasted" %in% names(fc)) expect_length(fc$w_forecasted, 5) }) test_that("forecast_svp errors on raw numeric input", { set.seed(42) y <- sim_svp(200, phi = 0.95, sigy = 1, sigv = 0.3)$y expect_error(forecast_svp(y, H = 5), "svp/svp_t/svp_ged") }) test_that("forecast_svp: all three output representations are stored", { set.seed(42) y <- sim_svp(300, phi = 0.95, sigy = 1, sigv = 0.3)$y fit <- svp(y, p = 1) fc <- forecast_svp(fit, H = 10) expect_length(fc$log_var_forecast, 10) expect_length(fc$var_forecast, 10) expect_length(fc$vol_forecast, 10) expect_length(fc$P_forecast, 10) # Default output is log-variance expect_equal(fc$w_forecasted, fc$log_var_forecast) }) test_that("forecast_svp: output parameter selects primary output", { set.seed(42) y <- sim_svp(300, phi = 0.95, sigy = 1, sigv = 0.3)$y fit <- svp(y, p = 1) fc_var <- forecast_svp(fit, H = 5, output = "variance") expect_equal(fc_var$w_forecasted, fc_var$var_forecast) fc_vol <- forecast_svp(fit, H = 5, output = "volatility") expect_equal(fc_vol$w_forecasted, fc_vol$vol_forecast) }) test_that("forecast_svp: P_forecast is positive and increasing", { set.seed(42) y <- sim_svp(500, phi = 0.95, sigy = 1, sigv = 0.3)$y fit <- svp(y, p = 1) fc <- forecast_svp(fit, H = 20) expect_true(all(fc$P_forecast > 0)) # MSE should generally increase (not strictly for all h, but trend) expect_true(fc$P_forecast[20] > fc$P_forecast[1]) }) test_that("forecast_svp: sigma2_forecast is positive", { set.seed(42) y <- sim_svp(300, phi = 0.95, sigy = 1, sigv = 0.3)$y fit <- svp(y, p = 1) fc <- forecast_svp(fit, H = 10) expect_true(all(fc$var_forecast > 0)) expect_true(all(fc$vol_forecast > 0)) }) test_that("forecast_svp: long horizon converges toward 0 (log-var)", { set.seed(42) y <- sim_svp(500, phi = 0.90, sigy = 1, sigv = 0.3)$y fit <- svp(y, p = 1) fc <- forecast_svp(fit, H = 100) # Long-horizon log-variance forecast should converge toward 0 expect_true(abs(fc$log_var_forecast[100]) < abs(fc$log_var_forecast[1]) + 0.1) }) test_that("forecast_svp: Student-t uses E[u^2] = nu/(nu-2)", { set.seed(42) sim <- sim_svp(500, phi = 0.95, sigy = 1, sigv = 0.3, errorType = "Student-t", nu = 5) fit <- svp(sim$y, p = 1, errorType = "Student-t") fc <- forecast_svp(fit, H = 5) # var_forecast should incorporate nu/(nu-2) = 5/3 factor expect_true(all(fc$var_forecast > 0)) }) test_that("forecast_svp: GED uses E[u^2] = 1", { set.seed(42) sim <- sim_svp(500, phi = 0.95, sigy = 1, sigv = 0.3, errorType = "GED", nu = 1.5) fit <- svp(sim$y, p = 1, errorType = "GED") fc <- forecast_svp(fit, H = 5) expect_true(all(fc$var_forecast > 0)) }) test_that("plot.svp_forecast works without error", { set.seed(42) sim <- sim_svp(300, phi = 0.95, sigy = 1, sigv = 0.3, leverage = TRUE, rho = -0.3) fit <- svp(sim$y, p = 1, leverage = TRUE) fc <- forecast_svp(fit, H = 5) expect_silent(plot(fc)) }) test_that("companionMat returns correct dimensions", { C <- wARMASVp:::companionMat(c(0.7, 0.2), p = 2, q = 1) expect_equal(dim(C), c(2, 2)) expect_equal(unname(C[1, 1]), 0.7) expect_equal(unname(C[1, 2]), 0.2) }) # =========================================================================== # # Regression test: forecast MSE uses full P_filt_T matrix (Bug 3 fix) # =========================================================================== # test_that("forecast_svp p=2: P_forecast increases with horizon (full P_T)", { set.seed(42) y <- sim_svp(500, phi = c(0.20, 0.63), sigy = 1, sigv = 1)$y fit <- svp(y, p = 2) fc <- forecast_svp(fit, H = 5) # MSE should be non-decreasing with horizon for a stationary AR expect_true(all(diff(fc$P_forecast) >= -1e-10)) # All MSE values should be positive expect_true(all(fc$P_forecast > 0)) # Var forecast should all be positive expect_true(all(fc$var_forecast > 0)) }) # =========================================================================== # # BPF forecasting now supported (Fix 4, 2026-04-03) # =========================================================================== # test_that("forecast_svp works with filter_method='particle'", { set.seed(42) y <- sim_svp(300, phi = 0.95, sigy = 1, sigv = 0.3)$y fit <- svp(y, p = 1) fc <- forecast_svp(fit, H = 3, filter_method = "particle") expect_s3_class(fc, "svp_forecast") expect_equal(length(fc$log_var_forecast), 3) expect_true(all(is.finite(fc$log_var_forecast))) # P_filt_T should be a 1x1 matrix from BPF expect_equal(dim(fc$filter_output$P_filt_T), c(1L, 1L)) })