##################################################
# VAR regressor matrix
##################################################
makeregs <- cmpfun(function(dat,cut,p){
t <- dim(dat)[1]
M <- dim(dat)[2]
K <- M + p*(M^2)
Z <- matrix(NA,t*M,K)
for (i in (cut+p+1):t){
ztemp <- diag(M)
for (j in 1:p){
xtemp <- t(diag(M) %x% dat[i-j,])
ztemp <- cbind(ztemp,xtemp)
}
Z[((i-1)*M+1):(i*M),] <- ztemp
}
return(Z[((cut+p)*M+1):(t*M),])
})
##################################################
# Helper function
##################################################
lastcol <- cmpfun(function(x){
if (is.matrix(x)){
out <- x[,dim(x)[2]]
} else {
out <- x[length(x)]
}
return(out)
})
##################################################
# Another helper function
##################################################
beta.reshape <- cmpfun(function(beta, M, p){
auxa <- matrix(rep(NA, length(beta)), nrow = M)
auxa[1:M] <- beta[1:M]
for (pp in 1:p){
auxa[,((pp-1)*M+2):(pp*M+1)] <- t(matrix(beta[(M+1+(pp-1)*(M^2)):(pp*(M^2)+M)], nrow = M))
}
return(auxa)
})
##################################################
# Regressor matrix for forecasting
##################################################
makeregs.fc <- cmpfun(function(dat,p){
# Dimensions
T <- dim(dat)[1]
M <- dim(dat)[2]
# Keep only most recent lags which are needed for forecasting
aux <- rbind(dat[(T-p+1):T,,drop=FALSE],matrix(0,1,M))
# Make regressors
return(makeregs(aux,0,p))
})
##################################################
# OLS based prior for BVAR-SV model
##################################################
tsprior <- cmpfun(function(priordat,nlag,ndraws=4000){
M <- dim(priordat)[2]
K <- M + nlag*(M^2) # nr of beta parameters
numa <- 0.5*M*(M-1) # nr of VCV elements
yt <- t(priordat[(nlag+1):(dim(priordat)[1]),]) # LHS variable
tau <- dim(yt)[2] # New sample size
Zt <- makeregs(priordat,0,nlag) # Regressor matrix
vbar <- matrix(0,K,K)
xhy <- matrix(0,K,1)
for (i in 1:tau){
zhat1 <- Zt[((i-1)*M+1):(i*M),]
vbar <- vbar + t(zhat1) %*% zhat1
xhy <- xhy + t(zhat1) %*% matrix(yt[,i],M,1)
}
aols <- solve(vbar) %*% xhy
sse2 <- matrix(0,M,M)
for (i in 1:tau){
e <- matrix(yt[,i] - Zt[((i-1)*M+1):(i*M),] %*% aols,M,1)
sse2 <- sse2 + e %*% t(e)
}
hbar <- sse2/tau
hbarinv <- solve(hbar)
vbar <- matrix(0,K,K)
for (i in 1:tau){
zhat1 <- Zt[((i-1)*M+1):(i*M),]
vbar <- vbar + t(zhat1) %*% hbarinv %*% zhat1
}
vbar <- solve(vbar)
achol <- t(chol(hbar))
ssig <- diag(achol)
for (i in 1:M){
for (j in 1:M){
achol[j,i] <- achol[j,i]/ssig[i]
}
}
achol <- solve(achol)
a0 <- matrix(0,numa,1)
ic <- 1
for (i in 2:M){
for (j in 1:(i-1)){
a0[ic,1] <- achol[i,j]
ic <- ic + 1
}
}
ssig1 <- log(ssig^2)
hbar1 <- solve(tau*hbar)
hdraw <- matrix(0,M,M)
a02mo <- matrix(0,numa,numa)
a0mean <- matrix(0,numa,1)
for (irep in 1:ndraws){
hdraw <- solve(rWishart(1,tau,hbar1)[,,1])
achol <- t(chol(hdraw))
ssig <- diag(achol)
for (i in 1:M){
for (j in 1:M){
achol[j,i] <- achol[j,i]/ssig[i]
}
}
achol <- solve(achol)
a0draw <- matrix(0,numa,1)
ic <- 1
for (i in 2:M){
for (j in 1:(i-1)){
a0draw[ic,1] <- achol[i,j]
ic <- ic + 1
}
}
a02mo <- a02mo + a0draw %*% t(a0draw)
a0mean <- a0mean + a0draw
}
a02mo <- a02mo / ndraws
a0mean <- a0mean / ndraws
a02mo <- a02mo - a0mean %*% t(a0mean)
return(list(B_OLS=aols, VB_OLS = vbar, A_OLS = a0, sigma_OLS = ssig1, VA_OLS = a02mo))
})
##################################################
# Simulate VAR(1) with TVP and SV
##################################################
sim.var1.sv.tvp <- cmpfun(function(B0 = NULL, A0 = NULL, Sig0 = NULL, Q = NULL, S = NULL, W = NULL, t = 500, init = 1000){
if (is.null(B0)) B0 <- cbind(rep(0,2), 0.6*diag(2)) # defaults to bivariate process with zero mean and moderately high persistence
M <- nrow(B0)
if (is.null(A0)) A0 <- rep(0, 0.5*M*(M-1))
if (is.null(Sig0)) Sig0 <- rep(0, M)
if (is.null(Q)) Q <- 1e-10*as.matrix(diag(length(B0))) # defaults to very small variance (almost no parameter drift)
if (is.null(S)) S <- 1e-10*as.matrix(diag(length(A0)))
if (is.null(W)) W <- 1e-10*as.matrix(diag(length(Sig0)))
# Reshape initial parameter vector
aux <- rep(NA,M^2 + M)
aux[1:M] <- B0[,1]
for (ll in 1:M){
aux[(M+1+(ll-1)*M):(M+ll*M)] <- B0[ll,2:(M+1)]
}
B0 <- aux
# Initialize stuff
npar <- length(B0)
ystar <- matrix(0,1,M)
Btsim <- B0
Btall <- array(NA, c(M,M + 1, t))
Htall <- array(NA, c(M,M,t))
corall <- matrix(NA,M*(M-1)*0.5,t)
sigall <- matrix(NA,M,t)
Atsim <- A0
Sigtsim <- Sig0
Q.c <- t(chol(Q))
S.c <- t(chol(S))
W.c <- t(chol(W))
yall <- matrix(NA,t,M)
for (j in 1:(t+init)){
# Draw Bt
Btsim <- Btsim + Q.c %*% rnorm(npar)
# Draw At
Atsim <- Atsim + S.c %*% rnorm(length(Atsim))
# Draw Sigt
Sigtsim <- Sigtsim + W.c %*% rnorm(M)
# Create the VAR covariance matrix
capAtsim <- diag(M)
ic <- 1
for (k in 2:M){
capAtsim[k,1:(k-1)] <- t(Atsim[ic:(ic+k-2)])
ic <- ic + k - 1
}
Hsim <- solve(capAtsim)*diag(as.vector(exp(0.5*Sigtsim)))
Hsim <- Hsim %*% t(Hsim)
# Draw Yt
Zsim <- makeregs.fc(ystar,1)
ysim <- Zsim %*% Btsim + t(chol(Hsim)) %*% rnorm(M)
ystar <- rbind(ystar, t(ysim))
# Save post-init draws
if (j > init){
Btall[,,j-init] <- Btsim
Htall[,,j-init] <- Hsim
yall[j-init,] <- t(ysim)
}
}
# Return list
return(list(data = yall, Beta = Btall, H = Htall))
})
##############################################################################
# Get parameters of mixture normal approximation to log-chi2 distribution
##############################################################################
getmix <- cmpfun(function(){
q <- c(0.00730, 0.10556, 0.00002, 0.04395, 0.34001, 0.24566, 0.25750) # probabilities
m <- c(-10.12999, -3.97281, -8.56686, 2.77786, 0.61942, 1.79518, -1.08819) # means
u2 <- c(5.79596, 2.61369, 5.17950, 0.16735, 0.64009, 0.34023, 1.26261) #variances
return(list(q=q,m=m,u2=u2))
})
##################################################
# Estimate Primiceri BVAR with SV and TVP
##################################################
bvar.sv.tvp <- cmpfun(function(Y, p = 1, tau = 40, nf = 10, pdrift = TRUE, nrep = 50000, nburn = 5000, thinfac = 10, itprint = 10000, save.parameters = TRUE, k_B = 4, k_A = 4, k_sig = 1, k_Q = 0.01, k_S = 0.1, k_W = 0.01, pQ = NULL, pW = NULL, pS = NULL){
# Input checks
if (is.null(ncol(Y))) stop( "Y must be a matrix with at least two columns" )
if (is.matrix(Y)) if (ncol(Y) < 2) stop( "Y must be a matrix with at least two columns" )
if (p != as.integer(p)) stop( "p: Number of lags must be in {1, 2, 3,...}" )
if ((tau + p) >= nrow(Y)) stop( "Too few observations for the given choices of p and tau" )
if (nf < 1) stop( "Please set nf to 1 or higher ")
if (nf != as.integer(nf)){
nf <- round(nf)
warning( "nf rounded to nearest integer" )
}
if ( any(c(k_Q, k_S, k_W) <= 0) | any(c(length(k_Q), length(k_S), length(k_W)) != 1) ) stop( "Prior parameters in k_Q, k_S and k_W must be strictly positive scalars" )
# Default values for prior parameters
if (is.null(pQ)) Qprior <- tau else Qprior <- pQ
if (is.null(pW)) Wprior <- dim(Y)[2] + 1 else Wprior <- pW
if (is.null(pS)) Sprior <- (1:(dim(Y)[2])) + 1 else Sprior <- pS
# Matrix dimensions
t <- dim(Y)[1] # Time series and cross section dimensions
M <- dim(Y)[2]
numa <- 0.5*M*(M-1) # Nr of VCV matrix elements
K <- M + p*(M^2) # Nr of beta parameters
# Make VAR regressor matrix
Z <- makeregs(Y,tau,p)
# Redefine LHS variables
y <- t(Y[(tau+p+1):t,])
t <- dim(y)[2] # new sample size for Bayes analysis
# Numerical parameters for initializing draws
consQ <- 0.0001
consS <- 0.0001
consH <- 0.01
consW <- 0.0001
# Get OLS inputs for prior parameters
prior <- tsprior(Y[1:(tau+p),],p,2000)
# Make prior parameters (Gaussian priors)
B_0_prmean <- prior$B_OLS
B_0_prvar <- k_B*prior$VB_OLS
A_0_prmean <- prior$A_OLS
A_0_prvar <- k_A*prior$VA_OLS
# log Gaussian prior
sigma_prmean <- prior$sigma_OLS
sigma_prvar <- k_sig*diag(M)
# inverse Wishart priors (Q = covariance of B(t), W = covariance of log SIGMA(t), S = covariance of A(t))
Q_prmean <- ((k_Q)^2)*Qprior*prior$VB_OLS
Q_prvar <- Qprior
W_prmean <- ((k_W)^2)*Wprior*diag(M)
W_prvar <- Wprior
S_prmean <- vector("list",M-1)
S_prvar <- matrix(0,M-1,1)
ind <- 1
for (ii in 2:M){
S_prmean[[ii-1]] <- ((k_S)^2)*Sprior[ii-1]*prior$VA_OLS[((ii-1)+(ii-3)*(ii-2)/2):ind,((ii-1)+(ii-3)*(ii-2)/2):ind];
S_prvar[ii-1,1] <- Sprior[ii-1]
ind <- ind + ii
}
# Initialize empty matrices for posterior draws
Ht <- matrix(1,t,1) %x% (consH*diag(M))
Htchol <- matrix(1,t,1) %x% (sqrt(consH)*diag(M))
Qdraw <- consQ*diag(K)
Sdraw <- consS*diag(numa)
Sblockdraw <- vector("list",M-1)
ijc <- 1
for (jj in 2:M){
Sblockdraw[[jj-1]] <- Sdraw[((jj-1)+(jj-3)*(jj-2)/2):ijc,((jj-1)+(jj-3)*(jj-2)/2):ijc]
ijc = ijc + jj
}
Wdraw <- consW*diag(M)
Btdraw <- matrix(0,K,t)
Atdraw <- matrix(0,numa,t)
Sigtdraw <- matrix(0,M,t)
sigt <- matrix(1,t,1) %x% (0.01*diag(M))
statedraw <- 5*matrix(1,t,M)
Zs <- matrix(1,t,1) %x% diag(M)
prw <- matrix(0,7,1)
# new stuff (March 29, 2015)
nrep2 <- nrep/thinfac # effective number of draws
# re-design forecast output (save only thinned draws)
fc.y <- fc.m <- array(0,c(M,nf,nrep2))
fc.v <- array(0,c(M*(M+1)*0.5,nf,nrep2))
if (save.parameters == TRUE){
# arrays for parameter draws
Bt.alldraws <- array(0, c(K,t,nrep2))
Ht.alldraws <- At.alldraws <- array(0, c(M,M*t,nrep2))
Sigt.alldraws <- array(0, c(M, t, nrep2))
} else {
Bt.alldraws <- Ht.alldraws <- NULL
}
# Storage matrices for (running) posterior means
Bt_postmean <- matrix(0,K,t)
At_postmean <- matrix(0,numa,t)
Sigt_postmean <- matrix(0,M,t)
Ht_postmean <- matrix(0,t,1) %x% (consH*diag(M))
Qmean <- matrix(0,K,K)
Smean <- matrix(0,numa,numa)
Wmean <- matrix(0,M,M)
sigmean <- matrix(0,t,M)
cormean <- matrix(0,t,numa)
sig2mo <- matrix(0,t,M)
cor2mo <- matrix(0,t,numa)
# Elements of mixture normal approximation to log chi2
tmp <- getmix()
q <- tmp$q
m <- tmp$m
u2 <- tmp$u2
# Gibbs sampler
prints <- seq(from=nburn,to=(nrep+nburn),by=itprint)
print(paste(Sys.time(),"-- now starting MCMC"))
# auxiliary counter for saved draws
aux.ct <- 0
for (irep in 1:(nrep+nburn)){
if (irep %in% prints) print(paste(Sys.time(),"-- now at iteration",irep))
# Draw beta
Btdraw <- carterkohn(y,Z,Ht,Qdraw,K,M,t,B_0_prmean,B_0_prvar)$bdraws
# Draw Q, the covariance of B(t)
sse_2 <- Btdraw[,2:t] - Btdraw[,1:(t-1)]
sse_2 <- sse_2 %*% t(sse_2)
Qdraw <- solve(rWishart(1,t+Q_prvar,solve(sse_2+Q_prmean))[,,1])
# Draw alpha
yhat <- alphahelper(y, Z, Btdraw)
Zc <- -t(yhat);
sigma2temp <- t(exp(Sigtdraw))
Atdraw <- {}
ind <- 1
for (ii in 2:M){
Atblockdraw <- carterkohn(yhat[ii,,drop=FALSE],Zc[,1:(ii-1),drop=FALSE],sigma2temp[,ii,drop=FALSE],matrix(Sblockdraw[[ii-1]],ii-1,ii-1), ii-1,1,t,A_0_prmean[((ii-1)+(ii-3)*(ii-2)/2):ind,],A_0_prvar[((ii-1)+(ii-3)*(ii-2)/2):ind,((ii-1)+(ii-3)*(ii-2)/2):ind,drop=FALSE])$bdraws
Atdraw <- rbind(Atdraw,Atblockdraw)
ind <- ind + ii
}
sse_2 <- Atdraw[,2:t] - Atdraw[,1:(t-1)]
sse_2 <- sse_2 %*% t(sse_2)
ijc <- 1
for (jj in 2:M){
Sinv <- solve(sse_2[((jj-1)+(jj-3)*(jj-2)/2):ijc,((jj-1)+(jj-3)*(jj-2)/2):ijc] + S_prmean[[jj-1]])
Sblockdraw[[jj-1]] <- solve(rWishart(1,t-1+S_prvar[jj-1],Sinv)[,,1])
ijc <- ijc + jj
}
# Draw Sigma
capAt <- sigmahelper1(Atdraw, M)
aux <- sigmahelper2(capAt, yhat, q, m, u2, Sigtdraw, Zs, Wdraw, sigma_prmean, sigma_prvar)
Sigtdraw <- aux$Sigtdraw
sigt <- aux$sigt
# Draw W, the covariance of SIGMA(t)
sse_2 <- Sigtdraw[,2:t] - Sigtdraw[,1:(t-1)]
sse_2 <- sse_2 %*% t(sse_2)
Wdraw <- solve(rWishart( 1, t + W_prvar, solve(sse_2 + W_prmean))[,,1])
# Create the VAR covariance matrix
aux2 <- sigmahelper3(capAt, sigt)
Ht <- aux2$Ht
Htsd <- aux2$Htsd
##############################################################################################################
# Save post-burnin draws and forecasts
##############################################################################################################
if ( (irep > nburn) & ( (irep-nburn) %% thinfac == 0) ){
aux.ct <- aux.ct + 1 # counter for saved draws
Bt_postmean <- Bt_postmean + Btdraw
At_postmean <- At_postmean + Atdraw
Sigt_postmean <- Sigt_postmean + Sigtdraw
Ht_postmean <- Ht_postmean + Ht
Qmean <- Qmean + Qdraw
ikc <- 1
for (kk in 2:M){
Sdraw[((kk-1)+(kk-3)*(kk-2)/2):ikc,((kk-1)+(kk-3)*(kk-2)/2):ikc] <- Sblockdraw[[kk-1]]
ikc <- ikc + kk
}
Smean <- Smean + Sdraw
Wmean <- Wmean + Wdraw
# Get time-varying correlations and variances
aux3 <- getvc(Ht)
sigmean <- sigmean + aux3$out1
cormean <- cormean + aux3$out2
# Forecasting part
if (pdrift == TRUE){
# Forecasts (with parameter drift)
tempfc <- getfcsts(lastcol(Btdraw), lastcol(Atdraw), lastcol(Sigtdraw), Qdraw, Sdraw, Wdraw, t(y), nf, p)
fc.m[,,aux.ct] <- tempfc$mean
fc.v[,,aux.ct] <- tempfc$variance
fc.y[,,aux.ct] <- tempfc$draw
} else {
# Forecasts (without parameter drift)
parmat <- beta.reshape(Btdraw[,t], M, p) # Current Beta parameter (in matrix format)
fcdat <- matrix(t(y[,(t-p+1):t]), nrow = p) # Conditioning data
auxb <- solve(sigmahelper1(matrix(lastcol(Atdraw), ncol = 1), M)) * diag(as.vector(exp(0.5*lastcol(Sigtdraw))))
tmpvar <- auxb %*% t(auxb) # Forecast variance
for (hhh in 1:nf){
auxl <- varfcst(parmat, tmpvar, fcdat, hhh)
fc.m[,hhh,aux.ct] <- auxl$mean
fc.v[,hhh,aux.ct] <- vechC(auxl$variance)
fc.y[,hhh,aux.ct] <- mvndrawC(auxl$mean, auxl$variance)
}
}
# Save parameter draws
if (save.parameters == TRUE){
Bt.alldraws[,,aux.ct] <- Btdraw
Ht.alldraws[,,aux.ct] <- t(Ht)
Sigt.alldraws[,,aux.ct] <- Sigtdraw
At.alldraws[,,aux.ct] <- t(capAt)
}
}
}
# Final steps
Bt_postmean <- Bt_postmean / nrep2
At_postmean <- At_postmean / nrep2
Sigt_postmean <- Sigt_postmean / nrep2
Ht_postmean <- Ht_postmean / nrep2
Qmean <- Qmean / nrep2
Smean <- Smean / nrep2
Wmean <- Wmean / nrep2
sigmean <- sigmean / nrep2
cormean <- cormean / nrep2
# Prepare outputs
beta.out <- array(NA,c(M,M*p+1,t))
h.out <- array(NA,c(M,M,t))
for (jj in 1:t){
beta.out[,,jj] <- beta.reshape(Bt_postmean[,jj], M, p)
h.out[,,jj] <- Ht_postmean[((jj-1)*M+1):(jj*M),]
}
# Return list of outputs
return(list(Beta.postmean = beta.out, H.postmean = h.out, Q.postmean = Qmean, S.postmean = Smean, W.postmean = Wmean, fc.mdraws = fc.m, fc.vdraws = fc.v, fc.ydraws = fc.y, Beta.draws = Bt.alldraws,
H.draws = Ht.alldraws, logs2.draws = Sigt.alldraws, A.draws = At.alldraws, M = M, p = p))
})
# Helper function to revert vech operator (needed to spot variance elements from VCV matrix)
vels <- cmpfun(function(n){
aux <- matrix(0, n, n)
aux[lower.tri(aux, diag = TRUE)] <- 1:(0.5*n*(n+1))
return(diag(aux))
})
predictive.density <- cmpfun(function(fit, v = 1, h = 1, cdf = FALSE){
# Retrieve number of variables/horizons from fit
nv <- length(fit$fc.ydraws[, 1, 1])
nh <- length(fit$fc.ydraws[1, , 1])
# Input check
if (v > nv | h > nh | v != round(v) | h != round(h)) stop("Please choose appropriate variable and horizon indices")
# Locate variance
v.ind <- vels(nv)[v]
# Get means and standard deviations
m <- fit$fc.mdraws[v, h, ]
s <- sqrt(fit$fc.vdraws[v.ind, h, ])
# Finally: Return forecast pdf/cdf
if (cdf == FALSE){
return(function(q) sapply(q, function(o) mean(dnorm(o, mean = m, sd = s))))
} else {
return(function(q) sapply(q, function(o) mean(pnorm(o, mean = m, sd = s))))
}
})
predictive.draws <- cmpfun(function(fit, v = 1, h = 1){
# Retrieve number of variables/horizons from fit
nv <- length(fit$fc.ydraws[, 1, 1])
nh <- length(fit$fc.ydraws[1, , 1])
# Input check
if (v > nv | h > nh | v != round(v) | h != round(h)) stop("Please choose appropriate variable and horizon indices")
# Draws for y
y <- fit$fc.ydraws[v, h, ]
# Draws for m
m <- fit$fc.mdraws[v, h, ]
# Draws for v
v <- fit$fc.vdraws[vels(nv)[v], h, ]
# Return draws in list
return(list(y = y, m = m, v = v))
})
parameter.draws <- cmpfun(function(fit, type = "lag1", row = 1, col = 1){
# Input checks
if (is.null(fit$Beta.draws)) stop("Parameter draws in fit have not been saved -- please run again, using the option `save.parameters = TRUE'.")
nms <- c("intercept", paste0("lag", 1:fit$p), "vcv")
if (!type %in% nms) stop(paste("Type unknown -- please enter one of the following:", paste(nms, collapse = "; ")))
if (type == "intercept"){
if (!row %in% 1:fit$M) stop(paste("Invalid row selected -- please enter one of the following:", paste(1:fit$M, collapse = "; ")))
} else if (type %in% c(paste0("lag", 1:fit$p), "vcv")){
if (!row %in% 1:fit$M | !col %in% 1:fit$M) stop(paste("Invalid row or col selected -- please enter one of the following:", paste(1:fit$M, collapse = "; ")))
}
# Intermediate stuff
Beta.draws <- fit$Beta.draws
t <- dim(Beta.draws)[2]
# Get parameters
if (type == "vcv"){
aux.seq <- seq(from = col, by = fit$M, length.out = t)
out <- t(fit$H.draws[row, aux.seq, ])
} else {
if (type == "intercept"){
# Parameter output
out <- t(Beta.draws[row, , ])
# Needed for checking below
aux.col <- 1
} else if (type %in% paste0("lag", 1:fit$p)){
# Lag order
lo <- as.numeric(substr(type, 4, nchar(type)))
# Find position in storage output
ind <- fit$M + (lo - 1)*(fit$M^2) + (row - 1)*fit$M + col
# Get draws
out <- t(Beta.draws[ind, , ])
# Needed for checking below
aux.col <- 1 + (lo-1)*fit$M + col
}
# Check (compare to slower beta.reshape function, for one randomly chosen MCMC draw and time period)
aux.ind <- sample.int(dim(Beta.draws)[3], 1)
aux.t <- sample.int(dim(Beta.draws)[2], 1)
if (out[aux.ind, aux.t] != beta.reshape(Beta.draws[, aux.t, aux.ind], fit$M, fit$p)[row, aux.col]) stop("Wrong output...")
}
# Message
if (type == "intercept"){
message(paste("Element", row, "of intercept vector. Format: MCMC draws in rows, time in columns."))
} else {
message(paste0("Element [", row, ",", col, "] of ", type, " matrix. Format: MCMC draws in rows, time in columns."))
}
return(out)
})
ARtoMA <- cmpfun(function(A, nhor){
# Infer dimensions from A parameters
M <- nrow(A)
p <- ncol(A)/M
Phi <- matrix(0, M, M*nhor)
# See recursive formula for MA (see e.g. page 28 in http://www.jmulti.de/download/help/var.pdf)
for (s in 1:nhor){
tmp <- matrix(0, M, M)
for (j in 1:s){
if (s == j){
aux <- diag(M)
} else {
aux <- Phi[, ((s-j-1)*M+1):((s-j)*M)]
}
if (j <= p) tmp <- tmp + aux %*% A[,((j-1)*M+1):(j*M)]
}
Phi[,((s-1)*M+1):(s*M)] <- tmp
}
Phi
})
matmult <- cmpfun(function(mat, mult){
if (mult == 0){
out <- diag(nrow(mat))
} else if (mult == 1){
out <- mat
} else {
out <- mat
for (c in 1:(mult-1)) out <- out %*% mat
}
return(out)
})
IRFmats <- cmpfun(function(A, H.chol = NULL, nhor, orthogonal = TRUE){
# Dimensions
M <- nrow(A) # nr of variables
# AR matrices
p <- ncol(A)/M
# Construct companion form matrices
if (p > 1){
# VAR matrices
Ac <- matrix(0, M*p, M*p)
Ac[1:M, ] <- A
Ac[-(1:M), 1:(M*(p-1))] <- diag(M*(p-1))
} else {
Ac <- A
}
# Matrix with impulse responses
Phi <- matrix(0, M, M*(nhor+1))
for (s in 0:nhor){
aux <- matmult(Ac, s)[1:M, 1:M]
if (!is.null(H.chol)) aux <- aux %*% H.chol
Phi[,(s*M+1):((s+1)*M)] <- aux
}
Phi
})
impulse.responses <- cmpfun(function(fit, impulse.variable = 1, response.variable = 2, t = NULL, nhor = 20, scenario = 2, draw.plot = TRUE){
# Get coefficient draws from fit
Beta.draws <- fit$Beta.draws
nd <- dim(Beta.draws)[3]
if (is.null(t)) t <- dim(Beta.draws)[2]
out <- matrix(0, nd, nhor + 1)
M <- fit$M
p <- fit$p
# Get relevant stuff for VCV matrix
H.sel <- fit$H.draws[,((t-1)*M+1):(t*M),]
A.sel <- fit$A.draws[,((t-1)*M+1):(t*M),]
if (scenario == 3){
# Compute mean of sigma (over both time and MCMC draws, as in Primiceri's code)
sig <- apply(exp(0.5*fit$logs2.draws), 1, mean)
sig <- diag(sig)
} else {
sig <- NULL
}
# Compute IR for each MC iteration
for (j in 1:nd){
# Cholesky of VCV matrix, depending on specification
if (scenario == 1){ # No orthogonalization at all
H.chol <- NULL
} else if (scenario == 2){ # Standard orthogonalization
H.chol <- t(chol(H.sel[,,j]))
} else if (scenario == 3){ # Orthogonalization as in Primiceri
H.chol <- t(solve(A.sel[,,j])) %*% sig
}
# Compute Impulse Responses
aux <- IRFmats(A = beta.reshape(Beta.draws[,t,j], M, p)[,-1], H.chol = H.chol, nhor = nhor)
aux <- aux[response.variable, seq(from = impulse.variable, by = M, length = nhor + 1)]
out[j,] <- aux
}
# Make plot
if (draw.plot){
pdat <- t(apply(out[,-1], 2, function(z) quantile(z, c(0.05, 0.25, 0.5, 0.75, 0.95))))
xax <- 1:nhor
matplot(x = xax, y = pdat, type = "n", ylab = "", xlab = "Horizon", bty = "n", xlim = c(1, nhor))
polygon(c(xax, rev(xax)), c(pdat[,5], rev(pdat[,4])), col = "grey60", border = NA)
polygon(c(xax, rev(xax)), c(pdat[,4], rev(pdat[,3])), col = "grey30", border = NA)
polygon(c(xax, rev(xax)), c(pdat[,3], rev(pdat[,2])), col = "grey30", border = NA)
polygon(c(xax, rev(xax)), c(pdat[,2], rev(pdat[,1])), col = "grey60", border = NA)
lines(x = xax, y = pdat[,3], type = "l", col = 1, lwd = 2.5)
abline(h = 0, lty = 2)
}
list(contemporaneous = out[,1], irf = out[,-1])
})
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.