1

I am trying to create an affine term structure model derived from statsmodels.tsa.statespace.MLEModel (code below) which is initialized using least squares.

'''

class affine_term_structure(sm.tsa.statespace.MLEModel):
    def __init__(self, yields, tau, k_states=3, **kwargs):
       # Initialize the statespace
       super(affine_term_structure, self).__init__(yields, k_states=k_states, **kwargs)

       self.initialize_known(np.zeros(self.k_states), np.eye(self.k_states) * 10000)

    def update(self, params, **kwargs):
       params = super(dynamic_nelson_siegel, self).update(params, **kwargs)

       # Extract the parameters
       Phi = np.reshape(params[:9], (3, 3))
       k = np.array(params[9:12])
       Sx = np.zeros((3, 3))
       Sx[np.tril_indices(3)] = params[12:18]
       lmbd = params[18]
       sy = params[-1]

       b = self.nss(self.tau, lmbd)

       self['transition'] = Phi  # transition matrix
       self['state_intercept'] = k  # transition offset
       self['state_cov'] = Sx @ Sx.T  # transition covariance. 3x3 SPD matrix

       self['design'] = b  # design matrix
       # self['obs_intercept'] = 0  # observation intercept
       self['obs_cov'] = sy * sy * np.eye(self.k_endog)  # observation covariance

'''

However, I noticed that on running the filter/smoother the states were being excessively smoothed. Digging through the filtering results it seems like the state_cov is not being used in the prediction step.

For example

self.predicted_state_cov[:,:,1]

matches

self.transition[:,:,0] @ self.filtered_state_cov[:,:,0] @ self.transition[:,:,0].T

Though I would have expected it to be equal to

self.transition[:,:,0] @ self.filtered_state_cov[:,:,0] @ self.transition[:,:,0].T + self.state_cov[:,:,0]

For good order, please note that all parameter matrices are time invariant.

Im not sure what Im missing here and any help would be much appreciated.

Thanks

raghav
  • 11
  • 1

1 Answers1

1

In Statsmodels, the state equation is:

x(t+1) = T x(t) + R eta(t+1)

where eta(t+1) ~ N(0, Q)

When you set state_cov, you're setting Q, but you also need to set R, which is selection.

For example, if you want your state equation to be:

x(t+1) = T x(t) + eta(t+1)

Then you would do something like:

self['selection'] = np.eye(3)

It is not the case that R is the identity in every state space model, and it can't even always be initialized to the identity matrix, since the dimension of x(t) and the dimension of eta(t) can be different. That's why R is not automatically initialized to the identity matrix.

cfulton
  • 2,855
  • 2
  • 14
  • 13