def test_dynamic_factor(): steps = 10 exog = np.random.normal(size=steps) # DFM: 2 series, AR(2) factor mod1 = dynamic_factor.DynamicFactor([[0, 0]], k_factors=1, factor_order=2) mod2 = sarimax.SARIMAX([0], order=(2, 0, 0)) actual = mod1.impulse_responses([-0.9, 0.8, 1., 1., 0.5, 0.2], steps) desired = mod2.impulse_responses([0.5, 0.2, 1], steps) assert_allclose(actual[:, 0], -0.9 * desired) assert_allclose(actual[:, 1], 0.8 * desired) # DFM: 2 series, AR(2) factor, exog mod1 = dynamic_factor.DynamicFactor(np.zeros((steps, 2)), k_factors=1, factor_order=2, exog=exog) mod2 = sarimax.SARIMAX([0], order=(2, 0, 0)) actual = mod1.impulse_responses([-0.9, 0.8, 5, -2, 1., 1., 0.5, 0.2], steps) desired = mod2.impulse_responses([0.5, 0.2, 1], steps) assert_allclose(actual[:, 0], -0.9 * desired) assert_allclose(actual[:, 1], 0.8 * desired) # DFM, 3 series, VAR(2) factor, exog, error VAR # TODO: This is just a smoke test mod = dynamic_factor.DynamicFactor(np.random.normal(size=(steps, 3)), k_factors=2, factor_order=2, exog=exog, error_order=2, error_var=True, enforce_stationarity=False) mod.impulse_responses(mod.start_params, steps)
def test_recreate_model(): nobs = 100 endog = np.ones((nobs, 3)) * 2.0 exog = np.ones(nobs) k_factors = [0, 1, 2] factor_orders = [0, 1, 2] error_orders = [0, 1] error_vars = [False, True] error_cov_types = ['diagonal', 'scalar'] import itertools names = [ 'k_factors', 'factor_order', 'error_order', 'error_var', 'error_cov_type' ] for element in itertools.product(k_factors, factor_orders, error_orders, error_vars, error_cov_types): kwargs = dict(zip(names, element)) mod = dynamic_factor.DynamicFactor(endog, exog=exog, **kwargs) mod2 = dynamic_factor.DynamicFactor(endog, exog=exog, **mod._get_init_kwds()) check_equivalent_models(mod, mod2)
def test_dynamic_factor_time_varying(revisions, updates): # This is primarily a test that the `news` method works with a time-varying # setup (i.e. time-varying state space matrices). It tests a time-varying # DynamicFactor model where the time-varying component has been set to # zeros against a time-invariant version of the model. # Construct previous and updated datasets endog = dta[['realgdp', 'unemp']].copy() endog['realgdp'] = np.log(endog['realgdp']).diff() * 400 endog = endog.iloc[1:] comparison_type = None if updates: endog1 = endog.loc[:'2009Q2'].copy() endog2 = endog.loc[:'2009Q3'].copy() else: endog1 = endog.loc[:'2009Q3'].copy() endog2 = endog.loc[:'2009Q3'].copy() # Without updates and without NaN values, we need to specify that # the type of the comparison object that we're passing is "updated" comparison_type = 'updated' if revisions: # TODO: add test for only one of the variables revising? endog1.iloc[-1] = 0. exog1 = np.ones_like(endog1['realgdp']) exog2 = np.ones_like(endog2['realgdp']) params1 = np.r_[0.9, 0.2, 0.0, 0.0, 1.2, 1.1, 0.5, 0.2] params2 = np.r_[0.9, 0.2, 1.2, 1.1, 0.5, 0.2] # Compute the news from a model with an exog term (so the model is # time-varying), but with the coefficient set to zero (so that it will be # equivalent to the time-invariant model) mod1 = dynamic_factor.DynamicFactor(endog1, exog=exog1, k_factors=1, factor_order=2) res1 = mod1.smooth(params1) news1 = res1.news(endog2, exog=exog2, start='2008Q1', end='2009Q3', comparison_type=comparison_type) # Compute the news from a model without a trend term mod2 = dynamic_factor.DynamicFactor(endog1, k_factors=1, factor_order=2) res2 = mod2.smooth(params2) news2 = res2.news(endog2, start='2008Q1', end='2009Q3', comparison_type=comparison_type) attrs = ['total_impacts', 'update_impacts', 'revision_impacts', 'news', 'weights', 'update_forecasts', 'update_realized', 'prev_impacted_forecasts', 'post_impacted_forecasts', 'revisions_iloc', 'revisions_ix', 'updates_iloc', 'updates_ix'] for attr in attrs: w = getattr(news1, attr) x = getattr(news2, attr) if isinstance(x, pd.Series): assert_series_equal(w, x) else: assert_frame_equal(w, x)
def test_dynamic_factor(): np.random.seed(93739) nobs = 100 eps = np.random.normal(size=nobs) exog = np.random.normal(size=(nobs, 1)) eps1 = np.zeros(nobs) eps2 = np.zeros(nobs) eps2[49] = 1 eps3 = np.zeros(nobs) eps3[50:] = 1 # DFM: 2 series, AR(2) factor mod1 = dynamic_factor.DynamicFactor([[0, 0]], k_factors=1, factor_order=2) mod2 = sarimax.SARIMAX([0], order=(2, 0, 0)) actual = mod1.simulate([-0.9, 0.8, 1., 1., 0.5, 0.2], nobs, measurement_shocks=np.c_[eps1, eps1], state_shocks=eps, initial_state=np.zeros(mod1.k_states)) desired = mod2.simulate([0.5, 0.2, 1], nobs, state_shocks=eps, initial_state=np.zeros(mod2.k_states)) assert_allclose(actual[:, 0], -0.9 * desired) assert_allclose(actual[:, 1], 0.8 * desired) # DFM: 2 series, AR(2) factor, exog mod1 = dynamic_factor.DynamicFactor(np.zeros((nobs, 2)), k_factors=1, factor_order=2, exog=exog) mod2 = sarimax.SARIMAX([0], order=(2, 0, 0)) actual = mod1.simulate([-0.9, 0.8, 5, -2, 1., 1., 0.5, 0.2], nobs, measurement_shocks=np.c_[eps1, eps1], state_shocks=eps, initial_state=np.zeros(mod1.k_states)) desired = mod2.simulate([0.5, 0.2, 1], nobs, state_shocks=eps, initial_state=np.zeros(mod2.k_states)) assert_allclose(actual[:, 0], -0.9 * desired + 5 * exog[:, 0]) assert_allclose(actual[:, 1], 0.8 * desired - 2 * exog[:, 0]) # DFM, 3 series, VAR(2) factor, exog, error VAR # TODO: This is just a smoke test mod = dynamic_factor.DynamicFactor(np.random.normal(size=(nobs, 3)), k_factors=2, factor_order=2, exog=exog, error_order=2, error_var=True) mod.simulate(mod.start_params, nobs)
def test_start_params_nans(): ix = pd.date_range('1960-01-01', '1982-10-01', freq='QS') dta = np.log( pd.DataFrame(results_varmax.lutkepohl_data, columns=['inv', 'inc', 'consump'], index=ix)).diff().iloc[1:] endog1 = dta.iloc[:-1] mod1 = dynamic_factor.DynamicFactor(endog1, k_factors=1, factor_order=1) endog2 = dta.copy() endog2.iloc[-1:] = np.nan mod2 = dynamic_factor.DynamicFactor(endog2, k_factors=1, factor_order=1) assert_allclose(mod2.start_params, mod1.start_params)
def test_memory_no_likelihood_multivariate_extra(univariate, diffuse, collapsed): # Test with multivariate data, missing values, and collapsed approach endog = dta[['infl', 'realint']].iloc[:20].copy() endog.iloc[0, 0] = np.nan endog.iloc[4:6, :] = np.nan mod = dynamic_factor.DynamicFactor(endog, k_factors=1, factor_order=1) if diffuse: mod.ssm.initialize_diffuse() if univariate: mod.ssm.filter_univariate = True if collapsed: mod.ssm.filter_collapsed = True params = [4, -4.5, 0.8, 0.9, -0.5] res1 = mod.filter(params) mod.ssm.memory_no_likelihood = True res2 = mod.filter(params) # Check that we really did conserve memory in the second case assert_equal(len(res1.llf_obs), 20) assert_equal(res2.llf_obs, None) # Check that the loglikelihood computations are identical assert_allclose(res1.llf, res2.llf)
def setup_class(cls, true, k_factors, factor_order, cov_type='approx', included_vars=['dln_inv', 'dln_inc', 'dln_consump'], demean=False, filter=True, **kwargs): cls.true = true # 1960:Q1 - 1982:Q4 dta = pd.DataFrame(results_varmax.lutkepohl_data, columns=['inv', 'inc', 'consump'], index=pd.date_range('1960-01-01', '1982-10-01', freq='QS')) dta['dln_inv'] = np.log(dta['inv']).diff() dta['dln_inc'] = np.log(dta['inc']).diff() dta['dln_consump'] = np.log(dta['consump']).diff() endog = dta.loc['1960-04-01':'1978-10-01', included_vars] if demean: endog -= dta.iloc[1:][included_vars].mean() cls.model = dynamic_factor.DynamicFactor(endog, k_factors=k_factors, factor_order=factor_order, **kwargs) if filter: cls.results = cls.model.smooth(true['params'], cov_type=cov_type)
def test_predict_custom_index(): np.random.seed(328423) endog = pd.DataFrame(np.random.normal(size=(50, 2))) mod = dynamic_factor.DynamicFactor(endog, k_factors=1, factor_order=1) res = mod.smooth(mod.start_params) out = res.predict(start=1, end=1, index=['a']) assert_equal(out.index.equals(pd.Index(['a'])), True)
def test_forecast_exog(): # Test forecasting with various shapes of `exog` nobs = 100 endog = np.ones((nobs, 2)) * 2.0 exog = np.ones(nobs) mod = dynamic_factor.DynamicFactor(endog, exog=exog, k_factors=1, factor_order=1) res = mod.smooth(np.r_[[0] * 2, 2.0, 2.0, 1, 1., 0.]) # 1-step-ahead, valid exog_fcast_scalar = 1. exog_fcast_1dim = np.ones(1) exog_fcast_2dim = np.ones((1, 1)) assert_allclose(res.forecast(1, exog=exog_fcast_scalar), 2.) assert_allclose(res.forecast(1, exog=exog_fcast_1dim), 2.) assert_allclose(res.forecast(1, exog=exog_fcast_2dim), 2.) # h-steps-ahead, valid h = 10 exog_fcast_1dim = np.ones(h) exog_fcast_2dim = np.ones((h, 1)) assert_allclose(res.forecast(h, exog=exog_fcast_1dim), 2.) assert_allclose(res.forecast(h, exog=exog_fcast_2dim), 2.) # h-steps-ahead, invalid assert_raises(ValueError, res.forecast, h, exog=1.) assert_raises(ValueError, res.forecast, h, exog=[1, 2]) assert_raises(ValueError, res.forecast, h, exog=np.ones((h, 2)))
def __init__(self, true, k_factors, factor_order, cov_type='oim', included_vars=['dln_inv', 'dln_inc', 'dln_consump'], demean=False, filter=True, **kwargs): self.true = true # 1960:Q1 - 1982:Q4 dta = pd.DataFrame(results_varmax.lutkepohl_data, columns=['inv', 'inc', 'consump'], index=pd.date_range('1960-01-01', '1982-10-01', freq='QS')) dta['dln_inv'] = np.log(dta['inv']).diff() dta['dln_inc'] = np.log(dta['inc']).diff() dta['dln_consump'] = np.log(dta['consump']).diff() endog = dta.ix['1960-04-01':'1978-10-01', included_vars] if demean: endog -= dta.ix[1:, included_vars].mean() self.model = dynamic_factor.DynamicFactor(endog, k_factors=k_factors, factor_order=factor_order, **kwargs) if filter: self.results = self.model.filter(true['params'], cov_type=cov_type)
def test_dynamic_factor_diag_error_cov(): # Can test fixing the off-diagonal error covariance parameters to zeros # with `error_cov_type='unstructured'` against the case # `error_cov_type='diagonal'`. endog = np.log(macrodata[['cpi', 'realgdp']]).diff().iloc[1:] endog = (endog - endog.mean()) / endog.std() # Basic model mod1 = dynamic_factor.DynamicFactor(endog, k_factors=1, factor_order=1, error_cov_type='diagonal') mod2 = dynamic_factor.DynamicFactor(endog, k_factors=1, factor_order=1, error_cov_type='unstructured') constraints = {'cov.chol[2,1]': 0} # Start pretty close to optimum to speed up test start_params = [-4.5e-06, -1.0e-05, 9.9e-01, 9.9e-01, -1.4e-01] res1 = mod1.fit(start_params=start_params, disp=False) res2 = mod2.fit_constrained(constraints, start_params=res1.params, includes_fixed=False, disp=False) # Check that the right parameters were fixed assert_equal(res1.fixed_params, []) assert_equal(res2.fixed_params, ['cov.chol[2,1]']) # Check that MLE finds the same parameters in either case # (need to account for the fact that diagonal params are variances but # unstructured params are standard deviations) params = np.r_[res1.params[:2], res1.params[2:4]**0.5, res1.params[4]] desired = np.r_[params[:3], 0, params[3:]] assert_allclose(res2.params, desired, atol=1e-5) # Now smooth at the actual parameters (to allow high precision testing # below, even if there are small differences between MLE fitted parameters) with mod2.fix_params(constraints): res2 = mod2.smooth(params) # Can't check some parameters-related values because of the different # parameterization (i.e. cov_params, bse, pvalues, etc. won't match). check_results(res1, res2, check_params=False)
def test_known_initialization(): # Need to test that "known" initialization is taken into account in # time series simulation np.random.seed(38947) nobs = 100 eps = np.random.normal(size=nobs) eps1 = np.zeros(nobs) eps2 = np.zeros(nobs) eps2[49] = 1 eps3 = np.zeros(nobs) eps3[50:] = 1 # SARIMAX # (test that when state shocks are shut down, the initial state # geometrically declines according to the AR parameter) mod = sarimax.SARIMAX([0], order=(1, 0, 0)) mod.ssm.initialize_known([100], [[0]]) actual = mod.simulate([0.5, 1.], nobs, state_shocks=eps1) assert_allclose(actual, 100 * 0.5**np.arange(nobs)) # Unobserved components # (test that the initial level shifts the entire path) mod = structural.UnobservedComponents([0], 'local level') mod.ssm.initialize_known([100], [[0]]) actual = mod.simulate([1., 1.], nobs, measurement_shocks=eps, state_shocks=eps2) assert_allclose(actual, 100 + eps + eps3) # VARMAX # (here just test that with an independent VAR we have each initial state # geometrically declining at the appropriate rate) transition = np.diag([0.5, 0.2]) mod = varmax.VARMAX([[0, 0]], order=(1, 0), trend='nc') mod.initialize_known([100, 50], np.diag([0, 0])) actual = mod.simulate(np.r_[transition.ravel(), 1., 0, 1.], nobs, measurement_shocks=np.c_[eps1, eps1], state_shocks=np.c_[eps1, eps1]) assert_allclose( actual, np.c_[100 * 0.5**np.arange(nobs), 50 * 0.2**np.arange(nobs)]) # Dynamic factor # (test that the initial state declines geometrically and then loads # correctly onto the series) mod = dynamic_factor.DynamicFactor([[0, 0]], k_factors=1, factor_order=1) mod.initialize_known([100], [[0]]) print(mod.param_names) actual = mod.simulate([0.8, 0.2, 1.0, 1.0, 0.5], nobs, measurement_shocks=np.c_[eps1, eps1], state_shocks=eps1) tmp = 100 * 0.5**np.arange(nobs) assert_allclose(actual, np.c_[0.8 * tmp, 0.2 * tmp])
def test_dfm(missing=None): mod = dynamic_factor.DynamicFactor(dta, k_factors=2, factor_order=1) mod.update(mod.start_params) sim_cfa = mod.simulation_smoother(method='cfa') res = mod.ssm.smooth() # Test zero variates sim_cfa.simulate(np.zeros((mod.k_states, mod.nobs))) assert_allclose(sim_cfa.simulated_state, res.smoothed_state)
def test_apply_results(): endog = np.arange(200).reshape(100, 2) exog = np.ones(100) params = [0.1, -0.2, 1., 2., 1., 1., 0.5, 0.1] mod1 = dynamic_factor.DynamicFactor(endog[:50], k_factors=1, factor_order=2, exog=exog[:50]) res1 = mod1.smooth(params) mod2 = dynamic_factor.DynamicFactor(endog[50:], k_factors=1, factor_order=2, exog=exog[50:]) res2 = mod2.smooth(params) res3 = res2.apply(endog[:50], exog=exog[:50]) assert_equal(res1.specification, res3.specification) for attr in [ 'nobs', 'llf', 'llf_obs', 'loglikelihood_burn', 'cov_params_default' ]: assert_equal(getattr(res3, attr), getattr(res1, attr)) for attr in [ 'filtered_state', 'filtered_state_cov', 'predicted_state', 'predicted_state_cov', 'forecasts', 'forecasts_error', 'forecasts_error_cov', 'standardized_forecasts_error', 'forecasts_error_diffuse_cov', 'predicted_diffuse_state_cov', 'scaled_smoothed_estimator', 'scaled_smoothed_estimator_cov', 'smoothing_error', 'smoothed_state', 'smoothed_state_cov', 'smoothed_state_autocov', 'smoothed_measurement_disturbance', 'smoothed_state_disturbance', 'smoothed_measurement_disturbance_cov', 'smoothed_state_disturbance_cov' ]: assert_equal(getattr(res3, attr), getattr(res1, attr)) assert_allclose(res3.forecast(10, exog=np.ones(10)), res1.forecast(10, exog=np.ones(10)))
def test_dynamic_factor(temp_filename): mod = dynamic_factor.DynamicFactor(macrodata[['realgdp', 'realcons' ]].diff().iloc[1:].values, k_factors=1, factor_order=1) res = mod.smooth(mod.start_params) res.summary() res.save(temp_filename) res2 = dynamic_factor.DynamicFactorResults.load(temp_filename) assert_allclose(res.params, res2.params) assert_allclose(res.bse, res2.bse) assert_allclose(res.llf, res2.llf)
def test_extend_results(): endog = np.arange(200).reshape(100, 2) exog = np.ones(100) params = [0.1, -0.2, 1., 2., 1., 1., 0.5, 0.1] mod1 = dynamic_factor.DynamicFactor(endog, k_factors=1, factor_order=2, exog=exog) res1 = mod1.smooth(params) mod2 = dynamic_factor.DynamicFactor(endog[:50], k_factors=1, factor_order=2, exog=exog[:50]) res2 = mod2.smooth(params) res3 = res2.extend(endog[50:], exog=exog[50:]) assert_allclose(res3.llf_obs, res1.llf_obs[50:]) for attr in [ 'filtered_state', 'filtered_state_cov', 'predicted_state', 'predicted_state_cov', 'forecasts', 'forecasts_error', 'forecasts_error_cov', 'standardized_forecasts_error', 'forecasts_error_diffuse_cov', 'predicted_diffuse_state_cov', 'scaled_smoothed_estimator', 'scaled_smoothed_estimator_cov', 'smoothing_error', 'smoothed_state', 'smoothed_state_cov', 'smoothed_state_autocov', 'smoothed_measurement_disturbance', 'smoothed_state_disturbance', 'smoothed_measurement_disturbance_cov', 'smoothed_state_disturbance_cov' ]: desired = getattr(res1, attr) if desired is not None: desired = desired[..., 50:] assert_equal(getattr(res3, attr), desired) assert_allclose(res3.forecast(10, exog=np.ones(10)), res1.forecast(10, exog=np.ones(10)))
def test_dfm_missing(reset_randomstate): # This test is not captured by the TestTrivariate and TestDFM tests above # because it has k_states = 1 endog = np.random.normal(size=(100, 3)) endog[0, :1] = np.nan mod = dynamic_factor.DynamicFactor(endog, k_factors=1, factor_order=1) mod.ssm.filter_collapsed = True res = mod.smooth(mod.start_params) mod.ssm.filter_collapsed = False res2 = mod.smooth(mod.start_params) assert_allclose(res.llf, res2.llf)
def simulate_k_factor1(nobs=1000): mod_sim = dynamic_factor.DynamicFactor(np.zeros((1, 4)), k_factors=1, factor_order=1, error_order=1) loadings = [1.0, -0.75, 0.25, -0.3, 0.5] p = np.r_[loadings[:mod_sim.k_endog], [10] * mod_sim.k_endog, 0.5, [0.] * mod_sim.k_endog] ix = pd.period_range(start='1935-01', periods=nobs, freq='M') endog = pd.DataFrame(mod_sim.simulate(p, nobs), index=ix) true = pd.Series(p, index=mod_sim.param_names) # Compute levels series (M and Q) ix = pd.period_range(start=endog.index[0] - 1, end=endog.index[-1], freq=endog.index.freq) levels_M = 1 + endog.reindex(ix) / 100 levels_M.iloc[0] = 100 levels_M = levels_M.cumprod() log_levels_M = np.log(levels_M) * 100 log_levels_Q = ( np.log(levels_M).resample('Q', convention='e').sum().iloc[:-1] * 100) # This is an alternative way to compute the quarterly levels # endog_M = endog.iloc[:, :3] # x = endog.iloc[:, 3:] # endog_Q = (x + 2 * x.shift(1) + 3 * x.shift(2) + 2 * x.shift(3) + # x.shift(4)).resample('Q', convention='e').last().iloc[:-1] / 3 # levels_Q = 1 + endog.iloc[:, 3:] / 100 # levels_Q.iloc[0] = 100 # Here is another alternative way to compute the quarterly levels # weights = np.array([1, 2, 3, 2, 1]) # def func(x, weights): # return np.sum(weights * x) # r = endog_M.rolling(5) # (r.apply(func, args=(weights,), raw=False).resample('Q', convention='e') # .last().iloc[:-1].tail()) # Compute the growth rate series that we'll actually run the model on endog_M = log_levels_M.iloc[:, :3].diff() endog_Q = log_levels_Q.iloc[:, 3:].diff() return endog_M, endog_Q, log_levels_M, log_levels_Q, true
def test_dynamic_factor(missing, periods): endog = np.array([[0.5, 1.2, -0.2, 0.3, -0.1, 0.4, 1.4, 0.9], [-0.2, -0.3, -0.1, 0.1, 0.01, 0.05, -0.13, -0.2]]).T exog = np.ones_like(endog[:, 0]) if missing == 'init': endog[0:2, :] = np.nan elif missing == 'mixed': endog[2:4, 0] = np.nan endog[3:6, 1] = np.nan elif missing == 'all': endog[:] = np.nan mod = dynamic_factor.DynamicFactor(endog, k_factors=1, factor_order=2, exog=exog) mod.update([1.0, -0.5, 0.3, -0.1, 1.2, 2.3, 0.5, 0.1]) check_filter_output(mod, periods) check_smoother_output(mod, periods)
def test_dynamic_factor_invalid(): # Test for invalid uses of parameter fixing endog = np.log(macrodata[['cpi', 'realgdp', 'realinv']]).diff().iloc[1:] endog = (endog - endog.mean()) / endog.std() # Basic model mod1 = dynamic_factor.DynamicFactor( endog, k_factors=1, factor_order=1, error_cov_type='diagonal') # Check loading constraints = {'loading.f1.cpi': 0.5} with mod1.fix_params(constraints): assert_(mod1._has_fixed_params) assert_equal(mod1._fixed_params, constraints) assert_equal(mod1._fixed_params_index, [0]) assert_equal(mod1._free_params_index, [1, 2, 3, 4, 5, 6]) res1 = mod1.fit_constrained(constraints, disp=False) assert_(res1._has_fixed_params) assert_equal(res1._fixed_params, constraints) assert_equal(res1._fixed_params_index, [0]) assert_equal(res1._free_params_index, [1, 2, 3, 4, 5, 6]) # With k_factors=1 and factor_order=1, we can fix the factor AR coefficient # even with `enforce_stationarity=True`. # Fix factor AR coefficient with mod1.fix_params({'L1.f1.f1': 0.5}): assert_(mod1._has_fixed_params) assert_equal(mod1._fixed_params, {'L1.f1.f1': 0.5}) assert_equal(mod1._fixed_params_index, [6]) assert_equal(mod1._free_params_index, [0, 1, 2, 3, 4, 5]) # With k_factors > 1 or factor_order > 1, we can only fix the entire set of # factor AR coefficients when `enforce_stationarity=True`. mod2 = dynamic_factor.DynamicFactor( endog, k_factors=1, factor_order=2, error_cov_type='diagonal') with pytest.raises(ValueError): with mod2.fix_params({'L1.f1.f1': 0.5}): pass constraints = {'L1.f1.f1': 0.3, 'L2.f1.f1': 0.1} with mod2.fix_params(constraints): assert_(mod2._has_fixed_params) assert_equal(mod2._fixed_params, constraints) assert_equal(mod2._fixed_params_index, [6, 7]) assert_equal(mod2._free_params_index, [0, 1, 2, 3, 4, 5]) res2 = mod2.fit_constrained(constraints, disp=False) assert_(res2._has_fixed_params) assert_equal(res2._fixed_params, constraints) assert_equal(res2._fixed_params_index, [6, 7]) assert_equal(res2._free_params_index, [0, 1, 2, 3, 4, 5]) # (same as previous, now k_factors=2) mod3 = dynamic_factor.DynamicFactor( endog, k_factors=2, factor_order=1, error_cov_type='diagonal') with pytest.raises(ValueError): with mod3.fix_params({'L1.f1.f1': 0.3}): pass constraints = dict([('L1.f1.f1', 0.3), ('L1.f2.f1', 0.1), ('L1.f1.f2', -0.05), ('L1.f2.f2', 0.1)]) with mod3.fix_params(constraints): assert_(mod3._has_fixed_params) assert_equal(mod3._fixed_params, constraints) assert_equal(mod3._fixed_params_index, [9, 10, 11, 12]) assert_equal(mod3._free_params_index, [0, 1, 2, 3, 4, 5, 6, 7, 8]) res3 = mod3.fit_constrained(constraints, disp=False) assert_(res3._has_fixed_params) assert_equal(res3._fixed_params, constraints) assert_equal(res3._fixed_params_index, [9, 10, 11, 12]) assert_equal(res3._free_params_index, [0, 1, 2, 3, 4, 5, 6, 7, 8]) # Now, with enforce_stationarity=False, we can fix any of the factor AR # coefficients mod4 = dynamic_factor.DynamicFactor( endog, k_factors=1, factor_order=2, error_cov_type='diagonal', enforce_stationarity=False) with mod4.fix_params({'L1.f1.f1': 0.6}): assert_(mod4._has_fixed_params) assert_equal(mod4._fixed_params, {'L1.f1.f1': 0.6}) assert_equal(mod4._fixed_params_index, [6]) assert_equal(mod4._free_params_index, [0, 1, 2, 3, 4, 5, 7]) mod5 = dynamic_factor.DynamicFactor( endog, k_factors=2, factor_order=1, error_cov_type='diagonal', enforce_stationarity=False) with mod5.fix_params({'L1.f1.f1': 0.6}): assert_(mod5._has_fixed_params) assert_equal(mod5._fixed_params, {'L1.f1.f1': 0.6}) assert_equal(mod5._fixed_params_index, [9]) assert_equal(mod5._free_params_index, [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12]) # Check error variance # (mod1 has error_cov_type='diagonal', so we can fix any that we like) constraints = {'sigma2.cpi': 0.9, 'sigma2.realinv': 3} with mod1.fix_params(constraints): assert_(mod1._has_fixed_params) assert_equal(mod1._fixed_params, constraints) assert_equal(mod1._fixed_params_index, [3, 5]) assert_equal(mod1._free_params_index, [0, 1, 2, 4, 6]) res1 = mod1.fit_constrained(constraints, disp=False) assert_(res1._has_fixed_params) assert_equal(res1._fixed_params, constraints) assert_equal(res1._fixed_params_index, [3, 5]) assert_equal(res1._free_params_index, [0, 1, 2, 4, 6]) # Check unstructured error variance # (also reduce k_endog and fix some other parameters to make MLE go faster) mod6 = dynamic_factor.DynamicFactor( endog[['cpi', 'realgdp']], k_factors=1, factor_order=1, error_cov_type='unstructured') constraints = { 'loading.f1.cpi': 1., 'loading.f1.realgdp': 1., 'cov.chol[1,1]': 0.5, 'cov.chol[2,1]': 0.1} with mod6.fix_params(constraints): assert_(mod6._has_fixed_params) assert_equal(mod6._fixed_params, constraints) assert_equal(mod6._fixed_params_index, [0, 1, 2, 3]) assert_equal(mod6._free_params_index, [4, 5]) res6 = mod6.fit_constrained(constraints, disp=False) assert_(res6._has_fixed_params) assert_equal(res6._fixed_params, constraints) assert_equal(res6._fixed_params_index, [0, 1, 2, 3]) assert_equal(res6._free_params_index, [4, 5])