Fit a structural model for a time series by maximum likelihood.
1 2 
x 
a univariate numeric time series. Missing values are allowed. 
type 
the class of structural model. If omitted, a BSM is used
for a time series with 
init 
initial values of the variance parameters. 
fixed 
optional numeric vector of the same length as the total
number of parameters. If supplied, only 
optim.control 
List of control parameters for

Structural time series models are (linear Gaussian) statespace models for (univariate) time series based on a decomposition of the series into a number of components. They are specified by a set of error variances, some of which may be zero.
The simplest model is the local level model specified by
type = "level"
. This has an underlying level m[t] which
evolves by
m[t+1] = m[t] + xi[t], xi[t] ~ N(0, σ^2_ξ)
The observations are
x[t] = m[t] + eps[t], eps[t] ~ N(0, σ^2_\eps)
There are two parameters, σ^2_ξ and σ^2_eps. It is an ARIMA(0,1,1) model, but with restrictions on the parameter set.
The local linear trend model, type = "trend"
, has the same
measurement equation, but with a timevarying slope in the dynamics for
m[t], given by
m[t+1] = m[t] + n[t] + xi[t], xi[t] ~ N(0, σ^2_ξ)
n[t+1] = n[t] + ζ[t], ζ[t] ~ N(0, σ^2_ζ)
with three variance parameters. It is not uncommon to find σ^2_ζ = 0 (which reduces to the local level model) or σ^2_ξ = 0, which ensures a smooth trend. This is a restricted ARIMA(0,2,2) model.
The basic structural model, type = "BSM"
, is a local
trend model with an additional seasonal component. Thus the measurement
equation is
x[t] = m[t] + s[t] + eps[t], eps[t] ~ N(0, σ^2_eps)
where s[t] is a seasonal component with dynamics
s[t+1] = s[t]  …  s[t  s + 2] + w[t], w[t] ~ N(0, σ^2_w)
The boundary case σ^2_w = 0 corresponds to a deterministic (but arbitrary) seasonal pattern. (This is sometimes known as the ‘dummy variable’ version of the BSM.)
A list of class "StructTS"
with components:
coef 
the estimated variances of the components. 
loglik 
the maximized loglikelihood. Note that as all these
models are nonstationary this includes a diffuse prior for some
observations and hence is not comparable to 
loglik0 
the maximized loglikelihood with the constant used prior to R 3.0.0, for backwards compatibility. 
data 
the time series 
residuals 
the standardized residuals. 
fitted 
a multiple time series with one component for the level, slope and seasonal components, estimated contemporaneously (that is at time t and not at the end of the series). 
call 
the matched call. 
series 
the name of the series 
code 
the 
model, model0 
Lists representing the Kalman Filter used in the
fitting. See 
xtsp 
the 
Optimization of structural models is a lot harder than many of the
references admit. For example, the AirPassengers
data
are considered in Brockwell & Davis (1996): their solution appears to
be a local maximum, but nowhere near as good a fit as that produced by
StructTS
. It is quite common to find fits with one or more
variances zero, and this can include sigma^2_eps.
Brockwell, P. J. & Davis, R. A. (1996). Introduction to Time Series and Forecasting. Springer, New York. Sections 8.2 and 8.5.
Durbin, J. and Koopman, S. J. (2001) Time Series Analysis by State Space Methods. Oxford University Press.
Harvey, A. C. (1989) Forecasting, Structural Time Series Models and the Kalman Filter. Cambridge University Press.
Harvey, A. C. (1993) Time Series Models. 2nd Edition, Harvester Wheatsheaf.
KalmanLike
, tsSmooth
;
stl
for different kind of (seasonal) decomposition.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17  ## see also JohnsonJohnson, Nile and AirPassengers
require(graphics)
trees < window(treering, start = 0)
(fit < StructTS(trees, type = "level"))
plot(trees)
lines(fitted(fit), col = "green")
tsdiag(fit)
(fit < StructTS(log10(UKgas), type = "BSM"))
par(mfrow = c(4, 1)) # to give appropriate aspect ratio for next plot.
plot(log10(UKgas))
plot(cbind(fitted(fit), resids=resid(fit)), main = "UK gas consumption")
## keep some parameters fixed; trace optimizer:
StructTS(log10(UKgas), type = "BSM", fixed = c(0.1,0.001,NA,NA),
optim.control = list(trace = TRUE))

Questions? Problems? Suggestions? Tweet to @rdrrHQ or email at ian@mutexlabs.com.
All documentation is copyright its authors; we didn't write any of that.