FK83 / bvarsv

Analysis of the Primiceri (REStud, 2005) model
28 stars 14 forks source link

Two questions about "path" of predictive.draws #12

Open RightHandOfDoom opened 8 months ago

RightHandOfDoom commented 8 months ago

Hello! First: thanks for this awesome package!

The first question I have a question is about the output of the predictive.draws()-function. This is my workflow:

data(usmacro.update) library(purrr) model<-bvar.sv.tvp(usmacro.update,nrep=500,nburn=50)

inf_proj<-map(1:10, function(h) predictive.draws(model,v=1, h=h)$y) une_proj<-map(1:10, function(h) predictive.draws(model,v=2,h=h)$y) ir_proj<-map(1:10, function(h) predictive.draws(model,v=3,h=h)$y)

this gives me three objects (one for each variable), which are lists with 10 entries each (one for each forecast horizon), where each list entry is 50 forecast draws at any horizon. For instance, inf_proj[[3]] is a numeric vector with 50 draws of of the first variable (inflation) three periods ahead.

The question I have is how these entries relate to earlier forecast horizons (i.e. inf_proj[[1]] and inf_proj[[2]]) as well as later ones (e.g. inf_proj[[4]], inf_proj[[5]], and so on). The reason is that I want to trace out "paths" of forecasted variables over the forecast horizon, e.g. the path a variable could take from t+1 to t+10.

The second questions I have is about the connection between predictive draws for all variables at any given horizon. For instance, how are the draws for inf_proj[[3]], une_proj[[3]], and ir_proj[[3]] related to one another, as well as to previous draws?

The reason I am asking is because in the end, I would like to produce predictive draws for the first and the second variable when the third follows a provided path. For instance, the vector c(0.022,0.025,0.0275,0.03,0.03,0.035,0.03,0.030.028,0.025).

To achieve this, my approach would have been to re-write the bvar.sv.tvp-functions such that the predictive draws for the third variable at every horizon are the same number (e.g. 50 draws of 0.022 for h=1, 50 draws of 0.025 for h=2, .. and so forth).

Any help or hint is deeply appreciated! Thank you very much for your support!

mboldin commented 8 months ago

I have worked on cases for classical VAR modeling with similar objectives, holding one item fixed or on a fixed path and simulating forward the remainder of the VAR.

In the non Bayesian VAR case I would make a custom re-formulation of the model (not re estimating but modifying the equations) and then use a 'canned' bootstrap simulator on this model

For the Bayesian case it is harder if you want to be truly Bayesian all the way through. But there is an option to simply treat the BVAR parameters as if they came from a classical VAR and reformulate.

I would need to know more about your model to say more or how.

For your other questions, I will look at the predictive draw routine and verify it is bootstrap like. If so on each draw, the next forecast would be tied directly to the prior in a chain p(y(t+1)~|y(t)) where ~ represents a random variable, while y(t) is fixed. So everything in a full draw is connected and independently derived from any other draw.

On Sun, Feb 25, 2024, 2:16 AM RightHandOfDoom @.***> wrote:

Hello! First: thanks for this awesome package!

The first question I have a question is about the output of the predictive.draws()-function. This is my workflow:

data(usmacro.update) library(purrr) model<-bvar.sv.tvp(usmacro.update,nrep=500,nburn=50)

inf_proj<-map(1:10, function(h) predictive.draws(model,v=1, h=h)$y) une_proj<-map(1:10, function(h) predictive.draws(model,v=2,h=h)$y) ir_proj<-map(1:10, function(h) predictive.draws(model,v=3,h=h)$y)

this gives me three objects (one for each variable), which are lists with 10 entries each (one for each forecast horizon), where each list entry is 50 forecast draws at any horizon. For instance, inf_proj[[3]] is a numeric vector with 50 draws of of the first variable (inflation) three periods ahead.

The question I have is how these entries relate to earlier forecast horizons (i.e. inf_proj[[1]] and inf_proj[[2]]) as well as later ones (e.g. inf_proj[[4]], inf_proj[[5]], and so on). The reason is that I want to trace out "paths" of forecasted variables over the forecast horizon, e.g. the path a variable could take from t+1 to t+10.

The second questions I have is about the connection between predictive draws for all variables at any given horizon. For instance, how are the draws for inf_proj[[3]], une_proj[[3]], and ir_proj[[3]] related to one another, as well as to previous draws?

The reason I am asking is because in the end, I would like to produce predictive draws for the first and the second variable when the third follows a provided path. For instance, the vector c(0.022,0.025,0.0275,0.03,0.03,0.035,0.03,0.030.028,0.025).

To achieve this, my approach would have been to re-write the bvar.sv.tvp-functions such that the predictive draws for the third variable at every horizon are the same number (e.g. 50 draws of 0.022 for h=1, 50 draws of 0.025 for h=2, .. and so forth).

Any help or hint is deeply appreciated! Thank you very much for your support!

— Reply to this email directly, view it on GitHub https://github.com/FK83/bvarsv/issues/12, or unsubscribe https://github.com/notifications/unsubscribe-auth/AASXOMXQUMCQXYCYEXNK3ELYVLQNFAVCNFSM6AAAAABDYUNZEKVHI2DSMVQWIX3LMV43ASLTON2WKOZSGE2TENRTGY3DGNQ . You are receiving this because you are subscribed to this thread.Message ID: @.***>

RightHandOfDoom commented 8 months ago

Hello @mboldin !! Thank you very much for your helpful response. However, I am sadly not very experienced in these operations. Here is the an R-rewrite of the "getfcsts"function which produces the predictive draw (it is used inside the bvar.sv.tvp()-function): [Yes, I used ChatGPT to rewrite this :D - it might contain some errors]

getfcsts <- function(Bt0, At0, Sigt0, Qdraw, Sdraw, Wdraw, ydat, nf, p) {

Initialize parameters

Btfc <- Bt0 Atfc <- At0 Sigtfc <- Sigt0 ystar <- ydat M <- ncol(ystar) fcd <- matrix(0, nrow = M, ncol = nf) fcm <- matrix(0, nrow = M, ncol = nf) fcv <- matrix(0, nrow = M * (M + 1) / 2, ncol = nf)

for (hh in 1:nf) {

Draw Bt

Btfc <- Btfc + mvndrawC(rep(0, length(Btfc)), Qdraw)
# Draw At
Atfc <- Atfc + mvndrawC(rep(0, length(Atfc)), Sdraw)
# Draw Sigt
Sigtfc <- Sigtfc + mvndrawC(rep(0, length(Sigtfc)), Wdraw)

# Create the VAR covariance matrix
aux1 <- Atfc
capAtfc <- sigmahelper1(aux1, M)
aux2 <- matrix(0, nrow = M, ncol = M)
diag(aux2) <- exp(0.5 * Sigtfc)
Hfc <- solve(capAtfc) %*% aux2
Hfc <- Hfc %*% t(Hfc)

# Save fc variance
fcv[, hh] <- vechC(Hfc)

# Make & save fc mean
Zfc <- makeregs_fcC(ystar, p)
mtemp <- Zfc %*% Btfc
fcm[, hh] <- mtemp

# Draw & save realization
ytemp <- mvndrawC(mtemp, Hfc)
ystar <- cbind(ystar, t(ytemp))
fcd[, hh] <- ytemp

}

return(list(mean = fcm, variance = fcv, draw = fcd)) }

####################################################### along with rewrites of the helper functions: sigmahelper1 <- function(Atdraw, M) { t <- ncol(Atdraw) capAt <- matrix(0, nrow = M * t, ncol = M)

for (i in 1:t) { capatemp <- diag(M) aatemp <- Atdraw[, i] ic <- 1 for (j in 2:(M + 1)) { capatemp[j - 1, 1:(j - 1)] <- t(aatemp[ic:(ic + j - 3)]) ic <- ic + j - 1 } capAt[(i - 1) M + 1:(i M), ] <- capatemp } return(capAt)}

makeregs_fcC <- function(ydat, p) { M <- ncol(ydat) out <- diag(M) aux <- out

for (i in 1:p) { tmp <- ydat[nrow(ydat) - i + 1, ] out <- cbind(out, kronecker(aux, tmp)) } return(out)}

mvndrawC <- function(mu, sig) { k <- length(mu) aux <- rnorm(k) csig <- t(chol(sig)) out <- mu + csig %*% aux return(out)} #######################################################

My original idea am was trying to rewrite getfcsts() to draw values for the non-pre-specified ones after setting the path. For instance, I asked the world's most popular chatbot how this function needed to be modified given a value for variable 3 at horizon 4 (just to see how the plumbing would work). The result is this:

"getfcsts_fixed <- function(Bt0, At0, Sigt0, Qdraw, Sdraw, Wdraw, ydat, nf, p, val3_hor4_fix) {

Initialize parameters

Btfc <- Bt0 Atfc <- At0 Sigtfc <- Sigt0 ystar <- ydat M <- ncol(ystar) fcd <- matrix(0, nrow = M, ncol = nf) fcm <- matrix(0, nrow = M, ncol = nf) fcv <- matrix(0, nrow = M * (M + 1) / 2, ncol = nf)

for (hh in 1:nf) {

Fix value for variable 3 at horizon 4

ytemp <- rep(0, M)
if (hh == 4) {
  ytemp[3] <- val3_hor4_fix
}

# Draw Bt
Btfc <- Btfc + mvndrawC(rep(0, length(Btfc)), Qdraw)
# Draw At
Atfc <- Atfc + mvndrawC(rep(0, length(Atfc)), Sdraw)
# Draw Sigt
Sigtfc <- Sigtfc + mvndrawC(rep(0, length(Sigtfc)), Wdraw)

# Create the VAR covariance matrix
aux1 <- Atfc
capAtfc <- sigmahelper1(aux1, M)
aux2 <- matrix(0, nrow = M, ncol = M)
diag(aux2) <- exp(0.5 * Sigtfc)
Hfc <- solve(capAtfc) %*% aux2
Hfc <- Hfc %*% t(Hfc)

# Save fc variance
fcv[, hh] <- vechC(Hfc)

# Make & save fc mean
Zfc <- makeregs_fcC(ystar, p)
mtemp <- Zfc %*% Btfc
fcm[, hh] <- mtemp

# Draw & save realization for variables 1 and 2
ytemp[-3] <- mvndrawC(mtemp[-3], Hfc[-3, -3])

ystar <- cbind(ystar, t(ytemp))
fcd[, hh] <- ytemp

}

return(list(mean = fcm, variance = fcv, draw = fcd)) } " Please let me know if anything comes to your mind. Greatly appreciated !!

mboldin commented 8 months ago

Two problems --

1 for your first set of code

data(usmacro.update) I get

Warning message: In data(usmacro.update) : data set ‘usmacro.update’ not found

2 for your second set of code, I did to see any function call or steps to use the functions

On Sun, Feb 25, 2024 at 3:13 PM RightHandOfDoom @.***> wrote:

Hello @mboldin https://github.com/mboldin !! Thank you very much for your helpful response. However, I am sadly not very experienced in these operations. Here is the an R-rewrite of the "getfcsts"function which produces the predictive draw (it is used inside the bvar.sv.tvp()-function): [Yes, I used ChatGPT to rewrite this :D - it might contain some errors]

getfcsts <- function(Bt0, At0, Sigt0, Qdraw, Sdraw, Wdraw, ydat, nf, p) { Initialize parameters

Btfc <- Bt0 Atfc <- At0 Sigtfc <- Sigt0 ystar <- ydat M <- ncol(ystar) fcd <- matrix(0, nrow = M, ncol = nf) fcm <- matrix(0, nrow = M, ncol = nf) fcv <- matrix(0, nrow = M * (M + 1) / 2, ncol = nf)

for (hh in 1:nf) {

Draw Bt

Btfc <- Btfc + mvndrawC(rep(0, length(Btfc)), Qdraw)

Draw At

Atfc <- Atfc + mvndrawC(rep(0, length(Atfc)), Sdraw)

Draw Sigt

Sigtfc <- Sigtfc + mvndrawC(rep(0, length(Sigtfc)), Wdraw)

Create the VAR covariance matrix

aux1 <- Atfc capAtfc <- sigmahelper1(aux1, M) aux2 <- matrix(0, nrow = M, ncol = M) diag(aux2) <- exp(0.5 Sigtfc) Hfc <- solve(capAtfc) %% aux2 Hfc <- Hfc %*% t(Hfc)

Save fc variance

fcv[, hh] <- vechC(Hfc)

Make & save fc mean

Zfc <- makeregs_fcC(ystar, p) mtemp <- Zfc %*% Btfc fcm[, hh] <- mtemp

Draw & save realization

ytemp <- mvndrawC(mtemp, Hfc) ystar <- cbind(ystar, t(ytemp)) fcd[, hh] <- ytemp

}

return(list(mean = fcm, variance = fcv, draw = fcd)) }

####################################################### along with rewrites of the helper functions: sigmahelper1 <- function(Atdraw, M) { t <- ncol(Atdraw) capAt <- matrix(0, nrow = M * t, ncol = M)

for (i in 1:t) { capatemp <- diag(M) aatemp <- Atdraw[, i] ic <- 1 for (j in 2:(M + 1)) { capatemp[j - 1, 1:(j - 1)] <- t(aatemp[ic:(ic + j - 3)]) ic <- ic + j - 1 } capAt[(i - 1) M + 1:(i M), ] <- capatemp } return(capAt)}

makeregs_fcC <- function(ydat, p) { M <- ncol(ydat) out <- diag(M) aux <- out

for (i in 1:p) { tmp <- ydat[nrow(ydat) - i + 1, ] out <- cbind(out, kronecker(aux, tmp)) } return(out)}

mvndrawC <- function(mu, sig) { k <- length(mu) aux <- rnorm(k) csig <- t(chol(sig)) out <- mu + csig %*% aux return(out)} #######################################################

My original idea am was trying to rewrite getfcsts() to draw values for the non-pre-specified ones after setting the path. For instance, I asked the world's most popular chatbot how this function needed to be modified given a value for variable 3 at horizon 4 (just to see how the plumbing would work). The result is this:

"getfcsts_fixed <- function(Bt0, At0, Sigt0, Qdraw, Sdraw, Wdraw, ydat, nf, p, val3_hor4_fix) { Initialize parameters

Btfc <- Bt0 Atfc <- At0 Sigtfc <- Sigt0 ystar <- ydat M <- ncol(ystar) fcd <- matrix(0, nrow = M, ncol = nf) fcm <- matrix(0, nrow = M, ncol = nf) fcv <- matrix(0, nrow = M * (M + 1) / 2, ncol = nf)

for (hh in 1:nf) {

Fix value for variable 3 at horizon 4

ytemp <- rep(0, M) if (hh == 4) { ytemp[3] <- val3_hor4_fix }

Draw Bt

Btfc <- Btfc + mvndrawC(rep(0, length(Btfc)), Qdraw)

Draw At

Atfc <- Atfc + mvndrawC(rep(0, length(Atfc)), Sdraw)

Draw Sigt

Sigtfc <- Sigtfc + mvndrawC(rep(0, length(Sigtfc)), Wdraw)

Create the VAR covariance matrix

aux1 <- Atfc capAtfc <- sigmahelper1(aux1, M) aux2 <- matrix(0, nrow = M, ncol = M) diag(aux2) <- exp(0.5 Sigtfc) Hfc <- solve(capAtfc) %% aux2 Hfc <- Hfc %*% t(Hfc)

Save fc variance

fcv[, hh] <- vechC(Hfc)

Make & save fc mean

Zfc <- makeregs_fcC(ystar, p) mtemp <- Zfc %*% Btfc fcm[, hh] <- mtemp

Draw & save realization for variables 1 and 2

ytemp[-3] <- mvndrawC(mtemp[-3], Hfc[-3, -3])

ystar <- cbind(ystar, t(ytemp)) fcd[, hh] <- ytemp

}

return(list(mean = fcm, variance = fcv, draw = fcd)) } " Please let me know if anything comes to your mind. Greatly appreciated !!

— Reply to this email directly, view it on GitHub https://github.com/FK83/bvarsv/issues/12#issuecomment-1963048281, or unsubscribe https://github.com/notifications/unsubscribe-auth/AASXOMQPTIIRSN5JG6BVT7TYVOLOBAVCNFSM6AAAAABDYUNZEKVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTSNRTGA2DQMRYGE . You are receiving this because you were mentioned.Message ID: @.***>