#' Simplified call for multivariate MSE estimation: no constraints, no regularization, no customization
#'
#' @param L Filter-length
#' @param weight_func Spectrum: DFT-matrix or alternative (for example model-based) estimate: first column is the target variable, additional columns are explanatory variables
#' @param Lag Nowcast (Lag=0), Forecast (Lag<0), Backcast (Lag>0)
#' @param Gamma Generic target specification: typically symmetric Lowpass (trend) or Bandpass (cycle) filters. Highpass and anticipative allpass (forecast) can be specified too
#' @return mdfa_obj MDFA object
#' @export
#'
MDFA_mse<-function(L,weight_func,Lag,Gamma)
{
cutoff<-pi
lin_eta<-F
lambda<-0
eta<-0
weight_constraint<-rep(1/(ncol(weight_func)-1),ncol(weight_func)-1)
lambda_cross<-lambda_smooth<-0
lambda_decay<-c(0,0)
lin_expweight<-F
shift_constraint<-rep(0,ncol(weight_func)-1)
grand_mean<-F
c_eta<-F
weights_only<-F
weight_structure<-c(0,0)
white_noise<-F
synchronicity<-F
b0_H0<-NULL
lag_mat<-matrix(rep(0:(L-1),ncol(weight_func)),nrow=L)
troikaner<-F
i1<-i2<-F
mdfa_obj<-mdfa_analytic(L,lambda,weight_func,Lag,Gamma,eta,cutoff,i1,i2,weight_constraint,
lambda_cross,lambda_decay,lambda_smooth,lin_eta,shift_constraint,grand_mean,
b0_H0,c_eta,weight_structure,white_noise,
synchronicity,lag_mat,troikaner)
return(list(mdfa_obj=mdfa_obj))
}
#' Simplified call for multivariate MSE estimation with filter constraints: no regularization, no customization
#'
#' @param L Filter-length
#' @param weight_func Spectrum: DFT-matrix or alternative (for example model-based) estimate: first column is the target variable, additional columns are explanatory variables
#' @param Lag Nowcast (Lag=0), Forecast (Lag<0), Backcast (Lag>0)
#' @param Gamma Generic target specification: typically symmetric Lowpass (trend) or Bandpass (cycle) filters. Highpass and anticipative allpass (forecast) can be specified too
#' @param i1 Boolean. If T a first-order filter constraint in frequency zero is obtained: amplitude of real-time filter must match weight_constraint (handles integration order one)
#' @param i2 Boolean. If T a second-order filter constraint in frequency zero is obtained: time-shift of real-time filter must match target (together with i1 handles integration order two)
#' @param weight_constraint Vector of amplitude constraints in frequency zero (typically 1 for lowpass and zero for bandpass or highpass)
#' @param shift_constraint Vector of time-shift constraints in frequency zero (typically zero for lowpass)
#' @return mdfa_obj MDFA object
#' @export
#'
MDFA_mse_constraint<-function(L,weight_func,Lag,Gamma,i1,i2,weight_constraint,shift_constraint)
{
cutoff<-pi
lin_eta<-F
lambda<-0
eta<-0
lambda_cross<-lambda_smooth<-0
lambda_decay<-c(0,0)
lin_expweight<-F
grand_mean<-F
c_eta<-F
weights_only<-F
weight_structure<-c(0,0)
white_noise<-F
synchronicity<-F
b0_H0<-NULL
lag_mat<-matrix(rep(0:(L-1),ncol(weight_func)),nrow=L)
troikaner<-F
mdfa_obj<-mdfa_analytic(L,lambda,weight_func,Lag,Gamma,eta,cutoff,i1,i2,weight_constraint,
lambda_cross,lambda_decay,lambda_smooth,lin_eta,shift_constraint,grand_mean,
b0_H0,c_eta,weight_structure,white_noise,
synchronicity,lag_mat,troikaner)
return(list(mdfa_obj=mdfa_obj))
}
#' Simplified call for multivariate customization: no regularization, no constraints
#'
#' @param L Filter-length
#' @param weight_func DFT-matrix or alternative (for example model-based) estimate: first column is the target variable, additional columns are explanatory variables
#' @param Lag Nowcast (Lag=0), Forecast (Lag<0), Backcast (Lag>0)
#' @param Gamma Generic target specification: typically symmetric Lowpass (trend) or Bandpass (cycle) filters. Highpass and anticipative allpass (forecast) can be specified too
#' @param cutoff Specifies start-frequency in stopband from which Smoothness is emphasized (corresponds typically to the cutoff of the lowpass target). Is not used if eta=0.
#' @param lambda Customization parameter: Timeliness is emphasized in the ATS-trilemma if lambda>0
#' @param eta Customization parameter: Smoothness is emphasized in the ATS-trilemma if eta>0
#' @return mdfa_obj MDFA object
#' @export
#'
MDFA_cust<-function(L,weight_func,Lag,Gamma,cutoff,lambda,eta)
{
lin_eta<-F
weight_constraint<-rep(1/(ncol(weight_func)-1),ncol(weight_func)-1)
lambda_cross<-lambda_smooth<-0
lambda_decay<-c(0,0)
lin_expweight<-F
shift_constraint<-rep(0,ncol(weight_func)-1)
grand_mean<-F
c_eta<-F
weights_only<-F
weight_structure<-c(0,0)
white_noise<-F
synchronicity<-F
b0_H0<-NULL
lag_mat<-matrix(rep(0:(L-1),ncol(weight_func)),nrow=L)
troikaner<-F
i1<-i2<-F
mdfa_obj<-mdfa_analytic(L,lambda,weight_func,Lag,Gamma,eta,cutoff,i1,i2,weight_constraint,
lambda_cross,lambda_decay,lambda_smooth,lin_eta,shift_constraint,grand_mean,
b0_H0,c_eta,weight_structure,white_noise,
synchronicity,lag_mat,troikaner)
return(list(mdfa_obj=mdfa_obj))
}
#' Simplified call for multivariate customization with filter constraints: no regularization
#'
#' @param L Filter-length
#' @param weight_func DFT-matrix or alternative (for example model-based) estimate: first column is the target variable, additional columns are explanatory variables
#' @param Lag Nowcast (Lag=0), Forecast (Lag<0), Backcast (Lag>0)
#' @param Gamma Generic target specification: typically symmetric Lowpass (trend) or Bandpass (cycle) filters. Highpass and anticipative allpass (forecast) can be specified too
#' @param cutoff Specifies start-frequency in stopband from which Smoothness is emphasized (corresponds typically to the cutoff of the lowpass target). Is not used if eta=0.
#' @param i1 Boolean. If T a first-order filter constraint in frequency zero is obtained: amplitude of real-time filter must match weight_constraint (handles integration order one)
#' @param i2 Boolean. If T a second-order filter constraint in frequency zero is obtained: time-shift of real-time filter must match target (together with i1 handles integration order two)
#' @param weight_constraint Vector of amplitude constraints in frequency zero (typically 1 for lowpass and zero for bandpass or highpass)
#' @param shift_constraint Vector of time-shift constraints in frequency zero (typically zero for lowpass)
#' @param lambda Customization parameter: Timeliness is emphasized in the ATS-trilemma if lambda>0
#' @param eta Customization parameter: Smoothness is emphasized in the ATS-trilemma if eta>0
#' @return mdfa_obj MDFA object
#' @export
#'
MDFA_cust_constraint<-function(L,weight_func,Lag,Gamma,cutoff,lambda,eta,i1,i2,weight_constraint,shift_constraint)
{
lin_eta<-F
lambda_cross<-lambda_smooth<-0
lambda_decay<-c(0,0)
lin_expweight<-F
grand_mean<-F
c_eta<-F
weights_only<-F
weight_structure<-c(0,0)
white_noise<-F
synchronicity<-F
b0_H0<-NULL
lag_mat<-matrix(rep(0:(L-1),ncol(weight_func)),nrow=L)
troikaner<-F
mdfa_obj<-mdfa_analytic(L,lambda,weight_func,Lag,Gamma,eta,cutoff,i1,i2,weight_constraint,
lambda_cross,lambda_decay,lambda_smooth,lin_eta,shift_constraint,grand_mean,
b0_H0,c_eta,weight_structure,white_noise,
synchronicity,lag_mat,troikaner)
return(list(mdfa_obj=mdfa_obj))
}
#' Simplified call for multivariate MSE and customization with regularization but no constraints
#'
#' @param L Filter-length
#' @param weight_func DFT-matrix or alternative (for example model-based) estimate: first column is the target variable, additional columns are explanatory variables
#' @param Lag Nowcast (Lag=0), Forecast (Lag<0), Backcast (Lag>0)
#' @param Gamma Generic target specification: typically symmetric Lowpass (trend) or Bandpass (cycle) filters. Highpass and anticipative allpass (forecast) can be specified too
#' @param cutoff Specifies start-frequency in stopband from which Smoothness is emphasized (corresponds typically to the cutoff of the lowpass target). Is not used if eta=0.
#' @param lambda Customization parameter: Timeliness is emphasized in the ATS-trilemma if lambda>0
#' @param eta Customization parameter: Smoothness is emphasized in the ATS-trilemma if eta>0
#' @param lambda_cross Regularization: cross-sectional term
#' @param lambda_decay Regularization: decay term
#' @param lambda_smooth Regularization: smoothness term
#' @param troikaner Boolean: if T then additional statistics such as ATS and degrees of freedom are computed (numerically involving)
#' @param b0_H0: Null-hypothesis towards which the parameter vector/matrix will be shrunken when imposing regularization
#' @return mdfa_obj MDFA object
#' @export
#'
MDFA_reg<-function(L,weight_func,Lag,Gamma,cutoff,lambda,eta,lambda_cross,lambda_decay,lambda_smooth,troikaner=F,b0_H0=NULL)
{
lin_eta<-F
weight_constraint<-rep(1/(ncol(weight_func)-1),ncol(weight_func)-1)
lin_expweight<-F
shift_constraint<-rep(0,ncol(weight_func)-1)
grand_mean<-F
c_eta<-F
weights_only<-F
weight_structure<-c(0,0)
white_noise<-F
synchronicity<-F
lag_mat<-matrix(rep(0:(L-1),ncol(weight_func)),nrow=L)
i1<-i2<-F
mdfa_obj<-mdfa_analytic(L,lambda,weight_func,Lag,Gamma,eta,cutoff,i1,i2,weight_constraint,
lambda_cross,lambda_decay,lambda_smooth,lin_eta,shift_constraint,grand_mean,
b0_H0,c_eta,weight_structure,white_noise,
synchronicity,lag_mat,troikaner)
return(list(mdfa_obj=mdfa_obj))
}
#' Simplified call for multivariate MSE/customization with regularization and constraints
#'
#' @param L Filter-length
#' @param weight_func DFT-matrix or alternative (for example model-based) estimate: first column is the target variable, additional columns are explanatory variables
#' @param Lag Nowcast (Lag=0), Forecast (Lag<0), Backcast (Lag>0)
#' @param Gamma Generic target specification: typically symmetric Lowpass (trend) or Bandpass (cycle) filters. Highpass and anticipative allpass (forecast) can be specified too
#' @param cutoff Specifies start-frequency in stopband from which Smoothness is emphasized (corresponds typically to the cutoff of the lowpass target). Is not used if eta=0.
#' @param i1 Boolean. If T a first-order filter constraint in frequency zero is obtained: amplitude of real-time filter must match weight_constraint (handles integration order one)
#' @param i2 Boolean. If T a second-order filter constraint in frequency zero is obtained: time-shift of real-time filter must match target (together with i1 handles integration order two)
#' @param lambda Customization parameter: Timeliness is emphasized in the ATS-trilemma if lambda>0
#' @param eta Customization parameter: Smoothness is emphasized in the ATS-trilemma if eta>0
#' @param weight_constraint Vector of amplitude constraints in frequency zero (typically 1 for lowpass and zero for bandpass or highpass)
#' @param shift_constraint Vector of time-shift constraints in frequency zero (typically zero for lowpass)
#' @param lambda_cross Regularization: cross-sectional term
#' @param lambda_decay Regularization: decay term
#' @param lambda_smooth Regularization: smoothness term
#' @param troikaner Boolean: if T then additional statistics such as ATS and degrees of freedom are computed (numerically involving)
#' @param b0_H0: Null-hypothesis towards which the parameter vector/matrix will be shrunken when imposing regularization
#' @return mdfa_obj MDFA object
#' @export
#'
MDFA_reg_constraint<-function(L,weight_func,Lag,Gamma,cutoff,lambda,eta,lambda_cross,lambda_decay,lambda_smooth,i1,i2,weight_constraint,shift_constraint,troikaner=F,b0_H0=NULL)
{
lin_eta<-F
lin_expweight<-F
grand_mean<-F
c_eta<-F
weights_only<-F
weight_structure<-c(0,0)
white_noise<-F
synchronicity<-F
lag_mat<-matrix(rep(0:(L-1),ncol(weight_func)),nrow=L)
mdfa_obj<-mdfa_analytic(L,lambda,weight_func,Lag,Gamma,eta,cutoff,i1,i2,weight_constraint,
lambda_cross,lambda_decay,lambda_smooth,lin_eta,shift_constraint,grand_mean,
b0_H0,c_eta,weight_structure,white_noise,
synchronicity,lag_mat,troikaner)
return(list(mdfa_obj=mdfa_obj))
}
#' Main estimation routine: Sets-up the generic optimization criteria proposed in MDFA-Legacy project (book)
#'
#' @param L Filter-length
#' @param lambda Customization parameter: Timeliness is emphasized in the ATS-trilemma if lambda>0
#' @param weight_func DFT-matrix or alternative (for example model-based) estimate: first column is the target variable, additional columns are explanatory variables
#' @param Lag Nowcast (Lag=0), Forecast (Lag<0), Backcast (Lag>0)
#' @param Gamma Generic target specification: typically symmetric Lowpass (trend) or Bandpass (cycle) filters. Highpass and anticipative allpass (forecast) can be specified too
#' @param eta Customization parameter: Smoothness is emphasized in the ATS-trilemma if eta>0
#' @param cutoff Specifies start-frequency in stopband from which Smoothness is emphasized (corresponds typically to the cutoff of the lowpass target). Is not used if eta=0.
#' @param i1 Boolean. If T a first-order filter constraint in frequency zero is obtained: amplitude of real-time filter must match weight_constraint (handles integration order one)
#' @param i2 Boolean. If T a second-order filter constraint in frequency zero is obtained: time-shift of real-time filter must match target (together with i1 handles integration order two)
#' @param weight_constraint Constraint vector in the case i1==T
#' @param lambda_cross Regularization: cross-sectional term
#' @param lambda_decay Regularization: decay term
#' @param lambda_smooth Regularization: smoothness term
#' @param lin_eta Boolean: impose continuous or discontinuous Smoothness customization
#' @param shift_constraint Constraint vector in the case i2==T
#' @param grand_mean Boolean: if T then a grand-mean parametrization is imposed (default is F)
#' @param b0_H0 Regularization: shrinkage target (arbitrary designs can be replicated by imposing strong regularization)
#' @param c_eta Boolean: impose mild/strong smoothness customization (default is F)
#' @param weight_structure Add structure to the optimization criterion (default value is weight_structure<-c(0,0): no structure imposed)
#' @param white_noise Impose a flat DFT (phase information is maintained)
#' @param synchronicity Impose a zero shift across series (amplitude information is maintained)
#' @param lag_mat Matrix for implementing effective lags in a mixed-frequency setting
#' @param troikaner Boolean: if T then degrees oif freedom will be computed (time-consuming computations if K is large)
#' @return b Matrix of optimal filter coefficients
#' @return trffkt Complex transfer function of optimal multivariate filter
#' @return rever Criterion value (corresponds to a sample estimate of the MSE if lambda=eta=0)
#' @return freezed_degrees_freedom Degrees of freedom (when imposing regularization the degrres of freedom are smaller than L times the number of explanatory series)
#' @return Accuracy Accuracy term in decomposition of MSE
#' @return Smoothness Smoothness term in decomposition of MSE
#' @return Timeliness Timeliness term in decomposition of MSE
#' @return MS_error Sample estimate of MSE: consistent estimate in the cases lambda>0 and/or eta>0
#' @return degrees_freedom complementary of freezed_degrees_freedom
#' @return edof alternative complementary of freezed_degrees_freedom
#' @return tic Troikaner information criterion: based on sub-dimension of shrinkage space
#' @export
#'
mdfa_analytic<-function(L,lambda,weight_func,Lag,Gamma,eta,cutoff,i1,i2,weight_constraint,
lambda_cross,lambda_decay,lambda_smooth,lin_eta,shift_constraint,grand_mean,
b0_H0,c_eta,weight_structure,white_noise,
synchronicity,lag_mat,troikaner)
{
# Enforce meaningful parameter values
lambda<-abs(lambda)
eta<-abs(eta)
cutoff<-min(abs(cutoff),pi)
# Resolution of discrete frequency-grid
K<-nrow(weight_func)-1
weight_target<-weight_func[,1]
weight_func<-weight_func*exp(-1.i*Arg(weight_target))
white_noise_synchronicity_obj<-white_noise_synchronicity(weight_func,white_noise,synchronicity)
weight_func<-white_noise_synchronicity_obj$weight_func
if (i2&i1&any(weight_constraint==0))
{
print(rep("!",100))
print("Warning: i2<-T is not meaningful when i1<-T and weight_constraint=0 (bandpass)")
print(rep("!",100))
}
if (!(length(b0_H0)==L*(dim(weight_func)[2]-1))&length(b0_H0)>0)
print(paste("length of b0_H0 vector is ",length(b0_H0),": it should be ",L*(dim(weight_func)[2]-1)," instead",sep=""))
# The function spect_mat_comp rotates all DFTs such that first column is real!#Lag<-0
spec_mat<-spec_mat_comp(weight_func,L,Lag,c_eta,lag_mat)$spec_mat
#spec_mat[,2] spec_math-spec_mat
structure_func_obj<-structure_func(weight_func,spec_mat)
Gamma_structure<-structure_func_obj$Gamma_structure
spec_mat_structure<-structure_func_obj$spec_mat_structure
Gamma_structure_diff<-structure_func_obj$Gamma_structure_diff
spec_mat_structure_diff<-structure_func_obj$spec_mat_structure_diff
# weighting of amplitude function in stopband
omega_Gamma<-as.integer(cutoff*K/pi)
if ((K-omega_Gamma+1)>0)
{
# Replicate results in McElroy-Wildi (trilemma paper)
if (lin_eta)
{
eta_vec<-c(rep(1,omega_Gamma),1+rep(eta,K-omega_Gamma+1))
} else
{
if (c_eta)
{
eta_vec<-c(rep(1,omega_Gamma+1),(1:(K-omega_Gamma))*pi/K +1)^(eta/10)
} else
{
eta_vec<-c(rep(1,omega_Gamma),(1:(K-omega_Gamma+1))^(eta/2))
}
}
weight_h<-weight_func*eta_vec
} else
{
eta_vec<-rep(1,K+1)
weight_h<-weight_func* eta_vec
}
# Frequency zero receives half weight
weight_h[1,]<-weight_h[1,]*ifelse(c_eta,1,1/sqrt(2))
# DFT target variable
weight_target<-weight_h[,1]
# Rotate all DFT's such that weight_target is real (rotation does not alter mean-square error). Note that target of strutural
# additional structural elements and of original MDFA are the same i.e. rotation must be the same and weight_target are identical too.
weight_h<-weight_h*exp(-1.i*Arg(weight_target))
weight_target<-Re(weight_target*exp(-1.i*Arg(weight_target)))
# If structure (forecasting) is imposed then we have to undo the customization weighting due to eta (no emphasis of stopband)
if (sum(abs(weight_structure))>0)
{
weight_target_structure<-weight_target_structure_diff<-weight_target/eta_vec
} else
{
weight_target_structure<-weight_target_structure_diff<-rep(0,K+1)
}
# DFT's explaining variables: target variable can be an explaining variable too
weight_h_exp<-as.matrix(weight_h[,2:(dim(weight_h)[2])])
# The spectral matrix is inflated in stopband: effect of eta
spec_mat<-t(t(spec_mat)*eta_vec) #dim(spec_mat) as.matrix(Im(spec_mat[150,]))
# Compute design matrix and regularization matrix
mat_obj<-mat_func(i1,i2,L,weight_h_exp,lambda_decay,lambda_cross,lambda_smooth,Lag,weight_constraint,shift_constraint,grand_mean,b0_H0,c_eta,lag_mat)
des_mat<-mat_obj$des_mat
reg_mat<-mat_obj$reg_mat
reg_xtxy<-mat_obj$reg_xtxy
w_eight<-mat_obj$w_eight
# Solve estimation problem
mat_x<-des_mat%*%spec_mat#spec_mat[,1]<-1
X_new<-t(Re(mat_x))+sqrt(1+Gamma*lambda)*1.i*t(Im(mat_x))
# xtx can be written either in Re(t(Conj(X_new))%*%X_new) or as below:
xtx<-t(Re(X_new))%*%Re(X_new)+t(Im(X_new))%*%Im(X_new)
# If abs(weight_structure)>0 then additional structure is instilled into MDFA-criterion: one-step ahead MSE
if (sum(abs(weight_structure))>0)
{
X_new_structure<-t(abs(weight_structure[1])*des_mat%*%spec_mat_structure)
xtx_structure<-t(Re(X_new_structure))%*%Re(X_new_structure)+t(Im(X_new_structure))%*%Im(X_new_structure)
X_new_structure_diff<-t(abs(weight_structure[2])*des_mat%*%spec_mat_structure_diff)
xtx_structure_diff<-t(Re(X_new_structure_diff))%*%Re(X_new_structure_diff)+t(Im(X_new_structure_diff))%*%Im(X_new_structure_diff)
Gamma_structure_diff<-abs(weight_structure)[2]*Gamma_structure
Gamma_structure<-abs(weight_structure)[1]*Gamma_structure
} else
{
X_new_structure<-x_new_structure_diff<-0*des_mat%*%spec_mat_structure
xtx_structure<-xtx_structure_diff<-0*t(Re(X_new_structure))%*%Re(X_new_structure)+t(Im(X_new_structure))%*%Im(X_new_structure)
}
# The filter restrictions (i1<-T and/or i2<-T) appear as constants on the right hand-side of the equation:
xtxy<-t(Re(t(w_eight)%*%spec_mat)%*%Re(t(spec_mat)%*%t(des_mat))+
Im(t(w_eight)%*%t(t(spec_mat)*sqrt(1+Gamma*lambda)))%*%Im(t(t(t(spec_mat)*sqrt(1+Gamma*lambda)))%*%t(des_mat)))
# scaler makes scales of regularization and unconstrained optimization `similar'
scaler<-mean(diag(xtx))
if (sum(abs(weight_structure))>0)
{
X_inv<-solve(xtx+xtx_structure+xtx_structure_diff+scaler*reg_mat)
bh<-as.vector(X_inv%*%(((t(Re(X_new)*weight_target))%*%Gamma)+
((t(Re(X_new_structure)*weight_target_structure))%*%Gamma_structure)+
((t(Re(X_new_structure_diff)*weight_target_structure_diff))%*%Gamma_structure_diff)-
xtxy-scaler*reg_xtxy))
} else
{
X_inv<-solve(xtx+scaler*reg_mat)
bh<-as.vector(X_inv%*%(((t(Re(X_new)*weight_target))%*%Gamma)-xtxy-scaler*reg_xtxy)) #weight_target[1]<-1
}
b<-matrix(nrow=L,ncol=length(weight_h_exp[1,]))
# Reconstruct original parameters from the set of possibly contrained ones
bhh<-t(des_mat)%*%bh
for (k in 1:L)
{
b[k,]<-bhh[(k)+(0:(length(weight_h_exp[1,])-1))*L]
}
weight_cm<-matrix(w_eight,ncol=(length(weight_h_exp[1,])))
# Add level and/or time-shift constraints (if i1<-F and i2<-F then this matrix is zero)
b<-b+weight_cm
# Transferfunction
trffkt<-matrix(nrow=K+1,ncol=length(weight_h_exp[1,]))
trffkth<-trffkt
trffkt[1,]<-apply(b,2,sum)
trffkth[1,]<-trffkt[1,]
for (j in 1:length(weight_h_exp[1,]))
{
for (k in 0:(K))
{
trffkt[k+1,j]<-(b[,j]%*%exp(1.i*k*lag_mat[,j+1]*pi/(K)))
}
}
trt<-apply(((trffkt)*exp(1.i*(0-Lag)*pi*(0:(K))/K))*weight_h_exp,1,sum)
# DFA criterion which accounts for customization but not for regularization term
# MDFA-Legacy : new normalization for all error terms below
rever<-sum(abs(Gamma*weight_target-Re(trt)-1.i*sqrt(1+lambda*Gamma)*Im(trt))^2)*pi/(K+1)
# MS-filter error : DFA-criterion without effects by lambda or eta (one must divide spectrum by eta_vec)
MS_error<-sum((abs(Gamma*weight_target-trt)/eta_vec)^2)*pi/(K+1)
# Definition of Accuracy, time-shift and noise suppression terms
Gamma_cp<-Gamma[1+0:as.integer(K*(cutoff/pi))]
Gamma_cn<-Gamma[(2+as.integer(K*(cutoff/pi))):(K+1)]
trt_cp<-(trt/eta_vec)[1+0:as.integer(K*(cutoff/pi))]
trt_cn<-(trt/eta_vec)[(2+as.integer(K*(cutoff/pi))):(K+1)]
weight_target_cp<-(weight_target/eta_vec)[1+0:as.integer(K*(cutoff/pi))]
weight_target_cn<-(weight_target/eta_vec)[(2+as.integer(K*(cutoff/pi))):(K+1)]
# define singular observations
Accuracy<-sum(abs(Gamma_cp*weight_target_cp-abs(trt_cp))^2)*2*pi/(K+1)
Timeliness<-4*sum(abs(Gamma_cp)*abs(trt_cp)*sin(Arg(trt_cp)/2)^2*weight_target_cp)*2*pi/(K+1)
Smoothness<-sum(abs(Gamma_cn*weight_target_cn-abs(trt_cn))^2)*2*pi/(K+1)
Shift_stopband<-4*sum(abs(Gamma_cn)*abs(trt_cn)*sin(Arg(trt_cn)/2)^2*weight_target_cn)*2*pi/(K+1)
# The following computations are time-consuming if K is `large'
# By default they are skipped i.e. troikaner=F
# Additional output: degrees of freedom, AIC
if (troikaner)
{
# The following derivations of the DFA-criterion are equivalent
# They are identical with rever (up to normalization by (2*(K+1)^2))
trth<-((X_new)%*%(X_inv%*%t(Re(X_new))))%*%(weight_target*Gamma)
# The projection matrix
Proj_mat<-((X_new)%*%(X_inv%*%t(Re(X_new))))
# The residual projection matrix
res_mat<-diag(rep(1,dim(Proj_mat)[1]))-Proj_mat
# DFA criterion: first possibility (all three variants are identical)
sum(abs(res_mat%*%(weight_target*Gamma))^2)*pi/(K+1)
# Residuals (DFT of filter error)
resi<-res_mat%*%(weight_target*Gamma)
# DFA criterion: second possibility
t(Conj(resi))%*%resi*pi/(K+1)
t((weight_target*Gamma))%*%(t(Conj(res_mat))%*%(res_mat))%*%(weight_target*Gamma)*pi/(K+1)
freezed_degrees_freedom<-2*Re(sum(diag(t(Conj(res_mat))%*%(res_mat))))
# Re(t(Conj(res_mat))%*%(res_mat))-Re(res_mat)
degrees_freedom<-2*K+1-freezed_degrees_freedom
# The following expression equates to zero i.e. projection matrix is a projection for real part
# Re(t(Conj(res_mat))%*%(res_mat))-Re(res_mat)
M<-((X_new)%*%(X_inv%*%t(Conj(X_new))))
res_M<-diag(rep(1,dim(M)[1]))-M
# The following is a real number but due to numerical rounding errors we prefer to take the real part of the result
edof<-Re(K+1-sum(eigen(res_M)$values))
# Troikaner
tic<-ifelse(freezed_degrees_freedom<2*K+1&freezed_degrees_freedom>1,log(rever)+2*(K-freezed_degrees_freedom+1)/(freezed_degrees_freedom-2),NA)
tic<-log(rever)+2*edof/(2*K)
return(list(b=b,trffkt=trffkt,rever=rever,freezed_degrees_freedom=freezed_degrees_freedom,tic=tic,degrees_freedom=degrees_freedom,Accuracy=Accuracy,Smoothness=Smoothness,Timeliness=Timeliness,MS_error=MS_error,edof=edof))
} else
{
# Simplified (shorter) return
return(list(b=b,trffkt=trffkt,rever=rever,Accuracy=Accuracy,Smoothness=Smoothness,Timeliness=Timeliness,MS_error=MS_error))
}
}
#' This function sets-up the spectral matrix for closed-form solution of the optimization problem in the multivariate case: it relies on the multivariate DFT; it organizes lead/lags in the case of mixed-frequency data.
#'
#' @param weight_func DFT-matrix or alternative (for example model-based) estimate: first column is the target variable, additional columns are explanatory variables
#' @param L Filter-length
#' @param Lag Nowcast (Lag=0), Forecast (Lag<0), Backcast (Lag>0)
#' @param c_eta Boolean weight of frequency zero (default is F)
#' @param lag_mat Matrix for implementing effective lags in a mixed-frequency setting
#' @return spec_mat Spectral matrix set-up for closed-form solution of optimization problem
#' @export
#'
spec_mat_comp<-function(weight_func,L,Lag,c_eta,lag_mat)
{
K<-length(weight_func[,1])-1
weight_h<-weight_func
# Frequency zero receives half weight
# Chris mod: avoid halving
# MDFA-Legacy: the DFT in frequency zero is weighted by 1/sqrt(2) (the weight of frequency zero is 0.5 in mean-square)
if (!c_eta)
weight_h[1,]<-weight_h[1,]/sqrt(2)
# Extract DFT target variable (first column)
weight_target<-weight_h[,1]
# Rotate all DFT's such that weight_target is real (rotation does not alter mean-square error)
weight_h<-weight_h*exp(-1.i*Arg(weight_target))#Im(exp(-1.i*Arg(weight_target)))
weight_target<-weight_target*exp(-1.i*Arg(weight_target))
# DFT's explaining variables (target variable can be an explaining variable too)
weight_h_exp<-as.matrix(weight_h[,2:(dim(weight_h)[2])])
spec_mat<-as.vector(t(as.matrix(weight_h_exp[1,])%*%t(as.matrix(rep(1,L)))))
for (j in 1:(K))#j<-1 h<-2 lag_mat<-matrix(rep(0:1,3),ncol=3) Lag<-2
{
omegak<-j*pi/K
# We feed the daily structure of the mixed_frequency data lag_mat
exp_mat<-matrix(nrow=L,ncol=ncol(weight_h_exp))
for (h in 1:ncol(exp_mat))
exp_mat[,h]<-exp(1.i*omegak*(lag_mat[,h+1]-Lag))
# Inclusion of the time-varying lag-structure of the mixed-frequency data
spec_mat<-cbind(spec_mat,as.vector(t(weight_h_exp[j+1,]*t(exp_mat))))
}
dim(spec_mat)
return(list(spec_mat=spec_mat))#as.matrix(Re(spec_mat[1,]))
}
#' This function sets-up the design matrix of the generic optimization problem: it combines data, regularization features and filter constraints
#'
#' @param i1 Boolean. If T a first-order filter constraint in frequency zero is obtained: amplitude of real-time filter must match weight_constraint (handles integration order one)
#' @param i2 Boolean. If T a second-order filter constraint in frequency zero is obtained: time-shift of real-time filter must match target (together with i1 handles integration order two)
#' @param L Filter-length
#' @param weight_h_exp DFT of explanatory variables
#' @param lambda_decay Regularization: decay term
#' @param lambda_cross Regularization: cross-sectional term
#' @param lambda_smooth Regularization: smoothness term
#' @param Lag Nowcast (Lag=0), Forecast (Lag<0), Backcast (Lag>0)
#' @param weight_constraint Constraint vector in the case i1==T
#' @param shift_constraint Constraint vector in the case i2==T
#' @param grand_mean Boolean: if T then a grand-mean parametrization is imposed (default is F)
#' @param b0_H0 Regularization: shrinkage target (arbitrary designs can be replicated by imposing strong regularization)
#' @param c_eta Boolean: impose mild/strong smoothness customization (default is F)
#' @param lag_mat Matrix for implementing effective lags in a mixed-frequency setting
#' @return des_mat Design matrix
#' @return reg_mat Bilinear form (regularization matrix)
#' @return reg_xtxy Constants from regularization
#' @return w_eight Constants from filter constraints
#'
mat_func<-function(i1,i2,L,weight_h_exp,lambda_decay,lambda_cross,lambda_smooth,Lag,weight_constraint,shift_constraint,grand_mean,b0_H0,c_eta,lag_mat)
{
# MDFA-Legacy: new functions
# Regularization
reg_mat_obj<-reg_mat_func(weight_h_exp,L,c_eta,lambda_decay,Lag,grand_mean,lambda_cross,lambda_smooth,lag_mat)
Q_smooth<-reg_mat_obj$Q_smooth
Q_cross<-reg_mat_obj$Q_cross
Q_decay<-reg_mat_obj$Q_decay
lambda_decay<-reg_mat_obj$lambda_decay
lambda_smooth<-reg_mat_obj$lambda_smooth
lambda_cross<-reg_mat_obj$lambda_cross
# MDFA-Legacy: new functions
# weight vector for constraints
w_eight<-w_eight_func(i1,i2,Lag,weight_constraint,shift_constraint,L,weight_h_exp)$w_eight
# MDFA-Legacy: new functions
# Grand-mean and Constraints
des_mat<-des_mat_func(i2,i1,L,weight_h_exp,weight_constraint,shift_constraint,Lag)$des_mat
# Transforming back from grand-mean if necessary (des_mat assumes grand-mean)
if (!grand_mean&length(weight_h_exp[1,])>1)
{
Q_centraldev_original<-centraldev_original_func(L,weight_h_exp)$Q_centraldev_original
} else
{
Q_centraldev_original<-NULL
}
if (!grand_mean&length(weight_h_exp[1,])>1)
{
# apply A^{-1} to A*R giving R where A and R are defined in MDFA_Legacy book
#and des_mat=A*R i.e. t(Q_centraldev_original%*%t(des_mat)) is R (called des_mat in my code)
des_mat<-t(Q_centraldev_original%*%t(des_mat))
}
# Here we fold all three regularizations (cross, smooth and decay) into a single reg-matrix
if ((length(weight_h_exp[1,])>1))
{
if (grand_mean)
{
reg_t<-(Q_smooth+Q_decay+t(Q_centraldev_original)%*%Q_cross%*%Q_centraldev_original)
} else
{
reg_t<-(Q_smooth+Q_decay+Q_cross)
}
} else
{
reg_t<-(Q_smooth+Q_decay)
}
# Normalize regularization terms (which are multiplied by des_mat) in order to disentangle i1/i2 effects
reg_mat<-(des_mat)%*%reg_t%*%t(des_mat)#sum(diag(reg_mat))
if (is.null(b0_H0))
b0_H0<-rep(0,length(w_eight))
b0_H0<-as.vector(b0_H0)
if (lambda_smooth+lambda_decay[2]+lambda_cross>0)
{
disentangle_des_mat_effect<-sum(diag(reg_t))/sum(diag(reg_mat))
if (abs(sum(diag(reg_mat)))>0)
{
disentangle_des_mat_effect<-sum(diag(reg_t))/sum(diag(reg_mat))
} else
{
disentangle_des_mat_effect<-1
}
reg_mat<-reg_mat*disentangle_des_mat_effect
reg_xtxy<-des_mat%*%reg_t%*%(w_eight-b0_H0)*(disentangle_des_mat_effect)#+t(w_eight)%*%reg_t%*%t(des_mat)
} else
{
reg_xtxy<-des_mat%*%reg_t%*%(w_eight-b0_H0)#+t(w_eight)%*%reg_t%*%t(des_mat)
dim(des_mat)
dim(reg_t)
}
return(list(des_mat=des_mat,reg_mat=reg_mat,reg_xtxy=reg_xtxy,w_eight=w_eight))
}
#' This function transforms grand-mean parametrization back to original coefficients
#'
#' @param L Filter-length
#' @param weight_h_exp DFT of explanatory variables
#' @return Q_centraldev_original Transformation matrix
#'
centraldev_original_func<-function(L,weight_h_exp)
{
# Grand-mean parametrization: des_mat is implemented in terms of grand-mean and Q_centraldev_original can
# be used to invert back to original coefficients
Q_centraldev_original<-matrix(data=rep(0,((L)*length(weight_h_exp[1,]))^2),nrow=(L)*length(weight_h_exp[1,]),ncol=(L)*length(weight_h_exp[1,]))
Q_centraldev_original<-diag(rep(1,L*length(weight_h_exp[1,])))
if (L>1)
{
diag(Q_centraldev_original[1:L,L+1:L])<-rep(-1,L)
for (i in 2:length(weight_h_exp[1,])) #i<-2
{
diag(Q_centraldev_original[(i-1)*L+1:L,1:L])<-rep(1,L)
diag(Q_centraldev_original[(i-1)*L+1:L,(i-1)*L+1:L])<-rep(1,L)
diag(Q_centraldev_original[1:L,(i-1)*L+1:L])<-rep(-1,L)
}
}
Q_centraldev_original<-solve(Q_centraldev_original)
return(list(Q_centraldev_original=Q_centraldev_original))
}
#' This function calls the regularization settings (bilinear forms) for cross-correlation, smoothness and decay patterns
#'
#' @param weight_h_exp DFT of explanatory variables
#' @param L Filter-length
#' @param c_eta Boolean: impose mild/strong smoothness customization (default is F)
#' @param lambda_decay Regularization: decay term
#' @param Lag Nowcast (Lag=0), Forecast (Lag<0), Backcast (Lag>0)
#' @param grand_mean Boolean: if T then a grand-mean parametrization is imposed (default is F)
#' @param lambda_cross Regularization: cross-sectional term
#' @param lambda_smooth Regularization: smoothness term
#' @param lag_mat Matrix for implementing effective lags in a mixed-frequency setting
#' @return Q_smooth Smoothness term (matrix)
#' @return Q_cross Cross-sectional term (matrix)
#' @return Q_decay Decay term (matrix)
#' @return lambda_decay Re-parameterized decay-weight
#' @return lambda_smooth Re-parameterized smoothness-weight
#' @return lambda_cross Re-parameterized cross-sectional-weight
#'
reg_mat_func<-function(weight_h_exp,L,c_eta,lambda_decay,Lag,grand_mean,lambda_cross,lambda_smooth,lag_mat)
{
lambda_smooth<-100*tan(min(abs(lambda_smooth),0.999999999)*pi/2)
lambda_cross<-100*tan(min(abs(lambda_cross),0.9999999999)*pi/2)
if (c_eta)
{
# Chris replication: imposing non-linear transform to lambda_decay[1] too
lambda_decay<-c(min(abs(tan(min(abs(lambda_decay[1]),0.999999999)*pi/2)),1),100*tan(min(abs(lambda_decay[2]),0.999999999)*pi/2))
} else
{
lambda_decay<-c(min(abs(lambda_decay[1]),1),100*tan(min(abs(lambda_decay[2]),0.999999999)*pi/2))
}
# New regularization function
Q_obj<-Q_reg_func(L,weight_h_exp,lambda_decay,lambda_smooth,lambda_cross,Lag,lag_mat,grand_mean,c_eta)
Q_smooth<-Q_obj$Q_smooth
Q_decay<-Q_obj$Q_decay
Q_cross<-Q_obj$Q_cross
# The Q_smooth and Q_decay matrices address regularizations for original unconstrained parameters (Therefore dimension L^2)
# At the end, the matrix des_mat is used to map these regularizations to central-deviance parameters
# accounting for first order constraints!
return(list(Q_smooth=Q_smooth,Q_cross=Q_cross,Q_decay=Q_decay,lambda_decay=lambda_decay,
lambda_smooth=lambda_smooth,lambda_cross=lambda_cross))
}
#' This function sets-up the regularization matrices
#'
#' @param L Filter-length
#' @param weight_h_exp DFT of explanatory variables
#' @param lambda_decay Regularization: decay term
#' @param lambda_smooth Regularization: smoothness term
#' @param lambda_cross Regularization: cross-sectional term
#' @param Lag Nowcast (Lag=0), Forecast (Lag<0), Backcast (Lag>0)
#' @param lag_mat Matrix for implementing effective lags in a mixed-frequency setting
#' @param grand_mean Boolean: if T then a grand-mean parametrization is imposed (default is F)
#' @param c_eta Boolean: impose mild/strong smoothness customization (default is F)
#' @return Q_smooth Smoothness term (matrix)
#' @return Q_decay Decay term (matrix)
#' @return Q_cross Cross-sectional term (matrix)
#'
# Function for setting-up the bilinear forms of the regularization
# It is a technical function which does not deserve specific description
Q_reg_func<-function(L,weight_h_exp,lambda_decay,lambda_smooth,lambda_cross,Lag,lag_mat,grand_mean,c_eta)
{
Q_smooth<-matrix(data=rep(0,((L)*length(weight_h_exp[1,]))^2),nrow=(L)*length(weight_h_exp[1,]),ncol=(L)*length(weight_h_exp[1,]))
Q_decay<-matrix(data=rep(0,((L)*length(weight_h_exp[1,]))^2),nrow=(L)*length(weight_h_exp[1,]),ncol=(L)*length(weight_h_exp[1,]))
# Cross-sectional regularization if dimension>1
if ((length(weight_h_exp[1,])>1))
{
# The cross-sectional regularization is conveniently implemented on central-deviance parameters. The regularization is expressed on the
# unconstrained central-deviance parameters (dimension L), then mapped to the original (unconstrained) parameters (dimension L) with Q_centraldev_original
# and then maped back to central-deviance with constraint (dim L-1) with des_mat (mathematically unnecessarily complicate but more convenient to implement in code).
Q_cross<-matrix(data=rep(0,((L)*length(weight_h_exp[1,]))^2),nrow=(L)*length(weight_h_exp[1,]),ncol=(L)*length(weight_h_exp[1,]))
Q_centraldev_original<-matrix(data=rep(0,((L)*length(weight_h_exp[1,]))^2),nrow=(L)*length(weight_h_exp[1,]),ncol=(L)*length(weight_h_exp[1,]))
} else
{
# 16.08.2012
Q_cross<-NULL
}
for (i in 1:L)
{
# For symmetric filters or any historical filter with Lag>0 the decay must be symmetric about b_max(0,Lag)
# lambda_decay is a 2-dim vector: the first component controls for the exponential decay and the second accounts for the strength of the regularization
# The maximal weight is limited to 1e+4
Q_decay[i,i]<-min((1+lambda_decay[1])^(2*abs(i-1-max(0,Lag))),1e+4)
# Original idea: with mixed-frequency data the decay should account for the effective lag (of the lower frequency data) as measured on the high-frequency scale: this is not a clever idea...
# Q_decay[i,i]<-min((1+lambda_decay[1])^(2*abs(lag_mat[i,1+1]-max(0,Lag))),1e+4)
if (L>4)
{
if(i==1)
{
Q_smooth[i,i:(i+2)]<-c(1,-2,1)
} else
{
if(i==2)
{
Q_smooth[i,(i-1):(i+2)]<-c(-2,5,-4,1)
} else
{
if(i==L)
{
Q_smooth[i,(i-2):i]<-c(1,-2,1)
} else
{
if(i==L-1)
{
Q_smooth[i,(i-2):(i+1)]<-c(1,-4,5,-2)
} else
{
Q_smooth[i,(i-2):(i+2)]<-c(1,-4,6,-4,1)
}
}
}
}
} else
{
print("L<=4: no smoothness regularization imposed!!!!!!!!!")
}
}
if (length(weight_h_exp[1,])>1)
{
for (j in 1:max(1,(length(weight_h_exp[1,])-1))) #j<-1
{
if (L>4)
Q_smooth[j*L+1:L,j*L+1:L]<-Q_smooth[1:L,1:L]
for (i in 1:L)
Q_decay[j*L+i,j*L+i]<-min((1+lambda_decay[1])^(2*abs(i-1-max(0,Lag))),1e+4)
# Original idea: with mixed-frequency data the decay should account for the effective lag (of the lower frequency data) as measured on the high-frequency scale: this is not a clever idea...
# Q_decay[j*L+i,j*L+i]<-min((1+lambda_decay[1])^(2*abs(lag_mat[i,1+j+1]-max(0,Lag))),1e+4)
}
Q_centraldev_original<-diag(rep(1,L*length(weight_h_exp[1,])))
if (L>1)
{
diag(Q_centraldev_original[1:L,L+1:L])<-rep(-1,L)
for (i in 2:length(weight_h_exp[1,])) #i<-2
{
diag(Q_centraldev_original[(i-1)*L+1:L,1:L])<-rep(1,L)
diag(Q_centraldev_original[(i-1)*L+1:L,(i-1)*L+1:L])<-rep(1,L)
diag(Q_centraldev_original[1:L,(i-1)*L+1:L])<-rep(-1,L)
}
}
Q_centraldev_original<-solve(Q_centraldev_original)
# 06.08.2012: the following if allows for either grand-mean parametrization (I-MDFA version prior to 30.07.2012) or original parameters
# If grand_mean==T then the code replicates I-MDFA as released prior 30.07.2012
# If grand_mean==F then the new parametrization is used.
# Differences between both approaches: see section 7.2 of my elements paper posted on SEFBlog (both codes are identical when no regularization is imposed. Otherwise the later version (grand_mean==F) is logically more consistent becuase it treats all series identically (no asymmetry)).
if (grand_mean)
{
diag(Q_cross[L+1:((length(weight_h_exp[1,])-1)*L),L+1:((length(weight_h_exp[1,])-1)*L)])<-
rep(1,((length(weight_h_exp[1,])-1)*L))
} else
{
#30.07.2012:new definition (parametrization) of Q_cross (Lambda_{cross} in the elements-paper)
diag(Q_cross)<-1
for (i in 1:length(weight_h_exp[1,]))
{
for (j in 1:L)
{
Q_cross[(i-1)*L+j,j+(0:(length(weight_h_exp[1,])-1))*L]<-Q_cross[(i-1)*L+j,j+(0:(length(weight_h_exp[1,])-1))*L]-1/length(weight_h_exp[1,])
}
}
}
} else
{
# define matrix for univariate case
Q_centraldev_original<-NULL
}
# Normalizing the troika are new: disentangle the effect by L
Q_decay<-Q_decay*lambda_decay[2]
Q_cross<-Q_cross*lambda_cross #Qh<-Q_cross
Q_smooth<-Q_smooth*lambda_smooth
if (lambda_decay[2]>0)
{
# The second parameter in lambda_decay accounts for the strength of the regularization
Q_decay<-lambda_decay[2]*(Q_decay/(sum(diag(Q_decay))))
}
if (lambda_cross>0)
{
if (c_eta)
{
Q_cross<-lambda_cross^2*(Q_cross/(sum(diag(Q_cross))))
} else
{
Q_cross<-lambda_cross*(Q_cross/(sum(diag(Q_cross))))
}
}
if (lambda_smooth>0&L>4)
{
Q_smooth<-lambda_smooth*(Q_smooth/(sum(diag(Q_smooth))))
}
return(list(Q_smooth=Q_smooth,Q_decay=Q_decay,Q_cross=Q_cross))
}
#' This function specifies the constant in case of filter constraints with/without regularization
#'
#' @param i1 Boolean. If T a first-order filter constraint in frequency zero is obtained: amplitude of real-time filter must match weight_constraint (handles integration order one)
#' @param i2 Boolean. If T a second-order filter constraint in frequency zero is obtained: time-shift of real-time filter must match target (together with i1 handles integration order two)
#' @param Lag Nowcast (Lag=0), Forecast (Lag<0), Backcast (Lag>0)
#' @param weight_constraint Constraint vector in the case i1==T
#' @param shift_constraint Constraint vector in the case i2==T
#' @param L Filter-length
#' @param weight_h_exp DFT of explanatory variables
#' @return w_eight Vector of filter weights entering closed-form solution
#'
w_eight_func<-function(i1,i2,Lag,weight_constraint,shift_constraint,L,weight_h_exp)
{
if (i1)
{
if (i2)
{
# impose constraints to b_Lag, b_{Lag+1} instead of b_{L-1} and b_L
# Therefore the decay regularization does not potentially conflict with filter constraints
if (Lag<1)
{
# corrected time-shift expression if A(0) different from 1
w_eight<-c(-(Lag-1)*weight_constraint[1]-shift_constraint[1]*weight_constraint[1],
Lag*weight_constraint[1]+shift_constraint[1]*weight_constraint[1],rep(0,L-2))
} else
{
# corrected time-shift expression if A(0) different from 1
w_eight<-c(rep(0,Lag),weight_constraint[1]-shift_constraint[1]*weight_constraint[1],
shift_constraint[1]*weight_constraint[1],rep(0,L-Lag-2))
}
if (length(weight_h_exp[1,])>1)
{
for (j in 2:length(weight_h_exp[1,]))
{
if (Lag<1)
{
# corrected time-shift expression if A(0) different from 1
w_eight<-c(w_eight,-(Lag-1)*weight_constraint[j]-shift_constraint[j]*weight_constraint[j],
Lag*weight_constraint[j]+shift_constraint[j]*weight_constraint[j],rep(0,L-2))
} else
{
# corrected time-shift expression if A(0) different from 1
w_eight<-c(w_eight,c(rep(0,Lag),weight_constraint[j]-shift_constraint[j]*weight_constraint[j],
shift_constraint[j]*weight_constraint[j],rep(0,L-Lag-2)))
}
}
}
} else
{
if (Lag<1)
{
w_eight<-c(weight_constraint[1],rep(0,L-1))
} else
{
w_eight<-c(rep(0,Lag),weight_constraint[1],rep(0,L-Lag-1))
}
if (length(weight_h_exp[1,])>1)
{
for (j in 2:length(weight_h_exp[1,]))
{
if (Lag<1)
{
w_eight<-c(w_eight,weight_constraint[j],rep(0,L-1))
} else
{
w_eight<-c(w_eight,rep(0,Lag),weight_constraint[j],rep(0,L-Lag-1))
}
}
}
}
} else
{
# MDFA-Legacy : the case i2==T i1==F is fixed, at last.
if (i2)
{
if (Lag<1)
{
w_eight<-rep(0,L)
} else
{
w_eight<-rep(0,L)
}
if (length(weight_h_exp[1,])>1)
{
for (j in 2:length(weight_h_exp[1,]))
{
if (Lag<1)
{
w_eight<-c(w_eight,rep(0,L))
} else
{
w_eight<-c(w_eight,rep(0,L))
}
}
}
} else
{
w_eight<-rep(0,L*length(weight_h_exp[1,]))
}
}
return(list(w_eight= w_eight))
}
#' This function sets-up the data-based part of the design matrix, accounting for i1/i2 constraints (this is the effective design-matrix in the absence of regularization). It is originally written in grand-mean parametrization (which makes it more tedious). Singularities in the case i1=F, i2=T are avoided by `displacing' the constraints by a small number.
#'
#' @param i2 Boolean. If T a second-order filter constraint in frequency zero is obtained: time-shift of real-time filter must match target (together with i1 handles integration order two)
#' @param i1 Boolean. If T a first-order filter constraint in frequency zero is obtained: amplitude of real-time filter must match weight_constraint (handles integration order one)
#' @param L Filter-length
#' @param weight_h_exp DFT of explanatory variables
#' @param weight_constraint Constraint vector in the case i1==T
#' @param shift_constraint Constraint vector in the case i2==T
#' @param Lag Nowcast (Lag=0), Forecast (Lag<0), Backcast (Lag>0)
#' @return des_mat Data-based design matrix
#'
des_mat_func<-function(i2,i1,L,weight_h_exp,weight_constraint,shift_constraint,Lag)
{
# Here we implement the matrix which links freely determined central-deviance parameters and constrained original parameters
# In the MDFA_Legacy book t(des_mat) corresponds to A%*%R (R links constrained and unconstrained parameters and A maps central-deviance to original parameters)
# Please note that:
# 1. Here I'm working with central-deviance parameters
# 2. The same matrix R applies to either parameter set
# 3. If I work with central-deviance parameters then R maps the freely determined set to the constrained (central-deviance)
# and A then maps the constrained (central-deviance) set to original constrained parameters.
if (i2)
{
if (i1)
{
# First and second order restrictions
des_mat<-matrix(data=rep(0,(L-2)*L*(length(weight_h_exp[1,]))^2),nrow=(L-2)*length(weight_h_exp[1,]),ncol=(L)*length(weight_h_exp[1,]))
for (i in 1:(L-2))
{
if (Lag<1)
{
des_mat[i,i+2+(0:(length(weight_h_exp[1,])-1))*L]<-1
des_mat[i,1+(0:(length(weight_h_exp[1,])-1))*L]<-i
des_mat[i,2+(0:(length(weight_h_exp[1,])-1))*L]<--(i+1)
} else
{
des_mat[i,ifelse(i<Lag+1,i,i+2)+(0:(length(weight_h_exp[1,])-1))*L]<-1
des_mat[i,Lag+1+(0:(length(weight_h_exp[1,])-1))*L]<-ifelse(i<Lag+1,-(Lag+2-i),i-Lag)
des_mat[i,Lag+2+(0:(length(weight_h_exp[1,])-1))*L]<-ifelse(i<Lag+1,(Lag+1-i),-(i-Lag+1))
}
}
if (length(weight_h_exp[1,])>1)
{
for (j in 1:max(1,(length(weight_h_exp[1,])-1)))
{
for (i in 1:(L-2))
{
if (Lag<1)
{
des_mat[i+j*(L-2),i+2]<--1
des_mat[i+j*(L-2),1]<--i
des_mat[i+j*(L-2),2]<-(i+1)
} else
{
des_mat[i+j*(L-2),ifelse(i<Lag+1,i,i+2)]<--1
des_mat[i+j*(L-2),Lag+1]<--ifelse(i<Lag+1,-(Lag+2-i),i-Lag)
des_mat[i+j*(L-2),Lag+2]<--ifelse(i<Lag+1,(Lag+1-i),-(i-Lag+1))
}
if (Lag<1)
{
des_mat[i+j*(L-2),i+2+j*L]<-1
des_mat[i+j*(L-2),1+j*L]<-i
des_mat[i+j*(L-2),2+j*L]<--(i+1)
} else
{
des_mat[i+j*(L-2),ifelse(i<Lag+1,i+j*L,i+2+j*L)]<-1
des_mat[i+j*(L-2),Lag+1+j*L]<-ifelse(i<Lag+1,-(Lag+2-i),i-Lag)
des_mat[i+j*(L-2),Lag+2+j*L]<-ifelse(i<Lag+1,(Lag+1-i),-(i-Lag+1))
}
}
}
}
} else
{
des_mat<-matrix(data=rep(0,(L-1)*L*(length(weight_h_exp[1,]))^2),nrow=(L-1)*length(weight_h_exp[1,]),ncol=(L)*length(weight_h_exp[1,]))
# MDFA-Legacy : the case i2==T i1==F is fixed, at last
# Avoid singularities in the time-shift specification
epsi<-1.e-02
if (Lag>=1)
shift_constraint[which(abs(shift_constraint)<epsi)]<-shift_constraint[which(abs(shift_constraint)<epsi)]+epsi
if (Lag<1)
shift_constraint[abs(-Lag-shift_constraint)<epsi]<-shift_constraint[which(abs(-Lag-shift_constraint)<epsi)]+epsi
for (i in 1:(L-1))
{
if (Lag<1)
{
# Forecast and nowcast
# we have to differentiate the case with vanishing shift and non-vansihing shift
# For a vanishing shift we select b2 for the constraint because then we are sure that the equations can be solved
# For a non-vanishing shift we select b1 because then we are sure that the equations can be solved (irrespective of the shift)
# See MDFA-legacy book for reference
# shift is different from zero: b1 is isolated (new formulas)
des_mat[i,ifelse(i<1,i,i+1)+(0:(length(weight_h_exp[1,])-1))*L]<-1
des_mat[i,1+(0:(length(weight_h_exp[1,])-1))*L]<--(-Lag+i-shift_constraint[1])/
(-Lag-shift_constraint[1])
} else
{
# Backcast: we have to differentiate the case with vanishing shift and non-vansihing shift
# For a vanishing shift we select b2 for the constraint because then we are sure that the equations can be solved
# For a non-vanishing shift we select b1 because then we are sure that the equations can be solved (irrespective of the shift)
# See MDFA-legacy book for reference
# shift is different from zero: b1 is isolated (new formulas: the signs change because of multiplication with -s)
des_mat[i,ifelse(i<Lag+1,i,i+1)+(0:(length(weight_h_exp[1,])-1))*L]<-1
des_mat[i,Lag+1+(0:(length(weight_h_exp[1,])-1))*L]<-
ifelse(i<Lag+1,(-(Lag+1-i)-shift_constraint[1])/shift_constraint[1],(-(Lag-i)-shift_constraint[1])/shift_constraint[1])
}
}
if (length(weight_h_exp[1,])>1)
{
for (j in 1:max(1,(length(weight_h_exp[1,])-1)))#j<-1
{
for (i in 1:(L-1))
{
if (Lag<1)
{
# shift is different from zero: b1 is isolated (new formulas)
des_mat[i+j*(L-1),ifelse(i<1,i,i+1)]<--1
des_mat[i+j*(L-1),1]<-(-Lag+i-shift_constraint[j+1])/(-Lag-shift_constraint[j+1])
} else
{
# shift is different from zero: b1 is isolated (new formulas: the signs change because of multiplication with -s)
des_mat[i+j*(L-1),ifelse(i<Lag+1,i,i+1)]<--1
des_mat[i+j*(L-1),Lag+1]<-
-ifelse(i<Lag+1,(-(Lag+1-i)-shift_constraint[j+1])/shift_constraint[j+1],(-(Lag-i)-shift_constraint[j+1])/shift_constraint[j+1])
}
if (Lag<1)
{
# shift is different from zero: b1 is isolated (new formulas)
des_mat[i+j*(L-1),ifelse(i<1,i,i+1)+j*L]<-1
des_mat[i+j*(L-1),1+j*L]<--(-Lag+i-shift_constraint[j+1])/(-Lag-shift_constraint[j+1])
} else
{
# shift is different from zero: b1 is isolated (new formulas: the signs change because of multiplication with -s)
des_mat[i+j*(L-1),ifelse(i<Lag+1,i,i+1)+j*L]<-1
des_mat[i+j*(L-1),Lag+1+j*L]<-
ifelse(i<Lag+1,(-(Lag+1-i)-shift_constraint[j+1])/shift_constraint[j+1],(-(Lag-i)-shift_constraint[j+1])/shift_constraint[j+1])
}
}
}
}
}
} else
{
if (i1)
{
des_mat<-matrix(data=rep(0,(L-1)*L*(length(weight_h_exp[1,]))^2),nrow=(L-1)*length(weight_h_exp[1,]),ncol=(L)*length(weight_h_exp[1,]))
for (i in 1:(L-1))
{
# The i1-constraint is imposed on b_max(0,Lag) (instead of b_L ) in order to avoid a conflict with the exponential decay requirement
if (Lag<1)
{
des_mat[i,i+1+(0:(length(weight_h_exp[1,])-1))*L]<-1
des_mat[i,1+(0:(length(weight_h_exp[1,])-1))*L]<--1
} else
{
# Lag cannot be larger than (L-1)/2 (symmetric filter)
des_mat[i,ifelse(i<Lag+1,i,i+1)+(0:(length(weight_h_exp[1,])-1))*L]<-1
des_mat[i,Lag+1+(0:(length(weight_h_exp[1,])-1))*L]<--1
}
}
if (length(weight_h_exp[1,])>1)
{
for (j in 1:max(1,(length(weight_h_exp[1,])-1))) #j<-1
{
for (i in 1:(L-1))
{
# The i1-constraint is imposed on b_max(0,Lag) (instead of b_L ) in order to avoid a conflict with the exponential decay requirement
if (Lag<1)
{
des_mat[i+j*(L-1),i+1]<--1
des_mat[i+j*(L-1),1]<-1
des_mat[i+j*(L-1),i+1+j*L]<-1
des_mat[i+j*(L-1),1+j*L]<--1
} else
{
# Lag cannot be larger than (L-1)/2 (symmetric filter)
des_mat[i+j*(L-1),ifelse(i<Lag+1,i,i+1)]<--1
des_mat[i+j*(L-1),Lag+1]<-1
des_mat[i+j*(L-1),ifelse(i<Lag+1,i,i+1)+j*L]<-1
des_mat[i+j*(L-1),Lag+1+j*L]<--1
}
}
}
}
} else
{
des_mat<-matrix(data=rep(0,(L)*L*(length(weight_h_exp[1,]))^2),nrow=(L)*length(weight_h_exp[1,]),ncol=(L)*length(weight_h_exp[1,]))
for (i in 1:(L))
{
des_mat[i,i+(0:(length(weight_h_exp[1,])-1))*L]<-1
}
if (length(weight_h_exp[1,])>1)
{
for (j in 1:max(1,(length(weight_h_exp[1,])-1)))
{
for (i in 1:(L))
{
des_mat[i+(j)*(L),i]<--1
des_mat[i+(j)*(L),i+j*L]<-1
}
}
}
}
}
return(list(des_mat=des_mat))
}
#' This function decomposes the MSE-criterion into Accuracy, Smoothness and Timeliness components
#'
#' @param Gamma Generic target specification: typically symmetric Lowpass (trend) or Bandpass (cycle) filters. Highpass and anticipative allpass (forecast) can be specified too
#' @param trffkt Complex transfer function of optimal multivariate filter
#' @param weight_func DFT-matrix
#' @param cutoff Specifies start-frequency in stopband from which Smoothness is emphasized (corresponds typically to the cutoff of the lowpass target). Is not used if eta=0.
#' @param Lag Nowcast (Lag=0), Forecast (Lag<0), Backcast (Lag>0)
#' @return Accuracy Accuracy term in decomposition of MSE
#' @return Smoothness Smoothness term in decomposition of MSE
#' @return Timeliness Timeliness term in decomposition of MSE
#' @return MS_error Sample estimate of MSE: consistent estimate in the cases lambda>0 and/or eta>0
#'
MS_decomp_total<-function(Gamma,trffkt,weight_func,cutoff,Lag)
{
if (!(length(trffkt[,1])==length(weight_func[,1])))
{
len_w<-min(length(trffkt[,1]),length(weight_func[,1]))
if (length(trffkt[,1])<length(weight_func[,1]))
{
len_r<-(length(weight_func[,1])-1)/(length(trffkt[,1])-1)
weight_funch<-weight_func[c(1,(1:(len_w-1))*len_r),]
trffkth<-trffkt
} else
{
len_r<-1/((length(weight_func[,1])-1)/(length(trffkt[,1])-1))
trffkth<-trffkt[c(1,(1:(len_w-1))*len_r),]
weight_funch<-weight_func
}
} else
{
len_w<-length(trffkt[,1])
weight_funch<-weight_func
trffkth<-trffkt
Gammah<-Gamma
}
if (length(Gamma)>len_w)
{
len_r<-(length(Gamma)-1)/(len_w-1)
Gammah<-Gamma[c(1,(1:(len_w-1))*len_r)]
}
weight_h<-weight_funch
K<-length(weight_funch[,1])-1
weight_target<-weight_h[,1]
# Rotate all DFT's such that weight_target is real (rotation does not alter mean-square error)
weight_h<-weight_h*exp(-1.i*Arg(weight_target))
weight_target<-Re(weight_target*exp(-1.i*Arg(weight_target)))
# DFT's explaining variables: target variable can be an explaining variable too
weight_h_exp<-as.matrix(weight_h[,2:(dim(weight_h)[2])])
trt<-apply(((trffkth)*exp(1.i*(0-Lag)*pi*(0:(K))/K))*weight_h_exp,1,sum)
# MS-filter error : DFA-criterion without effects by lambda or eta (one must divide spectrum by eta_vec)
MS_error<-sum((abs(Gammah*weight_target-trt))^2)/(2*(K+1)^2)
Gamma_cp<-Gammah[1+0:as.integer(K*(cutoff/pi))]
Gamma_cn<-Gammah[(2+as.integer(K*(cutoff/pi))):(K+1)]
trt_cp<-trt[1+0:as.integer(K*(cutoff/pi))]
trt_cn<-trt[(2+as.integer(K*(cutoff/pi))):(K+1)]
weight_target_cp<-weight_target[1+0:as.integer(K*(cutoff/pi))]
weight_target_cn<-weight_target[(2+as.integer(K*(cutoff/pi))):(K+1)]
# define singular observations
Accuracy<-sum(abs(Gamma_cp*weight_target_cp-abs(trt_cp))^2)/(2*(K+1)^2)
Timeliness<-4*sum(abs(Gamma_cp)*abs(trt_cp)*sin(Arg(trt_cp)/2)^2*weight_target_cp)/(2*(K+1)^2)
Smoothness<-sum(abs(Gamma_cn*weight_target_cn-abs(trt_cn))^2)/(2*(K+1)^2)
Shift_stopband<-4*sum(abs(Gamma_cn)*abs(trt_cn)*sin(Arg(trt_cn)/2)^2*weight_target_cn)/(2*(K+1)^2)
return(list(Accuracy=Accuracy,Smoothness=Smoothness,Timeliness=Timeliness,MS_error=MS_error))
}
#' This function allows for additional structure in the optimization criteria (features are not implemented yet)
#'
#' @param weight_func DFT-matrix
#' @param spec_mat Spectral matrix
#' @return Gamma_structure Target structure
#' @return spec_mat_structure Spectral matrix structure
#' @return Gamma_structure_diff Differenced target structure
#' @return spec_mat_structure Differenced spectral matrix structure
#'
structure_func<-function(weight_func,spec_mat)
{
K<-nrow(weight_func)-1
# We have to initialize spect_mat_structure and spec_mat_structure_diff by an arbitrary matrix of right dimensions
spec_mat_structure<-spec_mat_structure_diff<-spec_mat
Gamma_structure<-Gamma_structure_diff<-rep(0,K+1)
return(list(Gamma_structure=Gamma_structure,spec_mat_structure=spec_mat_structure,
Gamma_structure_diff=Gamma_structure_diff,spec_mat_structure_diff=spec_mat_structure_diff ))
}
#' This function allows for particular parametrizations of DFT (not implemented yet)
#'
#' @param weight_func DFT-matrix
#' @param white_noise Boolean for flat spectrum
#' @param synchronicity Boolean for synchronous explanatory variables
#' @return weight_func Parameterized DFT
#'
white_noise_synchronicity<-function(weight_func,white_noise,synchronicity)
{
return(list(weight_func=weight_func))
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.