FunctionalCoefficientVARResult#

class cultivars.multivariate.nonlinear.functional_coefficient.FunctionalCoefficientVARResult(*, endog, names, order, trend, delay, state_name, state_values, transition_series, grid, curves, curve_se, bandwidth, bandwidth_searched, effective_params, sigma_u, resid, fittedvalues, nobs)[source]

Bases: _SummaryMixin

A fitted functional-coefficient VAR: coefficient curves over the state.

The estimate of

\[y_t = c(z_t) + \sum_{i=1}^{p} A_i(z_t)\, y_{t-i} + u_t, \qquad z_t = s_{t-d},\]

where every coefficient is an unknown smooth function of the delayed state \(z_t\) and \(s\) is either one of the variables (the self-exciting case) or an external series. At each grid point \(u\) the curves come from one Epanechnikov-weighted local-linear least squares on the augmented design \([x_t,\ x_t (z_t - u)]\),

\[\min_{a, b} \sum_t K_h(z_t - u)\, \bigl\lVert y_t - a' x_t - b' x_t (z_t - u) \bigr\rVert^2,\]

all equations sharing the weights; the level \(a(u)\) is reported and the slope \(b(u)\) discarded. The curves are evaluated on a grid over the trimmed state range and the result reads coefficients at any state value by linear interpolation between grid points.

Deliberately absent: llf, n_params, information criteria. A kernel estimator maximizes no likelihood; its complexity is effective_params, the trace of the smoother matrix.

Note

Everything is local to the state’s support. The curves live on [grid[0], grid[-1]] – the state range after trimming trim from each tail – and every method that takes a state value refuses one outside it rather than extrapolating. The bands in coefficient_curve() are one pointwise standard error, conditional on the bandwidth: they measure precision at this smoothing, not uncertainty over smoothings. sigma_u is a single covariance, corrected by nobs - effective_params, under the model’s assumption that the innovations are homoskedastic in the state. In the self-exciting case with delay <= order the intercept is fitted local-constant because its local slope is exactly collinear with the design.

Variables:
  • endog – The observed panel.

  • names – Variable labels, in column order.

  • order – Autoregressive order.

  • trend – Deterministic specification.

  • delay – Delay of the state variable.

  • state_name – The state variable’s label – a variable name when self-exciting, "external" otherwise.

  • state_values – The delayed state z_t, aligned with resid.

  • transition_series – The raw state series, aligned with endog.

  • grid – (G,) state values the curves are evaluated on.

  • curves – (G, w, k) local-linear level coefficients, design-major: curves[g, :, i] is equation i’s coefficient vector at grid[g], columns ordered deterministics first, then lags.

  • curve_se – (G, w, k) pointwise standard errors, conditional on the bandwidth.

  • bandwidth – The bandwidth the curves were estimated at.

  • bandwidth_searched – Whether the bandwidth came from leave-one-out cross-validation rather than the caller.

  • effective_params – Trace of the smoother matrix – the kernel estimator’s analogue of a parameter count.

  • sigma_u – (k, k) innovation covariance, corrected by the effective degrees of freedom and assumed constant in the state.

  • resid – Residuals of the local fits at the observed states.

  • fittedvalues – One-step conditional means at the observed states.

  • nobs – Effective sample size.

See also

References

Cai, Z., Fan, J., & Yao, Q. (2000). Functional-coefficient regression models for nonlinear time series. Journal of the American Statistical Association, 95(451), 941-956.

Chen, R., & Tsay, R. S. (1993). Functional-coefficient autoregressive models. Journal of the American Statistical Association, 88(421), 298-308.

Example

A bivariate system whose first equation has the own-lag coefficient \(0.8 \tanh(y_{1,t-1})\) and whose second is a linear AR(1). The estimated curve tracks the tanh and its band covers it, and the second equation’s curve is flat:

>>> import numpy as np
>>> rng = np.random.default_rng(0)
>>> y = np.zeros((250, 2))
>>> for t in range(1, 250):
...     a = 0.8 * np.tanh(y[t - 1, 0])
...     y[t, 0] = a * y[t - 1, 0] + 0.5 * rng.standard_normal()
...     y[t, 1] = 0.4 * y[t - 1, 1] + 0.5 * rng.standard_normal()
>>> model = FunctionalCoefficientVAR(y, order=1, transition_variable="y1")
>>> res = model.fit(bandwidth=1.2, n_grid=21)
>>> res.names, res.state_name, res.delay, res.nobs, res.bandwidth_searched
(('y1', 'y2'), 'y1', 1, 249, False)
>>> res.grid.shape, res.curves.shape, res.curve_se.shape, res.state_values.shape
((21,), (21, 3, 2), (21, 3, 2), (249,))
>>> low, point, high = res.coefficient_curve("y1", "y1.L1").T
>>> truth = 0.8 * np.tanh(res.grid)
>>> within_two = np.abs(point - truth) < 2.0 * (high - point)
>>> bool(point[0] < 0.0 < point[-1]), bool(within_two.mean() > 0.8)
(True, True)
>>> flat = res.coefficient_curve("y2", "y2.L1")[:, 1]
>>> bool(flat.max() - flat.min() < 0.5)
True
>>> bool(2.0 < res.effective_params < 8.0)
True

Private attributes#

_n_deterministic

Deterministic columns per equation.

Private methods#

_from_fit(fit, model)

Assemble the public result from a raw fit and its specification.

_matrix_at(u)

The full (w, k) coefficient matrix at one state value.

_regressor_labels()

Per-equation regressor labels, in design order.

_summary_table()

Build the structured summary.