Nothing
#' @importFrom grDevices dev.new
#' @importFrom graphics abline hist lines par
#' @importFrom methods missingArg
#' @importFrom stats pnorm pt density median model.extract model.matrix pgamma qgamma qnorm quantile rbeta rbinom rexp rgamma rnorm runif sd terms na.omit acf pacf qqnorm residuals
#' @importFrom utils setTxtProgressBar txtProgressBar
#' @importFrom Formula Formula model.part
#' @importFrom mvtnorm pmvnorm pmvt
#' @importFrom GIGrvg rgig
#' @importFrom coda mcmc
#' @title Returns of the closing prices of three financial indexes
#'
#' @description These data correspond to the returns on closing prices of the Colcap,
#' Bovespa, and S&P 500 indexes from February 10, 2010 to March 31, 2016 (1505 time
#' points). Colcap is a leading indicator of the price dynamics of the 20 most liquid
#' shares on the Colombian stock market. Bovespa is the Brazilian stock market index,
#' the world's thirteenth largest and most important stock exchange, and the first in
#' Latin America. Finally, the Standard & Poor's 500 (S&P 500) index is a stock index
#' based on the 500 largest companies in the United States.
#'
#' @docType data
#'
#' @usage data(returns)
#'
#' @format A data frame with 1505 rows and 4 variables:
#' \describe{
#' \item{Date}{a vector that indicates the date each measurement was performed.}
#' \item{COLCAP}{a numerical vector indicating the returns on closing prices of COLCAP.}
#' \item{SP500}{a numerical vector indicating the returns on closing prices of SP500.}
#' \item{BOVESPA}{a numerical vector indicating the returns on closing prices of BOVESPA.}
#' }
#' @keywords datasets
#' @references Romero, L.V. and Calderon, S.A. (2021) Bayesian estimation of a multivariate TAR model when the noise
#' process follows a Student-t distribution. Communications in Statistics - Theory and Methods, 50, 2508-2530.
#' @examples
#' data(returns)
#' dev.new()
#' plot(ts(as.matrix(returns[,-1])), main="Returns")
#'
"returns"
#'
#' @title Rainfall and two river flows in Colombia
#'
#' @description The data represent daily rainfall (in mm) and two river flows (in \eqn{m^3}/s)
#' in southern Colombia. A meteorological station located at an altitude of 2400 meters was
#' used to measure rainfall. The El Trebol hydrological station was used to measure the flow
#' in the Bedon river at an altitude of 1720 meters. The Villalosada hydrological station
#' measured the flow in the La Plata river at an altitude of 1300 meters. Geographically, the
#' stations are located near the equator. The last characteristic allows for control over
#' hydrological and meteorological factors that might distort the dynamic relationship between
#' rainfall and river flows. January 1, 2006, to April 14, 2009, was the sample period.
#' @docType data
#'
#' @usage data(riverflows)
#'
#' @format A data frame with 1200 rows and 4 variables:
#' \describe{
#' \item{Date}{a vector that indicates the date each measurement was performed.}
#' \item{Bedon}{a numerical vector indicating the Bedon river flow.}
#' \item{LaPlata}{a numerical vector indicating the La Plata river flow.}
#' \item{Rainfall}{a numerical vector indicating the rainfall.}
#' }
#' @keywords datasets
#' @references Calderon, S.A. and Nieto, F.H. (2017) Bayesian analysis of multivariate threshold autoregressive models
#' with missing data. Communications in Statistics - Theory and Methods, 46, 296-318.
#' @examples
#' data(riverflows)
#' dev.new()
#' plot(ts(as.matrix(riverflows[,-1])), main="Rainfall and river flows")
#'
"riverflows"
#'
#'
#' @title Deviance information criterion (DIC)
#' @description This function computes the Deviance Information Criterion (DIC) for objects of class \code{mtar}.
#' @param ... one or several objects of the class \emph{mtar}.
#' @param verbose an (optional) logical switch indicating if should the report of results be printed. By default,\code{verbose} is set to TRUE.
#' @param digits an (optional) integer indicating the number of digits to print. By default,\code{digits} is set to \code{max(3, getOption("digits") - 2)}.
#' @return A \code{data.frame} with the values of the DIC for each \emph{mtar} object in the input.
#' @references Spiegelhalter D.J., Best N.G., Carlin B.P. and Van Der Linde A. (2002) Bayesian Measures of Model Complexity and Fit.
#' Journal of the Royal Statistical Society Series B (Statistical Methodology), 64(4), 583–639.
#' @references Spiegelhalter D.J., Best N.G., Carlin B.P. and Van der Linde A. (2014). The deviance information criterion:
#' 12 years on. Journal of the Royal Statistical Society Series B (Statistical Methodology), 76(3), 485–493.
#' @export DIC
#' @seealso \link{WAIC}
#' @examples
#' \donttest{
#' ###### Example 1: Returns of the closing prices of three financial indexes
#' data(returns)
#' fit1a <- mtar(~ COLCAP + BOVESPA | SP500, data=returns, row.names=Date,
#' dist="Gaussian", ars=list(p=c(1,1,2)), n.burnin=2000,
#' n.sim=3000, n.thin=2)
#' fit1b <- update(fit1a,dist="Slash")
#' fit1c <- update(fit1a,dist="Student-t")
#' DIC(fit1a,fit1b,fit1c)
#'
#' ###### Example 2: Rainfall and two river flows in Colombia
#' data(riverflows)
#' fit2a <- mtar(~ Bedon + LaPlata | Rainfall, data=riverflows, row.names=Date,
#' dist="Gaussian", ars=list(p=c(5,5,5)), n.burnin=2000,
#' n.sim=3000, n.thin=2)
#' fit2b <- update(fit2a,dist="Slash")
#' fit2c <- update(fit2a,dist="Student-t")
#' DIC(fit2a,fit2b,fit2c)
#' }
#'
DIC <- function(...,verbose=TRUE,digits=max(3, getOption("digits") - 2)){
mtlogLik <- function(dist,y,X,beta,Sigma,delta,log,nu){
resu <- y-X%*%beta
if(dist %in% c("Skew-normal","Skew-Student-t")){
A <- chol2inv(chol(Sigma + as.vector(delta^2)*diag(k)))
muv <- resu%*%(A*matrix(delta,k,k,byrow=TRUE))
Sigmav <- diag(k) - matrix(delta,k,k)*A*matrix(delta,k,k,byrow=TRUE)
out <- colSums(t(resu)*tcrossprod(A,resu))
if(dist=="Skew-normal"){
if(k > 1) sum0 <- apply(muv,1,function(x) pmvnorm(lower=-x,upper=rep(Inf,k),sigma=Sigmav))
else sum0 <- apply(muv,1,function(x) pnorm(-x/sqrt(Sigmav),lower.tail=FALSE))
out <- 2^k*exp(-out/2)*(det(A)^(1/2))*sum0/(2*pi)^(k/2)
}
if(dist=="Skew-Student-t"){
muv <- muv*matrix(sqrt((nu + k)/(nu + out)),nrow(muv),k)
if(k > 1) sum0 <- apply(muv,1,function(x) pmvt(lower=-x,upper=rep(Inf,k),sigma=Sigmav,df=round(nu,0)+k))
else sum0 <- apply(muv,1,function(x) pt(-x/sqrt(Sigmav),df=nu,lower.tail=FALSE))
out <- 2^k*(1 + out/nu)^(-(nu+k)/2)*(det(A)^(1/2))*gamma((nu+k)/2)*sum0/((nu*pi)^(k/2)*gamma(nu/2))
}
}else{
out <- colSums(t(resu)*tcrossprod(chol2inv(chol(Sigma)),resu))
if(dist=="Gaussian") out <- exp(-out/2)
if(dist=="Laplace")
out <- besselK(sqrt(out)/2,(2-k)/2)*out^((2-k)/4)/(2^((k+2)/2))
if(dist=="Student-t")
out <- (1 + out/nu)^(-(nu+k)/2)*gamma((nu+k)/2)/((nu/2)^(k/2)*gamma(nu/2))
if(dist=="Contaminated normal")
out <- nu[1]*exp(-out*nu[2]/2)*nu[2]^(k/2) + (1-nu[1])*exp(-out/2)
if(dist=="Slash")
out <- ifelse(out==0,nu/(nu+k),gamma((k+nu)/2)*(nu/2)*pgamma(1,shape=(k+nu)/2,rate=out/2)/((out/2)^((k+nu)/2)))
if(dist=="Hyperbolic")
out <- besselK(nu*sqrt(1+out),(2-k)/2)*(1+out)^((2-k)/4)*nu^(k/2)/besselK(nu,1)
out <- out/((2*pi)^(k/2)*det(Sigma)^(1/2))
}
out <- -2*sum(log(out))
if(log) out <- out + 2*sum(y)
return(out)
}
another <- list(...)
if(any(lapply(another,function(xx) class(xx)[1])!="mtar"))
stop("Only mtar-type objects are supported!!",call.=FALSE)
call. <- match.call()
out <- matrix(0,length(another),1)
outnames <- vector()
for(l in 1:(length(another))){
n.sim <- another[[l]]$n.sim
dist <- another[[l]]$dist
Dbar <- vector()
k <- ncol(another[[l]]$data[[1]]$y)
Dbarv <- vector()
if(another[[l]]$regim > 1) lims <- (another[[l]]$ps+1):(length(another[[l]]$threshold.series))
for(j in 1:n.sim){
Dbar <- 0
if(another[[l]]$regim > 1){
Z <- another[[l]]$threshold.series[lims-another[[l]]$chains$h[j]]
regs <- cut(Z,breaks=c(-Inf,sort(another[[l]]$chains$thresholds[,j]),Inf),labels=FALSE)
}else regs <- matrix(1,nrow(another[[l]]$data[[1]]$y),1)
for(i in 1:another[[l]]$regim){
betai <- matrix(another[[l]]$chains[[i]]$location[,((j-1)*k + 1):(j*k)],ncol(another[[l]]$data[[i]]$X),k)
Sigmai <- matrix(another[[l]]$chains[[i]]$scale[,((j-1)*k + 1):(j*k)],k,k)
places <- regs==i
if(another[[l]]$dist %in% c("Skew-Student-t"))
Dbar <- Dbar + mtlogLik(dist=dist,y=another[[l]]$data[[i]]$y[places,],X=another[[l]]$data[[i]]$X[places,],beta=betai,Sigma=Sigmai,delta=another[[l]]$chains$delta[,j],log=another[[l]]$log,nu=another[[l]]$chains$extra[,j])
if(another[[l]]$dist %in% c("Skew-normal"))
Dbar <- Dbar + mtlogLik(dist=dist,y=another[[l]]$data[[i]]$y[places,],X=another[[l]]$data[[i]]$X[places,],beta=betai,Sigma=Sigmai,delta=another[[l]]$chains$delta[,j],log=another[[l]]$log)
if(another[[l]]$dist %in% c("Student-t","Hyperbolic","Slash","Contaminated normal"))
Dbar <- Dbar + mtlogLik(dist=dist,y=another[[l]]$data[[i]]$y[places,],X=another[[l]]$data[[i]]$X[places,],beta=betai,Sigma=Sigmai,log=another[[l]]$log,nu=another[[l]]$chains$extra[,j])
if(another[[l]]$dist %in% c("Gaussian","Laplace"))
Dbar <- Dbar + mtlogLik(dist=dist,y=another[[l]]$data[[i]]$y[places,],X=another[[l]]$data[[i]]$X[places,],beta=betai,Sigma=Sigmai,log=another[[l]]$log)
}
Dbarv <- c(Dbarv,Dbar)
}
Dhat <- 0
if(another[[l]]$dist %in% c("Skew-Student-t","Student-t","Hyperbolic","Slash","Contaminated normal"))
extra <- rowMeans(matrix(another[[l]]$chains$extra,ncol=n.sim))
if(another[[l]]$dist %in% c("Skew-Student-t","Skew-normal"))
delta <- rowMeans(matrix(another[[l]]$chains$delta,ncol=n.sim))
if(another[[l]]$regim > 1){
h <- as.integer(round(mean(another[[l]]$chains$h)))
thresholds <- rowMeans(matrix(another[[l]]$chains$thresholds,ncol=n.sim))
Z <- another[[l]]$threshold.series[lims-h]
regs <- cut(Z,breaks=c(-Inf,sort(thresholds),Inf),labels=FALSE)
}else regs <- matrix(1,nrow(another[[l]]$data[[1]]$y),1)
for(i in 1:another[[l]]$regim){
location <- matrix(0,nrow(another[[l]]$chains[[i]]$location),k)
scale <- matrix(0,k,k)
for(j in 1:k){
location[,j] <- rowMeans(matrix(another[[l]]$chains[[i]]$location[,seq(j,n.sim*k,by=k)],nrow(location),n.sim))
scale[,j] <- rowMeans(matrix(another[[l]]$chains[[i]]$scale[,seq(j,n.sim*k,by=k)],k,n.sim))
}
places <- regs==i
if(another[[l]]$dist %in% c("Skew-Student-t"))
Dhat <- Dhat + mtlogLik(dist=dist,y=another[[l]]$data[[i]]$y[places,],X=another[[l]]$data[[i]]$X[places,],beta=location,Sigma=scale,delta=delta,log=another[[l]]$log,nu=extra)
if(another[[l]]$dist %in% c("Skew-normal"))
Dhat <- Dhat + mtlogLik(dist=dist,y=another[[l]]$data[[i]]$y[places,],X=another[[l]]$data[[i]]$X[places,],beta=location,Sigma=scale,delta=delta,log=another[[l]]$log)
if(another[[l]]$dist %in% c("Student-t","Hyperbolic","Slash","Contaminated normal"))
Dhat <- Dhat + mtlogLik(dist=dist,y=another[[l]]$data[[i]]$y[places,],X=another[[l]]$data[[i]]$X[places,],beta=location,Sigma=scale,log=another[[l]]$log,nu=extra)
if(another[[l]]$dist %in% c("Gaussian","Laplace"))
Dhat <- Dhat + mtlogLik(dist=dist,y=another[[l]]$data[[i]]$y[places,],X=another[[l]]$data[[i]]$X[places,],beta=location,Sigma=scale,log=another[[l]]$log)
}
out[l] <- Dhat + 2*(mean(Dbarv) - Dhat)
outnames[l] <- as.character(call.[l+1])
}
rownames(out) <- outnames
colnames(out) <- "DIC"
out <- round(out,digits=digits)
if(verbose) print(out)
return(invisible(out))
}
#'
#' @title Watanabe-Akaike or Widely Available Information Criterion (WAIC)
#' @description This function computes the Watanabe-Akaike or Widely Available Information Criterion (WAIC) for objects of class \code{mtar}.
#' @param ... one or several objects of the class \emph{mtar}.
#' @param verbose an (optional) logical switch indicating if should the report of results be printed. By default,\code{verbose} is set to TRUE.
#' @param digits an (optional) integer indicating the number of digits to print. By default,\code{digits} is set to \code{max(3, getOption("digits") - 2)}.
#' @return A \code{data.frame} with the values of the WAIC for each \emph{mtar} object in the input.
#' @references Watanabe S. (2010). Asymptotic Equivalence of Bayes Cross Validation and Widely Applicable Information Criterion in
#' Singular Learning Theory. The Journal of Machine Learning Research, 11, 3571–3594.
#' @export WAIC
#' @seealso \link{DIC}
#' @examples
#' \donttest{
#' ###### Example 1: Returns of the closing prices of three financial indexes
#' data(returns)
#' fit1a <- mtar(~ COLCAP + BOVESPA | SP500, data=returns, row.names=Date,
#' dist="Gaussian", ars=list(p=c(1,1,2)), n.burnin=100,
#' n.sim=3000, n.thin=2)
#' fit1b <- update(fit1a,dist="Slash")
#' fit1c <- update(fit1a,dist="Student-t")
#' WAIC(fit1a,fit1b,fit1c)
#'
#' ###### Example 2: Rainfall and two river flows in Colombia
#' data(riverflows)
#' fit2a <- mtar(~ Bedon + LaPlata | Rainfall, data=riverflows, row.names=Date,
#' dist="Gaussian", ars=list(p=c(5,5,5)), n.burnin=100,
#' n.sim=3000, n.thin=2)
#' fit2b <- update(fit2a,dist="Slash")
#' fit2c <- update(fit2a,dist="Student-t")
#' WAIC(fit2a,fit2b,fit2c)
#' }
#'
WAIC <- function(...,verbose=TRUE,digits=max(3, getOption("digits") - 2)){
Lik <- function(dist,y,X,beta,Sigma,delta,log,nu){
resu <- y-X%*%beta
if(dist %in% c("Skew-normal","Skew-Student-t")){
A <- chol2inv(chol(Sigma + as.vector(delta^2)*diag(k)))
muv <- resu%*%(A*matrix(delta,k,k,byrow=TRUE))
Sigmav <- diag(k) - matrix(delta,k,k)*A*matrix(delta,k,k,byrow=TRUE)
out <- colSums(t(resu)*tcrossprod(A,resu))
if(dist=="Skew-normal"){
if(k > 1) sum0 <- apply(muv,1,function(x) pmvnorm(lower=-x,upper=rep(Inf,k),sigma=Sigmav))
else sum0 <- apply(muv,1,function(x) pnorm(-x/sqrt(Sigmav),lower.tail=FALSE))
out <- 2^k*exp(-out/2)*(det(A)^(1/2))*sum0/(2*pi)^(k/2)
}
if(dist=="Skew-Student-t"){
muv <- muv*matrix(sqrt((nu + k)/(nu + out)),nrow(muv),k)
if(k > 1) sum0 <- apply(muv,1,function(x) pmvt(lower=-x,upper=rep(Inf,k),sigma=Sigmav,df=round(nu,0)+k))
else sum0 <- apply(muv,1,function(x) pt(-x/sqrt(Sigmav),df=nu,lower.tail=FALSE))
out <- 2^k*(1 + out/nu)^(-(nu+k)/2)*(det(A)^(1/2))*gamma((nu+k)/2)*sum0/((nu*pi)^(k/2)*gamma(nu/2))
}
}else{
out <- colSums(t(resu)*tcrossprod(chol2inv(chol(Sigma)),resu))
if(dist=="Gaussian") out <- exp(-out/2)
if(dist=="Laplace")
out <- besselK(sqrt(out)/2,(2-k)/2)*out^((2-k)/4)/(2^((k+2)/2))
if(dist=="Student-t")
out <- (1 + out/nu)^(-(nu+k)/2)*gamma((nu+k)/2)/((nu/2)^(k/2)*gamma(nu/2))
if(dist=="Contaminated normal")
out <- nu[1]*exp(-out*nu[2]/2)*nu[2]^(k/2) + (1-nu[1])*exp(-out/2)
if(dist=="Slash")
out <- ifelse(out==0,nu/(nu+k),gamma((k+nu)/2)*(nu/2)*pgamma(1,shape=(k+nu)/2,rate=out/2)/((out/2)^((k+nu)/2)))
if(dist=="Hyperbolic")
out <- besselK(nu*sqrt(1+out),(2-k)/2)*(1+out)^((2-k)/4)*nu^(k/2)/besselK(nu,1)
out <- out/((2*pi)^(k/2)*det(Sigma)^(1/2))
}
if(log) out <- out*apply(matrix(y,nrow(X),k),1,function(x) prod(exp(-x)))
return(out)
}
another <- list(...)
if(any(lapply(another,function(xx) class(xx)[1])!="mtar"))
stop("Only mtar-type objects are supported!!",call.=FALSE)
call. <- match.call()
out <- matrix(0,length(another),1)
outnames <- vector()
for(l in 1:(length(another))){
n.sim <- another[[l]]$n.sim
dist <- another[[l]]$dist
Dbar <- matrix(0,nrow(another[[l]]$data[[1]]$y),1)
Dbarlog <- matrix(0,nrow(another[[l]]$data[[1]]$y),1)
k <- ncol(another[[l]]$data[[1]]$y)
if(another[[l]]$regim > 1) lims <- (another[[l]]$ps+1):(length(another[[l]]$threshold.series))
for(j in 1:n.sim){
for(i in 1:another[[l]]$regim){
betai <- matrix(another[[l]]$chains[[i]]$location[,((j-1)*k + 1):(j*k)],ncol(another[[l]]$data[[i]]$X),k)
Sigmai <- matrix(another[[l]]$chains[[i]]$scale[,((j-1)*k + 1):(j*k)],k,k)
if(another[[l]]$regim > 1){
Z <- another[[l]]$threshold.series[lims-another[[l]]$chains$h[j]]
regs <- cut(Z,breaks=c(-Inf,sort(another[[l]]$chains$thresholds[,j]),Inf),labels=FALSE)
}else regs <- matrix(1,nrow(another[[l]]$data[[i]]$y),1)
places <- regs==i
if(dist=="Skew-Student-t")
tempi <- Lik(dist=dist,y=another[[l]]$data[[i]]$y[places,],X=another[[l]]$data[[i]]$X[places,],beta=betai,Sigma=Sigmai,delta=another[[l]]$chains$delta[,j],log=another[[l]]$log,nu=another[[l]]$chains$extra[,j])
if(dist=="Skew-normal")
tempi <- Lik(dist=dist,y=another[[l]]$data[[i]]$y[places,],X=another[[l]]$data[[i]]$X[places,],beta=betai,Sigma=Sigmai,delta=another[[l]]$chains$delta[,j],log=another[[l]]$log)
if(dist %in% c("Student-t","Hyperbolic","Slash","Contaminated normal"))
tempi <- Lik(dist=dist,y=another[[l]]$data[[i]]$y[places,],X=another[[l]]$data[[i]]$X[places,],beta=betai,Sigma=Sigmai,log=another[[l]]$log,nu=another[[l]]$chains$extra[,j])
if(dist %in% c("Gaussian","Laplace"))
tempi <- Lik(dist=dist,y=another[[l]]$data[[i]]$y[places,],X=another[[l]]$data[[i]]$X[places,],beta=betai,Sigma=Sigmai,log=another[[l]]$log)
Dbar[places] <- Dbar[places] + tempi/n.sim
Dbarlog[places] <- Dbarlog[places] + log(tempi)/n.sim
}
}
a <- sum(unlist(lapply(Dbar,function(x) sum(log(x)))))
b <- sum(unlist(lapply(Dbarlog,sum)))
out[l] <- -2*a + 4*(a-b)
outnames[l] <- as.character(call.[l+1])
}
rownames(out) <- outnames
colnames(out) <- "WAIC"
out <- round(out,digits=digits)
if(verbose) print(out)
return(invisible(out))
}
#'
#' @title Bayesian estimation of a multivariate Threshold Autoregressive (TAR) model.
#' @description This function uses Gibbs sampling to generate a sample from the posterior
#' distribution of the parameters of a multivariate TAR model when the noise
#' process follows Gaussian, Student-\eqn{t}, Slash, Symmetric Hyperbolic,
#' Contaminated normal, Laplace, Skew-normal or skew-\eqn{t} distribution.
#' @param formula A three-part expression of type \code{Formula} describing the TAR model
#' to be fitted to the data. In the first part, the variables in the
#' multivariate output series are listed; in the second part, the threshold
#' series is specified, and in the third part, the variables in the
#' multivariate exogenous series are specified.
#' @param ars a list composed of three objects, namely: \code{p}, \code{q} and \code{d},
#' each of which corresponds to a vector of non-negative integers with as many
#' elements as there are regimes in the TAR model.
#' @param Intercept an (optional) logical variable. If \code{TRUE}, then the model
#' includes an intercept.
#' @param data an (optional) data frame, list or environment (or object coercible by
#' \link{as.data.frame} to a data frame) containing the variables in the model.
#' If not found in data, the variables are taken from \code{environment(formula)},
#' typically the environment from which \code{mtar} is called.
#' @param subset an (optional) vector specifying a subset of observations to be used in the
#' fitting process.
#' @param dist an (optional) character string that allows the user to specify the
#' multivariate distribution to be used to describe the noise process
#' behavior. The available options are: Gaussian ("Gaussian"), Student-\eqn{t}
#' ("Student-t"), Slash ("Slash"), Symmetric Hyperbolic ("Hyperbolic"),
#' Laplace ("Laplace"), Contaminated normal ("Contaminated normal"),
#' Skew-normal ("Skew-normal") and Skew-Student-\eqn{t} ("Skew-Student-t").
#' By default, \code{dist} is set to "Gaussian".
#'
#' @param n.sim an (optional) positive integer specifying the required number of iterations
#' for the simulation after the burn-in period. By default, \code{n.sim} is set
#' to 500.
#' @param n.burnin an (optional) positive integer specifying the required number of burn-in
#' iterations for the simulation. By default, \code{n.burnin} is set to 100.
#' @param n.thin an (optional) positive integer specifying the required thinning interval
#' for the simulation. By default, \code{n.thin} is set to 1.
#' @param row.names an (optional) vector that allows the user to name the time point to
#' which each row in the data set corresponds.
#' @param prior an (optional) list that allows the user to specify the values of the
#' hyperparameters, that is, allows to specify the values of the parameters
#' of the prior distributions.
#' @param log an (optional) logical variable. If \code{TRUE}, then the behaviour of the output
#' series is described using the exponentiated version of \code{dist}.
#' @param ... further arguments passed to or from other methods.
#'
#' @return an object of class \emph{mtar} in which the main results of the model fitted to the data are stored, i.e., a
#' list with components including
#' \tabular{ll}{
#' \code{chains} \tab list with several arrays, which store the values of each model parameter in each iteration of the simulation,\cr
#' \tab \cr
#' \code{n.sim} \tab number of iterations of the simulation after the burn-in period,\cr
#' \tab \cr
#' \code{n.burnin} \tab number of burn-in iterations in the simulation,\cr
#' \tab \cr
#' \code{n.thin} \tab thinning interval in the simulation,\cr
#' \tab \cr
#' \code{regim} \tab number of regimes, \cr
#' \tab \cr
#' \code{ars} \tab list composed of three objects, namely: \code{p}, \code{q} and \code{d},
#' each of which corresponds to a vector of non-negative integers with as
#' many elements as there are regimes in the TAR model,\cr
#' \tab \cr
#' \code{dist} \tab name of the multivariate distribution used to describe the behavior of
#' the noise process,\cr
#' \tab \cr
#' \code{threshold.series} \tab vector with the values of the threshold series,\cr
#' \tab \cr
#' \code{response.series} \tab matrix with the values of the output series,\cr
#' \tab \cr
#' \code{covariable.series} \tab matrix with the values of the exogenous series,\cr
#' \tab \cr
#' \code{Intercept} \tab If \code{TRUE}, then the model included an intercept term,\cr
#' \tab \cr
#' \code{formula} \tab the formula,\cr
#' \tab \cr
#' \code{call} \tab the original function call.\cr
#' }
#' @export mtar
#' @seealso \link{DIC}, \link{WAIC}
#' @references Nieto, F.H. (2005) Modeling Bivariate Threshold Autoregressive Processes in the Presence of Missing Data.
#' Communications in Statistics - Theory and Methods, 34, 905-930.
#' @references Romero, L.V. and Calderon, S.A. (2021) Bayesian estimation of a multivariate TAR model when the noise
#' process follows a Student-t distribution. Communications in Statistics - Theory and Methods, 50, 2508-2530.
#' @references Calderon, S.A. and Nieto, F.H. (2017) Bayesian analysis of multivariate threshold autoregressive models
#' with missing data. Communications in Statistics - Theory and Methods, 46, 296-318.
#' @examples
#' \donttest{
#' ###### Example 1: Returns of the closing prices of three financial indexes
#' data(returns)
#' fit1 <- mtar(~ COLCAP + BOVESPA | SP500, data=returns, row.names=Date,
#' dist="Gaussian", ars=list(p=c(1,1,2)), n.burnin=100,
#' n.sim=3000, n.thin=2)
#' summary(fit1)
#'
#' ###### Example 2: Rainfall and two river flows in Colombia
#' data(riverflows)
#' fit2 <- mtar(~ Bedon + LaPlata | Rainfall, data=riverflows, row.names=Date,
#' dist="Gaussian", ars=list(p=c(5,5,5)), n.burnin=2000,
#' n.sim=3000, n.thin=2)
#' summary(fit2)
#' }
#'
mtar <- function(formula, data, subset, Intercept=TRUE, ars, row.names, dist="Gaussian", prior=list(), n.sim=500, n.burnin=100, n.thin=1, log=FALSE, ...){
if(!(dist %in% c("Gaussian","Student-t","Hyperbolic","Laplace","Slash","Contaminated normal","Skew-Student-t","Skew-normal")))
stop("Only 'Gaussian', 'Student-t', 'Hyperbolic', 'Laplace', 'Slash', 'Contaminated normal', 'Skew-normal' and 'Skew-Student-t' distributions are supported!",call.=FALSE)
if(missing(data)) data <- environment(formula)
ars$p <- ceiling(abs(ars$p))
regim <- length(ars$p)
mmf <- match.call(expand.dots = FALSE)
m <- match(c("formula", "data", "subset", "na.action", "row.names"), names(mmf), 0)
mmf <- mmf[c(1,m)]
mmf$drop.unused.levels <- TRUE
mmf[[1]] <- as.name("model.frame")
mmf$formula <- Formula(formula)
mmf <- eval(mmf, parent.frame())
if(!missingArg(row.names)) row.names <- as.vector(as.character(model.extract(mmf,row.names)))
mx <- model.part(Formula(formula), data = mmf, rhs = 1, terms = TRUE)
D <- model.matrix(mx, data = mmf)
if(attr(terms(mx),"intercept")){
Dnames <- colnames(D)
D <- matrix(D[,-1],ncol=length(Dnames)-1)
colnames(D) <- Dnames[-1]
}
if(log){
if(any(D<0)) stop(paste0("There are non-positive values in the output series, so it cannot be described using the log-",tolower(dist)," distribution."),call.=FALSE)
D <- log(D)
}
k <- ncol(D)
if(regim > 1){
mz <- model.part(Formula(formula), data = mmf, rhs = 2, terms = TRUE)
Z <- model.matrix(mz, data = mmf)
if(attr(terms(mz),"intercept")){
Znames <- colnames(Z)
Z <- as.matrix(Z[,-1])
colnames(Z) <- Znames[-1]
}
ta <- vector()
}
if(!is.null(ars$q)){
ars$q <- ceiling(abs(ars$q))
if(max(ars$q) > 0){
mx2 <- model.part(Formula(formula), data = mmf, rhs = 3, terms = TRUE)
X2 <- model.matrix(mx2, data = mmf)
if(attr(terms(mx2),"intercept")){
X2names <- colnames(X2)
X2 <- as.matrix(X2[,-1])
colnames(X2) <- X2names[-1]
}
r <- ncol(X2)
}
}else ars$q <- rep(0,regim)
if(is.null(ars$d)) ars$d <- rep(0,regim) else ars$d <- ceiling(abs(ars$d))
if(is.null(prior$theta0)) prior$theta0 <- 0
if(is.null(prior$delta0)) prior$delta0 <- 1000000000
if(is.null(prior$omega0)) prior$omega0 <- 1/1000000000
if(is.null(prior$phi0)) prior$phi0 <- 1000000000
Omega0 <- diag(k)*prior$omega0
Phi0 <- diag(k)*prior$phi0
if(is.null(prior$tau0)) prior$tau0 <- k
if(is.null(prior$hmin)) prior$hmin <- 0 else prior$hmin <- ceiling(abs(prior$hmin))
if(is.null(prior$hmax)) prior$hmax <- 3 else prior$hmax <- ceiling(abs(prior$hmax))
prior$hmin <- min(prior$hmin,prior$hmax)
prior$hmax <- max(prior$hmin,prior$hmax)
data <- list()
chains <- list()
n.sim <- ceiling(abs(n.sim))
n.thin <- ceiling(abs(n.thin))
n.burnin <- ceiling(abs(n.burnin))
rep <- n.sim*n.thin + n.burnin
ids <- matrix(seq(1,n.sim*n.thin*k,k))
ids <- ids[seq(1,n.sim*n.thin,n.thin)]
ids <- n.burnin*k + as.vector(apply(matrix(ids),1,function(x) x + c(0:(k-1))))
Sigmanew2 <- list()
name <- list()
tn1 <- function(mu,var){
temp <- pnorm(0,mean=mu,sd=sqrt(var))
temp <- temp + runif(1)*(1 - temp)
return(ifelse(temp>0.9999999999999999,-mu*0.001,qnorm(temp)*sqrt(var) + mu))
}
myf1 <- function(x){
mu <- ais[,x]
var <- Ais2/usi[x]
tn1(mu=mu,var=var)
}
myf2 <- function(x){
mu <- ais[,x]
var <- Ais2/usi[x]
ind <- TRUE
indc <- 1
while(ind & indc<=30){
temp <- crossprod(Ais3/sqrt(usi[x]),matrix(rnorm(k*50),k,50))
temp2 <- colSums(mu + temp > 0)==k
indc <- indc + 1
ind <- !any(temp2)
}
if(ind){
myfout <- vector()
for(indc in 1:k) myfout <- c(myfout,tn1(mu=mu[indc],var=var[indc,indc]))
}else myfout <- (mu + temp)[,min(c(1:50)[temp2])]
myfout
}
if(regim > 1) ps <- max(ars$p,ars$q,ars$d,prior$hmax) else ps <- max(ars$p,ars$q,ars$d)
if(regim > 1){
Zs <- Z[(ps+1-prior$hmin):(nrow(D)-prior$hmin),]
t1 <- max(Zs);t0 <- min(Zs)
thresholds <- quantile(Zs,probs=c(1:(regim-1))/regim)
regs <- cut(Zs,breaks=c(-Inf,sort(thresholds),Inf),labels=FALSE)
thresholds.chains <- matrix(thresholds,regim-1,1)
hs.chains <- matrix(prior$hmin,1,1)
}else regs <- matrix(1,nrow(D)-ps,1)
for(i in 1:regim){
y <- matrix(D[(ps+1):nrow(D),1:k],ncol=k)
X <- matrix(1,nrow(y),1)
for(j in 1:ars$p[i]) X <- cbind(X,D[((ps+1)-j):(nrow(D)-j),])
name[[i]] <- c("(Intercept)",paste0(rep(colnames(D)[1:k],ars$p[i]),sort(paste0(".lag(",rep(1:ars$p[i],k))),")"))
if(!Intercept){
X <- matrix(X[,-1],nrow(X),ncol(X)-1)
name[[i]] <- name[[i]][-1]
}
if(ars$q[i]!=0){
for(j in 1:ars$q[i]) X <- cbind(X,X2[((ps+1)-j):(nrow(D)-j),])
name[[i]] <- c(name[[i]],paste0(rep(colnames(X2),ars$q[i]),sort(paste0(".lag(",rep(1:ars$q[i],r))),")"))
}
if(ars$d[i]!=0){
for(j in 1:ars$d[i]) X <- cbind(X,Z[((ps+1)-j):(nrow(D)-j),])
name[[i]] <- c(name[[i]],paste0(rep(colnames(Z),ars$d[i]),sort(paste0(".lag(",1:ars$d[i])),")"))
}
colnames(X) <- name[[i]]
if(!missingArg(row.names)){
row.names2 <- row.names[(ps+1):nrow(D)]
rownames(X) <- rownames(y) <- row.names2
}
colnames(y) <- colnames(D)
data[[i]] <- list()
data[[i]]$y <- y
data[[i]]$X <- X
places <- regs == i
X <- matrix(X[places,],sum(places),ncol(X))
y <- matrix(y[places,],nrow(X),ncol(y))
b0 <- chol2inv(chol(crossprod(X)))
betanew <- crossprod(b0,crossprod(X,y))
Sigmanew <- crossprod(y-X%*%betanew)/nrow(X)
Sigmanew2[[i]] <- chol2inv(chol(Sigmanew))
chains[[i]] <- list()
chains[[i]]$location <- betanew
chains[[i]]$scale <- Sigmanew
}
tol <- unlist(lapply(data,function(x) ncol(x$X)))*k*1.2
us <- matrix(1,nrow(data[[1]]$X),1)
ss <- matrix(0,nrow(data[[1]]$X),1)
zs <- matrix(0,nrow(data[[1]]$y),k)
chains$delta <- matrix(0,k,1)
if(dist=="Hyperbolic"){
if(is.null(prior$gamma0)) prior$gamma0 <- 0.1
if(is.null(prior$eta0)) prior$eta0 <- 4
chains$extra <- matrix((prior$gamma0+prior$eta0)/2,1,1)
nus <- matrix(seq(prior$gamma0,prior$eta0,length=10001),10001,1)
num1 <- nus[2:length(nus)] - nus[1:(length(nus)-1)]
num2 <- (nus[2:length(nus)] + nus[1:(length(nus)-1)])/2
resto <- log(nus) - log(besselK(nus,nu=1))
}
if(dist %in% c("Student-t","Skew-Student-t")){
if(is.null(prior$gamma0)) prior$gamma0 <- 2
if(is.null(prior$eta0)) prior$eta0 <- 100
chains$extra <- matrix((prior$gamma0+prior$eta0)/2,1,1)
nus <- matrix(seq(prior$gamma0,prior$eta0,length=10001),10001,1)
num1 <- nus[2:length(nus)] - nus[1:(length(nus)-1)]
num2 <- (nus[2:length(nus)] + nus[1:(length(nus)-1)])/2
resto <- (nus/2)*log(nus/2) - lgamma(nus/2)
}
if(dist=="Slash"){
if(is.null(prior$gamma0)) prior$gamma0 <- 1/1000000000
if(is.null(prior$eta0)) prior$eta0 <- 1/1000000000
chains$extra <- matrix(100,1,1)
}
if(dist=="Contaminated normal"){
chains$extra <- matrix(c(0.01,0.99),2,1)
if(is.null(prior$gamma01)) prior$gamma01 <- 1/1000000000
if(is.null(prior$eta01)) prior$eta01 <- 1/1000000000
if(is.null(prior$gamma02)) prior$gamma02 <- 1/1000000000
if(is.null(prior$eta02)) prior$eta02 <- 1/1000000000
}
Loglik <- function(h,thresholds){
regs <- cut(Z[(ps+1-h):(nrow(D)-h),],breaks=c(-Inf,sort(thresholds),Inf),labels=FALSE)
result <- 0
for(i in 1:regim){
places <- regs == i
X <- matrix(data[[i]]$X[places,],sum(places),ncol(data[[i]]$X))
y <- matrix(data[[i]]$y[places,] - matrix(chains$delta[,ncol(chains$delta)],nrow(X),k,byrow=TRUE)*zs[places,],nrow(X),k)
usi <- us[places]
Xu <- matrix(sqrt(usi),nrow(X),ncol(X))*X
yu <- matrix(sqrt(usi),nrow(X),k)*y
resu <- yu-Xu%*%chains[[i]]$location[,(ncol(chains[[i]]$location)-k+1):ncol(chains[[i]]$location)]
ds <- colSums(t(resu)*tcrossprod(Sigmanew2[[i]],resu))
result <- result -0.5*sum(ds - log(det(Sigmanew2[[i]])) - k*log(usi) + k*log(2*pi))
}
return(result)
}
bar <- txtProgressBar(min=0, max=rep, initial=0, width=min(50,rep), char="+", style=3)
for(j in 1:rep){
if(dist %in% c("Skew-normal","Skew-Student-t")){
bis <- matrix(0,k,1)
Bis <- matrix(0,k,k)
}
if(regim > 1){
hs <- hs.chains[,j]
thresholds <- thresholds.chains[,j]
regs <- cut(Z[(ps+1-hs):(nrow(D)-hs),],breaks=c(-Inf,sort(thresholds),Inf),labels=FALSE)
}
for(i in 1:regim){
places <- regs == i
X <- matrix(data[[i]]$X[places,],sum(places),ncol(data[[i]]$X))
n <- nrow(X); s <- ncol(X)
y2z <- matrix(data[[i]]$y[places,],n,k)
y <- matrix(y2z - matrix(chains$delta[,j],n,k,byrow=TRUE)*zs[places,],n,k)
mu0s <- matrix(prior$theta0,s,k)
Sigmarinv <- diag(s)/prior$delta0
if(dist %in% c("Gaussian","Skew-normal")) us[places] <- rep(1,n)
else{
resu <- y-X%*%chains[[i]]$location[,(1+(j-1)*k):(j*k)]
usi <- colSums(t(resu)*tcrossprod(Sigmanew2[[i]],resu))
}
if(dist=="Laplace")
us[places] <- apply(matrix(usi,length(usi),1),1,function(x) 1/rgig(n=1,lambda=(2-k)/2,chi=x,psi=1/4))
if(dist=="Hyperbolic")
us[places] <- apply(matrix(usi,length(usi),1),1,function(x) 1/rgig(n=1,lambda=(2-k)/2,chi=x+1,psi=chains$extra[,j]^2))
if(dist=="Student-t")
us[places] <- rgamma(n,shape=(chains$extra[,j]+k)/2,scale=2/(chains$extra[,j]+usi))
if(dist=="Skew-Student-t")
us[places] <- rgamma(n,shape=(chains$extra[,j]+2*k)/2,scale=2/(chains$extra[,j]+usi+rowSums(matrix(zs[places,]^2,n,k))))
if(dist=="Slash"){
u0 <- pgamma(q=1,shape=(chains$extra[,j]+k)/2,scale=2/usi)
us[places] <- qgamma(p=runif(n)*u0,shape=(chains$extra[,j]+k)/2,scale=2/usi)
us[places] <- ifelse(us[places]<.Machine$double.xmin,.Machine$double.xmin,us[places])
}
if(dist=="Contaminated normal"){
a <- chains$extra[1,j]*chains$extra[2,j]^(k/2)*exp(-chains$extra[2,j]*usi/2)
b <- (1-chains$extra[1,j])*exp(-usi/2)
us[places] <- ifelse(runif(n)<=a/(a+b),chains$extra[2,j],1)
}
usi <- us[places]
zsi <- matrix(0,n,k)
if(dist %in% c("Skew-normal","Skew-Student-t")){
ais <- matrix(chains$delta[,j],k,n)*tcrossprod(Sigmanew2[[i]],y2z-X%*%chains[[i]]$location[,(1+(j-1)*k):(j*k)])
Ais <- diag(k) + matrix(chains$delta[,j],k,k)*Sigmanew2[[i]]*matrix(chains$delta[,j],k,k,byrow=TRUE)
Ais2 <- chol2inv(chol(Ais))
if(k>1) Ais3 <- chol(Ais2)
ais <- crossprod(Ais2,ais)
if(k==1) zsi <- matrix(unlist(lapply(1:n,myf1)),n,k,byrow=TRUE)
else zsi <- matrix(unlist(lapply(1:n,myf2)),n,k,byrow=TRUE)
zs[places,] <- zsi
y <- matrix(data[[i]]$y[places,] - matrix(chains$delta[,j],n,k,byrow=TRUE)*zsi,n,k)
}
Xu <- matrix(sqrt(usi),n,s)*X
yu <- matrix(sqrt(usi),n,k)*y
A <- chol2inv(chol(Sigmarinv + crossprod(Xu)))
M <- crossprod(A,(crossprod(Xu,yu) + crossprod(Sigmarinv,mu0s)))
betanew <- M + crossprod(chol(A),matrix(rnorm(s*k),s,k))%*%chol(chains[[i]]$scale[,(1+(j-1)*k):(j*k)])
chains[[i]]$location <- cbind(chains[[i]]$location,betanew)
Omega <- Omega0 + crossprod(betanew-mu0s,Sigmarinv)%*%(betanew-mu0s) + crossprod(yu-Xu%*%betanew)
Omegachol <- chol(chol2inv(chol(Omega)))
Sigmanew2[[i]] <- tcrossprod(crossprod(Omegachol,matrix(rnorm(k*(prior$tau0+s+n)),k,prior$tau0+s+n)))
if(j < n.burnin) Sigmanew <- chol2inv(chol(Sigmanew2[[i]])) else Sigmanew <- Sigmanew2[[i]]
chains[[i]]$scale <- cbind(chains[[i]]$scale,Sigmanew)
if(dist=="Contaminated normal"){
resu <- y-X%*%betanew
ss[places] <- colSums(t(resu)*tcrossprod(Sigmanew2[[i]],resu))
}
if(dist %in% c("Skew-normal","Skew-Student-t")){
bis <- bis + rowSums(matrix(matrix(usi,k,n,byrow=TRUE)*t(zsi)*tcrossprod(Sigmanew2[[i]],(y2z-X%*%betanew)),k,n))
Bis <- Bis + Reduce(`+`, lapply(1:n,function(x) usi[x]*(matrix(zsi[x,],k,k)*Sigmanew2[[i]]*matrix(zsi[x,],k,k,byrow=TRUE))))
}
}
if(dist=="Hyperbolic"){
etanew <- length(us)*(resto - (1/2)*(nus^2*mean(1/us)))
etanew <- exp(etanew - max(etanew))
probs <- num1*(etanew[2:length(nus)] + etanew[1:(length(nus)-1)])/2
etanew <- sample(x=num2,size=1,prob=probs/sum(probs))
chains$extra <- cbind(chains$extra,matrix(etanew,1,1))
}
if(dist %in% c("Student-t","Skew-Student-t")){
etanew <- length(us)*resto + (nus/2)*sum(log(us)-us)
etanew <- exp(etanew - max(etanew))
probs <- num1*(etanew[2:length(nus)] + etanew[1:(length(nus)-1)])/2
etanew <- sample(x=num2,size=1,prob=probs/sum(probs))
chains$extra <- cbind(chains$extra,matrix(etanew,1,1))
}
if(dist=="Slash"){
etanew <- rgamma(1,shape=prior$gamma0+length(us),scale=2/(prior$eta0-sum(log(us))))
chains$extra <- cbind(chains$extra,matrix(etanew,1,1))
}
if(dist=="Contaminated normal"){
a <- us==chains$extra[2,j]
etanew1 <- max(0.01,rbeta(1,shape1=prior$gamma01+sum(a),shape2=prior$eta01+length(a)-sum(a)))
u0 <- pgamma(q=1,shape=(sum(a)*k + prior$gamma02)/2,scale=2/(prior$eta02 + sum(ss*a)))
etanew2 <- max(0.01,qgamma(p=runif(1)*u0,shape=(sum(a)*k + prior$gamma02)/2,scale=2/(prior$eta02 + sum(ss*a))))
chains$extra <- cbind(chains$extra,matrix(c(etanew1,etanew2),2,1))
}
if(dist %in% c("Skew-normal","Skew-Student-t")){
Bis2 <- chol2inv(chol(Bis + diag(k)/prior$phi0))
chains$delta <- cbind(chains$delta,Bis2%*%bis + crossprod(chol(Bis2),matrix(rnorm(k),k,1)))
}else chains$delta <- cbind(chains$delta,matrix(0,k,1))
if(regim > 1){
a0 <- (thresholds.chains[,j] - t0)/(t1 - t0)
if(length(a0) > 1) a0 <- c(a0[1],diff(a0))
tp <- 100000
a0 <- tp*c(a0,1-sum(a0))
ind <- TRUE
while(ind){
r0 <- rgamma(length(a0),shape=a0,scale=rep(1,length(a0)))
r0 <- r0/sum(r0)
thresholds.new <- t0 + cumsum(r0[-length(a0)])*(t1 - t0)
if(length(unique(thresholds.new))==(length(r0)-1)){
indl <- table(cut(Z[(ps+1-hs):(nrow(D)-hs),],breaks=c(-Inf,sort(thresholds.new),Inf),labels=FALSE))
if(length(indl) == regim) ind <- any(indl < tol)
}
}
a <- min(1,exp(Loglik(hs,thresholds.new) - Loglik(hs,thresholds.chains[,j]) +
sum((tp*r0-1)*log(a0/tp) - lgamma(tp*r0)) + lgamma(sum(tp*r0)) - sum((a0-1)*log(r0) - lgamma(a0)) - lgamma(sum(a0))))
if(runif(1) > a){
thresholds.new <- thresholds.chains[,j]
ta <- c(ta,0)
}
else ta <- c(ta,1)
thresholds.chains <- cbind(thresholds.chains,thresholds.new)
resul <- vector()
for(h in prior$hmin:prior$hmax) resul <- c(resul,Loglik(h,thresholds.new))
resul <- resul-max(resul)
resul <- exp(resul)/sum(exp(resul))
hs.chains <- cbind(hs.chains,sample(prior$hmin:prior$hmax,size=1,prob=resul))
}
setTxtProgressBar(bar,j)
}
for(i in 1:regim){
chains[[i]]$location <- matrix(chains[[i]]$location[,ids],nrow=nrow(chains[[i]]$location),ncol=n.sim*k)
rownames(chains[[i]]$location) <- name[[i]]
chains[[i]]$scale <- matrix(chains[[i]]$scale[,ids],nrow=k,ncol=k*n.sim)
colnames(chains[[i]]$scale) <- rep(colnames(D),n.sim)
rownames(chains[[i]]$scale) <- colnames(D)
}
if(dist %in% c("Skew-Student-t","Student-t","Hyperbolic","Slash","Contaminated normal"))
chains$extra <- matrix(chains$extra[,n.burnin + seq(1,n.sim*n.thin,n.thin)],nrow=ifelse(dist=="Contaminated normal",2,1),ncol=n.sim)
if(dist %in% c("Skew-normal","Skew-Student-t"))
chains$delta <- matrix(chains$delta[,n.burnin + seq(1,n.sim*n.thin,n.thin)],nrow=k,ncol=n.sim)
out_ <- list(data=data,chains=chains,n.sim=n.sim,regim=regim,name=name,dist=dist,ps=ps,ars=ars,formula=Formula(formula),Intercept=Intercept,call=match.call(),log=log,response.series=D)
if(regim > 1){
out_$chains$thresholds <- matrix(thresholds.chains[,n.burnin + seq(1,n.sim*n.thin,n.thin)],ncol=n.sim)
out_$chains$h <- hs.chains[,n.burnin + seq(1,n.sim*n.thin,n.thin)]
out_$threshold.series=Z
out_$ts=paste0(colnames(Z),".lag(",mean(out_$chains$h),")")
out_$ta=100*mean(ta[n.burnin+seq(1,n.sim*n.thin)])
}
if(max(ars$q) > 0) out_$covariable.series=X2
class(out_) <- "mtar"
return(out_)
}
#' @method coef mtar
#' @export
coef.mtar <- function(object,...,FUN=mean){
k <- ncol(object$data[[1]]$y)
n.sim <- object$n.sim
out_ <- list()
for(i in 1:object$regim){
out_[[i]] <- list()
out <- outs <- vector()
for(j in 1:k){
temp <- object$chains[[i]]$location[,seq(j,n.sim*k,k)]
temps <- matrix(matrix(object$chains[[i]]$scale,k,n.sim*k)[,seq(j,n.sim*k,k)],nrow=k)
out <- cbind(out,apply(temp,1,FUN))
outs <- cbind(outs,apply(temps,1,FUN))
}
out_[[i]]$location <- out
out_[[i]]$scale <- outs
colnames(out_[[i]]$location) <- colnames(out_[[i]]$scale) <- rownames(out_[[i]]$scale) <- colnames(object$data[[1]]$y)
}
if(object$regim > 1){
out_$delay <- as.integer(round(apply(matrix(object$chains$h,1,n.sim),1,FUN)))
out_$thresholds <- matrix(apply(object$chains$thresholds,1,FUN),object$regim-1,1)
rownames(out_$thresholds) <- paste0("Threshold",1:(object$regim-1))
colnames(out_$thresholds) <- ""
}
if(object$dist %in% c("Skew-normal","Skew-Student-t")){
out_$skewness <- matrix(apply(object$chains$delta,1,FUN),k,1)
rownames(out_$skewness) <- paste0("delta",1:k)
colnames(out_$skewness) <- ""
}
if(object$dist %in% c("Slash","Contaminated normal","Student-t","Hyperbolic","Skew-Student-t")){
out_$extra <- matrix(apply(object$chains$extra,1,FUN),nrow(object$chains$extra),1)
rownames(out_$extra) <- paste0("nu",1:nrow(object$chains$extra))
colnames(out_$extra) <- ""
}
return(out_)
}
#' @method summary mtar
#' @export
summary.mtar <- function(object, credible=0.95, digits=max(3, getOption("digits") - 2),...){
k <- ncol(object$data[[1]]$y)
n.sim <- object$n.sim
out_ <- list()
resumen <- function(x){
x <- matrix(x,ifelse(is.null(nrow(x)),1,nrow(x)),ifelse(is.null(ncol(x)),length(x),ncol(x)))
y <- matrix(0,nrow(x),4)
y[,1] <- rowMeans(x)
y[,2] <- apply(x,1,function(x) min(mean(sign(median(x))*x > 0),1-1/200000))
y[,2] <- 2*(1 - y[,2])
ks <- seq(credible,1,length=n.sim*(1-credible))
lis <- t(apply(x,1,quantile,probs=ks-credible))
lss <- t(apply(x,1,quantile,probs=ks))
dif <- apply(abs(lss-lis),1,which.min)
y[,3] <- lis[cbind(1:nrow(x),dif)]
y[,4] <- lss[cbind(1:nrow(x),dif)]
colnames(y) <- c(" Mean"," 2(1-PD) ","HDI_low","HDI_high")
return(y)
}
if(object$regim > 1){
thresholds <- matrix(round(resumen(matrix(object$chains$thresholds,nrow=object$regim-1)),digits=digits)[,c(1,3,4)],ncol=3)
h <- as.integer(round(mean(object$chains$h)))
thresholds1 <- paste0(c("(-Inf",paste0("(",round(thresholds[,1],digits=digits))),",",c(paste0(round(thresholds[,1],digits=digits),"]"),"Inf)"))
thresholds2 <- paste0(c("(-Inf",paste0("(",round(thresholds[,2],digits=digits))),",",c(paste0(round(thresholds[,2],digits=digits),"]"),"Inf)"))
thresholds3 <- paste0(c("(-Inf",paste0("(",round(thresholds[,3],digits=digits))),",",c(paste0(round(thresholds[,3],digits=digits),"]"),"Inf)"))
d <- data.frame(cbind(thresholds1,thresholds2,thresholds3))
rownames(d) <- paste("Regime",1:nrow(d))
colnames(d) <- rep(" ",3)
}
cat("\nResponse :",ifelse(length(colnames(object$data[[1]]$y))==1,colnames(object$data[[1]]$y),paste(colnames(object$data[[1]]$y),collapse=" | ")))
if(object$regim > 1) cat("\nThreshold series :",object$ts,"(Mean)")
cat("\nError distribution:",object$dist)
cat("\n\n")
if(object$regim > 1){
cat("\nThresholds (Mean, HDI_low, HDI_high)\n")
print(d)
out_$thresholds <- d
out_$location <- list()
out_$scale <- list()
}
for(i in 1:object$regim){
out <- outs <- vector()
for(j in 1:k){
temp <- object$chains[[i]]$location[,seq(j,n.sim*k,k)]
temps <- matrix(matrix(object$chains[[i]]$scale,k,n.sim*k)[,seq(j,n.sim*k,k)],nrow=k)
if(j > 1){
out <- cbind(out,matrix(0,nrow(out),1),round(resumen(temp),digits=digits))
outs <- cbind(outs,round(resumen(temps)[,c(1,3,4)],digits=digits+1))
}
else{
out <- round(resumen(temp),digits=digits)
outs <- round(resumen(temps)[,c(1,3,4)],digits=digits+1)
}
}
outs <- matrix(outs,k,3*k)
rownames(out) <- object$name[[i]]
outs <- matrix(cbind(outs,0),k,3*k+1)
outs <- outs[,c(seq(1,3*k,3),3*k+1,seq(2,3*k,3),3*k+1,seq(3,3*k,3))]
outs <- matrix(outs,k,length(outs)/k)
rownames(outs) <- colnames(object$data[[1]]$y)
colnames(outs) <- c(rownames(outs),"",rownames(outs),"",rownames(outs))
cat("\n\nRegime",i,":")
cat("\nAutoregressive coefficients\n")
print(format(out, justify = "right", format = "+/-", zero.print=" | "), quote=FALSE)
cat("\nScale parameter (Mean, HDI_low, HDI_high)\n")
print(format(outs, justify = "right", format = "+/-", zero.print=" ."), quote=FALSE)
out_$location[[i]] <- out
out_$scale[[i]] <- outs
}
if(object$dist %in% c("Skew-normal","Skew-Student-t")){
out <- round(resumen(object$chains$delta),digits=digits+1)
rownames(out) <- paste0(paste0("delta",1:k),paste0(rep("",max(nchar(object$name[[1]]))-6),collapse=" "))
cat("\n\nSkewness parameter","\n")
print(format(out, justify = "right", flag="+", zero.print=" . "), quote=FALSE)
out_$delta <- out
}
if(object$dist %in% c("Slash","Contaminated normal","Student-t","Hyperbolic","Skew-Student-t")){
out <- round(resumen(object$chains$extra),digits=digits+1)
out[,2] <- 0
if(object$dist %in% c("Slash","Student-t","Hyperbolic","Skew-Student-t")) rownames(out)[nrow(out)] <- paste0("nu",paste0(rep("",max(nchar(object$name[[1]]))-1),collapse=" "))
else rownames(out)[nrow(out):(nrow(out)-1)] <- paste0(c("nu2","nu1"),paste0(rep("",max(nchar(object$name[[1]]))-2),collapse=" "))
cat("\n\nExtra parameter","\n")
print(format(out, justify = "right", flag="+", zero.print=" . "), quote=FALSE)
out_$extra <- out
}
cat("\n\n")
return(invisible(out_))
}
#'
#' @method plot mtar
#' @export
plot.mtar <- function(x,...,identify){
n.sim <- x$n.sim
dist <- x$dist
k <- ncol(x$data[[1]]$y)
out <- matrix(NA,1,k)
idsi <- vector()
out_2 <- matrix(NA,1,2*k)
if(x$regim > 1) lims <- (x$ps+1):(length(x$threshold.series))
if(x$dist %in% c("Student-t","Hyperbolic","Slash","Contaminated normal"))
extra <- rowMeans(matrix(x$chains$extra,ncol=n.sim))
ids <- 1:nrow(x$data[[1]]$X)
for(i in 1:x$regim){
location <- matrix(0,nrow(x$chains[[i]]$location),k)
scale <- matrix(0,k,k)
for(j in 1:k){
location[,j] <- rowMeans(matrix(x$chains[[i]]$location[,seq(j,n.sim,by=k)],nrow(location),n.sim))
scale[,j] <- rowMeans(matrix(x$chains[[i]]$scale[,seq(j,n.sim,by=k)],k,n.sim))
}
if(x$regim > 1){
h <- as.integer(round(mean(x$chains$h)))
thresholds <- rowMeans(matrix(x$chains$thresholds,ncol=n.sim))
Z <- x$threshold.series[lims-h]
regs <- cut(Z,breaks=c(-Inf,sort(thresholds),Inf),labels=FALSE)
}else regs <- matrix(1,nrow(x$data[[i]]$y),1)
places <- regs==i
y <- x$data[[i]]$y[places,]
X <- x$data[[i]]$X[places,]
resu <- y-X%*%location
ei <- eigen(scale,symmetric=TRUE)
resu <- resu%*%(ei$vectors%*%diag(1/sqrt(as.vector(ei$values)))%*%t(ei$vectors))
out <- rbind(out,resu)
out_2 <- rbind(out_2,cbind(y,X%*%location))
idsi <- c(idsi,ids[places])
}
out <- matrix(out,nrow(x$data[[1]]$X),k)
TT <- 50000
sim <- matrix(rnorm(TT*k),TT,k)
if(dist=="Gaussian") u <- 1
if(dist=="Student-t") u <- 1/rgamma(TT,shape=extra/2,rate=extra/2)
if(dist=="Slash") u <- 1/rbeta(TT,shape1=extra/2,shape2=1)
if(dist=="Contaminated normal") u <- 1/(1 - (1-extra[2])*rbinom(TT,1,extra[1]))
if(dist=="Hyperbolic") u <- rgig(n=TT,lambda=1,chi=1,psi=extra^2)
if(dist=="Laplace") u <- rexp(TT,rate=1/8)
sim2 <- sort(rowSums(sim^2)*u)
out2 <- apply(matrix(rowSums(out*out),nrow(out),1),1,function(x) mean(sim2<=x))
out3 <- ifelse(out2>=0.5,1-out2,out2)
out3 <- qnorm(ifelse(.Machine$double.xmin>=out3,.Machine$double.xmin,out3))*ifelse(out2>0.5,-1,1)
sim <- sim*matrix(sqrt(u),TT,k)
for(i in 1:k){
temp <- apply(matrix(out[,i],nrow(out),1),1,function(x) mean(sim[,i]<=x))
temp2 <- ifelse(temp>=0.5,1-temp,temp)
out[,i] <- qnorm(ifelse(.Machine$double.xmin>=temp2,.Machine$double.xmin,temp2))*ifelse(temp>0.5,-1,1)
}
idsx <- sort(idsi,index=TRUE)$ix
out3 <- matrix(cbind(out,out3)[idsx,],length(out3),k+1)
out_2 <- na.omit(out_2);out_2 <- matrix(out_2[idsx,],nrow(out_2),ncol(out_2))
row.names(out3) <- row.names(x$data[[1]]$y)
row.names(out_2) <- row.names(x$data[[1]]$y)
nano_ <- list(...)
nano_$y <- out3[,k+1]
nano_$type <- "p"
if(is.null(nano_$pch)) nano_$pch <- 20
dev.new()
outm <- do.call("qqnorm",nano_)
abline(0,1,lty=3)
if(!missingArg(identify)) identify(outm$x,outm$y,n=max(1,floor(abs(identify))),labels=row.names(out3))
return(invisible(list(plot=out3,output=out_2)))
}
#' @title Forecasting of a multivariate TAR model.
#' @description This function computes forecasting from a fitted multivariate TAR model.
#' @param object an object of the class \emph{mtar}.
#' @param data an (optional) data frame, list or environment (or object coercible by
#' \link{as.data.frame} to a data frame) containing the future values of the threshold
#' series as well as the exogenous series in the model.
#' If not found in data, the variables are taken from \code{environment(formula)},
#' typically the environment from which \code{mtar} is called.
#' @param credible an (optional) value for the level of the credible intervals. By default, \code{credible} is set to 0.95.
#' @param row.names an vector that allows the user to name the time point to
#' which each row in the data set \code{data} corresponds.
#' @param out.of.sample an (optional) logical variable. If \code{TRUE}, then the log-score is computed, which is a measurement to assess density forecasts. Therefore, the data.frame specified in the argument \code{data} must to include the true values of the output series.
#' @param setar an (optional) positive integer indicating the component of the output series which is
#' the threshold variable. By default,\code{setar} is set to \code{NULL}, which indicates that the fitted model is not a SETAR.
#' @return a list with the following component
#' \tabular{ll}{
#' \code{ypred} \tab a matrix with the results of the forecasting,\cr
#' \tab \cr
#' \code{summary} \tab a matrix with the mean and credible intervals of the forecasting,\cr
#' }
#' @export forecasting
#' @references Nieto, F.H. (2005) Modeling Bivariate Threshold Autoregressive Processes in the Presence of Missing Data.
#' Communications in Statistics - Theory and Methods, 34, 905-930.
#' @references Romero, L.V. and Calderon, S.A. (2021) Bayesian estimation of a multivariate TAR model when the noise
#' process follows a Student-t distribution. Communications in Statistics - Theory and Methods, 50, 2508-2530.
#' @references Calderon, S.A. and Nieto, F.H. (2017) Bayesian analysis of multivariate threshold autoregressive models
#' with missing data. Communications in Statistics - Theory and Methods, 46, 296-318.
#' @references Karlsson, S. (2013) Chapter 15-Forecasting with Bayesian Vector Autoregression. In Elliott, G. and
#' Timmermann, A. Handbook of Economic Forecasting, Volume 2, 791–89, Elsevier.
#' @examples
#' \donttest{
#' ###### Example 1: Returns of the closing prices of three financial indexes
#' data(returns)
#' fit1 <- mtar(~ COLCAP + BOVESPA | SP500, data=returns, row.names=Date,
#' dist="Gaussian", ars=list(p=c(1,1,2)), n.burnin=100,
#' n.sim=3000, n.thin=2)
#' out1 <- forecasting(fit1,data=subset(returns,Date >= "2016-03-20"),row.names=Date)
#' out1$summary
#'
#' ###### Example 2: Rainfall and two river flows in Colombia
#' data(riverflows)
#' fit2 <- mtar(~ Bedon + LaPlata | Rainfall, data=riverflows, row.names=Date,
#' dist="Gaussian", ars=list(p=c(5,5,5)), n.burnin=2000,
#' n.sim=3000, n.thin=2)
#' out2 <- forecasting(fit2,data=subset(riverflows,Date >= "2009-04-09"),row.names=Date)
#' out2$summary
#' }
#'
forecasting <- function(object,data,out.of.sample=FALSE,credible=0.95,row.names,setar=NULL){
if(class(object)[1]!="mtar")
stop("Only mtar-type objects are supported!!",call.=FALSE)
regim <- object$regim
gendist <- function(dist,Sigma,extra,delta){
Sigma <- as.matrix(Sigma)
nor <- matrix(rnorm(ncol(Sigma)),1,ncol(Sigma))%*%chol(Sigma)
if(dist %in% c("Gaussian","Skew-normal")) u <- 1
if(dist %in% c("Student-t","Skew-Student-t")) u <- 1/rgamma(1,shape=extra/2,rate=extra/2)
if(dist=="Slash") u <- 1/rbeta(1,shape1=extra/2,shape2=1)
if(dist=="Contaminated normal") u <- 1/(1 - (1-extra[2])*rbinom(1,1,extra[1]))
if(dist=="Hyperbolic") u <- rgig(n=1,lambda=1,chi=1,psi=extra^2)
if(dist=="Laplace") u <- rexp(1,rate=1/8)
if(dist %in% c("Skew-normal","Skew-Student-t"))
out_ <- sqrt(u)*matrix(delta*qnorm(0.5 + runif(ncol(Sigma))*0.5) + nor,1,ncol(Sigma)) else out_ <- nor*sqrt(u)
return(out_)
}
if(out.of.sample){
Lik <- function(dist,y,M,Sigma,delta,log,nu){
resu <- matrix(y-M,1,k)
if(dist %in% c("Skew-normal","Skew-Student-t")){
D <- as.vector(delta)*diag(k); A <- chol2inv(chol(Sigma + D**2))
out0 <- resu%*%tcrossprod(A,resu)
muv <- resu%*%(A*matrix(delta,k,k,byrow=TRUE))
Sigmav <- diag(k) - matrix(delta,k,k)*A*matrix(delta,k,k,byrow=TRUE)
if(dist=="Skew-normal"){
out <- out0 + k*log(2*pi)
if(k > 1) out <- out - 2*log(pmvnorm(lower=-muv,upper=rep(Inf,k),sigma=Sigmav))
else out <- out - 2*log(pnorm(-muv/sqrt(Sigmav),lower.tail=FALSE))
}
if(dist=="Skew-Student-t"){
out <- (nu+k)*log(1 + out0/nu) - 2*lgamma((nu+k)/2) + 2*lgamma(nu/2) + k*log(nu*pi)
muv <- muv*sqrt((nu + k)/(nu + out0))
if(k > 1) out <- out - 2*log(pmvt(lower=-muv,upper=rep(Inf,k),sigma=Sigmav,df=round(nu,0)+k))
else out <- out - 2*log(pt(-muv/sqrt(Sigmav),df=nu,lower.tail=FALSE))
}
}else{
out <- resu%*%tcrossprod(chol2inv(chol(Sigma)),resu)
if(dist=="Laplace")
out <- -2*log(besselK(sqrt(out)/2,(2-k)/2)) - ((2-k)/2)*log(out) + (k+2)*log(2)
if(dist=="Student-t")
out <- (nu+k)*log(1 + out/nu) - 2*lgamma((nu+k)/2) + 2*lgamma(nu/2) + k*log(nu/2)
if(dist=="Contaminated normal")
out <- -2*log(nu[1]*exp(-out*nu[2]/2)*nu[2]^(k/2) + (1-nu[1])*exp(-out/2))
if(dist=="Slash")
out <- ifelse(out==0,-2*log(nu/(nu+k)),-2*lgamma((k+nu)/2) + (k+nu)*log(out/2) -2*log((nu/2)*pgamma(1,shape=(k+nu)/2,rate=out/2)))
if(dist=="Hyperbolic")
out <- -2*log(besselK(nu*sqrt(1+out),(2-k)/2)) -((2-k)/2)*log(1+out) - k*log(nu) +2*log(besselK(nu,1))
out <- out + k*log(2*pi)
}
out <- -(out + log(det(Sigma)))/2
if(log) out <- out + sum(y)
return(exp(out))
}
}
mmf <- match.call(expand.dots = FALSE)
m <- match(c("data", "row.names"), names(mmf), 0)
mmf <- mmf[c(1,m)]
mmf$drop.unused.levels <- TRUE
mmf[[1]] <- as.name("model.frame")
mmf <- eval(mmf, parent.frame())
row.names <- as.vector(as.character(model.extract(mmf,row.names)))
if(out.of.sample){
mx <- model.part(Formula(object$formula), data = mmf, rhs = 1, terms = TRUE)
D <- model.matrix(mx, data = mmf)
if(attr(terms(mx),"intercept")){
Dnames <- colnames(D)
D <- matrix(D[,-1],ncol=length(Dnames)-1)
colnames(D) <- Dnames[-1]
}
ytrue <- D
}
if(regim > 1 & is.null(setar)){
mz <- model.part(Formula(object$formula), data = mmf, rhs = 2, terms = TRUE)
Z <- model.matrix(mz, data = mmf)
if(attr(terms(mz),"intercept")){
Znames <- colnames(Z)
Z <- as.matrix(Z[,-1])
}
Z <- rbind(object$threshold.series,Z)
}
pasos <- length(row.names)
if(max(object$ars$q) > 0){
mx2 <- model.part(Formula(object$formula), data = mmf, rhs = 3, terms = TRUE)
X2 <- model.matrix(mx2, data = mmf)
if(attr(terms(mx2),"intercept")){
X2names <- colnames(X2)
X2 <- as.matrix(X2[,-1])
colnames(X2) <- X2names[-1]
}
X2 <- rbind(object$covariable.series,X2)
}
y <- object$response.series
n <- nrow(y)
k <- ncol(y)
ysim <- rbind(matrix(y,n,k*object$n.sim),matrix(0,pasos,k*object$n.sim))
if(out.of.sample){
prek <- matrix(0,pasos,object$n.sim)
ytrue <- rbind(matrix(y,n,k),matrix(ytrue,nrow(ytrue),k))
}
for(i in 1:object$n.sim){
h <- object$chains$h[i]
thresholds <- object$chains$thresholds[,i]
for(j in (n+1):(n+pasos)){
if(regim > 1){
if(!is.null(setar)) iz <- ysim[j-h,(i-1)*k + setar] else iz <- Z[j-h]
regs <- cut(iz,breaks=c(-Inf,sort(thresholds),Inf),labels=FALSE)
}else regs <- 1
X <- 1;for(l in 1:object$ars$p[regs]) X <- c(X,ysim[j-l,((i-1)*k+1):(i*k)])
if(!object$Intercept) X <- X[-1]
if(object$ars$q[regs] > 0) for(l in 1:object$ars$q[regs]) X <- c(X,X2[j-l,])
if(object$ars$d[regs] > 0) for(l in 1:object$ars$d[regs]) if(!is.null(setar)) X <- c(X,ysim[j-l,(i-1)*k + setar]) else X <- c(X,Z[j-l,])
M <- matrix(X,1,length(X))%*%object$chains[[regs]]$location[,((i-1)*k+1):(i*k)]
if(object$dist %in% c("Gaussian","Laplace")) extrai <- 0 else extrai <- object$chains$extra[,i]
if(object$dist %in% c("Skew-normal","Skew-Student-t")) deltai <- object$chains$delta[,i]
else deltai <- rep(0,k)
ysim[j,((i-1)*k+1):(i*k)] <- M + gendist(object$dist,object$chains[[regs]]$scale[,((i-1)*k+1):(i*k)],extrai,deltai)
if(out.of.sample){
Xous <- 1;for(l in 1:object$ars$p[regs]) Xous <- c(Xous,ytrue[j-l,])
if(!object$Intercept) Xous <- Xous[-1]
if(object$ars$q[regs] > 0) for(l in 1:object$ars$q[regs]) Xous <- c(Xous,X2[j-l,])
if(object$ars$d[regs] > 0) for(l in 1:object$ars$d[regs]) if(!is.null(setar)) Xous <- c(Xous,ytrue[j-l,setar]) else Xous <- c(Xous,Z[j-l,])
M <- matrix(Xous,1,length(Xous))%*%object$chains[[regs]]$location[,((i-1)*k+1):(i*k)]
prek[j-n,i] <- Lik(object$dist,ytrue[j,],M,object$chains[[regs]]$scale[,((i-1)*k+1):(i*k)],deltai,object$log,extrai)
}
}
}
ysim <- matrix(ysim[-c(1:n),],pasos,k*object$n.sim)
colnames(ysim) <- rep(colnames(y),object$n.sim)
if(object$log) ysim <- exp(ysim)
out_ <- vector()
predi <- function(x){
x <- matrix(x,1,length(x))
ks <- seq(credible,1,length=object$n.sim*(1-credible))
lis <- t(apply(x,1,quantile,probs=ks-credible))
lss <- t(apply(x,1,quantile,probs=ks))
dif <- apply(abs(lss-lis),1,which.min)
out_ <- c(mean(x),lis[dif],lss[dif])
names(out_) <- c("Mean","HDI_Low","HDI_high")
return(out_)
}
for(i in 1:k) out_ <- cbind(out_,t(apply(matrix(ysim[,seq(i,k*object$n.sim,k)],pasos,object$n.sim),1,predi)))
rownames(out_) <- row.names
rownames(ysim) <- row.names
out__ <- list(ypred=ysim,summary=out_,y=y)
if(out.of.sample) out__$log.score <- -log(rowMeans(prek))
class(out__) <- "forecastmtar"
return(out__)
}
#' @method plot forecastmtar
#' @export
plot.forecastmtar <- function(x,...,n,historical=list(),forecasts=list(),forecasts.PI=list(),main=NULL){
k <- ncol(x$y)
out_ <- x$summary
pasos <- nrow(out_)
y <- matrix(x$y,nrow(x$y),ncol(x$y))
if(missingArg(n)) n <- nrow(y) else n <- ceiling(abs(n))
y2 <- rbind(matrix(y[(nrow(y)-n+1):nrow(y),],ncol=k),matrix(out_[,seq(1,3*k,3)],ncol=k))
forecasts$xlim <- historical$xlim <- c(1,n+pasos)
forecasts$x <- (n+1):(n+pasos)
forecasts.PI$ylab <- forecasts.PI$xlab <- historical$xlab <- historical$ylab <- ""
if(is.null(historical$type)) historical$type <- "l"
if(is.null(historical$lty)) historical$lty <- 1
if(is.null(historical$col)) historical$col <- "black"
forecasts$xlim <- c(1,n+pasos)
if(is.null(forecasts$type)) forecasts$type <- "l"
if(is.null(forecasts$lty)) forecasts$lty <- 1
if(is.null(forecasts$col)) forecasts$col <- "blue"
if(is.null(forecasts$xlab)) forecasts$xlab <- ""
if(is.null(forecasts$ylab)) forecasts$ylab <- ""
if(is.null(forecasts.PI$density)) forecasts.PI$density <- NA
if(is.null(forecasts.PI$col)) forecasts.PI$col <- "light gray"
for(i in 1:k){
dev.new()
historical$ylim <- forecasts.PI$ylim <- forecasts$ylim <- range(y2[,i],out_[,1:3+3*(i-1)])
historical$x <- y[(nrow(y)-n+1):nrow(y),i]
if(is.null(main)) historical$main <- colnames(x$y)[i]
else historical$main <- main[i]
do.call("plot",historical)
xs <- c((n+1):(n+pasos),(n+pasos):(n+1))
ys <- c(out_[,2+3*(i-1)],out_[nrow(out_):1,3+3*(i-1)])
par(new=TRUE)
forecasts.PI$x <- xs
forecasts.PI$y <- ys
do.call("polygon",forecasts.PI)
forecasts$y <- out_[,1+3*(i-1)]
forecasts$main <- colnames(y)[i]
par(new=TRUE)
do.call("plot",forecasts)
}
}
#'
#' @title Converts chains from the Bayesian estimation of a multivariate TAR model to a mcmc object.
#' @description This function converts the chains obtained from the Bayesian estimation of a multivariate TAR model to a \code{mcmc} object to be analyzed with the \pkg{coda} package.
#' @param object an object of the class \emph{mtar}.
#'
#' @return a \code{mcmc}-type object.
#' @export convert
#' @examples
#' \donttest{
#' ###### Example 1: Returns of the closing prices of three financial indexes
#' data(returns)
#' fit1 <- mtar(~ COLCAP + BOVESPA | SP500, data=returns, row.names=Date,
#' dist="Gaussian", ars=list(p=c(1,1,2)), n.burnin=100,
#' n.sim=3000, n.thin=2)
#' chains1 <- convert(fit1)
#' summary(chains1$location[[1]])
#' plot(chains1$location[[1]])
#'
#' ###### Example 2: Rainfall and two river flows in Colombia
#' data(riverflows)
#' fit2 <- mtar(~ Bedon + LaPlata | Rainfall, data=riverflows, row.names=Date,
#' dist="Gaussian", ars=list(p=c(5,5,5)), n.burnin=2000,
#' n.sim=3000, n.thin=2)
#' chains2 <- convert(fit2)
#' summary(chains2$location[[2]])
#' plot(chains2$location[[2]])
#' }
#'
convert <- function(object){
if(class(object)[1]!="mtar")
stop("Only mtar-type objects are supported!!",call.=FALSE)
k <- ncol(object$data[[1]]$y)
yn <- colnames(object$data[[1]]$y)
n.sim <- object$n.sim
out <- list()
out$location <- list()
out$scale <- list()
for(r in 1:object$regim){
datos <- matrix(object$chains[[r]]$location,nrow=nrow(object$chains[[r]]$location),ncol=n.sim*k)
out_ <- vector()
for(i in 1:k){
temp <- t(matrix(datos[,seq(i,n.sim*k,k)],nrow=nrow(datos),ncol=n.sim))
colnames(temp) <- paste0(yn[i],":",rownames(object$chains[[r]]$location))
out_ <- cbind(out_,temp)
}
out$location[[r]] <- mcmc(out_)
datos <- matrix(object$chains[[r]]$scale,nrow=k,ncol=n.sim*k)
out_ <- vector()
for(i in 1:k){
for(j in i:k){
temp <- t(matrix(datos[i,seq(j,n.sim*k,k)],nrow=1,ncol=n.sim))
colnames(temp) <- paste0(yn[i],".",yn[j])
out_ <- cbind(out_,temp)
}
}
out$scale[[r]] <- mcmc(out_)
}
if(!(object$dist %in% c("Gaussian","Laplace"))){
datos <- matrix(object$chains$extra,nrow=nrow(object$chains$extra),ncol=n.sim)
out_ <- t(datos)
if(nrow(datos)==1) colnames(out_) <- "nu" else colnames(out_) <- paste("nu",1:nrow(datos))
out$extra <- mcmc(out_)
}
if(object$dist %in% c("Skew-normal","Skew-Student-t")){
datos <- matrix(object$chains$delta,nrow=nrow(object$chains$delta),ncol=n.sim)
out_ <- t(datos)
if(nrow(datos)==1) colnames(out_) <- "delta" else colnames(out_) <- paste("delta",1:nrow(datos))
out$skewness <- mcmc(out_)
}
if(object$regim > 1){
datos <- matrix(object$chains$thresholds,nrow=nrow(object$chains$thresholds),ncol=n.sim)
out_ <- t(datos)
if(nrow(datos)==1) colnames(out_) <- "threshold" else colnames(out_) <- paste("threshold",1:nrow(datos))
out$thresholds <- mcmc(out_)
out_ <- matrix(object$chains$h,nrow=n.sim,ncol=1)
colnames(out_) <- "delay"
out$delay <- mcmc(out_)
}
return(invisible(out))
}
#'
#' @title Simulation of multivariate time series according to a TAR model
#' @description This function simulates multivariate time series according to a user-specified TAR model.
#' @param n a positive integer value indicating the length of the desired output series.
#' @param k a positive integer value indicating the dimension of the desired output series.
#' @param ars a list composed of three objects, namely: \code{p}, \code{q} and \code{d},
#' each of which corresponds to a vector of \eqn{l} non-negative integers, where \eqn{l} represents the number of regimes in the TAR model.
#' @param Intercept an (optional) logical variable. If \code{TRUE}, then the model includes an intercept.
#' @param delay an (optional) non-negative integer value indicating the delay in the threshold series.
#' @param thresholds a vector with \eqn{l-1} real values sorted ascendingly.
#' @param parms a list with as many sublists as regimes in the user-specified TAR model. Each sublist is composed of two matrices. The first corresponds
#' to location parameters, while the second corresponds to scale parameters.
#' @param t.series a matrix with the values of the threshold series.
#' @param ex.series a matrix with the values of the multivariate exogenous series.
#' @param dist an (optional) character string which allows the user to specify the multivariate
#' distribution to be used to describe the behavior of the noise process. The
#' available options are: Gaussian ("Gaussian"), Student-\eqn{t} ("Student-t"),
#' Slash ("Slash"), Symmetric Hyperbolic ("Hyperbolic"), Laplace ("Laplace"), and
#' contaminated normal ("Contaminated normal"). By default,\code{dist} is set to
#' "Gaussian".
#' @param delta an (optional) vector with the values of the skewness parameters. By default,\code{delta} is set to \code{NULL}.
#' @param extra a value indicating the value of the extra parameter of the noise process distribution, if any.
#' @param setar an (optional) positive integer indicating the component of the output series which should
#' be the threshold variable. By default,\code{setar} is set to \code{NULL}.
#'
#' @return a \code{data.frame} containing the output series, threshold series (if any), and multivariate exogenous series (if any).
#' @export simtar
#' @examples
#' \donttest{
#' ###### Simulation of a trivariate TAR model with two regimes
#' n <- 2000
#' k <- 3
#' ars <- list(p=c(1,2))
#' Z <- as.matrix(arima.sim(n=n+max(ars$p),list(ar=c(0.5))))
#' Intercept <- TRUE
#' parms <- list()
#' for(j in 1:length(ars$p)){
#' np <- Intercept + ars$p[j]*k
#' parms[[j]] <- list()
#' parms[[j]]$location <- c(ifelse(runif(np*k)<=0.5,1,-1)*rbeta(np*k,shape1=4,shape2=16))
#' parms[[j]]$location <- matrix(parms[[j]]$location,np,k)
#' parms[[j]]$scale <- rgamma(k,shape=1,scale=1)*diag(k)
#' }
#' thresholds <- quantile(Z,probs=(0.85 + runif(1)*0.3)*seq(1,length(ars$p)-1)/length(ars$p))
#' out1 <- simtar(n=n,k=k,ars=ars,Intercept=Intercept,parms=parms,
#' thresholds=thresholds,t.series=Z,dist="Student-t",extra=6)
#' str(out1)
#'
#' fit1 <- mtar(~ Y1 + Y2 + Y3 | t.series, data=out1, ars=ars, dist="Student-t",
#' nsim=3000, n.burn=2000, n.thin=2)
#' summary(fit1)
#'
#' ###### Simulation of a trivariate VAR model
#' n <- 2000
#' k <- 3
#' ars <- list(p=2)
#' Intercept <- TRUE
#' parms <- list()
#' for(j in 1:length(ars$p)){
#' np <- Intercept + ars$p[j]*k
#' parms[[j]] <- list()
#' parms[[j]]$location <- c(ifelse(runif(np*k)<=0.5,1,-1)*rbeta(np*k,shape1=4,shape2=16))
#' parms[[j]]$location <- matrix(parms[[j]]$location,np,k)
#' parms[[j]]$scale <- rgamma(k,shape=1,scale=1)*diag(k)
#' }
#' out2 <- simtar(n=n,k=k,ars=ars,Intercept=Intercept,parms=parms,
#' dist="Slash",extra=2)
#' str(out2)
#'
#' fit2 <- mtar(~ Y1 + Y2 + Y3, data=out2, ars=ars, dist="Slash", nsim=3000,
#' n.burn=2000, n.thin=2)
#' summary(fit2)
#' toy <- data.frame(Date=rep(0,10))
#' f2 <- forecasting(fit2, data=toy, row.names=Date)
#' f2$summary
#' plot(f2, n=100)
#'
###### Simulation of a trivariate SETAR model with two regimes
#' n <- 5010
#' k <- 3
#' ars <- list(p=c(1,2))
#' Intercept <- TRUE
#' parms <- list()
#' for(j in 1:length(ars$p)){
#' np <- Intercept + ars$p[j]*k
#' parms[[j]] <- list()
#' parms[[j]]$location <- c(ifelse(runif(np*k)<=0.5,1,-1)*rbeta(np*k,shape1=4,shape2=16))
#' parms[[j]]$location <- matrix(parms[[j]]$location,np,k)
#' parms[[j]]$scale <- rgamma(k,shape=1,scale=1)*diag(k)
#' }
#' out3 <- simtar(n=n, k=k, ars=ars, Intercept=Intercept, parms=parms, delay=2,
#' thresholds=-1, dist="Laplace", setar=2)
#' str(out3)
#'
#' fit3 <- mtar(~ Y1 + Y2 + Y3 | Y2, data=out3, ars=ars, dist="Laplace",
#' nsim=3000,n.burn=2000, n.thin=2, prior=list(hmin=1))
#' summary(fit3)
#' toy <- data.frame(Date=rep(0,10))
#' f3 <- forecasting(fit3, setar=2, data=toy, row.names=Date)
#' f3$summary
#' plot(f3, n=100)
#' }
simtar <- function(n,k=2,ars=list(p=1),Intercept=TRUE,parms,delay=0,thresholds=0,t.series,ex.series,dist="Gaussian",delta=NULL,extra,setar=NULL){
n <- ceiling(abs(n))
k <- ceiling(abs(k))
if(k<=0 | k!=floor(k)) stop("The argument 'k' must be a positive integer!",call.=FALSE)
if(is.null(ars$p)) stop("The argument 'ars=list(p=)' must be a positive integer!",call.=FALSE)
regim <- length(ars$p)
if(is.null(ars$d) | regim==1) ars$d <- rep(0,length(ars$p))
if(is.null(ars$q) | missingArg(ex.series)) ars$q <- rep(0,length(ars$p))
if(regim > 1){
if(delay<0 | delay!=floor(delay)) stop("The argument 'delay' must be a non-negative integer!",call.=FALSE)
if(delay==0 & !is.null(setar)) stop("In SETAR models the argument 'delay' must be a positive integer!",call.=FALSE)
if(missingArg(t.series) & is.null(setar)) stop("The argument 't.series' is required!",call.=FALSE)
if(missingArg(thresholds)) stop("The argument 'thresholds' is required!",call.=FALSE) else thresholds <- sort(thresholds)
if(length(thresholds) != regim-1)
stop(paste0("The length of argument 'thresholds' must be ",regim-1,", and the length of the argument supplied by the user is ",length(thresholds)),call.=FALSE)
}else{
delay <- 0
ars$d <- rep(0,length(ars$p))
ars$q <- rep(0,length(ars$p))
}
ps <- max(ars$p,ars$q,ars$d,delay)
if(regim > 1 & is.null(setar)){
if(nrow(t.series)!=n+ps)
stop(paste0("The number of rows of the argument 't.series' must be ",n+ps,", and the number of rows of the argument supplied by the user is ",nrow(t.series)),call.=FALSE)
}
if(max(ars$q)>0){
if(missingArg(ex.series)) stop("An exogenous series is required!",call.=FALSE)
if(nrow(ex.series)!=n+ps)
stop(paste0("The number of rows of the argument 'ex.series' must be ",n+ps,", and the number of rows of the argument supplied by the user is ",nrow(ex.series)),call.=FALSE)
r <- ncol(ex.series)
}else r <- 0
if(!(dist %in% c("Gaussian","Student-t","Hyperbolic","Laplace","Slash","Contaminated normal","Skew-normal","Skew-Student-t")))
stop("Only 'Gaussian', 'Student-t', 'Hyperbolic', 'Laplace', 'Slash', 'Contaminated normal', 'Skew-normal' and 'Skew-Student-t' distributions are supported!",call.=FALSE)
if(dist %in% c("Student-t","Hyperbolic","Slash","Contaminated normal","Skew-Student-t")){
if(is.null(extra))
stop("For 'Student-t', 'Hyperbolic', 'Slash', 'Contaminated normal' and 'Skew-Student-t' distributions an extra parameter value must be specified!",call.=FALSE)
if((dist %in% c("Student-t","Skew-Student-t") & extra<=0) | (dist=="Hyperbolic" & extra<=0) | (dist=="Slash" & extra<=0))
stop("For 'Student-t', 'Skew-Student-t', 'Hyperbolic' and 'Slash' distributions the extra parameter value must be positive!",call.=FALSE)
if(dist=="Contaminated normal" & (any(extra<=0) | any(extra>=1)))
stop("For 'Contaminated normal' distribution the extra parameter must be a bidimensional vector with values in the interval (0,1)!",call.=FALSE)
}
if(dist %in% c("Skew-normal","Skew-Student-t") & is.null(delta))
stop("For 'Skew-normal' and 'Skew-Student-t' distributions an skewness parameter must be specified!",call.=FALSE)
myseries <- matrix(rnorm((n+ps)*k),n+ps,k)
for(i in 1:regim){
if(ncol(parms[[i]]$location)!=k | nrow(parms[[i]]$location)!=(Intercept+ars$p[i]*k+ars$q[i]*r+ars$d[i]))
stop(paste0("Dimension of location matrix in regime ",i," must be ",(Intercept+ars$p[i]*k+ars$q[i]*r+ars$d[i]),"X",k,"!"),call.=FALSE)
parms[[i]]$scale2 <- try(chol(parms[[i]]$scale),silent=TRUE)
if(!is.matrix(parms[[i]]$scale2)) stop(paste0("Scale matrix in regime ",i," is not positive definite!"),call.=FALSE)
}
for(i in 1:n){
current <- ps + i
if(regim > 1){
if(!is.null(setar)) t.series.c <- myseries[current-delay,setar]
else t.series.c <- t.series[current-delay]
regimeni <- cut(t.series.c,breaks=c(-Inf,thresholds,Inf),labels=1:regim)
}
else regimeni <- 1
if(Intercept) X <- 1 else X <- vector()
for(j in 1:ars$p[regimeni]) X <- c(X,myseries[current-j,])
if(ars$q[regimeni] > 0) for(j in 1:ars$q[regimeni]) X <- c(X,ex.series[current-j,])
if(ars$d[regimeni] > 0) for(j in 1:ars$d[regimeni]) if(!is.null(setar)) X <- c(X,myseries[current-j,setar]) else X <- c(X,t.series[current-j])
Theta <- parms[[regimeni]]$location
mu <- colSums(matrix(X,nrow(Theta),ncol(Theta))*Theta)
u <- 1
if(dist %in% c("Student-t","Skew-Student-t")) u <- 1/rgamma(1,shape=extra/2,rate=extra/2)
if(dist=="Slash") u <- 1/rbeta(1,shape1=extra/2,shape2=1)
if(dist=="Contaminated normal") if(runif(1)<=extra[1]) u <- 1/extra[2]
if(dist=="Laplace") u <- rexp(1,rate=1/8)
if(dist=="Hyperbolic") u <- rgig(n=1,lambda=1,chi=1,psi=extra^2)
if(dist %in% c("Skew-normal","Skew-Student-t")){
offset <- sqrt(u)*matrix(delta*qnorm(0.5 + runif(k)*0.5),k,1)
}
else offset <- matrix(0,k,1)
myseries[current,] <- crossprod(parms[[regimeni]]$scale2,matrix(sqrt(u)*rnorm(k),k,1)) + matrix(mu,k,1) + offset
}
for(i in 1:regim) parms[[i]]$scale2 <- NULL
datos <- data.frame(myseries)
colnames(datos) <- paste("Y",1:k,sep="")
if(regim > 1 & is.null(setar)) datos <- data.frame(datos,t.series) else datos <- data.frame(datos)
if(max(ars$q)>0){
colnames(ex.series) <- paste("X",1:r,sep="")
datos <- data.frame(datos,ex.series)
}
return(invisible(datos))
}
#' @method plot mtar
#' @export
plot.mtar <- function(x,...){
temp <- residuals(x)
dev.new()
par(mfrow=c(1,3))
qqnorm(temp$full,col="blue",main="Quantile-type residuals")
abline(0,1,lty=3)
acf(temp$full,main="Quantile-type residuals")
pacf(temp$full,main="Quantile-type residuals")
}
#' @method residuals mtar
#' @export
residuals.mtar <- function(object,...,type=c("quantile","mahalanobis"),plot.it=FALSE,identify){
type <- match.arg(type)
n.sim <- object$n.sim
dist <- object$dist
if(dist %in% c("Skew-normal","Skew-Student-t"))
stop("Models with Skew-normal or Skew-t as noise distribution are not supported!",call.=FALSE)
k <- ncol(object$data[[1]]$y)
resi <- matrix(NA,1,k)
idsi <- vector()
if(object$regim > 1) lims <- (object$ps+1):(length(object$threshold.series))
if(object$dist %in% c("Student-t","Hyperbolic","Slash","Contaminated normal"))
extra <- rowMeans(matrix(object$chains$extra,ncol=n.sim))
ids <- 1:nrow(object$data[[1]]$X)
if(object$regim > 1){
h <- as.integer(round(mean(object$chains$h)))
thresholds <- rowMeans(matrix(object$chains$thresholds,object$regim-1,ncol=n.sim))
Z <- object$threshold.series[lims-h]
regs <- cut(Z,breaks=c(-Inf,sort(thresholds),Inf),labels=FALSE)
}else regs <- matrix(1,nrow(object$data[[1]]$y),1)
for(i in 1:object$regim){
location <- matrix(0,nrow(object$chains[[i]]$location),k)
scale <- matrix(0,k,k)
for(j in 1:k){
location[,j] <- rowMeans(matrix(object$chains[[i]]$location[,seq(j,n.sim,by=k)],nrow(location),n.sim))
scale[,j] <- rowMeans(matrix(object$chains[[i]]$scale[,seq(j,n.sim,by=k)],k,n.sim))
}
places <- regs==i
y <- object$data[[i]]$y[places,]
X <- object$data[[i]]$X[places,]
resu <- y-X%*%location
ei <- eigen(scale,symmetric=TRUE)
resu <- resu%*%(ei$vectors%*%diag(1/sqrt(as.vector(ei$values)))%*%t(ei$vectors))
resi <- rbind(resi,resu)
idsi <- c(idsi,ids[places])
}
resi <- matrix(na.omit(resi),nrow(object$data[[1]]$X),k)
TT <- 50000
sim <- matrix(rnorm(TT*k),TT,k)
if(dist=="Gaussian") u <- 1
if(dist=="Student-t") u <- 1/rgamma(TT,shape=extra/2,rate=extra/2)
if(dist=="Slash") u <- 1/rbeta(TT,shape1=extra/2,shape2=1)
if(dist=="Contaminated normal") u <- 1/(1 - (1-extra[2])*rbinom(TT,1,extra[1]))
if(dist=="Hyperbolic") u <- rgig(n=TT,lambda=1,chi=1,psi=extra^2)
if(dist=="Laplace") u <- rexp(TT,rate=1/8)
sim2 <- sort(rowSums(sim^2)*u)
resi2 <- matrix(rowSums(resi^2),nrow(resi),1)
resij <- resi2
if(type=="quantile"){
resi2 <- apply(resi2,1,function(x) mean(sim2<=x))
resi3 <- ifelse(resi2>=0.5,1-resi2,resi2)
resij <- qnorm(ifelse(.Machine$double.xmin>=resi3,.Machine$double.xmin,resi3))*ifelse(resi2>0.5,-1,1)
}
idsx <- sort(idsi,index=TRUE)$ix
resij <- matrix(resij[idsx],length(resij),1)
if(type=="quantile"){
sim <- sim*matrix(sqrt(u),TT,k)
for(i in 1:k){
temp <- apply(matrix(resi[,i],nrow(resi),1),1,function(x) mean(sim[,i]<=x))
temp2 <- ifelse(temp>=0.5,1-temp,temp)
resi[,i] <- qnorm(ifelse(.Machine$double.xmin>=temp2,.Machine$double.xmin,temp2))*ifelse(temp>0.5,-1,1)
}
}
resi <- matrix(resi[idsx,],nrow(resi),k)
row.names(resij) <- row.names(resi) <- row.names(object$data[[1]]$y)
colnames(resij) <- " "
colnames(resi) <- colnames(object$data[[1]]$y)
if(plot.it==TRUE){
nano_ <- list(...)
nano_$y <- resij
nano_$type <- "p"
if(is.null(nano_$pch)) nano_$pch <- 20
if(is.null(nano_$ylim)) nano_$ylim <- 1.1*range(resij)
if(is.null(nano_$pch)) nano_$pch <- 20
if(is.null(nano_$col)) nano_$col <- "black"
if(is.null(nano_$main)) nano_$main <- ""
if(is.null(nano_$xlab)) nano_$xlab <- "Theoretical quantiles"
if(is.null(nano_$ylab)) nano_$ylab <- "Sample quantiles"
if(is.null(nano_$labels)) labels <- row.names(object$data[[1]]$y)
else{
labels <- nano_$labels
nano_$labels <- NULL
}
dev.new()
outm <- do.call("qqnorm",nano_)
abline(0,1,lty=3)
if(!missingArg(identify)) identify(outm$x,outm$y,n=max(1,floor(abs(identify))),labels=row.names(resij),labels=labels)
}
return(invisible(list(full=resij,by.component=resi)))
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.