"""
Tests for python wrapper of state space representation and filtering
Author: Chad Fulton
License: Simplified-BSD
References
----------
Kim, Chang-Jin, and Charles R. Nelson. 1999.
"State-Space Models with Regime Switching:
Classical and Gibbs-Sampling Approaches with Applications".
MIT Press Books. The MIT Press.
"""
import pickle
import numpy as np
import pandas as pd
from numpy.testing import assert_equal, assert_allclose
import pytest
from statsmodels.tsa.statespace import sarimax
from statsmodels.tsa.statespace.kalman_filter import KalmanFilter
from statsmodels.tsa.statespace.representation import Representation
from statsmodels.tsa.statespace.structural import UnobservedComponents
from .results import results_kalman_filter
@pytest.fixture()
def data():
true = results_kalman_filter.uc_uni
data_ = pd.DataFrame(
true['data'],
index=pd.date_range('1947-01-01', '1995-07-01', freq='QS'),
columns=['GDP']
)
data_['lgdp'] = np.log(data_['GDP'])
return data_
def test_pickle_fit_sarimax(data):
# Fit an ARIMA(1,1,0) to log GDP
mod = sarimax.SARIMAX(data['lgdp'], order=(1, 1, 0))
pkl_mod = pickle.loads(pickle.dumps(mod))
res = mod.fit(disp=-1, full_output=True, method='newton')
pkl_res = pkl_mod.fit(disp=-1, full_output=True, method='newton')
assert_allclose(res.llf_obs, pkl_res.llf_obs)
assert_allclose(res.tvalues, pkl_res.tvalues)
assert_allclose(res.smoothed_state, pkl_res.smoothed_state)
assert_allclose(res.resid.values, pkl_res.resid.values)
assert_allclose(res.impulse_responses(10), res.impulse_responses(10))
def test_unobserved_components_pickle():
# Tests for missing data
nobs = 20
k_endog = 1
np.random.seed(1208)
endog = np.random.normal(size=(nobs, k_endog))
endog[:4, 0] = np.nan
exog2 = np.random.normal(size=(nobs, 2))
index = pd.date_range('1970-01-01', freq='QS', periods=nobs)
endog_pd = pd.DataFrame(endog, index=index)
exog2_pd = pd.DataFrame(exog2, index=index)
models = [
UnobservedComponents(endog, 'llevel', exog=exog2),
UnobservedComponents(endog_pd, 'llevel', exog=exog2_pd),
]
for mod in models:
# Smoke tests
pkl_mod = pickle.loads(pickle.dumps(mod))
assert_equal(mod.start_params, pkl_mod.start_params)
res = mod.fit(disp=False)
pkl_res = pkl_mod.fit(disp=False)
assert_allclose(res.llf_obs, pkl_res.llf_obs)
assert_allclose(res.tvalues, pkl_res.tvalues)
assert_allclose(res.smoothed_state, pkl_res.smoothed_state)
assert_allclose(res.resid, pkl_res.resid)
assert_allclose(res.impulse_responses(10), res.impulse_responses(10))
def test_kalman_filter_pickle(data):
# Construct the statespace representation
true = results_kalman_filter.uc_uni
k_states = 4
model = KalmanFilter(k_endog=1, k_states=k_states)
model.bind(data['lgdp'].values)
model.design[:, :, 0] = [1, 1, 0, 0]
model.transition[([0, 0, 1, 1, 2, 3],
[0, 3, 1, 2, 1, 3],
[0, 0, 0, 0, 0, 0])] = [1, 1, 0, 0, 1, 1]
model.selection = np.eye(model.k_states)
# Update matrices with given parameters
(sigma_v, sigma_e, sigma_w, phi_1, phi_2) = np.array(
true['parameters']
)
model.transition[([1, 1], [1, 2], [0, 0])] = [phi_1, phi_2]
model.state_cov[
np.diag_indices(k_states) + (np.zeros(k_states, dtype=int),)] = [
sigma_v ** 2, sigma_e ** 2, 0, sigma_w ** 2
]
# Initialization
initial_state = np.zeros((k_states,))
initial_state_cov = np.eye(k_states) * 100
# Initialization: modification
initial_state_cov = np.dot(
np.dot(model.transition[:, :, 0], initial_state_cov),
model.transition[:, :, 0].T
)
model.initialize_known(initial_state, initial_state_cov)
pkl_mod = pickle.loads(pickle.dumps(model))
results = model.filter()
pkl_results = pkl_mod.filter()
assert_allclose(results.llf_obs[true['start']:].sum(),
pkl_results.llf_obs[true['start']:].sum())
assert_allclose(results.filtered_state[0][true['start']:],
pkl_results.filtered_state[0][true['start']:])
assert_allclose(results.filtered_state[1][true['start']:],
pkl_results.filtered_state[1][true['start']:])
assert_allclose(results.filtered_state[3][true['start']:],
pkl_results.filtered_state[3][true['start']:])
def test_representation_pickle():
nobs = 10
k_endog = 2
arr = np.arange(nobs * k_endog).reshape(k_endog, nobs) * 1.
endog = np.asfortranarray(arr)
mod = Representation(endog, k_states=2)
pkl_mod = pickle.loads(pickle.dumps(mod))
assert_equal(mod.nobs, pkl_mod.nobs)
assert_equal(mod.k_endog, pkl_mod.k_endog)
mod._initialize_representation()
pkl_mod._initialize_representation()
assert_equal(mod.design, pkl_mod.design)
assert_equal(mod.obs_intercept, pkl_mod.obs_intercept)
assert_equal(mod.initial_variance, pkl_mod.initial_variance)