STVARResult#

class cultivars.multivariate.nonlinear.smooth_transition.STVARResult(*, endog, names, order, trend, delay, threshold, threshold_name, threshold_values, transition_series, lower_coefficients, upper_coefficients, lower_deterministic, upper_deterministic, resid, fittedvalues, llf, nobs, n_params, transition, gamma, transition_scale, sigma_u)[source]#

A fitted smooth-transition vector autoregression.

The estimate of

\[y_t = (1 - G(z_t))\,\bigl(c_L + \textstyle\sum_{i} A_{L,i}\, y_{t-i}\bigr) + G(z_t)\,\bigl(c_U + \textstyle\sum_{i} A_{U,i}\, y_{t-i}\bigr) + u_t, \qquad z_t = s_{t-d},\]

with the transition weight either logistic or exponential in the standardized distance from the threshold,

\[G(z) = \bigl(1 + e^{-\gamma (z - c)/\sigma_z}\bigr)^{-1} \quad\text{or}\quad G(z) = 1 - e^{-\gamma (z - c)^2/\sigma_z^2},\]

estimated by concentrated maximum likelihood: given \((\gamma, c)\) the two regimes’ coefficients come from one weighted least-squares solve, and only the pair is searched on the log-determinant of the residual covariance. The record extends the observed-regime surface – the two coefficient stacks, regime-conditional irf, fevd, ma_representation and forecast, the stability of each regime, and comparison by information criteria – with the transition’s own parameters and the single covariance the smooth form admits.

Note

gamma is reported per standard deviation of the transition variable; divide by transition_scale for the speed on the original scale. The logistic weight equals one half at the threshold and is monotone in \(z\), so the regimes are directional; the exponential weight equals zero at the threshold and one far from it on either side, so the “upper” regime is the tails and the “lower” regime the middle. The likelihood is nearly flat in \(\gamma\) once the weight is effectively an indicator, so a very large fitted gamma is a lower bound rather than an estimate, and is_effectively_abrupt says when that has happened. Information criteria rank specifications but do not test for nonlinearity, because \((\gamma, c)\) are not identified under linearity. Standard errors are not yet available.

Variables:
  • transition – "logistic" or "exponential".

  • gamma – Transition speed, per standard deviation of the transition variable.

  • transition_scale – The standard deviation gamma is expressed against, retained so the weight path can be reproduced and so gamma can be read on the original scale.

  • sigma_u – Common innovation covariance, dof-corrected. One covariance rather than two: smooth weights never partition the sample, so a per-regime covariance has no subsample to be estimated from.

See also

  • STVAR – the model that produces this record.

  • TVARResult – the abrupt limit, with a covariance per regime.

  • STARResult – the univariate counterpart, split into LSTAR and ESTAR.

References

Auerbach, A. J., & Gorodnichenko, Y. (2012). Measuring the output responses to fiscal policy. American Economic Journal: Economic Policy, 4(2), 1-27.

Terasvirta, T., & Yang, Y. (2014). Specification, estimation and evaluation of vector smooth transition autoregressive models with applications. CREATES Research Paper 2014-08.

Example

A bivariate system whose own-lag coefficient slides from 0.6 to -0.3 as a logistic function of y1’s lag with speed 2 per unit; the fit recovers both regimes, a speed of the right size per standard deviation, and a weight path that spends a real share of the sample in between:

>>> import numpy as np
>>> rng = np.random.default_rng(1)
>>> y = np.zeros((400, 2))
>>> for t in range(1, 400):
...     g = 1.0 / (1.0 + np.exp(-2.0 * y[t - 1, 0]))
...     a = (1.0 - g) * 0.6 + g * -0.3
...     y[t] = a * y[t - 1] + rng.standard_normal(2)
>>> res = STVAR(y, order=1, transition_variable="y1").fit()
>>> res.transition, res.delay, res.threshold_name, res.nobs, res.n_params
('logistic', 1, 'y1', 399, 17.0)
>>> bool(1.0 < res.gamma < 3.0), bool(abs(res.threshold) < 0.5), res.is_effectively_abrupt
(True, True, False)
>>> lower, upper = np.diag(res.lower_coefficients[0]), np.diag(res.upper_coefficients[0])
>>> bool(np.all(np.abs(lower - 0.6) < 0.15)), bool(np.all(np.abs(upper + 0.3) < 0.25))
(True, True)
>>> weight = res.regime_weight
>>> between = np.mean((weight > 0.2) & (weight < 0.8))
>>> bool(0.2 < res.upper_fraction < 0.5), bool(between > 0.25)
(True, True)
>>> res.sigma_u.shape, bool(np.allclose(res._weight_at(np.array([res.threshold])), 0.5))
((2, 2), True)

Attributes#

transition

"logistic" or "exponential".

gamma

Transition speed per standard deviation of the transition variable.

transition_scale

Standard deviation of the delayed transition variable, the unit of gamma.

sigma_u

(k, k) common innovation covariance, dof-corrected.

delay

endog

fittedvalues

information_criteria

AIC, BIC, and HQIC derived from the likelihood and parameter count.

is_effectively_abrupt

Whether the fitted transition is so fast it is a hard threshold.

is_regimewise_stationary

Whether both regimes are stationary read as linear systems.

k_endog

Number of endogenous variables.

llf

lower_coefficients

lower_deterministic

lower_stability

Companion-eigenvalue verdict for the lower regime's lag stack.

n_params

names

nobs

order

regime_weight

The transition function evaluated over the sample.

resid

threshold

threshold_name

threshold_values

transition_series

trend

upper_coefficients

upper_deterministic

upper_fraction

Share of the effective sample carried by the upper regime.

upper_stability

Companion-eigenvalue verdict for the upper regime's lag stack.

Methods#

compare(*others[, criterion])

Rank this result against others by an information criterion.

equation(name, *, regime)

One equation of one regime, keyed by regressor.

fevd([horizon])

Forecast-error variance decomposition within one regime, held frozen.

forecast([steps, transition_future])

Iterate the fitted skeleton forward, blending regimes as it goes.

irf([horizon, orthogonalized, cumulative])

Impulse responses within one regime, held frozen.

likelihood_ratio_test(unrestricted)

Refuse the test: the threshold is unidentified under the null.

ma_representation([horizon])

Moving-average matrices of one regime, held frozen.

summary()

The estimation summary, renderable as text, HTML, or a dataframe.