使用 R 中的 VECM 用已知的 X 预报 Y

Nowcasting Y with known X, using VECM in R

我正在尝试使用另一个时间序列 (X) 作为预测变量来对时间序列数据 (Y) 进行临近预报。 X 和 Y 是协整的。 Y是2012年1月到2016年10月的月度数据,X是2012年1月到2017年2月的月度数据。

因此,我 运行 视频中显示的 VECM:https://www.youtube.com/watch?v=x9DcUA9puY0

然后,为了获得预测值,我 运行 通过 vec2var 命令在 VAR 中形成了它,并遵循了本主题的信息:https://stats.stackexchange.com/questions/223888/how-to-forecast-from-vecm-in-r

但是我无法用已知的 X 预测 Y,如何使用具有线性回归模型的 predict 函数来预测它。另外,我无法获得建模的 Y(Y 帽子)值。

这是我的代码:

# Cointegrated_series is a ZOO object, which contains two time series X and Y

library("zoo") 
library("xts") 
library("urca")
library("vars")

# Obtain lag length
Lagl <- VARselect(Cointegrated_series)$selection[[1]]

#Conduct Eigen test
cointest <- ca.jo(Cointegrated_series,K=Lagl,type = "eigen", ecdet = "const", 
                    spec = "transitory")
#Fit VECM
vecm <- cajorls(cointest)

#Transform VECM to VAR
var <- vec2var(cointest)

我尝试以不同的方式使用 predict 函数:predict(var)predict(var, newdata = 50)predict(var, newdata = 1000) - 结果相同。

尝试在 predict 方法中使用 tsDyn 包和 newdata 参数,如这里所述:https://stats.stackexchange.com/questions/261849/prediction-from-vecm-in-r-using-external-forecasts-of-regressors?rq=1

不工作。我的 newdata 是一个 ZOO 对象,其中 X 系列的值为 2016 年 11 月至 2017 年 2 月,Y 系列为 NA。因此,方法 returns NAs in forecast:

    # Cointegrated_series is a ZOO object, which contains 
#two time series X and Y from Jan 2012 to Oct 2016. Both X and Y are values.
    # newDat is a ZOO object, which contains two time series 
#X and Y from Nov 2016 to Feb 2017. X are values, Y are NAs.

    library(tsDyn)

    vecm <-VECM(Cointegrated_series, lag=2)

    predict(vecm,newdata = newDat, n.ahead=5)

这是一个结果:

                                                    Y             X
59                                                  NA            NA
60                                                  NA            NA
61                                                  NA            NA
62                                                  NA            NA
63                                                  NA            NA

例如,这是我在没有 newdata 参数的情况下调用 predict 后得到的结果:

predict(vecm, n.ahead=5)

                                              Y             X
59                                            65.05233      64.78006
60                                            70.54545      73.87368
61                                            75.65266      72.06513
62                                            74.76065      62.97242
63                                            70.03992      55.81045

所以,我的主要问题是:

  1. 如何使用 R 中的 VEC 模型用已知的 X 对 Y 进行临近预报?
  2. 如何获取建模的 Y(Y 帽子)值?

除此之外,我也找不到这些问题的答案:

  1. 如何在 R 中为 VECM 调用 Akaike 标准 (AIC)?

  2. vars 和 urca 包是否提供 VECM 的 F 和 t 统计信息?

UPD 10.04.2017 我稍微编辑了这个问题。请注意,我的问题适用于 "ragged edge" 问题,将其称为 "forecasting" 是不正确的 - 它是 "nowcasting".

UPD 11.04.2017

感谢您的回答!

完整代码如下:

library("lubridate")
library("zoo")
library("xts") 
library("urca")
library("vars")
library("forecast") 



Dat <- dget(file = "https://getfile.dokpub.com/yandex/get/https://yadi.sk/d/VJpQ75Rz3GsDKN")
NewDat <- dget(file = "https://getfile.dokpub.com/yandex/get/https://yadi.sk/d/T7qxxPUq3GsDLc")



Lagl <- VARselect(Dat)$selection[[1]]

#vars package

cointest_e <- ca.jo(Dat,K=Lagl,type = "eigen", ecdet = "const", 
                    spec = "transitory")


vecm <- cajorls(cointest_e)

var <- vec2var(cointest_e)

Predict1 <- predict(var)

Predict2 <- predict(var, newdata = NewDat)

Predict1$fcst$Y
Predict2$fcst$Y

Predict1$fcst$Y == Predict2$fcst$Y
Predict1$fcst$X == Predict2$fcst$X

#As we see, Predict1 and Predict2 are similar, so the information in NewDat
#didn't came into account.

library("tsDyn")

vecm2 <-VECM(Dat, lag=3)

predict(vecm2)
predict(vecm2, newdata=NewDat)

如果dget会return出错,请在这里下载我的数据:

https://yadi.sk/d/VJpQ75Rz3GsDKN - 数据

https://yadi.sk/d/T7qxxPUq3GsDLc - 对于 NewDat

关于临近预报

临近预报 我的意思是使用当前可用数据对不可用数据进行当月或上月预测。以下是一些参考资料:

Gianonne, Reichlin, Small:临近预报:宏观经济数据的实时信息内容 (2008)

Now-Casting 和实时数据流 (2013)

Marcellino, Schumacher:使用不规则边缘数据进行临近预报和预测的因子 MIDAS:德国 GDP 模型比较 (2010)

我觉得你的问题更多的是关于如何对协整变量进行临近预报,那我们稍后看看如何在 R 中实现它。

一般来说,根据格兰杰表示定理,协整变量可以用多种形式表示:

  • 长期关系:y 和 x 的同期值

  • VECM 表示:y 和 x 的(差异)由滞后(差异)和上一周期的纠错项解释。

所以我不确定您将如何在 VECM 表示中进行临近预报,因为它只包含过去的值?我可以看到两种可能性:

  1. 根据长期关系进行临近预报。所以你只需 运行 标准 OLS,然后从那里进行预测。

  2. 基于结构 VECM 进行临近预报,在其中添加已知变量 (X) 的同期值。在 R 中,您将执行此包 urca,但您需要检查 predict 函数是否允许您添加已知的 X 值。

关于长期关系方法,有趣的是您可以根据 VECM(X 未知)和 X 已知的 LT 获得 X 和 Y 的预测。这为您提供了一种方法关于模型准确性的想法(比较已知和预测的 X),您可以使用它来为 Y 创建预测平均方案?

首先,非常感谢@Matifou 提供的精彩包。 我回复晚了,但我也在努力找出同样的问题,但我没有找到解决方案。这就是我实现以下功能的原因,希望它对某些人有用:

#' @title Special predict method for VECM models
#' @description Predict method for VECM models given some known endogenus
#'  variables are known but one. It is just valid for one cointegration equation by the moment
#' @param object, an object of class ‘VECM’
#' @param new_data, a dataframe containing the forecast of all the endogenus variables
#'  but one, if there are exogenus variables, its forecast must be provided.
#' @param predicted_var, a string with the desired endogenus variable to be predicted.
#' @return A list with the predicted variable, predicted values and a dataframe with the
#' detailed values used for the construction of the forecast.
#' @examples
#' data(zeroyld)
#' # Fit a VECM with Johansen MLE estimator:
#' vecm.jo<-VECM(zeroyld, lag=2, estim="ML")
#' predict.vecm(vecm.jo, new_data = data.frame("long.run" = c(7:10)), predicted_var = "short.run")

predict.vecm <- function(object, new_data, predicted_var){
  if (inherits(object, "VECM")) {
    # Just valid for VECM models
    # Get endogenus and exogenus variables
    summary_vecm <- summary(object)
    model_vars <- colnames(object$model)
    endovars <- sub("Equation ", "", rownames(summary_vecm$bigcoefficients))
    if (!(predicted_var %in% endovars)) {
      stop("You must provide a valid endogenus variable.")
    }
    exovars <- NULL
    if (object$exogen) {
      ind_endovars <-
        unlist(sapply(endovars, function(x) grep(x, model_vars), simplify = FALSE))
      exovars <- model_vars[-ind_endovars]
      exovars <- exovars[exovars != "ECT"]
    }

    # First step: join new_data and (lags + 1) last values from the calibration data
    new_data <- data.frame(new_data)
    if (!all(colnames(new_data) %in% c(endovars, exovars))) {
      stop("new_data must have valid endogenus or exogenus column names.")
    }
    # Endovars but the one desired to be predicted
    endovars2 <- endovars[endovars != predicted_var]
    # if (!all(colnames(new_data) %in% c(endovars2, exovars))) {
    #   stop("new_data must have valid endogenus (all but the one desired to predict) or exogenus column names.")
    # }
    new_data <- new_data[, c(endovars2, exovars), drop = FALSE]
    new_data <- cbind(NA, new_data)
    colnames(new_data) <- c(predicted_var, endovars2, exovars)
    # Previous values to obtain lag values and first differences (lags + 1)
    dt_tail <- data.frame(tail(object$model[, c(endovars, exovars), drop = FALSE], object$lag + 1))
    new_data <- rbind(dt_tail, new_data)

    # Second step: get long rung relationship forecast (ECT term)
    ect_vars <- rownames(object$model.specific$beta)
    if ("const" %in% ect_vars) {
      new_data$const <- 1
    }
    ect_coeff <- object$model.specific$beta[, 1]
    new_data$ECT_0 <-
      apply(sweep(new_data[, ect_vars], MARGIN = 2, ect_coeff, `*`), MARGIN = 1, sum)
    # Get ECT-1 (Lag 1)
    new_data$ECT <- as.numeric(quantmod::Lag(new_data$ECT_0, 1))

    # Third step: get differences of the endogenus and exogenus variables provided in new_data
    diff_data <- apply(new_data[, c(endovars, exovars)], MARGIN = 2, diff)
    colnames(diff_data) <- paste0("DIFF_", c(endovars, exovars))
    diff_data <- rbind(NA, diff_data)
    new_data <- cbind(new_data, diff_data)

    # Fourth step: get x lags of the endogenus and exogenus variables
    for (k in 1:object$lag) {
      iter <- myLag(new_data[, paste0("DIFF_", endovars)], k)
      colnames(iter) <- paste0("DIFF_", endovars, " -", k)
      new_data <- cbind(new_data, iter)
    }

    # Fifth step: recursive calculatioon
    vecm_vars <- colnames(summary_vecm$bigcoefficients)
    if ("Intercept" %in% vecm_vars) {
      new_data$Intercept <- 1
    }
    vecm_vars[!(vecm_vars %in% c("ECT", "Intercept"))] <-
      paste0("DIFF_", vecm_vars[!(vecm_vars %in% c("ECT", "Intercept"))])
    equation <- paste("Equation", predicted_var)
    equation_coeff <- summary_vecm$coefficients[equation, ]
    predicted_var2 <- paste0("DIFF_", predicted_var)
    for (k in (object$lag + 2):nrow(new_data)) {
      # Estimate y_diff
      new_data[k, predicted_var2] <-
        sum(sweep(new_data[k, vecm_vars], MARGIN = 2, equation_coeff, `*`))
      # Estimate y_diff lags
      for (j in 1:object$lag) {
        new_data[, paste0(predicted_var2, " -", j)] <-
          as.numeric(quantmod::Lag(new_data[, predicted_var2], j))
      }
      # Estimate y
      new_data[k, predicted_var] <-
        new_data[(k - 1), predicted_var] + new_data[k, predicted_var2]
      # Estimate ECT
      new_data[k, "ECT_0"] <- sum(sweep(new_data[k, ect_vars], MARGIN = 2, ect_coeff, `*`))
      if (k < nrow(new_data)) {
        new_data[k + 1, "ECT"] <- new_data[k, "ECT_0"]
      }
    }
    predicted_values <- new_data[(object$lag + 2):nrow(new_data), predicted_var]
  } else {
    stop("You must provide a valid VECM model.")
  }

  return(
    list(
      predicted_variable = predicted_var,
      predicted_values = predicted_values,
      data = new_data
    )
  )
}


# Lag function applied to dataframes
myLag <- function(data, lag) data.frame(unclass(data[c(rep(NA, lag), 1:(nrow(data)-`lag)),]))`

@Andrey Goloborodko,在你的例子中,你应该申请:

NewDat <- NewDat[-1,] #Just new data is necessary to be provided
predict.vecm(vecm2, new_data=NewDat, predicted_var = "Y")
# $predicted_variable
# [1] "Y"
# 
# $predicted_values
# [1] 65.05233 61.29563 59.45109
# 
# $data
#                  Y   X       ECT_0         ECT     DIFF_Y DIFF_X  DIFF_Y -1 DIFF_X -1  DIFF_Y -2
# jul. 2016 92.40506 100 -29.0616718          NA         NA     NA         NA        NA         NA
# ago. 2016 94.03255  78  -0.7115037 -29.0616718   1.627486    -22         NA        NA         NA
# sep. 2016 78.84268  53  14.4653067  -0.7115037 -15.189873    -25   1.627486       -22         NA
# oct. 2016 67.99277  52   4.8300645  14.4653067 -10.849910     -1 -15.189873       -25   1.627486
# nov. 2016 65.05233  51   3.1042967   4.8300645  -2.940435     -1 -10.849910        -1 -15.189873
# dic. 2016 61.29563  50   0.5622618   3.1042967  -3.756702     -1  -2.940435        -1 -10.849910
# ene. 2017 59.45109  55  -7.3556104   0.5622618  -1.844535      5  -3.756702        -1  -2.940435
#           DIFF_X -2  DIFF_Y -3 DIFF_X -3 Intercept
# jul. 2016        NA         NA        NA         1
# ago. 2016        NA         NA        NA         1
# sep. 2016        NA         NA        NA         1
# oct. 2016       -22         NA        NA         1
# nov. 2016       -25   1.627486       -22         1
# dic. 2016        -1 -15.189873       -25         1
# ene. 2017        -1 -10.849910        -1         1