Nothing
#############################################
############ Rank test
#############################################
#'Test of the cointegrating rank
#'
#'Maximum-likelihood test of the cointegrating rank.
#'
#'This function computes the two maximum-likelihood tests for the cointegration
#'rank from Johansen (1996). Tests are: \describe{ \item{trace}{Test the
#'hypothesis of rank \sQuote{h} against rank \sQuote{K}, i.e. against the
#'alternative that the system is stationary.} \item{eigenvalue}{Test the
#'hypothesis of rank \sQuote{h} against rank \sQuote{h+1}.} }
#'
#'The test works for five specifications of the deterministic terms as in
#'Doornik et al (1998), to be specified in the previous call to
#'\code{\link{VECM}}: \describe{ \item{H_ql}{Unrestricted constant and trend:
#'use \code{include="both"} } \item{H_l}{Unrestricted constant and restricted
#'trend: use \code{include="const"}} and \code{LRinclude="trend"}
#'\item{H_lc}{Unrestricted constant and no trend: use \code{include="const"}}
#'\item{H_c}{Restricted constant and no trend: use \code{LRinclude="const"}}
#'\item{H_z}{No constant nor trend: use \code{include="none"}} }
#'
#'Two testing procedures can be used: \describe{ \item{Specific test}{By
#'specifying a value for \sQuote{r_null}. The \sQuote{pval} value returned
#'gives the speciifc p-value.} \item{Automatic test}{If not value is specified
#'for \sQuote{r_null}, the function makes a simple automatic test: returns the
#'rank (slot \sQuote{r}) of the first test not rejected (level specified by arg
#'\code{cval}) as recommend i.a. in Doornik et al (1998, p. 544).} }
#'
#'A full table with both test statistics ad their respective p-values is given
#'in the summary method.
#'
#'P-values are obtained from the gamma approximation from Doornik (1998, 1999).
#'Small sample values adjusted for the sample site are also available in the
#'summary method. Note that the \sQuote{effective sample size} for the these
#'values is different from output in gretl for example.
#'
#'@aliases rank.test summary.rank.test
#'@param vecm \sQuote{VECM} object computed with the function
#'\code{\link{VECM}}.
#'@param type Type of test, either 'trace' or 'eigenvalue'. See details below.
#'@param r_null Rank to test specifically.
#'@param cval Critical value level for the automatic test.
#'@param x The output from \code{rank.test} for the print method.
#'@param object The output from \code{rank.test} for the summary method.
#'@param ... Unused.
#'@return An object of class \sQuote{rank.test}, with \sQuote{print} and
#'\sQuote{summary methods}.
#'@section Comparison with urca: While \code{\link[urca]{ca.jo}} in package
#'\pkg{urca} and \code{rank.test} both implement Johansen tests, there are a
#'few differences:
#'
#'\itemize{ \item \code{rank.test} gives p-values, while \code{ca.jo} gives
#'only critical values. \item \code{rank.test} allows for five different
#'specifications of deterministic terms (see above), \code{ca.jo} for only
#'three. \item \code{ca.jo} allows for seasonal and exogenous regressors,
#'which is not available in \code{rank.test}. \item The lag is specified
#'differently: \code{K} from \code{ca.jo} corresponds to \code{lag}+1 in
#'\code{rank.test}. }
#'@author Matthieu Stigler
#'@export
#'@seealso \code{\link{VECM}} for estimating a VECM. \code{\link{rank.select}}
#'to estimate the rank based on information criteria.
#'
#'\code{\link[urca]{ca.jo}} in package \pkg{urca} for another implementation of
#'Johansen cointegration test (see section \sQuote{Comparison with urca} for
#'more infos).
#'@references - Doornik, J. A. (1998) Approximations to the Asymptotic
#'Distributions of Cointegration Tests, Journal of Economic Surveys, 12, 573-93
#'
#'- Doornik, J. A. (1999) Erratum [Approximations to the Asymptotic
#'Distribution of Cointegration Tests], Journal of Economic Surveys, 13, i
#'
#'- Doornik, Hendry and Nielsen (1998) Inference in Cointegrating Models: UK M1
#'Revisited, Journal of Economic Surveys, 12, 533-72
#'
#'- Johansen, S. (1996) Likelihood-based inference in cointegrated Vector
#'Autoregressive Models, Oxford University Press
#'@keywords ts
#'@examples
#'
#'
#'data(barry)
#'
#'## estimate the VECM with Johansen!
#'ve <- VECM(barry, lag=1, estim="ML")
#'
#'## specific test:
#'ve_test_spec <- rank.test(ve, r_null=1)
#'ve_test_spec_tr <- rank.test(ve, r_null=1, type="trace")
#'
#'ve_test_spec
#'ve_test_spec_tr
#'
#'## No specific test: automatic method
#'ve_test_unspec <- rank.test(ve)
#'ve_test_unspec_tr <- rank.test(ve, type="trace")
#'
#'ve_test_unspec
#'ve_test_unspec_tr
#'
#'## summary method: output will be same for all types/test procedure:
#'summary(ve_test_unspec_tr)
#'
#'## The function works for many specification of the VECM(), try:
#'rank.test(VECM(barry, lag=3, estim="ML"))
#'rank.test(VECM(barry, lag=3, include="both",estim="ML"))
#'rank.test(VECM(barry, lag=3, LRinclude="const",estim="ML"))
#'
#'## Note that the tests are simple likelihood ratio, and hence can be obtained also manually:
#'-2*(logLik(ve, r=1)-logLik(ve, r=2)) # eigen test, 1 against 2
#'-2*(logLik(ve, r=1)-logLik(ve, r=3)) # eigen test, 1 against 3
#'
rank.test <- function(vecm, type=c("eigen","trace"), r_null, cval=0.05){
type <- match.arg(type)
if(vecm$model.specific$estim!="ML") stop("Please note the 'vecm' object should be estimated with estim=' ML', not (default) OLS")
t <- vecm$t
k <- vecm$k
inc <- vecm$include
LR_inc <- vecm$model.specific$LRinclude
lambda <- vecm$model.specific$lambda
if(LR_inc!="none") lambda <- lambda[1:k]
###
if(LR_inc=="none") {
testCat <- switch(inc, "const"="H_lc", "both"="H_ql", "none"="H_z")
} else if(inc=="none"&LR_inc=="const") {
testCat <- "H_c"
} else if(inc=="const"&LR_inc=="trend") {
testCat <- "H_l"
} else {
stop("Sorry, rank.test does not work for model selected (due to specification of deterministic terms)\n")
}
## trace test:
trace <- -t*rev(cumsum(rev(log(1-lambda))))
## eigen
eigen <- -t*log(1-lambda)
## p-values:
trace_pval <- gamma_doornik_all(trace, nmp=length(trace):1, test=testCat, type="trace")
adjT <- vecm$t -floor(npar(vecm)/vecm$k)
trace_pval_T <- gamma_doornik_all(trace, nmp=length(trace):1, test=testCat, type="trace", smallSamp=TRUE, T=adjT)
eigen_pval <- gamma_doornik_all(eigen, nmp=length(eigen):1, test=testCat, type="eigen")
## select r
pvals <- switch(type, trace=trace_pval, eigen=eigen_pval)
if(missing(r_null)){
w.pvals <- if(all(pvals<cval)) length(pvals) else which(pvals>cval)[1]
pval <- pvals[w.pvals]
rank <- if(pval>cval) w.pvals-1 else w.pvals
r_null <- "unspec"
} else {
pval <- pvals[r_null+1]
rank <- r_null
r_null <- "specified"
}
## assemble
res <- list()
cal <- list(call=match.call())
cal$cval <- cval
cal$k <- k
cal$type <- type
cal$r_null <- r_null
res_df <- data.frame(r=0:(k-1), trace=trace, trace_pval=trace_pval, trace_pval_T=trace_pval_T, eigen=eigen, eigen_pval=eigen_pval)
res$res_df <- res_df
res$r <- rank
res$pval <- pval
res$call <- cal
class(res) <- "rank.test"
return(res)
}
#' @rdname rank.test
#' @export
print.rank.test <- function(x, ...) {
if(x$call$r_null=="unspec"){
cat("Rank selected:", x$r, "(first",x$call$type, "test with pval above", 100*x$call$cval, "%:", round(100*x$pval,1), "%)\n")
} else {
alter <- switch(x$call$type, "eigen" = x$r+1, "trace"= x$call$k)
cat("Test of rank ", x$r," versus ", alter, " (",x$call$type, " test), p-value: ", x$pval, ".\n", sep="")
}
invisible(x)
}
#' @rdname rank.test
#' @param digits The number of digits to use in \code{\link{format.pval}}
#' @export
summary.rank.test <- function(object, digits=max(1, getOption("digits") - 3), ...) {
res <- object$res_df
rownames(res) <- NULL
res[, c(3,4,6)] <- sapply(res[, c(3,4,6)], function(x) format.pval(x, eps=1e-03,digits = digits))
return(res)
}
#############################################
############ P val approximation
#############################################
gamma_doornik <- function(x, nmp,q, test=c("H_z", "H_c", "H_lc", "H_l", "H_ql"), type=c("trace", "eigen"), T, smallSamp=FALSE){
test <- match.arg(test)
type <- match.arg(type)
miss <- c(missing(x), missing(q))
if(all(miss)|all(!miss)) stop("Please provide only one of args 'x' or 'q'\n")
### TRACE CASE
if(type=="trace"){
## No corr:
paras_mean <- doornik_tab7_mean[,test]
paras_var <- doornik_tab7_var[,test]
val_mean <- c(nmp^2, nmp, 1, ifelse(nmp==1,1,0), ifelse(nmp==2,1,0), sqrt(nmp))
val_var <- c(nmp^2, nmp, 1, ifelse(nmp==1,1,0), ifelse(nmp==2,1,0))
mean <- val_mean%*% paras_mean
var <- val_var%*% paras_var
### Small sample case:
if(smallSamp){
paras_mean <- doornik_tab9_mean[,test]
paras_var <- doornik_tab9_var[,test]
vals <- c(sqrt(nmp)/T, nmp/T, nmp^2/T^2, ifelse(nmp==1, 1/T,0), ifelse(nmp==1,1,0), ifelse(nmp==2,1,0), ifelse(nmp==3,1,0))
mean_corr <- vals %*% paras_mean
var_corr <- vals %*% paras_var
mean <- exp(log(mean) +mean_corr)
var <- exp(log(var) +var_corr)
}
} else {
### EIGEN CASE
paras_mean_eig <- doornik_tab8_mean[,test]
paras_var_eig <- doornik_tab8_var[,test]
val_eig <- c(nmp, 1, ifelse(nmp==1,1,0), ifelse(nmp==2,1,0), sqrt(nmp))
mean <- val_eig%*% paras_mean_eig
var <- val_eig%*% paras_var_eig
}
## dfs
df1 <- mean^2/var
df2 <- mean/var
## Compute p val or quantiles
if(!missing(x)) res <- 1-pgamma(x, df1, df2)
if(!missing(q)) res <- qgamma(q, df1, df2)
names_res <- if(!missing(x)) "pval" else paste(100*q, "%", sep="")
names(res) <- names_res
## return res
return(res)
}
gamma_doornik_all <- function(x, nmp,q, test=c("H_z", "H_c", "H_lc", "H_l", "H_ql"), type=c("trace", "eigen"), smallSamp=FALSE, T){
## small checks
test <- match.arg(test)
type <- match.arg(type)
miss <- c(missing(x), missing(q))
if(all(miss)|all(!miss)) stop("Provide only one of args 'x' or 'q'\n")
## many x
if(!missing(x)){
res <- vector("numeric", length(x))
for(i in 1:length(x)) res[i] <- gamma_doornik(x=x[i], nmp=nmp[i], test=test, type=type, smallSamp= smallSamp, T=T)
names(res) <-paste("pval n-p", nmp, sep="=")
} else {
res <- matrix(NA, ncol=length(q), nrow=length(nmp))
for(i in 1:length(nmp)) res[i,] <- gamma_doornik(q=q, nmp=nmp[i], test=test, type=type, smallSamp= smallSamp, T=T)
rownames(res) <- paste("n-p", nmp, sep="=")
colnames(res) <- paste(100*q, "%", sep="")
}
return(res)
}
### Critical values tables (taken from Doornik, in gretl plugin/johansen.c
Hnames <- c("H_z", "H_c", "H_lc", "H_l", "H_ql")
doornik_tab7_mean <- matrix(c(2, -1, 0.07, 0.07, 0, 0, 2, 2.01, 0, 0.06, 0.05,
0, 2, 1.05, -1.55, -0.5, -0.23, 0, 2, 4.05, 0.5, -0.23, -0.07,
0, 2, 2.85, -5.1, -0.1, -0.06, 1.35), ncol=5, dimnames=list(1:6, Hnames))
doornik_tab7_var <- matrix(c(3, -0.33, -0.55, 0, 0, 3, 3.6, 0.75, -0.4, -0.3,
3, 1.8, 0, -2.8, -1.1, 3, 5.7, 3.2, -1.3, -0.5, 3, 4,
0.8, -5.8, -2.66), ncol=5, dimnames=list(1:5, Hnames))
doornik_tab8_mean <- matrix(c(6.0019, -2.7558, 0.67185, 0.1149, -2.7764, 5.9498,
0.43402, 0.04836, 0.018198, -2.3669, 5.8271, -1.6487, -1.6118,
-0.25949, -1.5666, 5.8658, 2.5595, -0.34443, -0.077991, -1.7552,
5.6364, -0.90531, -3.5166, -0.47966, -0.21447), ncol=5, dimnames=list(1:5, Hnames))
doornik_tab8_var <- matrix(c(1.8806, -15.499, 1.1136, 0.070508, 14.714, 2.2231,
-7.9064, 0.58592, -0.034324, 12.058, 2.0785, -9.7846, -3.368,
-0.24528, 13.074, 1.9955, -5.5428, 1.2425, 0.41949, 12.841, 2.0899,
-5.3303, -7.1523, -0.2526, 12.393), ncol=5, dimnames=list(1:5, Hnames))
doornik_tab9_mean <- matrix(c(-0.101, 0.499, 0.896, -0.562, 0.00229, 0.00662, 0,
0, 0.465, 0.984, -0.273, -244, 0, 0, 0.134, 0.422, 1.02, 2.17,
-0.00182, 0, -0.00321, 0.0252, 0.448, 1.09, -0.353, 0, 0, 0,
-0.819, 0.615, 0.896, 2.43, 0.00149, 0, 0), ncol=5, dimnames=list(1:7, Hnames))
doornik_tab9_var <- matrix(c(-0.204, 0.98, 3.11, -2.14, 0.0499, -0.0103, -0.00902,
0.224, 0.863, 3.38, -0.807, 0, 0, -0.0091, 0.422, 0.734, 3.76,
4.32, -0.00606, 0, -0.00718, 0, 0.836, 3.99, -1.33, -0.00298,
-0.00139, -0.00268, -1.29, 1.01, 3.92, 4.67, 0.00484, -0.00127,
-0.0199), ncol=5, dimnames=list(1:7, Hnames))
##########################################################################################
############ TEST: reproduce table in sec 10.1 of Doornik (1998) (with corr Doornik 1999)
##########################################################################################
if(FALSE){
## Individual test of p-vals:
gamma_doornik(49.14, nmp=4)
gamma_doornik(19.06, nmp=3)
gamma_doornik(8.89, nmp=2)
gamma_doornik(2.35, nmp=1)
## Individual test of quantiles:
gamma_doornik(q=c(0.9, 0.95, 0.99), nmp=4)
## Vector test of p-vals/quantiles:
gamma_doornik_all(x=c(49.14, 19.06, 8.89,2.35), nmp=4:1)
gamma_doornik_all(x=c(49.14, 19.06, 8.89,2.35), nmp=4:1, test="H_lc")
gamma_doornik_all(x=c(49.14, 19.06, 8.89,2.35), nmp=4:1, test="H_l")
gamma_doornik_all(x=c(49.14, 19.06, 8.89,2.35), nmp=4:1, type="eigen")
gamma_doornik_all(x=c(49.14, 19.06, 8.89,2.35), nmp=4:1, test="H_lc", type="eigen")
gamma_doornik_all(x=c(49.14, 19.06, 8.89,2.35), nmp=4:1, test="H_l", type="eigen")
gamma_doornik_all(q=c(0.9, 0.95, 0.99), nmp=4:1)
}
##########################################################################################
############ TEST: rank.test
##########################################################################################
if(FALSE){
library(tsDyn)
library(vars)
library(urca)
environment(rank.test) <- environment(star)
#data(Canada)
#data(denmark)
ve_can <- VECM(Canada, lag=1, estim="ML")
ve_can_l2 <- VECM(Canada, lag=2, estim="ML")
r_l1<- rank.test(ve_can)
summary(r_l1)
r_l2<- rank.test(ve_can_l2)
r_l2b<- rank.test(ve_can_l2, cval=0.15)
r_l2_ei<- rank.test(ve_can_l2, type="eigen", cval=0.25)
r_l2
r_l2b
r_l2_ei
summary(r_l2)
## with include="both"
ve_can_bo <- VECM(Canada, lag=1, estim="ML", include="both")
r_can_bo <- rank.test(ve_can_bo )
summary(r_can_bo)
## with include="both"
ve_can_none <- VECM(Canada, lag=1, estim="ML", include="none")
r_can_none <- rank.test(ve_can_none)
summary(r_can_none)
## with include="trend"
ve_can_tr <- VECM(Canada, lag=1, estim="ML", include="trend")
r_can_bo <- rank.test(ve_can_tr)
## with LRinclude=const
ve_can_LrCo <- VECM(Canada, lag=1, estim="ML", LRinclude="const")
r_can_LrCo <- rank.test(ve_can_LrCo)
summary(r_can_LrCo)
## with LRinclude=trend
ve_can_LrTr <- VECM(Canada, lag=1, estim="ML", LRinclude="trend", include="const")
ve_can_LrTr$model.specific$lambda
r_can_LrTr <- rank.test(ve_can_LrTr)
summary(r_can_LrTr )
}
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.