|
| 1 | +# Define the inputs of the function |
| 2 | +# X: a matrix with n rows and TT columns representing the observed data at each time t. |
| 3 | +# A: a transition matrix with size r*p+r*r. |
| 4 | +# C: an observation matrix with size n*r. |
| 5 | +# Q: a covariance matrix for the state equation disturbances with size r*p+r*r. |
| 6 | +# R: a covariance matrix for the observation disturbances with size n*n. |
| 7 | +# Z_0: the initial value of the state variable. |
| 8 | +# V_0: the initial value of the variance-covariance matrix of the state variable. |
| 9 | +# r: order of the state autoregression (AR) process. |
| 10 | +# p: number of lags in the state AR process. |
| 11 | +# i_idio: a vector of indicators specifying which variables are idiosyncratic noise variables.' |
| 12 | + |
| 13 | +# TODO: FINISH and VERIFY!! |
| 14 | +# Z_0 = F_0; V_0 = P_0 |
| 15 | +EMstepBMMQidio = function(X, A, C, Q, R, Z_0, V_0, XW0, NW, dgind, dnkron, dnkron_ind, r, p, R_mat, n, nq, sr, TT, rQi, rRi) { |
| 16 | + |
| 17 | + # Define dimensions of the input arguments |
| 18 | + rC = 5L # ncol(Rcon) |
| 19 | + pC = max(p, rC) |
| 20 | + rp = r * p |
| 21 | + rpC = r * pC |
| 22 | + nm = n - nq |
| 23 | + rC = rC * r # Note here replacing rC!! |
| 24 | + |
| 25 | + snm = seq_len(nm) |
| 26 | + srp = seq_len(rp) |
| 27 | + srpC = seq_len(rpC) |
| 28 | + rpC1nq = (rpC+1L):(rpC+nq) |
| 29 | + |
| 30 | + # Run Kalman filter with current parameter estimates |
| 31 | + kfs_res = SKFS(X, A, C, Q, R, Z_0, V_0, TRUE) |
| 32 | + |
| 33 | + # Extract values from the Kalman Filter output |
| 34 | + Zsmooth = kfs_res$F_smooth |
| 35 | + Vsmooth = kfs_res$P_smooth |
| 36 | + VVsmooth = kfs_res$PPm_smooth |
| 37 | + Zsmooth0 = kfs_res$F_smooth_0 |
| 38 | + Vsmooth0 = kfs_res$P_smooth_0 |
| 39 | + loglik = kfs_res$loglik |
| 40 | + |
| 41 | + # Normal Expectations for factors |
| 42 | + tmp = rbind(Zsmooth0[srpC], Zsmooth[-TT, srpC, drop = FALSE]) |
| 43 | + tmp2 = sum3(Vsmooth[srpC, srpC, -TT, drop = FALSE]) |
| 44 | + EZZ = crossprod(Zsmooth[, srpC, drop = FALSE]) %+=% (tmp2 + Vsmooth[srpC, srpC, TT]) # E(Z'Z) |
| 45 | + EZZ_BB = crossprod(tmp) %+=% (tmp2 + Vsmooth0[srpC, srpC]) # E(Z(-1)'Z(-1)) |
| 46 | + EZZ_FB = crossprod(Zsmooth[, srpC, drop = FALSE], tmp) %+=% sum3(VVsmooth[srpC, srpC,, drop = FALSE]) # E(Z'Z(-1)) |
| 47 | + |
| 48 | + # Expectations for idiosyncratic errors |
| 49 | + tmp = rbind(Zsmooth0[rpC1nq], Zsmooth[-TT, rpC1nq, drop = FALSE]) |
| 50 | + tmp2 = sum3(Vsmooth[rpC1nq, rpC1nq, -TT, drop = FALSE]) |
| 51 | + EZZ_u = diag(crossprod(Zsmooth[, rpC1nq, drop = FALSE])) + diag(tmp2 + Vsmooth[rpC1nq, rpC1nq, TT]) # E(Z'Z) |
| 52 | + EZZ_BB_u = diag(crossprod(tmp)) + diag(tmp2 + Vsmooth0[rpC1nq, rpC1nq]) # E(Z(-1)'Z(-1)) |
| 53 | + EZZ_FB_u = diag(diag(crossprod(Zsmooth[, rpC1nq, drop = FALSE], tmp)) + diag(rowSums(VVsmooth[rpC1nq, rpC1nq,, drop = FALSE], dims = 2L))) # E(Z'Z(-1)) |
| 54 | + |
| 55 | + # Update matrices A and Q |
| 56 | + A_new = A |
| 57 | + Q_new = Q |
| 58 | + |
| 59 | + # System matrices for factors |
| 60 | + A_new[sr, srp] = EZZ_FB[sr, , drop = FALSE] %*% ainv(EZZ_BB) |
| 61 | + if(rQi) { |
| 62 | + Qsr = (EZZ[sr, sr] - tcrossprod(A_new[sr, srp, drop = FALSE], EZZ_FB[sr,, drop = FALSE])) / TT |
| 63 | + Q_new[sr, sr] = if(rQi == 2L) Qsr else diag(diag(Qsr)) |
| 64 | + } else Q_new[sr, sr] = diag(r) |
| 65 | + |
| 66 | + # System matrices for errors |
| 67 | + A_new[rpC1nq, rpC1nq] = EZZ_FB_u / EZZ_BB_u |
| 68 | + if(rRi) { |
| 69 | + if(rRi == 2L) stop("Cannot estimate unrestricted observation covariance matrix together with AR(1) serial correlation") |
| 70 | + Q_new[rpC1nq, rpC1nq] = (diag(EZZ_u) - A_new[rpC1nq, rpC1nq] * EZZ_FB_u) / TT |
| 71 | + } else Q_new[rpC1nq, rpC1nq] = diag(nm) |
| 72 | + |
| 73 | + # Estimate matrix C using maximum likelihood approach |
| 74 | + denom = numeric(nm*r^2) |
| 75 | + nom = matrix(0, nm, r) |
| 76 | + |
| 77 | + for (t in seq_len(TT)) { |
| 78 | + nmiss = as.double(NW[t, 1:nm]) |
| 79 | + tmp = t(Zsmooth[t, sr]) |
| 80 | + tmp2 = crossprod(tmp) + Vsmooth[sr, sr, t] |
| 81 | + dim(tmp2) = NULL |
| 82 | + denom %+=% tcrossprod(tmp2, nmiss) |
| 83 | + nom %+=% (XW0[t, 1:nm] %*% tmp) |
| 84 | + nom %-=% ((Zsmooth[t, rpC1nq] %*% tmp + Vsmooth[rpC1nq, sr, t]) * nmiss) |
| 85 | + } |
| 86 | + |
| 87 | + dim(denom) = c(r, r, nm) |
| 88 | + dnkron[dnkron_ind] = aperm.default(denom, c(1L, 3L, 2L)) |
| 89 | + vec_C = solve.default(dnkron, unattrib(nom)) |
| 90 | + C_new = C |
| 91 | + C_new[1:nm, sr] = vec_C |
| 92 | + |
| 93 | + # Now updating the quarterly observation matrix C |
| 94 | + for (i in (nm+1):n) { |
| 95 | + denom = numeric(rC^2) |
| 96 | + nom = numeric(rC) |
| 97 | + i_idio_jQ = rpC + nm + 5*((i-nm)-1) + 1:5 |
| 98 | + |
| 99 | + for (t in 1:TT) { |
| 100 | + if(NW[t, i]) { |
| 101 | + denom %+=% (crossprod(Zsmooth[t, 1:rC, drop = FALSE]) + Vsmooth[1:rC, 1:rC, t]) |
| 102 | + nom %+=% (XW0[t, i] * Zsmooth[t, 1:rC]) |
| 103 | + nom %-=% (c(1,2,3,2,1) %*% (Zsmooth[t, i_idio_jQ] %*% t(Zsmooth[t, 1:rC]) + Vsmooth[i_idio_jQ, 1:rC, t])) |
| 104 | + } |
| 105 | + } |
| 106 | + |
| 107 | + dim(denom) = c(rC, rC) |
| 108 | + denom_inv = ainv(denom) |
| 109 | + C_i = denom_inv %*% nom |
| 110 | + tmp = tcrossprod(denom_inv, R_mat) |
| 111 | + C_i_constr = C_i - tmp %*% ainv(R_mat %*% tmp) %*% R_mat %*% C_i |
| 112 | + C_new[i, 1:rC] = C_i_constr |
| 113 | + |
| 114 | + # Update AR parameters for quarterly idiosyncratic errors |
| 115 | + V_0_new = V_0 |
| 116 | + V_0_new[i_idio_jQ, i_idio_jQ] = Vsmooth[i_idio_jQ, i_idio_jQ, 1] |
| 117 | + A_new[i_idio_jQ[1], i_idio_jQ[1]] = A_new[rpC1nq[i-nm], rpC1nq[i-nm]] |
| 118 | + Q_new[i_idio_jQ[1], i_idio_jQ[1]] = Q_new[rpC1nq[i-nm], rpC1nq[i-nm]] |
| 119 | + } |
| 120 | + |
| 121 | + # Set initial conditions |
| 122 | + V_0_new = V_0 |
| 123 | + V_0_new[srpC, srpC] = Vsmooth0[srpC, srpC] |
| 124 | + V_0_new[rpC1nq, rpC1nq] = diag(diag(Vsmooth0[rpC1nq, rpC1nq, drop = FALSE])) |
| 125 | + |
| 126 | + return(list(A = A_new, |
| 127 | + C = C_new, |
| 128 | + Q = Q_new, |
| 129 | + R = R, # R stays fixed |
| 130 | + F_0 = drop(Zsmooth0), |
| 131 | + P_0 = V_0_new, |
| 132 | + loglik = loglik)) |
| 133 | +} |
0 commit comments