From 70b418dfff39a0eb56c6d1321e24ad6a2073944e Mon Sep 17 00:00:00 2001 From: mitchelloharawild Date: Fri, 13 Sep 2024 08:55:51 +1000 Subject: [PATCH] Add IRF method for VAR Ref: #363 --- NAMESPACE | 2 ++ NEWS.md | 2 +- R/var.R | 27 +++++++++++++++++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/NAMESPACE b/NAMESPACE index 90d378f4..5b44f6ad 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,5 +1,6 @@ # Generated by roxygen2: do not edit by hand +S3method(IRF,VAR) S3method(breusch_godfrey,TSLM) S3method(components,ETS) S3method(fitted,AR) @@ -136,5 +137,6 @@ importFrom(stats,residuals) importFrom(stats,sd) importFrom(stats,time) importFrom(stats,ts) +importFrom(tsibble,as_tsibble) importFrom(utils,tail) useDynLib(fable, .registration = TRUE) diff --git a/NEWS.md b/NEWS.md index 77d4b831..e3cabf2b 100644 --- a/NEWS.md +++ b/NEWS.md @@ -2,7 +2,7 @@ ## New features -* Added generate() method for VAR models +* Added `generate()` and `IRF()` methods for VAR models. # fable 0.3.4 diff --git a/R/var.R b/R/var.R index ff80d3a3..71dbb55a 100644 --- a/R/var.R +++ b/R/var.R @@ -429,3 +429,30 @@ generate.VAR <- function(x, new_data, specials, ...){ new_data[colnames(coef)] <- split(.sim, col(.sim)) new_data } + +#' @export +IRF.VAR <- function(x, new_data, specials, impulse = NULL, ortho = FALSE, ...) { + new_data$.innov <- matrix(0, nrow = nrow(new_data), ncol = ncol(x$last_obs), + dimnames = dimnames(x$last_obs)) + # Zero out end of data + x$last_obs[seq_along(x$last_obs)] <- 0 + + # Remove regressors + n_ar <- x$spec$p*ncol(x$coef) + if(nrow(x$coef) > n_ar) { + x$coef[seq(n_ar + 1, nrow(x$coef)),] <- 0 + } + + # Add shocks + new_data$.innov[1, impulse] <- 1 + + # Orthogonalised shocks + if(ortho) { + # Use Cholesky decomposition to orthogonalise the shocks / innovations + new_data$.innov <- new_data$.innov %*% chol(x$fit$sigma2[[1L]]) + } + + irf <- generate(x, new_data, specials) + irf$.innov <- NULL + irf +} \ No newline at end of file