The initialisation is done by makeARIMA
and sets the initial state vector equal to zeros. Do not get confuse with fit$mod$a
, which returns the contemporaneous state vector at the last iteration, not the first one.
It seems that you are obtaining the prediction error, v
, before
running the prediction step, a_filt1
.
The Kalman filter recursions that reproduce the output from KalmanRun
can be implemented as follows (based on source code of KalmanRun
and package KFKSDS).
set.seed(123)
y <- arima.sim(n = 120, model = list(order = c(0,0,2), ma = c(0.6,0.4)))
fit <- arima(y, order = c(0,0,2), include.mean = FALSE)
# matrices of the state space representation of the model
ss <- fit$model
# storage for the contemporaneous state estimates and residuals
a.upd <- matrix(nrow = length(y), ncol = length(ss$a))
v <- rep(NA, length(y))
# initial state vector and corresponding covariance matrix
a.upd <- rbind(rep(0, length(ss$a)), a.upd)
P.upd <- ss$P
# Kalman filter recursions
for (i in seq_along(y))
{
# prediction
a.pred <- ss$T %*% a.upd[i,]
P.pred <- ss$T %*% P.upd %*% t(ss$T) + ss$V
# prediction error
v[i] <- y[i] - ss$Z %*% a.pred
# variance of prediction error, 'f'
M <- crossprod(P.pred, ss$Z)
f <- drop(ss$Z %*% M + ss$h)
# update of state vector and its covariance matrix
a.upd[i+1,] <- a.pred + M * v[i] / f
P.upd <- P.pred - tcrossprod(M) / f
}
# remove the initial state vector containing zeros
a.upd <- a.upd[-1,]
Now compare with KalmanRun
(remember setting the initial state vector to zeros):
ss$a <- rep(0, length(ss$a))
kf <- KalmanRun(y, ss)
head(cbind(kf$states[1,], a.upd[1,]))
# [,1] [,2]
# [1,] 1.1964116 1.1964116
# [2,] 0.7150462 0.7150462
# [3,] 0.3612108 0.3612108
all.equal(kf$states, a.upd)
# [1] TRUE
The residuals also match those returned by KalmanRun
:
all.equal(kf$resid, v)
# [1] TRUE
However, this does not match the residuals from the fitted model:
head(cbind(residuals(fit), v))
# [1,] 0.9941325 1.1964116
# [2,] 0.2668942 0.1986161
# [3,] 0.3804713 0.3151606
# [4,] 1.5094031 1.5725179
# [5,] 0.5247281 0.5066900
# [6,] -1.0697975 -1.0800751
Some further details remain to be checked to fully reproduce the fitted model, but I think this will help you to reproduce KalmanRun
.
For completeness I show the equations of the Kalman filter discussed above (Durbin and Koopman, 2001 Time Series Analysis by State Space Methods Section 4.2):
\begin{eqnarray}
\begin{array}{lll}
a_{t+1} = T a_{t|t} &
P_{t+1} = T P_{t|t} T^\top + V \\
v_t = y_t - Z a_t &
M_t = P_t Z^\top &
f_t = Z M_t + H \\
a_{t|t} = a_t + M_t v_t / f_t &
P_{t|t} = P_t - M_t M_t^\top / f_t \\
t = 1,2,\dots,n.
\end{array}
\end{eqnarray}
vec()
function and is this function really needed? Cannot we simply usec()
? The value ofi
in the expression ofv
is not defined in the code. $\endgroup$