Nothing
####################################################
## This file contains the isat-source of the gets
## package.
##
## CONTENTS:
##
## isat.default
## coef.isat #extraction functions
## fitted.isat #(all are S3 methods)
## gets.isat
## logLik.isat
## plot.isat
## predict.isat
## print.isat
## residuals.isat
## summary.isat
## vcov.isat
##
## biascorr #auxiliary functions:
## isattest
## isatvar
## isvarcor
## isvareffcor
## iim #make matrix of impulse indicators
## sim #make matrix of step indicators
## tim #make matrix of trend indicators
##
####################################################
####################################################
## ISAT FUNCTIONS
####################################################
##==================================================
## indicator saturation
isat.default <- function(y, mc=TRUE, ar=NULL, ewma=NULL, mxreg=NULL,
iis=FALSE, sis=TRUE, tis=FALSE, uis=FALSE, blocks=NULL,
ratio.threshold=0.8, max.block.size=30, t.pval=0.001,
wald.pval=t.pval, vcov.type=c("ordinary", "white", "newey-west"),
do.pet=FALSE, ar.LjungB=NULL, arch.LjungB=NULL,
normality.JarqueB=NULL, info.method=c("sc", "aic", "hq"),
user.diagnostics=NULL, user.estimator=NULL, gof.function=NULL,
gof.method=c("min","max"), include.gum=NULL,
include.1cut=FALSE, include.empty=FALSE, max.paths=NULL,
parallel.options=NULL, turbo=FALSE, tol=1e-07, LAPACK=FALSE,
max.regs=NULL, print.searchinfo=TRUE, plot=NULL, alarm=FALSE, ...)
{
##arguments:
isat.call <- sys.call()
vcov.type <- match.arg(vcov.type)
info.method <- match.arg(info.method)
gof.method <- match.arg(gof.method)
isat.args <- list(
mc = mc,
ar = ar,
ewma = ewma,
iis = iis,
sis = sis,
tis = tis,
uis = uis,
uis.logical = if(is.null(uis) | identical(uis, FALSE)){FALSE} else {TRUE},
blocks = blocks,
ratio.threshold = ratio.threshold,
max.block.size = max.block.size,
t.pval = t.pval,
wald.pval = wald.pval,
vcov.type = vcov.type,
do.pet = do.pet,
ar.LjungB = ar.LjungB,
arch.LjungB = arch.LjungB,
normality.JarqueB = normality.JarqueB,
info.method = info.method,
user.diagnostics = user.diagnostics,
user.estimator = user.estimator,
gof.function = gof.function,
gof.method = gof.method,
include.gum = include.gum,
include.1cut = include.1cut,
include.empty = include.empty,
max.paths = max.paths,
parallel.options = parallel.options,
turbo = turbo,
tol = tol,
LAPACK = LAPACK,
max.regs = max.regs
)
##check that any indicator method is selected
if(sis == FALSE && iis == FALSE && tis == FALSE && identical(uis, FALSE)){
stop("No Indicator Selection Method was selected. Either set iis, sis or tis as TRUE or specify uis.")
}
##warn to use robust coefficient variances
# suggestion by M-orca 02/10/2022: no time to test this, but potentially useful addition
# if(vcov.type != "ordinary"){
# warning("Using robust coefficient covariances is currently discouraged. Errors are likely and results are unlikely to be useful.\nReason is that robust estimators inflate p-values of indicators, leading to overidentification of indicators.\nRecommended to use 'ordinary' vcov type in isat and then to use robust estimators post-selection (i.e. to run arx() with vcov.type argument on the resulting isat object).")
# }
if(!is.null(ar) && identical(ar,0)){ar <- NULL}
if(!(is.numeric(ar) | is.null(ar))){stop("The 'ar' argument must be NULL or numeric.")}
##name of regressand:
y.name <- deparse(substitute(y))
if( y.name[1] == "" ){ y.name <- "y" }
##determine qstat.options:
if(is.null(ar)){
qstat.options <- c(1,1)
}else{
qstat.options <- c(max(ar),1)
}
##check include.gum argument:
if(!is.null(include.gum)){
warning("The 'include.gum' argument is ignored (temporarily deprecated in isat)")
}
include.gum <- TRUE
##make userEstArg:
if(is.null(user.estimator)){ #default (ols):
olsMethod <- switch(vcov.type,
"ordinary"=3, "white"=4, "newey-west"=5)
userEstArg <- list(name="ols", tol=tol, LAPACK=LAPACK,
method=olsMethod)
userEstArgArx <- NULL
}else{ #user-defined:
userEstArg <- user.estimator
userEstArgArx <- user.estimator
}
##make gof.function argument:
if(is.null(gof.function)){
gofFunArg <- list(name="infocrit", method=info.method)
}else{
gofFunArg <- gof.function
}
##max paths argument:
if( !is.null(max.paths) && max.paths < 1 ){
stop("'max.paths' cannot be smaller than 1")
}
##parallel.options argument:
if(!is.null(parallel.options)){
##if(numeric):
if(is.numeric(parallel.options)){
clusterSpec <- parallel.options
OScores <- detectCores()
if(parallel.options > OScores){
stop("parallel.options > number of cores/threads")
}
}
##varlist for clusterExport:
if(is.list(parallel.options)){
clusterVarlist <- parallel.options$varlist
}else{
clusterVarlist <- NULL
}
clusterVarlist <- c(clusterVarlist,
"dropvar", "getsFun", "ols", "infocrit", "diagnostics")
if(!is.null(user.diagnostics)){
clusterVarlist <- c(clusterVarlist, user.diagnostics$name)
}
if(!is.null(user.estimator)){
clusterVarlist <- c(clusterVarlist, user.estimator$name)
}
if(!is.null(gof.function)){
clusterVarlist <- c(clusterVarlist, gof.function$name)
}
#for the future?: add memory.limit()/memory.size() = max cores check?
} #end if(!is.null(parallel.options))
#OLD:
# ##parallel.options argument:
# if(!is.null(parallel.options)){
# if(is.numeric(parallel.options)){
# clusterSpec <- parallel.options
# }
# OScores <- detectCores()
# if(parallel.options > OScores){
# stop("parallel.options > number of cores/threads")
# }
# #to do: enable exportCluster argument?
# #add: memory.limit()/memory.size() = max cores check?
# }
##create regressors (no indicators), record info:
mX <- regressorsMean(y, mc=mc, ar=ar, ewma=ewma, mxreg=mxreg,
return.regressand = TRUE, return.as.zoo = TRUE, na.trim = TRUE)
y.n <- NROW(mX)
y.index <- index(mX)
y.index.as.char <- as.character(y.index)
y <- coredata(mX[,1])
#recall: y.name already defined above (in the beginning)
if(NCOL(mX)==1){
mX <-NULL
mXnames <- NULL
mXncol <- 0
mxkeep <- NULL
}else{
mXnames <- colnames(mX)[-1]
mX <- as.matrix(coredata(mX[,-1]))
colnames(mX) <- mXnames
mXncol <- NCOL(mX)
mxkeep <- 1:mXncol
}
##ar.LjungB argument:
arLjungB <- NULL
if(!is.null(ar.LjungB)){
arLjungB <- c(NA, ar.LjungB$pval)
if(is.null(ar.LjungB$lag)){
arLjungB[1] <- qstat.options[1]
}else{
arLjungB[1] <- ar.LjungB$lag
}
}
##arch.LjungB argument:
archLjungB <- NULL
if(!is.null(arch.LjungB)){
archLjungB <- c(NA, arch.LjungB$pval)
if(is.null(arch.LjungB$lag)){
archLjungB[1] <- qstat.options[2]
}else{
archLjungB[1] <- arch.LjungB$lag
}
}
##indicator saturation matrices:
ISmatrices <- list()
if(iis){ #impulse indicators
mIIS <- matrix(0,y.n,y.n)
diag(mIIS) <- 1
colnames(mIIS) <- paste0("iis", y.index.as.char)
ISmatrices <- c(ISmatrices,list(IIS=mIIS))
}
if(sis){ #step-shift indicators
mSIS <-matrix(0,y.n,y.n) #replace by , y.n, y.n-1 ?
loop.indx <- 1:y.n #replace by 2:y.n ?
tmp <- function(i){ mSIS[i,1:i] <<- 1 }
tmp <- sapply(loop.indx,tmp)
colnames(mSIS) <- paste0("sis", y.index.as.char)
mSIS <- mSIS[,-1]
ISmatrices <- c(ISmatrices,list(SIS=mSIS))
}
if(tis){ #trend indicators
mTIS <- matrix(0,y.n,y.n)
v1n <- seq(1,y.n)
loop.indx <- 1:y.n
tmp <- function(i){
mTIS[c(i:y.n),i] <<- v1n[1:c(y.n-i+1)]
}
tmp <- sapply(loop.indx,tmp)
colnames(mTIS) <- paste0("tis", y.index.as.char)
mTIS <- mTIS[,-1]
ISmatrices <- c(ISmatrices,list(TIS=mTIS))
}
##user-defined indicators/variables:
##----------------------------------
#if uis is a matrix or a data.frame:
if(!is.list(uis) && !identical(as.numeric(uis),0) || is.data.frame(uis)){
##handle colnames:
uis <- as.zoo(cbind(uis))
uis.names <- colnames(uis)
if(is.null(uis.names)){
uis.names <- paste0("uisxreg", 1:NCOL(uis))
}
if(any(uis.names == "")){
missing.colnames <- which(uis.names == "")
for(i in 1:length(missing.colnames)){
uis.names[missing.colnames[i]] <- paste0("uisxreg", missing.colnames[i])
}
}
##select sample:
uis <- na.trim(uis, sides="both", is.na="any")
uis.index.as.char <- as.character(index(uis))
t1 <- which(uis.index.as.char==y.index.as.char[1])
t2 <- which(uis.index.as.char
== y.index.as.char[length(y.index.as.char)])
uis <- coredata(uis)
uis <- window(uis, start=t1, end=t2)
uis <- cbind(coredata(as.zoo(uis)))
colnames(uis) <- uis.names
#check nrow(uis):
if(nrow(uis) != y.n) stop("nrow(uis) is unequal to no. of observations")
ISmatrices <- c(ISmatrices,list(UIS=uis))
} #end if uis is a matrix
##if uis is a list of matrices:
if(is.list(uis)){
#check nrow(uis[[i]]):
for(i in 1:length(uis)){
uis[[i]] <- as.matrix(coredata(as.zoo(uis[[i]])))
if(nrow(uis[[i]]) != y.n){
stop(paste("nrow(uis[[",i,"]]) is unequal to no. of observations",
sep=""))
}
} #end check nrow
uis.names <- paste0("UIS", 1:length(uis))
if(is.null(names(uis))){
names(uis) <- uis.names
}else{
for(i in 1:length(uis)){
if(names(uis)[i]==""){
names(uis)[i] <- uis.names[i]
}else{
names(uis)[i] <- paste0(uis.names[i], ".", names(uis)[i])
} #close if..else
} #close for..loop
}
ISmatrices <- c(ISmatrices,uis)
##to do: check indices of matrix against index(y)?
} #end if uis is a list of matrices
##check blocks:
if(is.list(blocks)){
if(length(ISmatrices)!=length(blocks)){
stop("No. of IS matrices is unequal to length(blocks)")
}
blocks.is.list <- TRUE
ISblocks <- blocks
}else{
blocks.is.list <- FALSE
ISblocks <- list()
}
##loop on ISmatrices:
##-------------------
estimations.total <- 0
getsFun.total <- 0
ISfinalmodels <- list()
for(i in 1:length(ISmatrices)){
##blocks:
if(!blocks.is.list){
ncol.adj <- NCOL(ISmatrices[[i]])
if(is.null(blocks)){
blockratio.value <- ncol.adj/(ratio.threshold*ncol.adj - mXncol)
blocksize.value <- ncol.adj/min(y.n*ratio.threshold, max.block.size)
no.of.blocks <- max(2,blockratio.value,blocksize.value)
no.of.blocks <- ceiling(no.of.blocks)
no.of.blocks <- min(ncol.adj, no.of.blocks) #ensure blocks < NCOL
}else{
no.of.blocks <- blocks
}
blocksize <- ceiling(ncol.adj/no.of.blocks)
partitions.t2 <- blocksize
for(j in 1:no.of.blocks){
if( blocksize*j <= ncol.adj ){
partitions.t2[j] <- blocksize*j
}
}
#check if last block contains last indicator:
if(partitions.t2[length(partitions.t2)] < ncol.adj){
partitions.t2 <- c(partitions.t2, ncol.adj)
}
blocksadj <- length(partitions.t2)
partitions.t1 <- partitions.t2 + 1
partitions.t1 <- c(1,partitions.t1[-blocksadj])
tmp <- list()
for(j in 1:blocksadj){
tmp[[j]] <- partitions.t1[j]:partitions.t2[j]
}
ISblocks[[i]] <- tmp
} #end if(!blocks.is.list)
##make blocks function for lapply/parLapply:
ISblocksFun <- function(j, i, ISmatrices, ISblocks, mX,
parallel.options, y, userEstArg, t.pval, wald.pval, do.pet,
arLjungB, archLjungB, normality.JarqueB, user.diagnostics,
gofFunArg, gof.method, mxkeep, include.gum, include.1cut,
include.empty, max.paths, turbo, tol, LAPACK, max.regs,
print.searchinfo){
##check if block contains 1 regressor:
if( length(ISblocks[[i]][[j]])==1 ){
tmp <- colnames(ISmatrices[[i]])[ ISblocks[[i]][[j]] ]
mXis <- cbind(ISmatrices[[i]][, ISblocks[[i]][[j]] ])
colnames(mXis) <- tmp
mXis <- cbind(mX, mXis)
}else{
mXis <- cbind(mX,ISmatrices[[i]][, ISblocks[[i]][[j]] ])
}
##apply dropvar:
mXis.names <- colnames(mXis)
original.mxkeep.names <- mXis.names[mxkeep]
mXis <- dropvar(mXis, tol=tol, LAPACK=LAPACK,
silent=!print.searchinfo)
mXis.names.afterdropvar <- colnames(mXis)
mxkeep.afterdropvar <- which(mXis.names.afterdropvar %in% original.mxkeep.names)
##print info:
if(is.null(parallel.options)){
if(print.searchinfo){
message("\n", appendLF=FALSE)
message(names(ISmatrices)[i],
" block ", j, " of ", length(ISblocks[[i]]), ":",
appendLF=TRUE)
#message("\n", appendLF=FALSE)
}
}
##gum:
getsis <- getsFun(y, mXis, untransformed.residuals=NULL,
user.estimator=userEstArg, gum.result=NULL, t.pval=t.pval,
wald.pval=wald.pval, do.pet=do.pet, ar.LjungB=arLjungB,
arch.LjungB=archLjungB, normality.JarqueB=normality.JarqueB,
user.diagnostics=user.diagnostics, gof.function=gofFunArg,
gof.method=gof.method, keep=mxkeep.afterdropvar, include.gum=include.gum,
include.1cut=include.1cut, include.empty=include.empty,
max.paths=max.paths, turbo=turbo, tol=tol, LAPACK=LAPACK,
max.regs=max.regs, print.searchinfo=print.searchinfo,
alarm=FALSE)
#estimations.counter counts the number of estimations for a single type of indicators
estimations.counter <<- estimations.counter + getsis$no.of.estimations
getsFun.counter <<- getsFun.counter + 1
if(is.null(getsis$specific.spec)){
ISspecific.models <- NULL
}else{
ISspecific.models <- names(getsis$specific.spec)
#For the future?:
# ISgums[[j]] <- getsis$gum.mean
# ISpaths[[j]] <- getsis$paths
# ISterminals.results[[j]] <- getsis$terminals.results
}
##return
return(ISspecific.models)
} #close ISblocksFun
# initialise counter for number of estimations of this type of indicator
estimations.counter <- 0
getsFun.counter <- 0
##do gets on each block: no parallel computing
if(is.null(parallel.options)){
ISspecific.models <- lapply(1:length(ISblocks[[i]]),
ISblocksFun, i, ISmatrices, ISblocks, mX, parallel.options,
y, userEstArg, t.pval, wald.pval, do.pet, arLjungB,
archLjungB, normality.JarqueB, user.diagnostics, gofFunArg,
gof.method, mxkeep, include.gum, include.1cut,
include.empty, max.paths, turbo, tol, LAPACK, max.regs,
print.searchinfo)
}
##do gets on each block: with parallel computing
if(!is.null(parallel.options)){
##print info:
if(print.searchinfo){
message("\n", appendLF=FALSE)
message("Preparing parallel computing...",
appendLF=TRUE)
message(names(ISmatrices)[i],
" blocks to search in parallel: ", length(ISblocks[[i]]),
appendLF=TRUE)
message("Searching...", appendLF=TRUE)
#message("\n", appendLF=FALSE)
}
blocksClust <- makeCluster(clusterSpec, outfile="") #make cluster
clusterExport(blocksClust, clusterVarlist,
envir=.GlobalEnv) #idea for the future?: envir=clusterEnvir
#OLD:
# clusterExport(blocksClust,
# c("dropvar", "getsFun", "ols", "infocrit", "diagnostics"),
# envir=.GlobalEnv)
ISspecific.models <- parLapply(blocksClust,
1:length(ISblocks[[i]]), ISblocksFun, i, ISmatrices,
ISblocks, mX, parallel.options, y, userEstArg, t.pval,
wald.pval, do.pet, arLjungB, archLjungB, normality.JarqueB,
user.diagnostics, gofFunArg, gof.method, mxkeep,
include.gum, include.1cut, include.empty, max.paths, turbo,
tol, LAPACK, max.regs, print.searchinfo)
stopCluster(blocksClust)
} #end if..
##print info:
if(print.searchinfo){
message("\n", appendLF=FALSE)
message("GETS of union of retained ",
names(ISmatrices)[i], " variables... ",
appendLF=TRUE)
}
##if no indicators retained from the blocks:
if(length(ISspecific.models) == 0){
isNames <- NULL
ISfinalmodels[[i]] <- NULL
}
##when indicators/variables(uis) retained from the blocks:
if(length(ISspecific.models) > 0){
isNames <- NULL
#which indicators/variables(uis) retained?:
for(j in 1:length(ISspecific.models)){
#check if mean is non-empty:
if(!is.null(ISspecific.models[[j]])){
isNames <- union(isNames, ISspecific.models[[j]])
}
} #end for(j) loop
isNames <- setdiff(isNames, mXnames)
#redo gets with union of retained indicators:
if(length(isNames) == 0){
ISfinalmodels[[i]] <- mXnames
}else{
mXisNames <- c(mXnames, isNames)
mXis <- cbind(mX,ISmatrices[[i]][,isNames])
colnames(mXis) <- mXisNames
# apply dropvar
mXis.names <- colnames(mXis)
original.mxkeep.names <- mXis.names[mxkeep]
mXis <- dropvar(mXis, tol=tol, LAPACK=LAPACK,
silent=!print.searchinfo)
mXis.names.afterdropvar <- colnames(mXis)
mxkeep.afterdropvar <- which(mXis.names.afterdropvar %in% original.mxkeep.names)
getsis <- getsFun(y, mXis, untransformed.residuals=NULL,
user.estimator=userEstArg, gum.result=NULL, t.pval=t.pval,
wald.pval=wald.pval, do.pet=do.pet, ar.LjungB=arLjungB,
arch.LjungB=archLjungB, normality.JarqueB=normality.JarqueB,
user.diagnostics=user.diagnostics, gof.function=gofFunArg,
gof.method=gof.method, keep=mxkeep.afterdropvar, include.gum=include.gum,
include.1cut=include.1cut, include.empty=include.empty,
max.paths=max.paths, turbo=turbo, tol=tol, LAPACK=LAPACK,
max.regs=max.regs, print.searchinfo=print.searchinfo,
alarm=FALSE)
# only done if at least one indicator of this type has been retained
# so if no search was done (because failed diagnostics), then not here
estimations.counter <- estimations.counter + getsis$no.of.estimations
getsFun.counter <- getsFun.counter + 1
ISfinalmodels[[i]] <- names(getsis$specific.spec)
}
} #end if(length(ISspecific.models > 0)
# before go to next type of indicator, save the number of estimations done
estimations.total <- estimations.total + estimations.counter
getsFun.total <- getsFun.total + getsFun.counter
} #end for(i) loop (on ISmatrices)
##add names to ISblocks:
names(ISblocks) <- names(ISmatrices)
##gets of union of all variables:
##-------------------------------
##some info:
if(print.searchinfo){
message("\n", appendLF=FALSE)
message("GETS of union of ALL retained variables...",
appendLF=TRUE)
#message("\n", appendLF=FALSE)
}
##if final models estimated:
if(length(ISfinalmodels)>0){
mIS <- NULL #becomes a matrix
#which indicators were retained?
for(i in 1:length(ISfinalmodels)){
isNames <- NULL
#check if non-empty:
if(!is.null(ISfinalmodels[[i]])){
isNames <- setdiff(ISfinalmodels[[i]], mXnames)
}
if(length(isNames)>0){
tmp <- cbind(ISmatrices[[i]][, isNames ])
colnames(tmp) <- isNames
mIS <- cbind(mIS, tmp)
}
} #end for loop
# apply dropvar
mXis.names <- colnames(cbind(mX,mIS))
original.mxkeep.names <- mXis.names[mxkeep]
mXis <- dropvar(cbind(mX,mIS), tol=tol, LAPACK=LAPACK,
silent=!print.searchinfo)
mXis.names.afterdropvar <- colnames(mXis)
mxkeep.afterdropvar <- which(mXis.names.afterdropvar %in% original.mxkeep.names)
} #end if(length(ISfinalmodels)>0)
##if no final models estimated:
if(length(ISfinalmodels)==0){
ISfinalmodels <- NULL
if(is.null(mX)){ mXis <- NULL }else{
mXis <- cbind(mX)
colnames(mXis) <- mXnames
}
}
##make return object:
##-------------------
##do final gets:
getsis <- getsFun(y, mXis, untransformed.residuals=NULL,
user.estimator=userEstArg, gum.result=NULL, t.pval=t.pval,
wald.pval=wald.pval, do.pet=do.pet, ar.LjungB=arLjungB,
arch.LjungB=archLjungB, normality.JarqueB=normality.JarqueB,
user.diagnostics=user.diagnostics, gof.function=gofFunArg,
gof.method=gof.method, keep=mxkeep.afterdropvar, include.gum=include.gum,
include.1cut=include.1cut, include.empty=include.empty,
max.paths=max.paths, turbo=turbo, tol=tol, LAPACK=LAPACK,
max.regs=max.regs, print.searchinfo=print.searchinfo,
alarm=FALSE)
estimations.total <- estimations.total + getsis$no.of.estimations
getsis$no.of.estimations <- estimations.total
getsFun.total <- getsFun.total + 1
getsis$no.of.getsFun.calls <- getsFun.total
##messages from final gets:
if( print.searchinfo && !is.null(getsis$messages)){
message(getsis$messages)
}
##estimate final model:
y <- zoo(y, order.by=y.index)
if(is.null(getsis$specific.spec)){
mXisNames <- NULL
mXis <- NULL
}else{
mXisNames <- colnames(mXis)[getsis$specific.spec]
mXis <- cbind(mXis[,getsis$specific.spec])
colnames(mXis) <- mXisNames
mXis <- zoo(mXis, order.by=y.index)
}
if(is.null(normality.JarqueB)){
normalityArg <- FALSE
}else{
normalityArg <- as.numeric(normality.JarqueB)
}
# Save original arx mc warning setting and disable it here
tmpmc <- getOption("mc.warning")
options(mc.warning = FALSE)
mod <- arx(y, mc=FALSE, mxreg=mXis, vcov.type=vcov.type,
qstat.options=qstat.options, normality.JarqueB=normalityArg,
user.estimator=userEstArgArx, user.diagnostics=user.diagnostics,
tol=tol, LAPACK=LAPACK, plot=FALSE)
mod$call <- NULL
# Set the old arx mc warning again
options(mc.warning = tmpmc)
##complete the returned object (result):
ISnames <- setdiff(mXisNames, mXnames) #names of retained impulses
#OLD:
# ISnames <- setdiff(getsis$aux$mXnames, mXnames) #names of retained impulses
if(length(ISnames)==0){ ISnames <- NULL }
colnames(mod$aux$mX) <- mod$aux$mXnames #needed for predict.isat?
getsis$gets.type <- "isat"
getsis$call <- isat.call
getsis <-
c(list(ISfinalmodels=ISfinalmodels, ISnames=ISnames), getsis, mod)
getsis$aux$t.pval <- t.pval #needed for biascorr
class(getsis) <- "isat"
if(alarm){ alarm() }
if( is.null(plot) ){ #determine whether to plot or not
plot <- getOption("plot")
if( is.null(plot) ){ plot <- FALSE }
}
if(plot){ plot.isat(getsis, coef.path=TRUE) }
getsis$aux$args <- isat.args
if(isat.args$iis &&
identical(userEstArg$name, "ols") &&
!any(isat.args$sis, isat.args$tis, isat.args$uis.logical)){
## Outlier Proportion and Distortion Test
# Proportion Test was previously executed in the print.isat function
#if(!is.null(getsis$call$iis) & isTRUE(eval(getsis$call$iis))){
# if(!any(eval(getsis$call$sis), eval(getsis$call$tis),
##change suggested by J-bat (implemented by G-man 12 June 2022):
# ifelse(is.logical(eval(getsis$call$uis)) & isTRUE(eval(getsis$call$uis)), TRUE, FALSE),
# !identical(userEstArg$name, "ols"))){
getsis$outlier.proportion.test <- outliertest(getsis)
getsis$outlier.distortion.test <- distorttest(getsis)
# }
}
return(getsis)
} #close isat function
##==================================================
coef.isat <- function(object, ...)
{
result <- object$coefficients
if(!is.null(result)){ names(result) <- names(object$specific.spec) }
return(result)
} #close coef.isat
##==================================================
## fitted values
fitted.isat <- function(object, ...)
{
result <- object$mean.fit
if(is.null(result)){ result <- object$fit }
return(result)
} #end fitted.isat
##==================================================
## gets modelling of 'isat' objects:
gets.isat <- function(x, t.pval=0.05, wald.pval=t.pval, vcov.type = NULL,
do.pet=TRUE, ar.LjungB=list(lag=NULL, pval=0.025),
arch.LjungB=list(lag=NULL, pval=0.025), normality.JarqueB=NULL,
user.diagnostics=NULL, info.method=c("sc","aic","aicc","hq"),
gof.function=NULL, gof.method=NULL, keep=NULL, include.gum=FALSE,
include.1cut=TRUE, include.empty=FALSE, max.paths=NULL, tol=1e-07,
turbo=FALSE, print.searchinfo=TRUE, plot=NULL, alarm=FALSE, ...)
{
# Check if one of these arguments is explicitly supplied to the function
# if not, then check if the original item has this arguemnt supplied
# if it does, take the setting of the original object
# if it does not, then take the default
if(missing(vcov.type)){vcov.type <- x$aux[["vcov.type"]]}
if(missing(user.diagnostics)){user.diagnostics <- x$aux[["user.diagnostics"]]}
if(missing(tol)){tol <- x$aux$tol}
if(missing(normality.JarqueB)){if(is.null(x$call$normality.JarqueB)){normality.JarqueB <- FALSE}else{normality.JarqueB <- x$call$normality.JarqueB}}
if(missing(arch.LjungB)){arch.LjungB <- x$call$arch.LjungB}
if(missing(ar.LjungB)){ar.LjungB <- x$call$ar.LjungB}
user.estimator <- x$aux$user.estimator
LAPACK <- x$aux$LAPACK
##create an arx-like object:
y <- x$aux$y
y <- as.matrix(y)
colnames(y) <- x$aux$y.name
mxreg <- x$aux$mX
colnames(mxreg) <- x$aux$mXnames
# Save original arx mc warning setting and disable it here
tmpmc <- getOption("mc.warning")
options(mc.warning = FALSE)
object <- do.call("arx",
list(y = y, mxreg = mxreg,
ewma = NULL, mc = FALSE, ar = NULL, log.ewma = NULL, # would be in mxreg already
vc = FALSE, arch = NULL, asym = NULL, # currently not possible via isat
vxreg = NULL, zero.adj = 0.1, # currently not possible via isat
vc.adj = TRUE, qstat.options = NULL, # currently not possible via isat
vcov.type = vcov.type,
normality.JarqueB = normality.JarqueB,
user.estimator = user.estimator,
user.diagnostics = user.diagnostics,
tol = tol,
LAPACK = LAPACK,
singular.ok = TRUE,
plot = NULL))
##github version:
#object <- as.arx(x, plot = FALSE, ar = FALSE) # some arguments pre-set because they will already be in isat if needed
##return result:
out <- getsm(
object,
t.pval,
wald.pval,
vcov.type,
do.pet,
ar.LjungB,
arch.LjungB,
normality.JarqueB,
user.diagnostics,
info.method,
gof.function,
gof.method,
keep,
include.gum,
include.1cut,
include.empty,
max.paths,
tol,
turbo,
print.searchinfo,
plot,
alarm
)
# Set the old arx mc warning again
options(mc.warning = tmpmc)
return(out)
} #close gets.isat() function
##==================================================
logLik.isat <- function(object, ...)
{
result <- object$logl
if(is.null(result)){
result <- NA # numeric(0) will throw error, cannot replace cell with numeric vector of length 0
#OLD:
#result <- numeric(0)
warning("'object$logl' is NULL")
}else{
attr(result, "df") <- length(object$coefficients)
attr(result, "nobs") <- object$n
}
class(result) <- "logLik"
return(result)
} #end logLik.isat
##==================================================
## plot isat object
plot.isat <- function(x, col=c("red","blue"),
lty=c("solid","solid"), lwd=c(1,1), coef.path=TRUE, ...)
{
# ##check if mean quation:
# if( is.null(x$mean.results) ){
# cat("No mean equation to plot\n")
# }
##if fitted mean:
if(!is.null(x$mean.fit)){
##check line width:
if(length(lwd)==1){
print("lwd needs two arguments, but only one provided. Single argument applied to all lines plotted.")
lwd=rep(lwd,2)
}else if (length(lwd)>2){
print("lwd needs two arguments, but more provided. First two used.")
lwd=lwd[1:2]
}
##check line type:
if(length(lty)==1){
print("lty needs two arguments, but only one provided. Single argument applied to all lines plotted.")
lty=rep(lty,2)
}else if (length(lwd)>2){
print("lty needs two arguments, but more provided. First two used.")
lty=lty[1:2]
}
##check colour:
if(length(col)!=2){
#####randomcol - returns random combination of colours of length 2
randomcol <- function()
{
r.r <- runif(2)
while(round(r.r[1],1)==round(r.r[2],1)) {#don't want colours too similar so add check
r.r <- runif(2)
}
g.r <- runif(2)
while(round(g.r[1],1)==round(g.r[2],1)) {#don't want colours too similar so add check
g.r <- runif(2)
}
b.r <- runif(2)
while(round(b.r[1],1)==round(b.r[2],1)) {#don't want colours too similar so add check
b.r <- runif(2)
}
col<-rgb(runif(2),runif(2),runif(2))
return(col)
} #end randomcol
###clashcol function - returns clashing (opposite) combination of colours
clashcol <- function()
{
#using http://forum.processing.org/one/topic/the-opposite-of-a-color.html formula for opposite colour
r.1 <- runif(1)
g.1 <- runif(1)
b.1 <- runif(1)
b.2 <- min(r.1,min(g.1,b.1)) + max(r.1,max(g.1,b.1))
col <- rgb(c(r.1,b.2-r.1),c(g.1,b.2-g.1),c(b.1,b.2-b.1))
return(col)
} #end clashcol
##if random:
if(col[1]=="random") {
col <- randomcol()
}else if(col[1]=="awful.clash") {
col <- clashcol()
}else{
print("Wrong number of colours specified; using random set of colours instead.")
col<-randomcol()
}
}
##get fitted and actual values, and dependent variable name
fitted <- x$mean.fit
actual <- zoo(x$aux$y, order.by=x$aux$y.index)
residuals <- x$std.residuals
actual.name <- x$aux$y.name
##get current par-values, set new ones:
def.par <- par(no.readonly=TRUE)
par(mar=c(2,2,0.5,0.5))
##if isat or coef-path:
if( (x$gets.type=="isat" || coef.path==TRUE) && length(x$ISnames)!=0 ){
par(mfrow=c(3,1))
is.x <- cbind(x$aux$mX[,x$aux$mXnames %in% x$ISnames])
is.coef.ests <- coef.isat(x)[x$ISnames]
coef.path.0 <- zoo(is.x %*% is.coef.ests, order.by=x$aux$y.index)
}else{
par(mfrow=c(2,1))
}
##comment?
if(is.regular(actual)) {
plot(actual, main = "",ylim=range(min(actual,fitted,na.rm=TRUE),max(actual,fitted,na.rm=TRUE)),
type="l",ylab="",xlab="",col=col[2])
}else{
plot(as.Date(index(actual)),coredata(actual), main = "",ylim=range(min(actual,fitted,na.rm=TRUE),max(actual,fitted,na.rm=TRUE)),
type="l",ylab="",xlab="",col=col[2])
}
if(is.regular(fitted)) {
lines(fitted,col=col[1])
}else{
lines(as.Date(index(fitted)),coredata(fitted),col=col[1])
}
legend("topleft",lty=lty,lwd=lwd,ncol=2,col=col[c(2,1)],legend=c(actual.name,"fitted"),bty="n")
if(is.regular(residuals)) {
plot(residuals,type="h",col=col[1])
}
else{
plot(as.Date(index(residuals)),coredata(residuals),type="h",col=col[1])
}
abline(0,0)
legend("topleft",lty=1,col=col[1],legend="standardised residuals",bty="n")
# legend("topleft",lty=1,col=col[1],legend=c(paste(actual.name,"standardised residuals",sep=": ")),bty="n")
##coefficient path
if( (x$gets.type=="isat" | coef.path==TRUE) & length(x$ISnames)!=0 ) {
## we only get standard error bars if TIS *not* run
###if tis is there and it is not null, then don't plot, else
if(!is.null(as.list(x$call)$tis) && as.logical(as.character(as.list(x$call)$tis))==TRUE){
message("\n", appendLF=FALSE)
message("NB: Because TIS selected, coefficient standard errors invalid hence not plotted",
appendLF=TRUE)
#OLD:
# cat("\nNB: Because TIS selected, coefficient standard errors invalid hence not plotted\n", sep="")
ylim.values <- range(coef.path.0)
if(is.regular(coef.path.0)) {
ylim.values <- range(coef.path.0)
plot(coef.path.0,type="l",col=col[1],ylim=ylim.values)
}else{
plot(as.Date(index(coef.path.0)),coredata(coef.path.0),type="l",col=col[1],ylim=ylim.values)
}
} else {
coef.path.v <- isatvar(x)
if(is.regular(coef.path.0)) {
ylim.values <- range(min(coef.path.0-qt(0.975, NROW(coef.path.0))*coef.path.v$const.se),
max(coef.path.0+qt(0.975, NROW(coef.path.0))*coef.path.v$const.se))
plot(coef.path.0,type="l",col=col[1],
ylim=ylim.values)
lines(coef.path.0+qt(0.975, NROW(coef.path.0))*coef.path.v$const.se,type="l",col=col[1],lty=3)
lines(coef.path.0-qt(0.975, NROW(coef.path.0))*coef.path.v$const.se,type="l",col=col[1],lty=3)
}else{
plot(as.Date(index(coef.path.0)),coredata(coef.path.0),type="l",col=col[1],ylim=ylim.values)
lines(as.Date(index(coef.path.0)),coredata(coef.path.0)+qt(0.975, NROW(coef.path.0))*coef.path.v$const.se,type="l",col=col[1],lty=3)
lines(as.Date(index(coef.path.0)),coredata(coef.path.0)-qt(0.975, NROW(coef.path.0))*coef.path.v$const.se,type="l",col=col[1],lty=3)
}
}
abline(0,0,lty=3)
legend("topleft",lty=1,col=col[1],legend=c(paste(actual.name,"Coefficient Path",sep=": ")),bty="n")
}
#return to old par-values:
par(def.par)
}
} #plot.isat closed
##==================================================
## forecast up to n.ahead
predict.isat <- function(object, n.ahead=12, newmxreg=NULL,
newindex=NULL, n.sim=2000, probs=NULL, ci.levels=NULL,
quantile.type=7, return=TRUE, verbose=FALSE, plot=NULL,
plot.options=list(), ...)
{
## 1 arguments of mean-equation
## 2 make plot.options argument
## 3 pass arguments on to predict.arx
## 4 return forecasts
##create new object to add stuff to in order to use predict.arx()
objectNew <- object
##-----------------------------------
## 1 arguments of mean-equation:
##-----------------------------------
##coefficients of mean spec in final model:
coefsMean <- coef.arx(objectNew, spec="mean")
##there is no mean equation:
if( length(coefsMean)==0 ){
objectNew$call$mc <- NULL
objectNew$call$ar <- NULL
objectNew$call$ewma <- NULL
objectNew$call$mxreg <- NULL
}
##there is a mean equation:
if( length(coefsMean)>0 ){
##initiate index counter (used for mxreg):
indxCounter <- 0
##mc argument:
mconstRetained <- "mconst" %in% names(coefsMean)
if( mconstRetained ){
objectNew$call$mc <- TRUE
indxCounter <- indxCounter + 1
}else{
objectNew$call$mc <- FALSE
#OLD (until version 0.27):
# objectNew$call$mc <- NULL
}
##ar argument:
gumTerms <- eval(object$call$ar)
#OLD:
# gumTerms <- eval(object$aux$call.gum$ar)
gumNamesAr <- paste0("ar", gumTerms)
whichRetained <- which( gumNamesAr %in% names(coefsMean) )
if( length(whichRetained)==0 ){
objectNew$call$ar <- NULL
}else{
objectNew$call$ar <- gumTerms[ whichRetained ]
indxCounter <- indxCounter + length(whichRetained)
}
##ewma argument:
gumTerms <- eval(object$call$ewma)
#OLD:
# gumTerms <- eval(object$aux$call.gum$ewma)
gumNamesEwma <- paste0("EqWMA(", gumTerms$length, ")")
whichRetained <- which( gumNamesEwma %in% names(coefsMean) )
if( length(whichRetained)==0 ){
objectNew$call$ewma <- NULL
}else{
objectNew$call$ewma <-
list( length=gumTerms$length[ whichRetained ] )
indxCounter <- indxCounter + length(whichRetained)
}
##mxreg argument:
if(indxCounter==0){ whichRetainedCoefs <- coefsMean }
if(indxCounter>0){ whichRetainedCoefs <- coefsMean[ -c(1:indxCounter) ] }
if( length(whichRetainedCoefs)==0 ){
objectNew$call$mxreg <- NULL
}else{
whichRetainedNames <- names(whichRetainedCoefs)
objectNew$call$mxreg <- whichRetainedNames
#more correct (but not needed, since mxreg only needs to be non-NULL)?:
# whichRetained <- which( object$aux$mXnames %in% whichRetainedNames )
# mxreg <- cbind(object$aux$mX[, whichRetained ])
# colnames(mxreg) <- whichRetainedNames
# objectNew$call$mxreg <- mxreg
}
} #end if( length(coefsMean)>0 )
##here: introduce the automated detection of indicators and how they
##should modify newmxreg?
##----------------------------------
## 2 make plot.options argument:
##----------------------------------
if(is.null(plot.options$start.at.origin)){
plot.options$start.at.origin <- FALSE
}
if(is.null(plot.options$line.at.origin)){
plot.options$line.at.origin <- TRUE
}
if(is.null(plot.options$fitted)){
plot.options$fitted <- TRUE
}
##-------------------------------------
## 3 pass arguments on to predict.arx:
##-------------------------------------
innov <- rnorm(n.ahead*n.sim) #force normal errors
result <- predict.arx(objectNew, spec="mean", n.ahead=n.ahead,
newmxreg=newmxreg, newvxreg=NULL, newindex=newindex,
n.sim=n.sim, innov=innov, probs=probs, ci.levels=ci.levels,
quantile.type=quantile.type, return=return, verbose=verbose,
plot=plot, plot.options=plot.options)
##---------------------
## 4 return forecasts:
##---------------------
if(return){ return(result) }
} #close predict.isat
##==================================================
# ## print isat results
print.isat <- function(x, signif.stars=TRUE, ...)
{
##messages from final gets:
#if(!is.null(x$messages)){ message(x$messages) }
##header:
cat("\n")
cat("Date:", x$date, "\n")
cat("Dependent var.:", x$aux$y.name, "\n")
cat("Method: Ordinary Least Squares (OLS)\n")
cat("Variance-Covariance:", switch(x$aux$vcov.type,
ordinary = "Ordinary", white = "White (1980)",
"newey-west" = "Newey and West (1987)"), "\n")
##header - sample info:
cat("No. of observations (mean eq.):", x$aux$y.n, "\n")
tmp <- zoo(x$aux$y, order.by=x$aux$y.index)
indexTrimmed <- index(na.trim(tmp))
isRegular <- is.regular(tmp, strict=TRUE)
isCyclical <- frequency(tmp) > 1
if(isRegular && isCyclical){
cycleTrimmed <- cycle(na.trim(tmp))
startYear <- floor(as.numeric(indexTrimmed[1]))
startAsChar <- paste(startYear,
"(", cycleTrimmed[1], ")", sep="")
endYear <- floor(as.numeric(indexTrimmed[length(indexTrimmed)]))
endAsChar <- paste(endYear,
"(", cycleTrimmed[length(indexTrimmed)], ")", sep="")
}else{
startAsChar <- as.character(indexTrimmed[1])
endAsChar <- as.character(indexTrimmed[length(indexTrimmed)])
}
cat("Sample:", startAsChar, "to", endAsChar, "\n")
####### START the part commented out 17 July 2019 by G-man:
#
# ##gum:
# if(specType=="mean"){
# cat("\n")
# cat("GUM mean equation:\n")
# cat("\n")
# printCoefmat(x$gum.mean, dig.tst=0, tst.ind=c(1,2),
# signif.stars=FALSE, P.values=FALSE, has.Pvalue=FALSE)
# }
# if(!is.null(x$gum.variance)){
# cat("\n")
# cat("GUM log-variance equation:\n")
# cat("\n")
# printCoefmat(x$gum.variance, signif.stars=FALSE)
# }
# cat("\n")
# cat("Diagnostics and fit:\n")
# cat("\n")
# printCoefmat(x$gum.diagnostics, dig.tst=0, tst.ind=2,
# signif.stars=FALSE, P.values=FALSE, has.Pvalue=FALSE)
#
#
# ##paths:
# cat("\n")
# cat("Paths searched: \n")
# cat("\n")
# if(is.null(x$paths)){
# print(NULL)
# }else{
# for(i in 1:length(x$paths)){
# cat("path",i,":",x$paths[[i]],"\n")
# }
# } #end if(is.null(x$paths))
#
# ##terminal models and results:
# if(!is.null(x$terminals)){
# cat("\n")
# cat("Terminal models: \n")
# cat("\n")
# for(i in 1:length(x$terminals)){
# cat("spec",i,":",x$terminals[[i]],"\n")
# }
# }
# if(!is.null(x$terminals.results)){
# cat("\n")
# printCoefmat(x$terminals.results, dig.tst=0, tst.ind=c(3,4),
# signif.stars=FALSE)
# }
#
####### END the part commented out 17 July 2019 by G-man
##specific model:
if(!is.null(x$specific.spec)){
cat("\n")
cat("SPECIFIC mean equation:\n")
cat("\n")
if(!is.null(x$mean.results)){
#print(x$mean.results)
# NEW (from Moritz, July 2020) as this more simple command works as expected:
printCoefmat(x$mean.results,signif.stars = signif.stars)
#OLD: DOES NOT WORK IN A PREDICTABLE WAY!
# printCoefmat(x$mean.results, signif.stars=FALSE,
# P.values=FALSE, has.Pvalues=FALSE)
}
if(x$specific.spec[1]==0){
cat("empty\n")
}
##in the future: use estimate.specific=FALSE more directly?
if(x$specific.spec[1]!=0 && is.null(x$mean.results)){
cat("Not estimated\n")
}
}
##diagnostics and fit:
if(!is.null(x$diagnostics)){
#fit-measures:
mGOF <- matrix(NA, 3, 1)
rownames(mGOF) <- c("SE of regression", "R-squared",
paste0("Log-lik.(n=", x$n, ")"))
colnames(mGOF) <- ""
mGOF[1,1] <- sigma.isat(x) #OLD: sqrt(x$sigma2)
mGOF[2,1] <- rsquared(x) #OLD: x$specific.diagnostics[4,1]
mGOF[3,1] <- as.numeric(logLik.isat(x)) #OLD: x$logl
#mGOF[4,1] <- outliertest(x)$#x$logl #OLD: as.numeric(logLik.arx(x))
cat("\n")
cat("Diagnostics and fit:\n")
cat("\n")
printCoefmat(x$diagnostics, tst.ind=2,signif.stars=signif.stars, has.Pvalue = TRUE)
if(!is.null(x$outlier.distortion.test)){
#cat("\nJiao-Pretis-Schwarz Outlier Distortion Test")
mOutl_d <- matrix(NA, 1, 3)
colnames(mOutl_d) <- c("Chi-sq","df", "p-value")
rownames(mOutl_d) <- c("Jiao-Pretis-Schwarz Outlier Distortion")
mOutl_d[1,] <- c(x$outlier.distortion.test$statistic,x$outlier.distortion.test$df,x$outlier.distortion.test$p.value)
cat("\n")
printCoefmat(mOutl_d, digits=6, signif.stars = TRUE,P.values = TRUE, has.Pvalue = TRUE, signif.legend = FALSE)
}
if(!is.null(x$outlier.proportion.test)){
#cat("\nJiao-Pretis Outlier Proportion Test")
mOutl_p <- matrix(NA, 2, 2)
colnames(mOutl_p) <- c("Stat.", "p-value")
rownames(mOutl_p) <- c("Jiao-Pretis Outlier Proportion", "Jiao-Pretis Outlier Count")
mOutl_p[1,] <- c(x$outlier.proportion.test$prop$statistic, x$outlier.proportion.test$prop$p.value)
mOutl_p[2,] <- c(x$outlier.proportion.test$count$statistic, x$outlier.proportion.test$count$p.value)
cat("\n")
printCoefmat(mOutl_p, digits=6, signif.stars = TRUE,P.values = TRUE, has.Pvalue = TRUE, signif.legend = FALSE)
}
printCoefmat(mGOF, digits=6, signif.stars=signif.stars)
}
}
#OLD:
##==================================================
# ## print isat results
# print.isat <- function(x, ...)
# {
# ##specification type:
# specType <- "mean"
#
# ##header:
# cat("\n")
# cat("Date:", x$date, "\n")
# cat("Dependent var.:", x$aux$y.name, "\n")
# cat("Method: Ordinary Least Squares (OLS)\n")
# cat("Variance-Covariance:", switch(x$aux$vcov.type,
# ordinary = "Ordinary", white = "White (1980)",
# "newey-west" = "Newey and West (1987)"), "\n")
#
# ##header - sample info:
# cat("No. of observations (mean eq.):", x$aux$y.n, "\n")
# tmp <- zoo(x$aux$y, order.by=x$aux$y.index)
#
# indexTrimmed <- index(na.trim(tmp))
# isRegular <- is.regular(tmp, strict=TRUE)
# isCyclical <- frequency(tmp) > 1
# if(isRegular && isCyclical){
# cycleTrimmed <- cycle(na.trim(tmp))
# startYear <- floor(as.numeric(indexTrimmed[1]))
# startAsChar <- paste(startYear,
# "(", cycleTrimmed[1], ")", sep="")
# endYear <- floor(as.numeric(indexTrimmed[length(indexTrimmed)]))
# endAsChar <- paste(endYear,
# "(", cycleTrimmed[length(indexTrimmed)], ")", sep="")
# }else{
# startAsChar <- as.character(indexTrimmed[1])
# endAsChar <- as.character(indexTrimmed[length(indexTrimmed)])
# }
# cat("Sample:", startAsChar, "to", endAsChar, "\n")
#
# ##gum:
# if(specType=="mean"){
# cat("\n")
# cat("GUM mean equation:\n")
# cat("\n")
# printCoefmat(x$gum.mean, dig.tst=0, tst.ind=c(1,2),
# signif.stars=FALSE, P.values=FALSE, has.Pvalue=FALSE)
# }
# if(!is.null(x$gum.variance)){
# cat("\n")
# cat("GUM log-variance equation:\n")
# cat("\n")
# printCoefmat(x$gum.variance, signif.stars=FALSE)
# }
# cat("\n")
# cat("Diagnostics and fit:\n")
# cat("\n")
# printCoefmat(x$gum.diagnostics, dig.tst=0, tst.ind=2,
# signif.stars=FALSE, P.values=FALSE, has.Pvalue=FALSE)
#
# ##paths:
# cat("\n")
# cat("Paths searched: \n")
# cat("\n")
# if(is.null(x$paths)){
# print(NULL)
# }else{
# for(i in 1:length(x$paths)){
# cat("path",i,":",x$paths[[i]],"\n")
# }
# } #end if(is.null(x$paths))
#
# ##terminal models and results:
# if(!is.null(x$terminals)){
# cat("\n")
# cat("Terminal models: \n")
# cat("\n")
# for(i in 1:length(x$terminals)){
# cat("spec",i,":",x$terminals[[i]],"\n")
# }
# }
# if(!is.null(x$terminals.results)){
# cat("\n")
# printCoefmat(x$terminals.results, dig.tst=0, tst.ind=c(3,4),
# signif.stars=FALSE)
# }
#
# ##specific model:
# if(specType=="mean" && !is.null(x$specific.spec)){
# cat("\n")
# cat("SPECIFIC mean equation:\n")
# cat("\n")
# if(!is.null(x$mean.results)){
# print(x$mean.results)
# #OLD: DOES NOT WORK IN A PREDICTABLE WAY!
# # printCoefmat(x$mean.results, signif.stars=FALSE,
# # P.values=FALSE, has.Pvalues=FALSE)
# }
# if(x$specific.spec[1]==0){
# cat("empty\n")
# }
# ##in the future: use estimate.specific=FALSE more directly?
# if(x$specific.spec[1]!=0 && is.null(x$mean.results)){
# cat("Not estimated\n")
# }
# }
#
# ##diagnostics and fit:
# if(!is.null(x$specific.diagnostics)){
#
# #fit-measures:
# mGOF <- matrix(NA, 3, 1)
# rownames(mGOF) <- c("SE of regression", "R-squared",
# paste("Log-lik.(n=", length(na.trim(x$std.residuals)), ")", sep=""))
# colnames(mGOF) <- ""
# mGOF[1,1] <- sigma.isat(x) #OLD: sqrt( RSS/(nobs-DFs) )
# mGOF[2,1] <- rsquared(x) #OLD: x$specific.diagnostics[4,1]
# mGOF[3,1] <- as.numeric(logLik.arx(x))
#
# cat("\n")
# cat("Diagnostics and fit:\n")
# cat("\n")
# printCoefmat(x$specific.diagnostics, dig.tst=0, tst.ind=2,
# signif.stars=FALSE)
# printCoefmat(mGOF, digits=6, signif.stars=FALSE)
#
# }
#
# ##messages:
# if(!is.null(x$messages)){
# message("\n", appendLF=FALSE)
# message(x$messages)
# }
#
# } #end print.isat
##==================================================
residuals.isat <- function(object, std=FALSE, ...)
{
if(is.null(object)){
result <- NULL
}else{
if(std){
result <- object$residuals/sigma.isat(object)
}else{
result <- object$residuals
}
}
return(result)
} #end residuals.isat
##==================================================
## SE of regression
sigma.isat <- function(object, ...)
{
if(is.null(object$residuals)){
result <- NA # J-bat: should not set NULL otherwise cannot replace cell in matrix
#OLD:
#result <- NULL
}else{
RSS <- sum(object$residuals^2)
result <- sqrt(RSS/(object$n - object$k))
}
return(result)
} #close sigma.isat
###==================================================
### summarise output
summary.isat <- function(object, ...)
{
summary.default(object)
} #end summary.isat
##==================================================
vcov.isat <- function(object, ...)
{
result <- object$vcov #also works if object$vcov.mean exists
if(!is.null(result)){
if(is.null(colnames(result))){
colnames(result) <- names(object$specific.spec)
}
if(is.null(rownames(result))){
rownames(result) <- names(object$specific.spec)
}
}
return(result)
} #end vcov.isat
##==================================================
## needs orthogonal variables, can be applied directly to the coefficient path though in an isat only model
### purposefully not entirely usefriendly - needs many arguments, but it should be an expert user function
biascorr <- function(b, b.se, p.alpha, T){
c_alpha <- abs(qt((1-(1-p.alpha))/2, T))
bt <- b/b.se
dr <- (dnorm(c_alpha-bt)-dnorm(-c_alpha-bt))/ (1-pnorm(c_alpha-bt) + pnorm(-c_alpha-bt))
dtbar <- bt - dr
drbar <- (dnorm(c_alpha-dtbar)-dnorm(-c_alpha-dtbar))/ (1-pnorm(c_alpha-dtbar) + pnorm(-c_alpha-dtbar))
#only correct if significant
b_1step <- b
b_1step[abs(bt)>c_alpha] <- b[abs(bt)>c_alpha]*(1-(dr/bt))[abs(bt)>c_alpha]
b_2step <- b
b_2step[abs(bt)>c_alpha] <- b[abs(bt)>c_alpha]*(1-(drbar/bt))[abs(bt)>c_alpha]
b_corr <- cbind(b, b_1step, b_2step)
colnames(b_corr) <- c("beta", "beta.1step", "beta.2step")
return(b_corr)
}
##==================================================
####### isat.test: forecast bias test as based on the working paper with a plot
### loads an isat object, and then conducts the bias analysis on it
### loads an isat object, and then conducts the bias analysis on it
#### Now with added efficiency and consistency correction
#### also on coefficient path of other break variables
isattest <- function(x, hnull=0, lr=FALSE, ci.pval = 0.99,
plot=NULL, plot.turn = FALSE, conscorr=FALSE, effcorr=FALSE,
mcor = 1, biascorr=FALSE, mxfull = NULL, mxbreak=NULL)
{
trend.incl <- FALSE
if(!is.null(as.list(x$call)$tis)){
if (as.list(x$call)$tis) {
stop("isat.test currently not implemented for trend-indicator saturation")
trend.incl <- TRUE
}
}
arcall <- as.list(x$call)$ar
x.var <- isatvar(x,lr=lr, conscorr=conscorr, effcorr=effcorr, mcor = mcor, mxfull = mxfull, mxbreak=mxbreak)
#misy1.var
if (biascorr==TRUE){
if (!is.null(as.list(x$call)$mxreg) | !is.null(arcall) | trend.incl){
biascorr <- FALSE
message("Bias Correction not applicable in isat regression with additional non-step covariates. Has been set to FALSE.")
}
}
T <- dim(x$aux$mX)[1]
N <- dim(x$aux$mX)[2]
crit <- abs(qt((1-ci.pval)/2, T-N))
bias.low <- matrix(0, T, 1)
bias.high <- matrix(0, T, 1)
ci.low <- matrix(0, T, 1)
ci.high <- matrix(0, T, 1)
x.mean <- matrix(0, T, 1)
if (lr == TRUE & !is.null(arcall))
{
x.is.lr <- x.var$lr.path
x.is.const <- x.var$const.path
} else {
x.is.lr <- NA
if (biascorr){
xbias <-biascorr(b=x.var$const.path, b.se=x.var$const.se, p.alpha = x$aux$t.pval, T=length(x.var$const.path))
x.is.const <- xbias$beta.2step
} else {
x.is.const <- x.var$const.path
}
}
if (lr == TRUE & !is.null(arcall))
{
ci.low <- x.var$lr.path-crit*x.var$lr.se
ci.high <- x.var$lr.path+crit*x.var$lr.se
bias.low[which((ci.low) > hnull)] <- 1
bias.high[which((ci.high) < hnull)] <- 1
bias.low <- bias.low*(x.var$lr.path-hnull)
bias.high <- bias.high*(x.var$lr.path-hnull)
x.mean <- x.var$lr.path
} else {
ci.low <- x.is.const-crit*x.var$const.se
ci.high <- x.is.const+crit*x.var$const.se
bias.low[which((ci.low) > hnull)] <- 1
bias.high[which((ci.high) < hnull)] <- 1
bias.low <- bias.low*(x.is.const-hnull)
bias.high <- bias.high*(x.is.const-hnull)
x.mean <- x.is.const
}
###determining the turning points
time <- x$aux$y.index
bias.sum.ar <- bias.low+bias.high
lr.path.d <- diff(bias.sum.ar)
if(all(lr.path.d==0)){
plot.turn <- FALSE
turn.ar <- NULL
} else {
turn.ar <- time[which(lr.path.d != 0)]+1
}
turn.ar.y <- bias.sum.ar[which(lr.path.d != 0)]
turn.x.lab <- turn.ar
turn.x <- turn.ar
fitted <- x$mean.fit
actual <- zoo(x$aux$y, order.by=x$aux$y.index)
ylabel_a <- "Coefficient"
ylabel_b <- "Bias"
Ylim_main <- c(min(actual, na.rm=TRUE)*1.2,max(actual, na.rm=TRUE)*1.2)
Ylim_bias <- c(min(bias.high, na.rm=TRUE)*1.2,max(bias.low, na.rm=TRUE)*1.2)
##plot argument:
if( is.null(plot) ){
plot <- getOption("plot")
if( is.null(plot) ){ plot <- FALSE }
}
if (plot){
par(mfrow=c(2,1), mar = c(2, 4,1,3))
plot(time, x.mean, ylim=Ylim_main, col="red", main=NULL, xlab=NA, ylab=ylabel_a, sub=NA, type="l")
lines(ci.low, col="red", lty=2)
lines(ci.high, col="red", lty=2)
if (is.null(mxbreak))
{
lines(actual, col="blue")
}
abline(a =hnull, b=0, col="black", lty=3, lwd=2)
plot(time, bias.low, type="h", col="red", ylim=Ylim_bias, main=NULL, xlab=NA, ylab=ylabel_b, sub=NA)
lines(bias.high, type="h", col="red")
if ( plot.turn ){
text(turn.x.lab, y=turn.ar.y, x=turn.x, pos=4, offset=-0.5, cex=0.8)
}
}
if (lr==TRUE & !is.null(arcall))
{
mean.var <- cbind(ci.low, ci.high, bias.low, bias.high)
colnames(mean.var) <- c("ci.low", "ci.high", "bias.high", "bias.low")
} else {
mean.var <- cbind( ci.low, ci.high, bias.low, bias.high)
colnames(mean.var) <- c("ci.low", "ci.high", "bias.high", "bias.low")
}
return(mean.var)
} #isattest function closed
##==================================================
####### isatvar: function to extract the variance of the coefficient path
#takes an isat gets object, returns:
# - the coefficient path (both relative to the full sample coefficient and the constant path itself)
# - the variance and standard errors of the coefficient path
# - if lr is specified and the isat object has AR terms, then also returns the LR coefficient path and its variance and standard errors
#input: "x" (an isat results object)
#new arguments:
#-conscorr applies the consistency correction from Johansen and Nielsen 2016
#-effcorr applies the efficiency correction from Johansen and Nielsen 2016
#-mxfull allows a full-sample break variable to be specified which is selected over using uis, so it can construct the MIS variance
isatvar <- function(x, lr=FALSE, conscorr=FALSE, effcorr=FALSE, mcor = 1, mxfull = NULL, mxbreak=NULL)
{
if (lr == TRUE && !is.null(mxfull)){
message("Warning: LR currently not defined with user-specified break variables. LR set to FALSE")
lr <- FALSE
}
if(!is.null(as.list(x$call)$uis) && is.null(mxfull)){
if (!is.null(as.list(x$call)$iis) || !is.null(as.list(x$call)$sis) ){
message("Warning: uis specified but no mxfull variable given. Using mconst instead.")
mxfull <- "mconst"
} else {
stop("uis specified but no mxfull variable given")
}
}
if (is.null(mxfull)){ ##if no full variable is specified, then the constant is used
mxfull <- "mconst"
}
if (!is.null(x$mean.fit)){
if (!is.null(mxbreak))
{
ISnames <- x$ISnames[grep(mxbreak, x$ISnames)]
####################################
} else {
mxbreak_iis <- "iis"
mxbreak_sis <- "sis"
ISnames <- c(x$ISnames[grep(mxbreak_iis, x$ISnames)], x$ISnames[grep(mxbreak_sis, x$ISnames)])
}
if (!is.null(ISnames)){
var.rel <- c( which(substr(x$aux$mXnames,1,6) %in% mxfull), which(x$aux$mXnames %in% ISnames))
if (conscorr==TRUE){
x$vcov.mean <- x$vcov.mean*as.numeric(isvarcor(x$aux$t.pval,1)[2]^2)
}
if (effcorr == TRUE){
rel_names <- x$aux$mXnames[!(x$aux$mXnames %in% x$ISnames)]
if (!is.null(rel_names)) {
# OLD:
#if (!is.null(x$keep)) {
# x$vcov.mean[x$keep, x$keep] <- x$vcov.mean[x$keep, x$keep] * as.numeric(isvareffcor(x$aux$t.pval, 1, mcor)[2]^2)
x$vcov.mean[rel_names, rel_names] <- x$vcov.mean[rel_names,
rel_names] * as.numeric(isvareffcor(x$aux$t.pval,
1, mcor)[2]^2)
}
}
#coefficient path function
is.x <- cbind(x$aux$mX[, x$aux$mXnames %in% ISnames])
is.coef.ests <- coef.isat(x)[ISnames]
if(is.null(mxfull)){
coef.path <- zoo(is.x %*% is.coef.ests, order.by = x$aux$y.index)
} else {
is.x[is.x!=0] <- 1 #the break variable is not necessarily an indicator variable
coef.path <- zoo(is.x %*% is.coef.ests, order.by = x$aux$y.index)
}
colnames(coef.path) <- "coef.path"
const <- coef.isat(x)[mxfull]
const.path <- coef.path + const
colnames(const.path) <- "const.path"
} else {
var.rel <- which(substr(x$aux$mXnames,1,6) %in% mxfull)
#coefficient path function
const <- coef.isat(x)[mxfull]
coef.path <- zoo(0, order.by = x$aux$y.index)
const.path <- coef.path + const
}
vcov.rel <- x$vcov.mean[var.rel,var.rel]
dim.var <- NCOL(vcov.rel)
const.var <- matrix(NA, dim.var, 1 )
#construct a matrix to multiply by the variances
dim.in <- NCOL(x$aux$mX[,var.rel])
const.mat <- matrix(NA, NROW(x$aux$mX[,var.rel]), dim.in)
if(is.null(mxfull)){
indic.mat <- x$aux$mX[,var.rel]
} else {
indic.mat <- x$aux$mX[,var.rel]
indic.mat[indic.mat!=0] <- 1
}
if (dim.var > 1) #if there are indicators retained
{
#order the breaks in correct order so the covariance matrix and relevance order is correct
if(is.null(mxfull)){
order.mat <- apply(indic.mat[,], 2, function(x) min(which(x==1))) #find where each indicator is first one, for sorting
} else { #if using a custom break variable
order.mat <- apply(indic.mat[,], 2, function(x) min(which(x!=0)))
}
indic.mat <- indic.mat[,order(order.mat)] #order the indicators
vcov.rel <- vcov.rel[order(order.mat),order(order.mat)] #order the covariance matrix
for (i in 1:dim.var)
{
const.var[i] <- sum(vcov.rel[1:i,1:i]) #sum over the expanding variance covariance matrix to get the variance of the sums of coefficients
}
const.mat <- indic.mat
for (j in 2:(dim.in))
{
const.mat[which(rowSums(as.matrix(const.mat[,(j):(dim.in)]))>0),j-1] <- 0 #puts zeros in the appropriate places to make sure the correct s.e. is applied for each point in time
}
ind.var.mat <- const.mat %*% const.var #the variance as it applies to each subsection
} else { #just the constant remains
const.var <- vcov.rel
const.mat <- indic.mat
ind.var.mat <- const.mat * const.var
}
ind.se.mat <- sqrt(ind.var.mat) #the standard errors of the coefficient as it changes with the SIS breaks
####the coefficient path of the LR mean
if(lr){
if (!is.null(as.list(x$call)$ar)){
if (!is.null(x$mean.fit)){
vcov.rel.tot <- x$vcov.mean
coef.rel <- coef.isat(x)
###coefficient path of LR mean
arcall <- as.list(x$call)$ar
arnames <- paste("ar",eval(as.expression(arcall)), sep="")
ar.coefs <- coef.isat(x)[arnames]
ar.sum <- sum(ar.coefs)
lr.path <- const.path/(1-ar.sum)
###variance of the coefficient path
ar.var <- vcov.rel.tot[arnames,arnames] #variance of ar() terms
armu.cov <- vcov.rel.tot[c(mxfull, ISnames), arnames] #covariance of ar(1) and const + sis
if (!is.null(ISnames)) {
var.rel <- c(which(substr(x$aux$mXnames, 1, 6) %in%
mxfull), which(x$aux$mXnames %in% ISnames))
} else {
var.rel <- which(substr(x$aux$mXnames, 1, 6) %in%
mxfull)
}
vcov.rel <- x$vcov.mean[var.rel, var.rel]
dim.var <- NCOL(vcov.rel)
const.var <- matrix(NA, dim.var, 1)
dim.in <- NCOL(x$aux$mX[, var.rel])
indic.mat <- x$aux$mX[, var.rel]
const.mat <- matrix(NA, NROW(x$aux$mX[, var.rel]), dim.in)
armu.cov.sum <- matrix(NA, dim.var, 1)
dim.ar <- NCOL(ar.var)
if (dim.var > 1) {
order.mat <- apply(indic.mat[, ], 2, function(x) min(which(x ==
1)))
indic.mat <- indic.mat[, order(order.mat)]
vcov.rel <- vcov.rel[order(order.mat), order(order.mat)] #ordering the variables for cumulative summing for covariances of sis
#do the same for the autoregressive terms
if (dim.ar > 1) #if more than one ar term
{
armu.cov <- armu.cov[order(order.mat), ]
} else {
armu.cov <- armu.cov[order(order.mat)]
}
for (i in 1:dim.var) {
const.var[i] <- sum(vcov.rel[1:i, 1:i])
if (dim.ar > 1) #if more than one ar term
{
armu.cov.sum[i] <- sum(armu.cov[1:i,])
} else {
armu.cov.sum[i] <- sum(armu.cov[1:i])
}
}
const.mat <- indic.mat
for (j in 2:(dim.in)) {
const.mat[which(rowSums(as.matrix(const.mat[,
(j):(dim.in)])) > 0), j - 1] <- 0
}
#variance of ar
ar.var.sum <- sum(ar.var)
ar.var.part <- ((const.path^2)/((1-ar.sum)^4))*ar.var.sum
#covariance and variance part of sis
ind.var.mat <- const.mat %*% const.var # this one should be ok
covar.is.part <- (1/(1-ar.sum)^2)*ind.var.mat
#covariance part of ar and sis
ind.ar.covar.mat <- const.mat %*% armu.cov.sum
covar.aris.part <- 2*((const.path)/(1-ar.sum)^2)*(1/(1-ar.sum))*ind.ar.covar.mat
lr.mean.var <- ar.var.part + covar.is.part + covar.aris.part
lr.mean.se <- sqrt(lr.mean.var)
} else { #if no steps retained
ar.var.sum <- sum(ar.var)
ar.var.part <- ((const.path^2)/((1-ar.sum)^4))*ar.var.sum
ind.var.mat <- vcov.rel
covar.is.part <- (1/(1-ar.sum)^2)*ind.var.mat
#covariance part of ar and sis
armu.cov.sum <- sum(armu.cov)
ind.ar.covar.mat <- armu.cov.sum
covar.aris.part <- 2*((const.path)/(1-ar.sum)^2)*(1/(1-ar.sum))*ind.ar.covar.mat
lr.mean.var <- ar.var.part + covar.is.part + covar.aris.part
lr.mean.se <- sqrt(lr.mean.var)
}
} #if isnullxmean closed
if(!is.null(as.list(x$call)$tis)){
if (as.list(x$call)$tis) { #if TIS
ind.var.mat <- NA
ind.se.mat <- NA
lr.path <- NA
lr.mean.var <- NA
lr.mean.se <- NA
}
}
const.varse <- cbind(coef.path, const.path, ind.var.mat, ind.se.mat, lr.path, lr.mean.var, lr.mean.se)
colnames(const.varse) <- c("coef.path", "const.path", "const.var", "const.se", "lr.path", "lr.var", "lr.se")
} else { #if there are no ar
if(!is.null(as.list(x$call)$tis)){
if (as.list(x$call)$tis) { #if TIS
ind.var.mat <- NA
ind.se.mat <- NA
}
}
const.varse <- cbind(coef.path, const.path, ind.var.mat, ind.se.mat)
colnames(const.varse) <- c("coef.path", "const.path", "const.var", "const.se")
} #if no ar closed
} else { #if no lr
if(!is.null(as.list(x$call)$tis)){
if (as.list(x$call)$tis) {
ind.var.mat <- NA
ind.se.mat <- NA
}
}
const.varse <- cbind(coef.path, const.path, ind.var.mat, ind.se.mat)
colnames(const.varse) <- c("coef.path", "const.path", "const.var", "const.se")
}#if lr closed
const.varse <- zoo(const.varse , order.by=x$aux$y.index)
return(const.varse)
} ##if (is null) closed
} #end isatvar
##==================================================
#### Impulse Indicator Consistency correction function for the sigma estimate
#Equations (9) and (15) in Johansen and Nielsen (2016)
isvarcor <- function(t.pval, sigma) {
alpha <- t.pval
sigmals <- sigma
c <- abs(qnorm(alpha/2))
psi <- pnorm(c) - pnorm(-c)
tau <- psi - 2*c*dnorm(c)
xi_sq <- tau/psi
xi <- sqrt(xi_sq)
corrxi <- 1/xi
sigmacorr <- sigmals * corrxi
object <- data.frame(cbind(sigmacorr, corrxi))
names(object) <- c("sigma.cor", "corxi")
return(object)
}
##==================================================
###### IS Efficiency Correction for the fixed regressors
### Equation (37) in Johansen and Nielsen (2016)
isvareffcor <- function(t.pval, se, m=1) {
alpha <- t.pval
c <- abs(qnorm(alpha/2))
psi <- pnorm(c) - pnorm(-c)
tau <- psi - 2*c*dnorm(c)
rhobeta <- 2*c*dnorm(c)/psi
etam <- (((1-rhobeta^m)/((1-rhobeta)*psi))^2 + 2 * (1-rhobeta^m)/((1-rhobeta)*psi)*rhobeta^m)*tau+rhobeta^(2*m)
se_cor <- se*sqrt(etam)
output <- data.frame(cbind(se_cor, sqrt(etam) ))
names(output) <- c("se.cor", "eta.m")
return(output)
}
#OLD VERSIONS OF biascorr...etc.:
###==================================================
### needs orthogonal variables, can be applied directly to the coefficient path though in an isat only model
#### purposefully not entirely usefriendly - needs many arguments, but it should be an expert user function
#biascorr <- function(b, b.se, p.alpha, T){
#
# c_alpha <- abs(qt((1-(1-p.alpha))/2, T))
# bt <- b/b.se
#
# dr <- (dnorm(c_alpha-bt)-dnorm(-c_alpha-bt))/ (1-pnorm(c_alpha-bt) + pnorm(-c_alpha-bt))
# dtbar <- bt - dr
# drbar <- (dnorm(c_alpha-dtbar)-dnorm(-c_alpha-dtbar))/ (1-pnorm(c_alpha-dtbar) + pnorm(-c_alpha-dtbar))
#
# #only correct if significant
#
# b_1step <- b
# b_1step[abs(bt)>c_alpha] <- b*(1-(dr/bt))[abs(bt)>c_alpha]
#
# b_2step <- b
# b_2step[abs(bt)>c_alpha] <- b*(1-(drbar/bt))[abs(bt)>c_alpha]
#
# b_corr <- cbind(b, b_1step, b_2step)
# colnames(b_corr) <- c("beta", "beta.1step", "beta.2step")
#
# return(b_corr)
#}
#
###==================================================
######## isat.test: forecast bias test as based on the working paper with a plot
#### loads an isat object, and then conducts the bias analysis on it
#
#isattest <- function(x, hnull=0, lr=FALSE, ci.pval = 0.99, plot=TRUE, plot.turn = FALSE, biascorr=FALSE){
#
# trend.incl <- FALSE
# if(!is.null(as.list(x$call)$tis)){
# if (as.list(x$call)$tis) {
# stop("isat.test currently not implemented for trend-indicator saturation")
# trend.incl <- TRUE
# }
# }
#
# arcall <- as.list(x$call)$ar
# x.var <- isatvar(x,lr=lr)
#
# if (biascorr==TRUE){
#
# if (!is.null(as.list(x$call)$mxreg) | !is.null(arcall) | trend.incl){
#
# biascorr <- FALSE
# print("Bias Correction not applicable in isat regression with additional non-step covariates. Has been set to FALSE.")
# }
# }
#
#
# T <- dim(x$aux$mX)[1]
# N <- dim(x$aux$mX)[2]
#
# crit <- abs(qt((1-ci.pval)/2, T-N))
# bias.low <- matrix(0, T, 1)
# bias.high <- matrix(0, T, 1)
#
# ci.low <- matrix(0, T, 1)
# ci.high <- matrix(0, T, 1)
# x.mean <- matrix(0, T, 1)
#
# if (lr == TRUE & !is.null(arcall))
# {
# x.is.lr <- x.var$lr.path
# x.is.const <- x.var$const.path
#
# } else {
#
# x.is.lr <- NA
#
# if (biascorr){
#
# #is2$aux$t.pval
#
# xbias <-biascorr(b=x.var$const.path, b.se=x.var$const.se, p.alpha = x$aux$t.pval, T=length(x.var$const.path))
#
# #xbias <-biascorr(b=x.var$const.path, b.se=x.var$const.se, p.alpha = as.list(x$call)$t.pval, T=length(x.var$const.path))
# x.is.const <- xbias$beta.2step
#
# } else {
# x.is.const <- x.var$const.path
#
# }
#
#
# }
#
#
# if (lr == TRUE & !is.null(arcall))
# {
#
# ci.low <- x.var$lr.path-crit*x.var$lr.se
# ci.high <- x.var$lr.path+crit*x.var$lr.se
#
# bias.low[which((ci.low) > hnull)] <- 1
# bias.high[which((ci.high) < hnull)] <- 1
#
# bias.low <- bias.low*(x.var$lr.path-hnull)
# bias.high <- bias.high*(x.var$lr.path-hnull)
#
# x.mean <- x.var$lr.path
#
# } else {
#
# ci.low <- x.is.const-crit*x.var$const.se
# ci.high <- x.is.const+crit*x.var$const.se
#
# bias.low[which((ci.low) > hnull)] <- 1
# bias.high[which((ci.high) < hnull)] <- 1
#
#
# bias.low <- bias.low*(x.is.const-hnull)
# bias.high <- bias.high*(x.is.const-hnull)
#
# x.mean <- x.is.const
#
# }
#
# ###determining the turning points
# time <- x$aux$y.index
# bias.sum.ar <- bias.low+bias.high
# lr.path.d <- diff(bias.sum.ar)
#
#
# if(all(lr.path.d==0)){
# plot.turn <- FALSE
# turn.ar <- NULL
# } else {
# turn.ar <- time[which(lr.path.d != 0)]+1
# }
#
# turn.ar.y <- bias.sum.ar[which(lr.path.d != 0)]
#
# turn.x.lab <- turn.ar
# turn.x <- turn.ar
#
# fitted <- x$mean.fit
# actual <- zoo(x$aux$y, order.by=x$aux$y.index)
#
# ylabel_a <- "Series"
# ylabel_b <- "Bias"
#
#
# par(mfrow=c(2,1), mar = c(2, 4,1,3))
# Ylim_main <- c(min(actual, na.rm=TRUE)*1.2,max(actual, na.rm=TRUE)*1.2)
# Ylim_bias <- c(min(bias.high, na.rm=TRUE)*1.2,max(bias.low, na.rm=TRUE)*1.2)
#
# if (plot){
#
# plot(time, x.mean, ylim=Ylim_main, col="blue", title(main=NULL, xlab=NULL), xlab=NA, ylab=ylabel_a, sub=NA, type="l")
# lines(ci.low, col="blue", lty=2)
# lines(ci.high, col="blue", lty=2)
# lines(actual)
# abline(a =hnull, b=0, col="black", lty=3, lwd=2)
#
# plot(time, bias.low, type="h", col="red", ylim=Ylim_bias, title(main=NULL, xlab=NULL), xlab=NA, ylab=ylabel_b, sub=NA)
# lines(bias.high, type="h", col="blue")
#
# if ( plot.turn ){
# text(turn.x.lab, y=turn.ar.y, x=turn.x, pos=4, offset=-0.5, cex=0.8)
# }
#
# }
#
#
# if (lr==TRUE & !is.null(arcall))
# {
# mean.var <- cbind(ci.low, ci.high, bias.low, bias.high)
# colnames(mean.var) <- c("ci.low", "ci.high", "bias.high", "bias.low")
#
#
# } else {
# mean.var <- cbind( ci.low, ci.high, bias.low, bias.high)
# colnames(mean.var) <- c("ci.low", "ci.high", "bias.high", "bias.low")
#
# }
#
#
# return(mean.var)
#
#} #isat.test function closedakes an isat gets object, returns:
## - the coefficient path (both relative to the full sample coefficient and the constant path itself)
## - the variance and standard errors of the coefficient path
## - if lr is specified and the isat object has AR terms, then also returns the LR coefficient path and its variance and standard errors
##input: "x" (an isat results object)
#
#
#isatvar <- function(x, lr=FALSE)
#{
#
# if (!is.null(x$mean.fit)){
# if (!is.null(x$ISnames)){
# var.rel <- c( which(substr(x$aux$mXnames,1,6) %in% "mconst"), which(x$aux$mXnames %in% x$ISnames)) #vector of where the constant and is terms are
#
# #coefficient path function
# is.x <- cbind(x$aux$mX[, x$aux$mXnames %in% x$ISnames])
# is.coef.ests <- coef.isat(x)[x$ISnames]
# coef.path <- zoo(is.x %*% is.coef.ests, order.by = x$aux$y.index)
# colnames(coef.path) <- "coef.path"
#
# const <- coef.isat(x)["mconst"]
# const.path <- coef.path + const
# colnames(const.path) <- "const.path"
#
# } else {
# var.rel <- which(substr(x$aux$mXnames,1,6) %in% "mconst")
#
# #coefficient path function
# const <- coef.isat(x)["mconst"]
#
# coef.path <- zoo(0, order.by = x$aux$y.index)
#
# const.path <- coef.path + const
#
# }
#
# vcov.rel <- x$vcov.mean[var.rel,var.rel]
# dim.var <- NCOL(vcov.rel)
# const.var <- matrix(NA, dim.var, 1 )
#
# #construct a matrix to multiply by the variances
# dim.in <- NCOL(x$aux$mX[,var.rel])
# indic.mat <- x$aux$mX[,var.rel]
# const.mat <- matrix(NA, NROW(x$aux$mX[,var.rel]), dim.in)
#
#
# if (dim.var > 1) #if there are indicators retained
# {
#
# #order the breaks in correct order so the covariance matrix and relevance order is correct
# order.mat <- apply(indic.mat[,], 2, function(x) min(which(x==1))) #find where each indicator is first one, for sorting
#
# indic.mat <- indic.mat[,order(order.mat)] #order the indicators
# vcov.rel <- vcov.rel[order(order.mat),order(order.mat)] #order the covariance matrix
#
# for (i in 1:dim.var)
# {
# const.var[i] <- sum(vcov.rel[1:i,1:i]) #sum over the expanding variance covariance matrix to get the variance of the sums of coefficients
# }
#
# const.mat <- indic.mat
#
# for (j in 2:(dim.in))
# {
#
# const.mat[which(rowSums(as.matrix(const.mat[,(j):(dim.in)]))>0),j-1] <- 0 #puts zeros in the appropriate places to make sure the correct s.e. is applied for each point in time
#
# }
#
# ind.var.mat <- const.mat %*% const.var #the variance as it applies to each subsection
#
# } else { #just the constant remains
#
# const.var <- vcov.rel
# const.mat <- indic.mat
# ind.var.mat <- const.mat * const.var
#
# }
#
# ind.se.mat <- sqrt(ind.var.mat) #the standard errors of the coefficient as it changes with the SIS breaks
#
# ####the coefficient path of the LR mean
#
# if(lr){
# if (!is.null(as.list(x$call)$ar)){
#
# if (!is.null(x$mean.fit)){
#
# vcov.rel.tot <- x$vcov.mean
# coef.rel <- coef.isat(x)
#
# ###coefficient path of LR mean
#
# arcall <- as.list(x$call)$ar
# arnames <- paste("ar",eval(as.expression(arcall)), sep="")
#
# ar.coefs <- coef.isat(x)[arnames]
# ar.sum <- sum(ar.coefs)
# lr.path <- const.path/(1-ar.sum)
#
# ###variance of the coefficient path
#
# ar.var <- vcov.rel.tot[arnames,arnames] #variance of ar() terms
# armu.cov <- vcov.rel.tot[c("mconst", x$ISnames), arnames] #covariance of ar(1) and const + sis
#
#
# if (!is.null(x$ISnames)) {
# var.rel <- c(which(substr(x$aux$mXnames, 1, 6) %in%
# "mconst"), which(x$aux$mXnames %in% x$ISnames))
# } else {
# var.rel <- which(substr(x$aux$mXnames, 1, 6) %in%
# "mconst")
# }
#
# vcov.rel <- x$vcov.mean[var.rel, var.rel]
# dim.var <- NCOL(vcov.rel)
# const.var <- matrix(NA, dim.var, 1)
# dim.in <- NCOL(x$aux$mX[, var.rel])
# indic.mat <- x$aux$mX[, var.rel]
# const.mat <- matrix(NA, NROW(x$aux$mX[, var.rel]), dim.in)
# armu.cov.sum <- matrix(NA, dim.var, 1)
#
# dim.ar <- NCOL(ar.var)
#
# if (dim.var > 1) {
# order.mat <- apply(indic.mat[, ], 2, function(x) min(which(x ==
# 1)))
# indic.mat <- indic.mat[, order(order.mat)]
# vcov.rel <- vcov.rel[order(order.mat), order(order.mat)] #ordering the variables for cumulative summing for covariances of sis
#
# #do the same for the autoregressive terms
#
# if (dim.ar > 1) #if more than one ar term
# {
# armu.cov <- armu.cov[order(order.mat), ]
#
# } else {
# armu.cov <- armu.cov[order(order.mat)]
# }
#
# for (i in 1:dim.var) {
# const.var[i] <- sum(vcov.rel[1:i, 1:i])
# if (dim.ar > 1) #if more than one ar term
# {
# armu.cov.sum[i] <- sum(armu.cov[1:i,])
# } else {
# armu.cov.sum[i] <- sum(armu.cov[1:i])
# }
# }
#
# const.mat <- indic.mat
# for (j in 2:(dim.in)) {
# const.mat[which(rowSums(as.matrix(const.mat[,
# (j):(dim.in)])) > 0), j - 1] <- 0
# }
#
# #variance of ar
# ar.var.sum <- sum(ar.var)
# ar.var.part <- ((const.path^2)/((1-ar.sum)^4))*ar.var.sum
#
# #covariance and variance part of sis
# ind.var.mat <- const.mat %*% const.var # this one should be ok
# covar.is.part <- (1/(1-ar.sum)^2)*ind.var.mat
#
# #covariance part of ar and sis
# ind.ar.covar.mat <- const.mat %*% armu.cov.sum
# covar.aris.part <- 2*((const.path)/(1-ar.sum)^2)*(1/(1-ar.sum))*ind.ar.covar.mat
#
# lr.mean.var <- ar.var.part + covar.is.part + covar.aris.part
# lr.mean.se <- sqrt(lr.mean.var)
#
# } else { #if no steps retained
#
# ar.var.sum <- sum(ar.var)
# ar.var.part <- ((const.path^2)/((1-ar.sum)^4))*ar.var.sum
#
# ind.var.mat <- vcov.rel
# covar.is.part <- (1/(1-ar.sum)^2)*ind.var.mat
#
# #covariance part of ar and sis
#
# armu.cov.sum <- sum(armu.cov)
# ind.ar.covar.mat <- armu.cov.sum
# covar.aris.part <- 2*((const.path)/(1-ar.sum)^2)*(1/(1-ar.sum))*ind.ar.covar.mat
#
# lr.mean.var <- ar.var.part + covar.is.part + covar.aris.part
# lr.mean.se <- sqrt(lr.mean.var)
#
# }
#
# } #if isnullxmean closed
#
# if(!is.null(as.list(x$call)$tis)){
# if (as.list(x$call)$tis) { #if TIS
#
# ind.var.mat <- NA
# ind.se.mat <- NA
# lr.path <- NA
# lr.mean.var <- NA
# lr.mean.se <- NA
# }
# }
# const.varse <- cbind(coef.path, const.path, ind.var.mat, ind.se.mat, lr.path, lr.mean.var, lr.mean.se)
# colnames(const.varse) <- c("coef.path", "const.path", "const.var", "const.se", "lr.path", "lr.var", "lr.se")
#
# } else { #if there are no ar
#
# if(!is.null(as.list(x$call)$tis)){
# if (as.list(x$call)$tis) { #if TIS
# ind.var.mat <- NA
# ind.se.mat <- NA
# }
# }
# const.varse <- cbind(coef.path, const.path, ind.var.mat, ind.se.mat)
# colnames(const.varse) <- c("coef.path", "const.path", "const.var", "const.se")
#
# } #if no ar closed
# } else { #if no lr
#
# if(!is.null(as.list(x$call)$tis)){
# if (as.list(x$call)$tis) {
# ind.var.mat <- NA
# ind.se.mat <- NA
# }
# }
# const.varse <- cbind(coef.path, const.path, ind.var.mat, ind.se.mat)
# colnames(const.varse) <- c("coef.path", "const.path", "const.var", "const.se")
#
#
#
# }#if lr closed
#
# const.varse <- zoo(const.varse , order.by=x$aux$y.index)
# return(const.varse)
#
# } ##if (is null) closed
#
#} #end isatvar
##==================================================
## make matrix of impulse indicators:
iim <- function(x, which.ones=NULL)
{
if(NROW(x)==1){
n <- x
mIIS <- matrix(0,n,n)
diag(mIIS) <- 1
colnames(mIIS) <- paste("iis", 1:n, sep="")
if(!is.null(which.ones)){ mIIS <- mIIS[,which.ones] }
mIIS <- as.zoo(mIIS)
}else{
n <- NROW(x)
mIIS <- matrix(0,n,n)
diag(mIIS) <- 1
x <- as.zoo(x)
x.index <- index(x)
xIsRegular <- is.regular(x, strict=TRUE)
if(xIsRegular && frequency(x)>1 ){
xIndexObs <- floor(as.numeric(x.index))
xCycle <- as.numeric(cycle(x))
xIndexAsChar <- paste(xIndexObs, "(", xCycle, ")", sep="")
xFrequency <- frequency(x)
}else{
xIndexAsChar <- as.character(x.index)
}
colnames(mIIS) <- paste("iis",
xIndexAsChar, sep="")
mIIS <- zoo(mIIS, order.by=x.index)
if(xIsRegular){ mIIS <- as.zooreg(mIIS) }
if(!is.null(which.ones)){
where.indicators <- which(index(mIIS) %in% which.ones)
if(length(where.indicators > 0)){
mIIS <- cbind(mIIS[,where.indicators])
}else{
stop("'which.ones' not in index")
}
}
} #end if(NROW(x)==1)else..
return(mIIS)
} #close iim
##==================================================
##make matrix of step indicators:
sim <- function(x, which.ones=NULL)
{
if(NROW(x)==1){
x.is.scalar <- TRUE
n <- x
if(is.null(which.ones)){
where.indicators <- 2:n
}else{
where.indicators <- which.ones
}
}else{
x.is.scalar <- FALSE
n <- NROW(x)
x <- as.zoo(x)
x.index <- index(x)
xIsRegular <- is.regular(x, strict=TRUE)
if(xIsRegular && frequency(x)>1 ){
xIndexObs <- floor(as.numeric(x.index))
xCycle <- as.numeric(cycle(x))
xIndexAsChar <- paste(xIndexObs, "(", xCycle, ")", sep="")
xFrequency <- frequency(x)
}else{
xIndexAsChar <- as.character(x.index)
}
if(is.null(which.ones)){
where.indicators <- 2:n
}else{
where.indicators <- which(x.index %in% which.ones)
if(length(where.indicators)==0) stop("'which.ones' not in index")
} #end if(is.null(which.ones))
} #end if(NROW(x)==1)else(..)
n.where.indicators <- length(where.indicators)
loop.indx <- 1:n.where.indicators
mSIS <-matrix(0,n,n.where.indicators)
tmp <- function(i){ mSIS[ c(where.indicators[i]:n) ,i] <<- 1 }
tmp <- sapply(loop.indx,tmp)
if(x.is.scalar){
colnames(mSIS) <- paste("sis", where.indicators, sep="")
mSIS <- as.zoo(mSIS)
}else{
colnames(mSIS) <- paste("sis",
xIndexAsChar[where.indicators], sep="")
if(xIsRegular && frequency(x)>1 ){
mSIS <- zooreg(mSIS, frequency=xFrequency,
start=c(xIndexObs[1],xCycle[1]))
}else{
mSIS <- zoo(mSIS, order.by=x.index)
}
}
return(mSIS)
} #close sim
##==================================================
## make matrix of trend indicators:
tim <- function(x, which.ones=NULL, log.trend=FALSE)
{
if(NROW(x)==1){
x.is.scalar <- TRUE
n <- x
if(is.null(which.ones)){
where.indicators <- 2:n
}else{
where.indicators <- which(1:n %in% which.ones)
}
}else{
x.is.scalar <- FALSE
n <- NROW(x)
x <- as.zoo(x)
x.index <- index(x)
xIsRegular <- is.regular(x, strict=TRUE)
if(xIsRegular && frequency(x)>1 ){
xIndexObs <- floor(as.numeric(x.index))
xCycle <- as.numeric(cycle(x))
xIndexAsChar <- paste(xIndexObs, "(", xCycle, ")", sep="")
xFrequency <- frequency(x)
}else{
xIndexAsChar <- as.character(x.index)
}
if(is.null(which.ones)){
where.indicators <- 2:n
}else{
where.indicators <- which(x.index %in% which.ones)
if(length(where.indicators)==0) stop("'which.ones' not in index")
}
}
n.where.indicators <- length(where.indicators)
mTIS <-matrix(0,n,n.where.indicators)
v1n <- seq(1,n)
loop.indx <- 1:n.where.indicators
tmp <- function(i){
t.trend <- v1n[1:c(n-where.indicators[i]+1)]
if(log.trend) t.trend <- log(t.trend)
mTIS[c(where.indicators[i]:n),i] <<- t.trend
}
tmp <- sapply(loop.indx,tmp)
if(x.is.scalar){
colnames(mTIS) <- paste("tis", where.indicators, sep="")
mTIS <- as.zoo(mTIS)
}else{
colnames(mTIS) <- paste("tis",
xIndexAsChar[where.indicators], sep="")
mTIS <- zoo(mTIS, order.by=x.index)
if(xIsRegular){ mTIS <- as.zooreg(mTIS) }
}
return(mTIS)
} #close tim
################################
################# New Functions July 2019
##############################
##############
### isatdates
#############
## Extract breakdates from isat object (based on first break index):
isatdates <- function(x){
mxbreak_iis <- "iis"
mxbreak_sis <- "sis"
mxbreak_tis <- "tis"
iis.names <- c(x$ISnames[grep(mxbreak_iis, x$ISnames)])
sis.names <- c(x$ISnames[grep(mxbreak_sis, x$ISnames)])
tis.names <- c(x$ISnames[grep(mxbreak_tis, x$ISnames)])
##### iis
if(length(iis.names) != 0){
iis.breaks <- data.frame(matrix(NA, nrow=NROW(iis.names), ncol=1))
names(iis.breaks) <- c("breaks")
is.m <- as.matrix(x$aux$mX[,iis.names])
is.index <- which(x$aux$mXnames %in% iis.names)
colnames(is.m) <- iis.names
iis.date <- apply(is.m,2, function(x) (which(x>0))[1])
iis.date.index <- iis.date
iis.date <- x$aux$y.index[iis.date]
iis.breaks$breaks <- iis.names
iis.breaks$date <- iis.date
iis.breaks$index <- iis.date.index
iis.breaks$coef <- x$mean.results$coef[is.index]
iis.breaks$coef.se <- x$mean.results$std.error[is.index]
iis.breaks$coef.t <- x$mean.results$`t-stat`[is.index]
iis.breaks$coef.p <- x$mean.results$`p-value`[is.index]
} else {
iis.breaks <- NULL
}
##### sis
if(length(sis.names) != 0){
sis.breaks <- data.frame(matrix(NA, nrow=NROW(sis.names), ncol=1))
names(sis.breaks) <- c("breaks")
sis.m <- as.matrix(x$aux$mX[,sis.names])
sis.index <- which(x$aux$mXnames %in% sis.names)
colnames(sis.m) <- sis.names
sis.date <- apply(sis.m,2, function(x) (which(x>0))[1])
sis.date.index <- sis.date
sis.date <- x$aux$y.index[sis.date]
sis.breaks$breaks <- sis.names
sis.breaks$date <- sis.date
sis.breaks$index <- sis.date.index
sis.breaks$coef <- x$mean.results$coef[sis.index]
sis.breaks$coef.se <- x$mean.results$std.error[sis.index]
sis.breaks$coef.t <- x$mean.results$`t-stat`[sis.index]
sis.breaks$coef.p <- x$mean.results$`p-value`[sis.index]
} else {
sis.breaks <- NULL
}
##### tis
if(length(tis.names) != 0){
tis.breaks <- data.frame(matrix(NA, nrow=NROW(tis.names), ncol=1))
names(tis.breaks) <- c("breaks")
tis.m <- as.matrix(x$aux$mX[,tis.names])
tis.index <- which(x$aux$mXnames %in% tis.names)
colnames(tis.m) <- tis.names
tis.date <- apply(tis.m,2, function(x) (which(x>0))[1])
tis.date.index <- tis.date
tis.date <- x$aux$y.index[tis.date]
tis.breaks$breaks <- tis.names
tis.breaks$date <- tis.date
tis.breaks$index <- tis.date.index
tis.breaks$coef <- x$mean.results$coef[tis.index]
tis.breaks$coef.se <- x$mean.results$std.error[tis.index]
tis.breaks$coef.t <- x$mean.results$`t-stat`[tis.index]
tis.breaks$coef.p <- x$mean.results$`p-value`[tis.index]
} else {
tis.breaks <- NULL
}
out <- list(iis.breaks, sis.breaks, tis.breaks)
names(out) <- c("iis", "sis", "tis")
return(out)
} #end function
####################
### isatvarcorrect
#####################
#### Function to correct variance estimates when using IIS
isatvarcorrect <- function(x, mcor = 1){
classx <- class(x)
if (classx=="isat"){
if (!is.null(x$aux$args$iis) & x$aux$args$iis==TRUE)
{
x$vcov.mean <- x$vcov.mean * as.numeric(isvarcor(x$aux$t.pval, 1)[2]^2)
rel_names <- x$aux$mXnames[!(x$aux$mXnames %in% x$ISnames)]
x$vcov.mean[rel_names, rel_names] <- x$vcov.mean[rel_names, rel_names] * as.numeric(isvareffcor(x$aux$t.pval, 1, mcor)[2]^2)
x$mean.results$std.error <- sqrt(diag(x$vcov.mean))
x$mean.results$`t-stat` <- x$mean.results$coef/x$mean.results$std.error
x$mean.results$`p-value` <- pt(abs(x$mean.results$`t-stat`), x$df, lower.tail=FALSE)*2
x$sigma2 <- x$sigma2*as.numeric(isvarcor(x$aux$t.pval, 1)[2]^2)
x$logl <- -x$n*log(2*x$sigma2*pi)/2 - x$rss/(2*x$sigma2)
return(x)
} else {
stop("iis not TRUE")
}
} else {
stop("x must be an isat object")
}
} #function closed
###################
####### vargaugeiis
###################
##### Function to Compute Variance of the gauge (for use in outliertest)
vargaugeiis <- function(t.pval, T, infty=FALSE, m=1){
alpha <- t.pval
c <- abs(qnorm(alpha/2))
fc <- dnorm(c)
psi <- pnorm(c) - pnorm(-c)
tau <- psi - 2*c*dnorm(c)
chi <- 3*psi - 2*c*(c^2+3)*fc
rho_sig <- (c^2 - tau/psi)*c*fc/tau
k <- 3
###m iterations
m_min1 <- m-1
eta_sigma_m_min1 <- ( ((1-rho_sig^m_min1)/((1-rho_sig)*tau))^2 + 2* ((1-rho_sig^m_min1)/((1-rho_sig)*tau) )*rho_sig^m_min1 ) *(chi-tau^2/psi)/(k-1)+rho_sig^(2*m_min1)
eta_gamma_m <- (c*fc)^2*eta_sigma_m_min1*(k-1) + 2*c*fc*rho_sig^(m-1)*(tau-psi)
###infinite iterations
eta_infty <- (chi-tau^2/psi)*(c*fc)^2/((1-rho_sig)*tau)^2
if (infty==TRUE){
viis <- psi*(1-psi) + eta_infty
} else {
viis <- psi*(1-psi) + eta_gamma_m
}
sdiis <- sqrt(viis)
viis_T <- viis/T
sdiis_T <- sqrt(viis/T)
out <- data.frame(cbind(viis_T, sdiis_T, viis, sdiis))
names(out) <- c("var_iisgauge", "sd_iisgauge", "asy_var_iisgauge", "asy_sd_iisgauge")
return(out)
}
################
#### outlier Proportion Test
################
#### Outlier proportion and count tests from Jiao and Pretis (2019)
outliertest <- function(x=NULL, noutl=NULL, t.pval=NULL, T=NULL, m=1, infty=FALSE, alternative="two.sided"){
# noutl=x$obs.gauge$obs.num[i]
# t.pval=x$obs.gauge$t.pval[i]
# T=x$n
#
if (!is.null(x)){
classx <- class(x)
if (classx=="isat"){
# if (any(x$call$sis, x$call$tis)==TRUE ){
# stop("Test only valid for iis")
# } else {
if ( x$aux$args$iis == TRUE){
ISnames <- c(x$ISnames[grep("iis", x$ISnames)])
noutl= length(ISnames)
t.pval <- x$aux$t.pval
T <- x$n
} else {
stop("iis must be TRUE")
}
#}
} else {
stop("x must be an isat object")
}
} #x null closed
gauge.null <- t.pval
gauge <- noutl/T
#### Standard Normal Test
gauge.sd <- vargaugeiis(t.pval=gauge.null, T=T, infty=infty, m=m)$sd_iisgauge
gaugetestval <- (gauge - gauge.null)/gauge.sd
if (alternative=="two.sided"){
pval <- 2*(pnorm(-abs(gaugetestval)))
}
if (alternative=="less"){
pval <- pnorm(gaugetestval)
}
if (alternative=="greater"){
pval <- 1- pnorm(gaugetestval)
}
### Poisson Test
gauge_n <- noutl
gauge_null_n <- gauge.null*T
poistestval <- poisson.test(gauge_n, r=gauge_null_n, alternative=alternative)
rval_norm <- list(statistic = gaugetestval, p.value = pval, estimate=gauge, null.value = gauge.null, alternative = alternative, method="Jiao-Pretis Outlier Proportion Test", data.name="Proportion of detected outliers")
attr(rval_norm, "class") <- "htest"
rval_pois <- list(statistic = gauge_n, p.value = poistestval$p.value, estimate=gauge_n, null.value = gauge_null_n, alternative = alternative, method="Jiao-Pretis Outlier Count Test", data.name="Number of detected outliers")
attr(rval_pois, "class") <- "htest"
out <- list(rval_norm, rval_pois)
names(out) <- c("proportion", "count")
return(out)
}
#######################
###mvrnormsim: reproduced from MASS
#######################
mvrnormsim <- function(n = 1, mu, Sigma, tol = 1e-06, empirical = FALSE){
p <- length(mu)
eS <- eigen(Sigma, symmetric = TRUE)
ev <- eS$values
X <- matrix(rnorm(p * n), n)
if (empirical) {
X <- scale(X, TRUE, FALSE)
X <- X %*% svd(X, nu = 0)$v
X <- scale(X, FALSE, TRUE)
}
X <- drop(mu) + eS$vectors %*% diag(sqrt(pmax(ev, 0)), p) %*% t(X)
nm <- names(mu)
if (is.null(nm) && !is.null(dn <- dimnames(Sigma))) {
nm <- dn[[1L]]
}
dimnames(X) <- list(nm, NULL)
if (n == 1) {
drop(X) } else {
t(X)
}
#return(X)
}
####################################
############# isatloop
####################################
##### Looping over isat iterations for different p-values of selection to be used in outlierscaletest
isatloop <- function(num=c(seq(from=20, to=1, by=-1)), t.pval.spec = FALSE, print=FALSE, y, ar=NULL, iis=TRUE, sis=FALSE, ...){
initialm <- arx(y=y, ar=ar)
n <- initialm$n
num <- num[rev(order(num))]
if (t.pval.spec == FALSE){
p.num <- num/n # scaling significance levels
} else { #if p-values are pre-specified
p.num <- num
}
K <- length(p.num)
obs.gauge <- data.frame(matrix(NA, nrow=K, ncol=4)) # record significance p value, sample gauge, expected number and sample number of outliers
names(obs.gauge) <- c("t.pval", "obs.prop", "p.num", "obs.num")
for (k in 1:K)
{
pval <- p.num[k]
if (print==TRUE)
{
print(paste("k:", k, "/", K, ", p:", pval, sep=""))
}
x <- do.call("isat", args = list(y = y, iis = iis, sis = sis, t.pval = pval, ar = ar, ...))
#mxreg=mxreg, mc=mc,
if (!is.null(x$ISnames)) {
ISnames <- c(x$ISnames[grep("iis", x$ISnames)])
noutl= length(ISnames)
is.gauge <- noutl/n
is.num <- noutl
} else {
is.gauge <- 0
is.num <- 0
}
if (print==TRUE)
{
print(paste("gauge k:", is.gauge, ", number k:", "is.num", sep=""))
}
obs.gauge$t.pval[k] <- pval
obs.gauge$obs.prop[k] <- is.gauge
obs.gauge$p.num[k] <- pval*n
obs.gauge$obs.num[k] <- is.num
}
out <- list(n, obs.gauge)
names(out) <- c("n", "obs.gauge")
return(out)
}
#######################
##### outlierscaletest
########################
#### Scaling outlier tests from Jiao and Pretis (2019)
outlierscaletest <- function(x, nsim = 10000){
###################
obs.gauge <- x$obs.gauge
n <- x$n ##need to extract n
p.num <- obs.gauge$t.pval
c <- qnorm(1 - p.num/2) # corresponding cut-offs # assume standardised error follows standard normal
fc <- dnorm(c)
psi <- 1 - p.num
tau_2_c <- psi - 2*c*fc
tau_4 <- 3
K <- length(p.num)
#######################
##### Scale Sum Test
######################
stand.obs.gauge <- n^(1/2)*(obs.gauge$obs.prop - obs.gauge$t.pval) # standardise gauge
scalesum.stat <- sum(stand.obs.gauge) # scaling sum statistic
if (K == 1) # covariance structure between test statistics of different significance levels
{
covar <- 0
} else {
covar <- 0
for (k in 1:(K - 1))
{
for (l in (k + 1):K)
{
covar <- covar + obs.gauge$t.pval[l] - obs.gauge$t.pval[k]*obs.gauge$t.pval[l]
}
}
}
var.scalesum.stat <- sum(obs.gauge$t.pval*(1 - obs.gauge$t.pval)) + 2*covar + sum(c*fc)^(2)*(tau_4 - 1) + 2*sum(c*fc)*sum(tau_2_c + obs.gauge$t.pval - 1) # variance for scaling sum test statistic
sd.scalesum.stat <- sqrt(var.scalesum.stat)
#### Sum Test Output
stand.scalesum.stat <- scalesum.stat/sd.scalesum.stat
scalesum.pval <- 2*(pnorm(-abs(stand.scalesum.stat)))
#######################
##### Scale Sup Test
######################
scalesup.stat <- max(abs(stand.obs.gauge)) # scaling sup statistic
N <- nsim # sample size used to simulate the limiting distribution (could also be added as the argument of function)
mu <- matrix(0, K, 1) # mean of GP
Sigma <- matrix(NA, K, K) # covariance of GP
for (s in 1:K)
{
for (t in 1:K)
{
if (s <= t)
{
Sigma[s, t] <- obs.gauge$t.pval[t]*(1 - obs.gauge$t.pval[s]) + c[s]*fc[s]*(tau_2_c[t] + obs.gauge$t.pval[t] - 1) + c[t]*fc[t]*(tau_2_c[s] + obs.gauge$t.pval[s] - 1) + c[s]*c[t]*fc[s]*fc[t]*(tau_4 - 1)
}
else
{
Sigma[s, t] <- Sigma[t, s]
}
}
}
GPsample <- mvrnormsim(N, mu, Sigma) # generate multivariate normal and dim of object is N by K
Limitsample <- apply(abs(GPsample), 1, max) # find largest value over rows of absolute of GPsample
pvalsample <- Limitsample # use empirical distribution to draw p value
pvalsample[Limitsample <= scalesup.stat] <- 0
pvalsample[Limitsample > scalesup.stat] <- 1
scalesup.pval <- mean(pvalsample)
##################################
##### Output of Sum and Sup Tests
rval_sum <- list(statistic = stand.scalesum.stat, p.value = scalesum.pval, estimate=NULL, null.value = NULL, alternative = NULL, method="Jiao-Pretis Outlier Scaling Sum Test", data.name="Scaling proportion of detected outliers (Sum)")
attr(rval_sum, "class") <- "htest"
rval_sup <- list(statistic = scalesup.stat, p.value = scalesup.pval, estimate=NULL, null.value = NULL, alternative = NULL, method="Jiao-Pretis Outlier Scaling Sup Test", data.name="Scaling proportion of detected outliers (Sup)")
attr(rval_sup, "class") <- "htest"
out <- list(rval_sum, rval_sup)
names(out) <- c("sum", "sup")
return(out)
} ###function closed
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.