33. Classical Prediction and Filtering With Linear Algebra#

33.1. Overview#

This is a sequel to the earlier lecture Classical Control with Linear Algebra.

That lecture used linear algebra – in particular, the LU decomposition – to formulate and solve a class of linear-quadratic optimal control problems.

In this lecture, we’ll be using a closely related decomposition, the Cholesky decomposition, to solve linear prediction and filtering problems.

We exploit the useful fact that there is an intimate connection between two superficially different classes of problems:

  • deterministic linear-quadratic (LQ) optimal control problems

  • linear least squares prediction and filtering problems

The first class of problems involves no randomness, while the second is all about randomness.

Nevertheless, essentially the same mathematics solves both types of problem.

This connection, which is often termed “duality,” is present whether one uses “classical” or “recursive” solution procedures.

In fact, we saw duality at work earlier when we formulated control and prediction problems recursively in lectures LQ dynamic programming problems, A first look at the Kalman filter, and The permanent income model.

A useful consequence of duality is that

  • With every LQ control problem, there is implicitly affiliated a linear least squares prediction or filtering problem.

  • With every linear least squares prediction or filtering problem there is implicitly affiliated a LQ control problem.

An understanding of these connections has repeatedly proved useful in cracking interesting applied problems.

For example, Sargent [Sargent, 1987] [chs. IX, XIV] and Hansen and Sargent [Hansen and Sargent, 1980] formulated and solved control and filtering problems using z-transform methods.

In this lecture, we begin to investigate these ideas by using mostly elementary linear algebra.

This is the main purpose and focus of the lecture.

However, after showing matrix algebra formulas, we’ll summarize classic infinite-horizon formulas built on z-transform and lag operator methods.

And we’ll occasionally refer to some of these formulas from the infinite dimensional problems as we present the finite time formulas and associated linear algebra.

We’ll start with the following standard import:

import numpy as np

33.1.1. References#

Useful references include [Whittle, 1963], [Hansen and Sargent, 1980], [Orfanidis, 1988], [Athanasios and Pillai, 1991], and [Muth, 1960].

33.2. Finite Dimensional Prediction#

Let (x1,x2,,xT)=x be a T×1 vector of random variables with mean Ex=0 and covariance matrix Exx=V.

Here V is a T×T positive definite matrix.

The i,j component Exixj of V is the inner product between xi and xj.

We regard the random variables as being ordered in time so that xt is thought of as the value of some economic variable at time t.

For example, xt could be generated by the random process described by the Wold representation presented in equation (33.16) in the section below on infinite dimensional prediction and filtering.

In that case, Vij is given by the coefficient on zij in the expansion of gx(z)=d(z)d(z1)+h, which equals h+k=0dkdk+ij.

We want to construct j step ahead linear least squares predictors of the form

E^[xT|xTj,xTj+1,,x1]

where E^ is the linear least squares projection operator.

(Sometimes E^ is called the wide-sense expectations operator)

To find linear least squares predictors it is helpful first to construct a T×1 vector ε of random variables that form an orthonormal basis for the vector of random variables x.

The key insight here comes from noting that because the covariance matrix V of x is a positive definite and symmetric, there exists a (Cholesky) decomposition of V such that

V=L1(L1)

and

LVL=I

where L and L1 are both lower triangular.

Form the T×1 random vector ε=Lx.

The random vector ε is an orthonormal basis for x because

  • L is nonsingular

  • Eεε=LExxL=I

  • x=L1ε

It is enlightening to write out and interpret the equations Lx=ε and L1ε=x.

First, we’ll write Lx=ε

(33.1)#L11x1=ε1L21x1+L22x2=ε2LT1x1+LTTxT=εT

or

(33.2)#j=0t1Lt,tjxtj=εt,t=1,2,T

Next, we write L1ε=x

(33.3)#x1=L111ε1x2=L221ε2+L211ε1xT=LTT1εT+LT,T11εT1+LT,11ε1,

or

(33.4)#xt=j=0t1Lt,tj1εtj

where Li,j1 denotes the i,j element of L1.

From (33.2), it follows that εt is in the linear subspace spanned by xt,xt1,,x1.

From (33.4) it follows that that xt is in the linear subspace spanned by εt,εt1,,ε1.

Equation (33.2) forms a sequence of autoregressions that for t=1,,T express xt as linear functions of xs,s=1,,t1 and a random variable (Lt,t)1εt that is orthogonal to each componenent of xs,s=1,,t1.

(Here (Lt,t)1 denotes the reciprocal of Lt,t while Lt,t1 denotes the t,t element of L1).

The equivalence of the subspaces spanned by εt,,ε1 and xt,,x1 means that for t1m1

(33.5)#E^[xtxtm,xtm1,,x1]=E^[xtεtm,εtm1,,ε1]

To proceed, it is useful to drill down and note that for t1m1 we can rewrite (33.4) in the form of the moving average representation

(33.6)#xt=j=0m1Lt,tj1εtj+j=mt1Lt,tj1εtj

Representation (33.6) is an orthogonal decomposition of xt into a part j=mt1Lt,tj1εtj that lies in the space spanned by [xtm,xtm+1,,x1] and an orthogonal component j=mt1Lt,tj1εtj that does not lie in that space but instead in a linear space knowns as its orthogonal complement.

It follows that

E^[xtxtm,xtm1,,x1]=j=0m1Lt,tj1εtj

33.2.1. Implementation#

Here’s the code that computes solutions to LQ control and filtering problems using the methods described here and in Classical Control with Linear Algebra.

import numpy as np
import scipy.stats as spst
import scipy.linalg as la

class LQFilter:

    def __init__(self, d, h, y_m, r=None, h_eps=None, β=None):
        """

        Parameters
        ----------
            d : list or numpy.array (1-D or a 2-D column vector)
                    The order of the coefficients: [d_0, d_1, ..., d_m]
            h : scalar
                    Parameter of the objective function (corresponding to the
                    quadratic term)
            y_m : list or numpy.array (1-D or a 2-D column vector)
                    Initial conditions for y
            r : list or numpy.array (1-D or a 2-D column vector)
                    The order of the coefficients: [r_0, r_1, ..., r_k]
                    (optional, if not defined -> deterministic problem)
            β : scalar
                    Discount factor (optional, default value is one)
        """

        self.h = h
        self.d = np.asarray(d)
        self.m = self.d.shape[0] - 1

        self.y_m = np.asarray(y_m)

        if self.m == self.y_m.shape[0]:
            self.y_m = self.y_m.reshape(self.m, 1)
        else:
            raise ValueError("y_m must be of length m = {self.m:d}")

        #---------------------------------------------
        # Define the coefficients of ϕ upfront
        #---------------------------------------------
        ϕ = np.zeros(2 * self.m + 1)
        for i in range(- self.m, self.m + 1):
            ϕ[self.m - i] = np.sum(np.diag(self.d.reshape(self.m + 1, 1) \
                                           @ self.d.reshape(1, self.m + 1),
                                           k=-i
                                           )
                                    )
        ϕ[self.m] = ϕ[self.m] + self.h
        self.ϕ = ϕ

        #-----------------------------------------------------
        # If r is given calculate the vector ϕ_r
        #-----------------------------------------------------
        if r is None:
            pass
        else:
            self.r = np.asarray(r)
            self.k = self.r.shape[0] - 1
            ϕ_r = np.zeros(2 * self.k + 1)
            for i in range(- self.k, self.k + 1):
                ϕ_r[self.k - i] = np.sum(np.diag(self.r.reshape(self.k + 1, 1) \
                                                 @ self.r.reshape(1, self.k + 1),
                                                 k=-i
                                                 )
                                        )
            if h_eps is None:
                self.ϕ_r = ϕ_r
            else:
                ϕ_r[self.k] = ϕ_r[self.k] + h_eps
                self.ϕ_r = ϕ_r

        #-----------------------------------------------------
        # If β is given, define the transformed variables
        #-----------------------------------------------------
        if β is None:
            self.β = 1
        else:
            self.β = β
            self.d = self.β**(np.arange(self.m + 1)/2) * self.d
            self.y_m = self.y_m * (self.β**(- np.arange(1, self.m + 1)/2)) \
                                   .reshape(self.m, 1)

    def construct_W_and_Wm(self, N):
        """
        This constructs the matrices W and W_m for a given number of periods N
        """

        m = self.m
        d = self.d

        W = np.zeros((N + 1, N + 1))
        W_m = np.zeros((N + 1, m))

        #---------------------------------------
        # Terminal conditions
        #---------------------------------------

        D_m1 = np.zeros((m + 1, m + 1))
        M = np.zeros((m + 1, m))

        # (1) Constuct the D_{m+1} matrix using the formula

        for j in range(m + 1):
            for k in range(j, m + 1):
                D_m1[j, k] = d[:j + 1] @ d[k - j: k + 1]

        # Make the matrix symmetric
        D_m1 = D_m1 + D_m1.T - np.diag(np.diag(D_m1))

        # (2) Construct the M matrix using the entries of D_m1

        for j in range(m):
            for i in range(j + 1, m + 1):
                M[i, j] = D_m1[i - j - 1, m]

        #----------------------------------------------
        # Euler equations for t = 0, 1, ..., N-(m+1)
        #----------------------------------------------
        ϕ = self.ϕ

        W[:(m + 1), :(m + 1)] = D_m1 + self.h * np.eye(m + 1)
        W[:(m + 1), (m + 1):(2 * m + 1)] = M

        for i, row in enumerate(np.arange(m + 1, N + 1 - m)):
            W[row, (i + 1):(2 * m + 2 + i)] = ϕ

        for i in range(1, m + 1):
            W[N - m + i, -(2 * m + 1 - i):] = ϕ[:-i]

        for i in range(m):
            W_m[N - i, :(m - i)] = ϕ[(m + 1 + i):]

        return W, W_m

    def roots_of_characteristic(self):
        """
        This function calculates z_0 and the 2m roots of the characteristic
        equation associated with the Euler equation (1.7)

        Note:
        ------
        numpy.poly1d(roots, True) defines a polynomial using its roots that can
        be evaluated at any point. If x_1, x_2, ... , x_m are the roots then
            p(x) = (x - x_1)(x - x_2)...(x - x_m)
        """
        m = self.m
        ϕ = self.ϕ

        # Calculate the roots of the 2m-polynomial
        roots = np.roots(ϕ)
        # Sort the roots according to their length (in descending order)
        roots_sorted = roots[np.argsort(abs(roots))[::-1]]

        z_0 = ϕ.sum() / np.poly1d(roots, True)(1)
        z_1_to_m = roots_sorted[:m]     # We need only those outside the unit circle

        λ = 1 / z_1_to_m

        return z_1_to_m, z_0, λ

    def coeffs_of_c(self):
        '''
        This function computes the coefficients {c_j, j = 0, 1, ..., m} for
                c(z) = sum_{j = 0}^{m} c_j z^j

        Based on the expression (1.9). The order is
            c_coeffs = [c_0, c_1, ..., c_{m-1}, c_m]
        '''
        z_1_to_m, z_0 = self.roots_of_characteristic()[:2]

        c_0 = (z_0 * np.prod(z_1_to_m).real * (- 1)**self.m)**(.5)
        c_coeffs = np.poly1d(z_1_to_m, True).c * z_0 / c_0

        return c_coeffs[::-1]

    def solution(self):
        """
        This function calculates {λ_j, j=1,...,m} and {A_j, j=1,...,m}
        of the expression (1.15)
        """
        λ = self.roots_of_characteristic()[2]
        c_0 = self.coeffs_of_c()[-1]

        A = np.zeros(self.m, dtype=complex)
        for j in range(self.m):
            denom = 1 - λ/λ[j]
            A[j] = c_0**(-2) / np.prod(denom[np.arange(self.m) != j])

        return λ, A

    def construct_V(self, N):
        '''
        This function constructs the covariance matrix for x^N (see section 6)
        for a given period N
        '''
        V = np.zeros((N, N))
        ϕ_r = self.ϕ_r

        for i in range(N):
            for j in range(N):
                if abs(i-j) <= self.k:
                    V[i, j] = ϕ_r[self.k + abs(i-j)]

        return V

    def simulate_a(self, N):
        """
        Assuming that the u's are normal, this method draws a random path
        for x^N
        """
        V = self.construct_V(N + 1)
        d = spst.multivariate_normal(np.zeros(N + 1), V)

        return d.rvs()

    def predict(self, a_hist, t):
        """
        This function implements the prediction formula discussed in section 6 (1.59)
        It takes a realization for a^N, and the period in which the prediction is 
        formed

        Output:  E[abar | a_t, a_{t-1}, ..., a_1, a_0]
        """

        N = np.asarray(a_hist).shape[0] - 1
        a_hist = np.asarray(a_hist).reshape(N + 1, 1)
        V = self.construct_V(N + 1)

        aux_matrix = np.zeros((N + 1, N + 1))
        aux_matrix[:(t + 1), :(t + 1)] = np.eye(t + 1)
        L = la.cholesky(V).T
        Ea_hist = la.inv(L) @ aux_matrix @ L @ a_hist

        return Ea_hist

    def optimal_y(self, a_hist, t=None):
        """
        - if t is NOT given it takes a_hist (list or numpy.array) as a
          deterministic a_t
        - if t is given, it solves the combined control prediction problem 
          (section 7)(by default, t == None -> deterministic)

        for a given sequence of a_t (either deterministic or a particular
        realization), it calculates the optimal y_t sequence using the method
        of the lecture

        Note:
        ------
        scipy.linalg.lu normalizes L, U so that L has unit diagonal elements
        To make things consistent with the lecture, we need an auxiliary
        diagonal matrix D which renormalizes L and U
        """

        N = np.asarray(a_hist).shape[0] - 1
        W, W_m = self.construct_W_and_Wm(N)

        L, U = la.lu(W, permute_l=True)
        D = np.diag(1 / np.diag(U))
        U = D @ U
        L = L @ np.diag(1 / np.diag(D))

        J = np.fliplr(np.eye(N + 1))

        if t is None:   # If the problem is deterministic

            a_hist = J @ np.asarray(a_hist).reshape(N + 1, 1)

            #--------------------------------------------
            # Transform the 'a' sequence if β is given
            #--------------------------------------------
            if self.β != 1:
                a_hist =  a_hist * (self.β**(np.arange(N + 1) / 2))[::-1] \
                                    .reshape(N + 1, 1)

            a_bar = a_hist - W_m @ self.y_m            # a_bar from the lecture
            Uy = np.linalg.solve(L, a_bar)             # U @ y_bar = L^{-1}
            y_bar = np.linalg.solve(U, Uy)             # y_bar = U^{-1}L^{-1}

            # Reverse the order of y_bar with the matrix J
            J = np.fliplr(np.eye(N + self.m + 1))
            # y_hist : concatenated y_m and y_bar
            y_hist = J @ np.vstack([y_bar, self.y_m])

            #--------------------------------------------
            # Transform the optimal sequence back if β is given
            #--------------------------------------------
            if self.β != 1:
                y_hist = y_hist * (self.β**(- np.arange(-self.m, N + 1)/2)) \
                                    .reshape(N + 1 + self.m, 1)

            return y_hist, L, U, y_bar

        else:           # If the problem is stochastic and we look at it

            Ea_hist = self.predict(a_hist, t).reshape(N + 1, 1)
            Ea_hist = J @ Ea_hist

            a_bar = Ea_hist - W_m @ self.y_m           # a_bar from the lecture
            Uy = np.linalg.solve(L, a_bar)             # U @ y_bar = L^{-1}
            y_bar = np.linalg.solve(U, Uy)             # y_bar = U^{-1}L^{-1}

            # Reverse the order of y_bar with the matrix J
            J = np.fliplr(np.eye(N + self.m + 1))
            # y_hist : concatenated y_m and y_bar
            y_hist = J @ np.vstack([y_bar, self.y_m])

            return y_hist, L, U, y_bar

Let’s use this code to tackle two interesting examples.

33.2.2. Example 1#

Consider a stochastic process with moving average representation

xt=(12L)εt

where εt is a serially uncorrelated random process with mean zero and variance unity.

If we were to use the tools associated with infinite dimensional prediction and filtering to be described below, we would use the Wiener-Kolmogorov formula (33.21) to compute the linear least squares forecasts E[xt+jxt,xt1,], for j=1,2.

But we can do everything we want by instead using our finite dimensional tools and setting d=r, generating an instance of LQFilter, then invoking pertinent methods of LQFilter.

m = 1
y_m = np.asarray([.0]).reshape(m, 1)
d = np.asarray([1, -2])
r = np.asarray([1, -2])
h = 0.0
example = LQFilter(d, h, y_m, r=d)

The Wold representation is computed by example.coeffs_of_c().

Let’s check that it “flips roots” as required

example.coeffs_of_c()
array([ 2., -1.])
example.roots_of_characteristic()
(array([2.]), -2.0, array([0.5]))

Now let’s form the covariance matrix of a time series vector of length N and put it in V.

Then we’ll take a Cholesky decomposition of V=L1L1 and use it to form the vector of “moving average representations” x=L1ε and the vector of “autoregressive representations” Lx=ε.

V = example.construct_V(N=5)
print(V)
[[ 5. -2.  0.  0.  0.]
 [-2.  5. -2.  0.  0.]
 [ 0. -2.  5. -2.  0.]
 [ 0.  0. -2.  5. -2.]
 [ 0.  0.  0. -2.  5.]]

Notice how the lower rows of the “moving average representations” are converging to the appropriate infinite history Wold representation to be described below when we study infinite horizon-prediction and filtering

Li = np.linalg.cholesky(V)
print(Li)
[[ 2.23606798  0.          0.          0.          0.        ]
 [-0.89442719  2.04939015  0.          0.          0.        ]
 [ 0.         -0.97590007  2.01186954  0.          0.        ]
 [ 0.          0.         -0.99410024  2.00293902  0.        ]
 [ 0.          0.          0.         -0.99853265  2.000733  ]]

Notice how the lower rows of the “autoregressive representations” are converging to the appropriate infinite-history autoregressive representation to be described below when we study infinite horizon-prediction and filtering

L = np.linalg.inv(Li)
print(L)
[[0.4472136  0.         0.         0.         0.        ]
 [0.19518001 0.48795004 0.         0.         0.        ]
 [0.09467621 0.23669053 0.49705012 0.         0.        ]
 [0.04698977 0.11747443 0.2466963  0.49926632 0.        ]
 [0.02345182 0.05862954 0.12312203 0.24917554 0.49981682]]

33.2.3. Example 2#

Consider a stochastic process Xt with moving average representation

Xt=(12L2)εt

where εt is a serially uncorrelated random process with mean zero and variance unity.

Let’s find a Wold moving average representation for xt that will prevail in the infinite-history context to be studied in detail below.

To do this, we’ll use the Wiener-Kolomogorov formula (33.21) presented below to compute the linear least squares forecasts E^[Xt+jXt1,] for j=1,2,3.

We proceed in the same way as in example 1

m = 2
y_m = np.asarray([.0, .0]).reshape(m, 1)
d = np.asarray([1, 0, -np.sqrt(2)])
r = np.asarray([1, 0, -np.sqrt(2)])
h = 0.0
example = LQFilter(d, h, y_m, r=d)
example.coeffs_of_c()
array([ 1.41421356, -0.        , -1.        ])
example.roots_of_characteristic()
(array([ 1.18920712, -1.18920712]),
 -1.4142135623731122,
 array([ 0.84089642, -0.84089642]))
V = example.construct_V(N=8)
print(V)
[[ 3.          0.         -1.41421356  0.          0.          0.
   0.          0.        ]
 [ 0.          3.          0.         -1.41421356  0.          0.
   0.          0.        ]
 [-1.41421356  0.          3.          0.         -1.41421356  0.
   0.          0.        ]
 [ 0.         -1.41421356  0.          3.          0.         -1.41421356
   0.          0.        ]
 [ 0.          0.         -1.41421356  0.          3.          0.
  -1.41421356  0.        ]
 [ 0.          0.          0.         -1.41421356  0.          3.
   0.         -1.41421356]
 [ 0.          0.          0.          0.         -1.41421356  0.
   3.          0.        ]
 [ 0.          0.          0.          0.          0.         -1.41421356
   0.          3.        ]]
Li = np.linalg.cholesky(V)
print(Li[-3:, :])
[[ 0.          0.          0.         -0.9258201   0.          1.46385011
   0.          0.        ]
 [ 0.          0.          0.          0.         -0.96609178  0.
   1.43759058  0.        ]
 [ 0.          0.          0.          0.          0.         -0.96609178
   0.          1.43759058]]
L = np.linalg.inv(Li)
print(L)
[[0.57735027 0.         0.         0.         0.         0.
  0.         0.        ]
 [0.         0.57735027 0.         0.         0.         0.
  0.         0.        ]
 [0.3086067  0.         0.65465367 0.         0.         0.
  0.         0.        ]
 [0.         0.3086067  0.         0.65465367 0.         0.
  0.         0.        ]
 [0.19518001 0.         0.41403934 0.         0.68313005 0.
  0.         0.        ]
 [0.         0.19518001 0.         0.41403934 0.         0.68313005
  0.         0.        ]
 [0.13116517 0.         0.27824334 0.         0.45907809 0.
  0.69560834 0.        ]
 [0.         0.13116517 0.         0.27824334 0.         0.45907809
  0.         0.69560834]]

33.2.4. Prediction#

It immediately follows from the “orthogonality principle” of least squares (see [Athanasios and Pillai, 1991] or [Sargent, 1987] [ch. X]) that

(33.7)#E^[xtxtm,xtm+1,x1]=j=mt1Lt,tj1εtj=[Lt,11Lt,21,,Lt,tm1 0 00]Lx

This can be interpreted as a finite-dimensional version of the Wiener-Kolmogorov m-step ahead prediction formula.

We can use (33.7) to represent the linear least squares projection of the vector x conditioned on the first s observations [xs,xs1,x1].

We have

(33.8)#E^[xxs,xs1,,x1]=L1[Is000(ts)]Lx

This formula will be convenient in representing the solution of control problems under uncertainty.

Equation (33.4) can be recognized as a finite dimensional version of a moving average representation.

Equation (33.2) can be viewed as a finite dimension version of an autoregressive representation.

Notice that even if the xt process is covariance stationary, so that V is such that Vij depends only on |ij|, the coefficients in the moving average representation are time-dependent, there being a different moving average for each t.

If xt is a covariance stationary process, the last row of L1 converges to the coefficients in the Wold moving average representation for {xt} as T.

Further, if xt is covariance stationary, for fixed k and j>0,LT,Tj1 converges to LTk,Tkj1 as T.

That is, the “bottom” rows of L1 converge to each other and to the Wold moving average coefficients as T.

This last observation gives one simple and widely-used practical way of forming a finite T approximation to a Wold moving average representation.

First, form the covariance matrix Exx=V, then obtain the Cholesky decomposition L1L1 of V, which can be accomplished quickly on a computer.

The last row of L1 gives the approximate Wold moving average coefficients.

This method can readily be generalized to multivariate systems.

33.3. Combined Finite Dimensional Control and Prediction#

Consider the finite-dimensional control problem, maximize

Et=0N{atyt12hyt212[d(L)yt]2}, h>0

where d(L)=d0+d1L++dmLm, L is the lag operator, a¯=[aN,aN1,a1,a0] a random vector with mean zero and Ea¯a¯=V.

The variables y1,,ym are given.

Maximization is over choices of y0,y1,yN, where yt is required to be a linear function of {yts1,t+m10; ats,ts0}.

We saw in the lecture Classical Control with Linear Algebra that the solution of this problem under certainty could be represented in the feedback-feedforward form

Uy¯=L1a¯+K[y1ym]

for some (N+1)×m matrix K.

Using a version of formula (33.7), we can express E^[a¯as,as1,,a0] as

E^[a¯as,as1,,a0]=U~1[000I(s+1)]U~a¯

where I(s+1) is the (s+1)×(s+1) identity matrix, and V=U~1U~1, where U~ is the upper triangular Cholesky factor of the covariance matrix V.

(We have reversed the time axis in dating the a’s relative to earlier)

The time axis can be reversed in representation (33.8) by replacing L with LT.

The optimal decision rule to use at time 0tN is then given by the (Nt+1)th row of

Uy¯=L1U~1[000I(t+1)]U~a¯+K[y1ym]

33.4. Infinite Horizon Prediction and Filtering Problems#

It is instructive to compare the finite-horizon formulas based on linear algebra decompositions of finite-dimensional covariance matrices with classic formulas for infinite horizon and infinite history prediction and control problems.

These classic infinite horizon formulas used the mathematics of z-transforms and lag operators.

We’ll meet interesting lag operator and z-transform counterparts to our finite horizon matrix formulas.

We pose two related prediction and filtering problems.

We let Yt be a univariate mth order moving average, covariance stationary stochastic process,

(33.9)#Yt=d(L)ut

where d(L)=j=0mdjLj, and ut is a serially uncorrelated stationary random process satisfying

(33.10)#Eut=0Eutus={1 if t=s0 otherwise

We impose no conditions on the zeros of d(z).

A second covariance stationary process is Xt given by

(33.11)#Xt=Yt+εt

where εt is a serially uncorrelated stationary random process with Eεt=0 and Eεtεs = 0 for all distinct t and s.

We also assume that Eεtus=0 for all t and s.

The linear least squares prediction problem is to find the L2 random variable X^t+j among linear combinations of {Xt, Xt1,} that minimizes E(X^t+jXt+j)2.

That is, the problem is to find a γj(L)=k=0γjkLk such that k=0|γjk|2< and E[γj(L)XtXt+j]2 is minimized.

The linear least squares filtering problem is to find a b(L)=j=0bjLj such that j=0|bj|2< and E[b(L)XtYt]2 is minimized.

Interesting versions of these problems related to the permanent income theory were studied by [Muth, 1960].

33.4.1. Problem Formulation#

These problems are solved as follows.

The covariograms of Y and X and their cross covariogram are, respectively,

(33.12)#CX(τ)=EXtXtτCY(τ)=EYtYtττ=0,±1,±2,CY,X(τ)=EYtXtτ

The covariance and cross-covariance generating functions are defined as

(33.13)#gX(z)=τ=CX(τ)zτgY(z)=τ=CY(τ)zτgYX(z)=τ=CYX(τ)zτ

The generating functions can be computed by using the following facts.

Let v1t and v2t be two mutually and serially uncorrelated white noises with unit variances.

That is, Ev1t2=Ev2t2=1,Ev1t=Ev2t=0,Ev1tv2s=0 for all t and s, Ev1tv1tj=Ev2tv2tj=0 for all j0.

Let xt and yt be two random processes given by

yt=A(L)v1t+B(L)v2txt=C(L)v1t+D(L)v2t

Then, as shown for example in [Sargent, 1987] [ch. XI], it is true that

(33.14)#gy(z)=A(z)A(z1)+B(z)B(z1)gx(z)=C(z)C(z1)+D(z)D(z1)gyx(z)=A(z)C(z1)+B(z)D(z1)

Applying these formulas to (33.9)(33.12), we have

(33.15)#gY(z)=d(z)d(z1)gX(z)=d(z)d(z1)+hgYX(z)=d(z)d(z1)

The key step in obtaining solutions to our problems is to factor the covariance generating function gX(z) of X.

The solutions of our problems are given by formulas due to Wiener and Kolmogorov.

These formulas utilize the Wold moving average representation of the Xt process,

(33.16)#Xt=c(L)ηt

where c(L)=j=0mcjLj, with

(33.17)#c0ηt=XtE^[Xt|Xt1,Xt2,]

Here E^ is the linear least squares projection operator.

Equation (33.17) is the condition that c0ηt can be the one-step-ahead error in predicting Xt from its own past values.

Condition (33.17) requires that ηt lie in the closed linear space spanned by [Xt, Xt1,].

This will be true if and only if the zeros of c(z) do not lie inside the unit circle.

It is an implication of (33.17) that ηt is a serially uncorrelated random process and that normalization can be imposed so that Eηt2=1.

Consequently, an implication of (33.16) is that the covariance generating function of Xt can be expressed as

(33.18)#gX(z)=c(z)c(z1)

It remains to discuss how c(L) is to be computed.

Combining (33.14) and (33.18) gives

(33.19)#d(z)d(z1)+h=c(z)c(z1)

Therefore, we have already shown constructively how to factor the covariance generating function gX(z)=d(z)d(z1)+h.

We now introduce the annihilation operator:

(33.20)#[j=fjLj]+j=0fjLj

In words, [00]+ means “ignore negative powers of L”.

We have defined the solution of the prediction problem as E^[Xt+j|Xt,Xt1,]=γj(L)Xt.

Assuming that the roots of c(z)=0 all lie outside the unit circle, the Wiener-Kolmogorov formula for γj(L) holds:

(33.21)#γj(L)=[c(L)Lj]+c(L)1

We have defined the solution of the filtering problem as E^[YtXt,Xt1,]=b(L)Xt.

The Wiener-Kolomogorov formula for b(L) is

b(L)=[gYX(L)c(L1)]+c(L)1

or

(33.22)#b(L)=[d(L)d(L1)c(L1)]+c(L)1

Formulas (33.21) and (33.22) are discussed in detail in [Whittle, 1983] and [Sargent, 1987].

The interested reader can there find several examples of the use of these formulas in economics Some classic examples using these formulas are due to [Muth, 1960].

As an example of the usefulness of formula (33.22), we let Xt be a stochastic process with Wold moving average representation

Xt=c(L)ηt

where Eηt2=1, and c0ηt=XtE^[Xt|Xt1,],c(L)=j=0mcjL.

Suppose that at time t, we wish to predict a geometric sum of future X’s, namely

ytj=0δjXt+j=11δL1Xt

given knowledge of Xt,Xt1,.

We shall use (33.22) to obtain the answer.

Using the standard formulas (33.14), we have that

gyx(z)=(1δz1)c(z)c(z1)gx(z)=c(z)c(z1)

Then (33.22) becomes

(33.23)#b(L)=[c(L)1δL1]+c(L)1

In order to evaluate the term in the annihilation operator, we use the following result from [Hansen and Sargent, 1980].

Proposition Let

  • g(z)=j=0gjzj where j=0|gj|2<+.

  • h(z1)= (1δ1z1)(1δnz1), where |δj|<1, for j=1,,n.

Then

(33.24)#[g(z)h(z1)]+=g(z)h(z1)j=1n δjg(δj)k=1kjn(δjδk) (1zδj)

and, alternatively,

(33.25)#[g(z)h(z1)]+=j=1nBj(zg(z)δjg(δj)zδj)

where Bj=1/k=1k+jn(1δk/δj).

Applying formula (33.25) of the proposition to evaluating (33.23) with g(z)=c(z) and h(z1)=1δz1 gives

b(L)=[Lc(L)δc(δ)Lδ]c(L)1

or

b(L)=[1δc(δ)L1c(L)11δL1]

Thus, we have

(33.26)#E^[j=0δjXt+j|Xt,xt1,]=[1δc(δ)L1c(L)11δL1]Xt

This formula is useful in solving stochastic versions of problem 1 of lecture Classical Control with Linear Algebra in which the randomness emerges because {at} is a stochastic process.

The problem is to maximize

(33.27)#E0limN t0Nβt[atyt12 hyt212 [d(L)yt]2]

where Et is mathematical expectation conditioned on information known at t, and where {at} is a covariance stationary stochastic process with Wold moving average representation

at=c(L)ηt

where

c(L)=j=0n~cjLj

and

ηt=atE^[at|at1,]

The problem is to maximize (33.27) with respect to a contingency plan expressing yt as a function of information known at t, which is assumed to be (yt1, yt2,,at, at1,).

The solution of this problem can be achieved in two steps.

First, ignoring the uncertainty, we can solve the problem assuming that {at} is a known sequence.

The solution is, from above,

c(L)yt=c(βL1)1at

or

(33.28)#(1λ1L)(1λmL)yt=j=1mAjk=0(λjβ)kat+k

Second, the solution of the problem under uncertainty is obtained by replacing the terms on the right-hand side of the above expressions with their linear least squares predictors.

Using (33.26) and (33.28), we have the following solution

(1λ1L)(1λmL)yt=j=1mAj[1βλjc(βλj)L1c(L)11βλjL1]at

Blaschke factors

The following is a useful piece of mathematics underlying “root flipping”.

Let π(z)=j=0mπjzj and let z1,,zk be the zeros of π(z) that are inside the unit circle, k<m.

Then define

θ(z)=π(z)((z1z1)(zz1))((z2z1)(zz2))((zkz1)(zzk))

The term multiplying π(z) is termed a “Blaschke factor”.

Then it can be proved directly that

θ(z1)θ(z)=π(z1)π(z)

and that the zeros of θ(z) are not inside the unit circle.

33.5. Exercises#

Exercise 33.1

Let Yt=(12L)ut where ut is a mean zero white noise with Eut2=1. Let

Xt=Yt+εt

where εt is a serially uncorrelated white noise with Eεt2=9, and Eεtus=0 for all t and s.

Find the Wold moving average representation for Xt.

Find a formula for the A1j’s in

EX^t+1Xt,Xt1,=j=0A1jXtj

Find a formula for the A2j’s in

E^Xt+2Xt,Xt1,=j=0A2jXtj

Exercise 33.2

Multivariable Prediction: Let Yt be an (n×1) vector stochastic process with moving average representation

Yt=D(L)Ut

where D(L)=j=0mDjLJ,Dj an n×n matrix, Ut an (n×1) vector white noise with EUt=0 for all t, EUtUs=0 for all st, and EUtUt=I for all t.

Let εt be an n×1 vector white noise with mean 0 and contemporaneous covariance matrix H, where H is a positive definite matrix.

Let Xt=Yt+εt.

Define the covariograms as CX(τ)=EXtXtτ,CY(τ)=EYtYtτ,CYX(τ)=EYtXtτ.

Then define the matrix covariance generating function, as in (32.21), only interpret all the objects in (32.21) as matrices.

Show that the covariance generating functions are given by

gy(z)=D(z)D(z1)gX(z)=D(z)D(z1)+HgYX(z)=D(z)D(z1)

A factorization of gX(z) can be found (see [Rozanov, 1967] or [Whittle, 1983]) of the form

D(z)D(z1)+H=C(z)C(z1),C(z)=j=0mCjzj

where the zeros of |C(z)| do not lie inside the unit circle.

A vector Wold moving average representation of Xt is then

Xt=C(L)ηt

where ηt is an (n×1) vector white noise that is “fundamental” for Xt.

That is, XtE^[XtXt1,Xt2]=C0ηt.

The optimum predictor of Xt+j is

E^[Xt+jXt,Xt1,]=[C(L)Lj]+ηt

If C(L) is invertible, i.e., if the zeros of det C(z) lie strictly outside the unit circle, then this formula can be written

E^[Xt+jXt,Xt1,]=[C(L)LJ]+C(L)1Xt