EncompassingTest#

class cultivars.forecast.comparison.EncompassingTest(*, statistic, pvalue, horizon, nobs, weight)[source]

Bases: _ForecastComparisonTest

Verdict of the forecast encompassing test: does A already contain what B knows?

Forecast A encompasses B when the optimal linear combination of the two,

\[y_t = (1 - \lambda)\, f_{A,t} + \lambda\, f_{B,t} + u_t,\]

puts zero weight on B. Since \(\lambda\) is the least-squares coefficient of \(e_{A,t}\) on \(e_{A,t} - e_{B,t}\), the null \(\lambda = 0\) is \(\mathbb{E}[e_{A,t}(e_{A,t} - e_{B,t})] = 0\), and the test is Diebold-Mariano machinery on the series \(d_t = e_{A,t}(e_{A,t} - e_{B,t})\) with the Harvey-Leybourne-Newbold correction and a one-sided \(t\) reference. The one-sided alternative is that B carries information A lacks; a rejection says combining would help, and the reported weight is the least-squares share B would get.

Variables:
  • statistic – The HLN-corrected statistic on e_A (e_A - e_B).

  • pvalue – Its upper-tail t p-value.

  • weight – Least-squares combination weight on B; zero under the null.

  • horizon – Forecast horizon behind the series.

  • nobs – Evaluation origins.

Note

The test is directional: “A encompasses B” and “B encompasses A” are two calls with the arguments swapped, and both can fail to reject on a short window, which says the window cannot tell, not that the forecasts are equivalent. The weight is reported unclipped, so a value above one or below zero is possible and says the least-squares combination extrapolates beyond the two forecasts.

See also

References

Harvey, D. I., Leybourne, S. J., & Newbold, P. (1998). Tests for forecast encompassing. Journal of Business & Economic Statistics, 16(2), 254-259.

Chong, Y. Y., & Hendry, D. F. (1986). Econometric evaluation of linear macro-economic models. Review of Economic Studies, 53(4), 671-690.

Example

A zero forecast does not encompass an informative one; swapped, the informative forecast encompasses the zero:

>>> import numpy as np
>>> rng = np.random.default_rng(0)
>>> x = rng.standard_normal(200)
>>> y = 0.5 * x + rng.standard_normal(200)
>>> forward = encompassing(y, np.zeros(200), 0.5 * x)
>>> forward
EncompassingTest(statistic=5.0330, pvalue=5.387e-07, weight=0.859, nobs=200)
>>> reverse = encompassing(y, 0.5 * x, np.zeros(200))
>>> bool(forward.reject()), bool(reverse.reject()), round(reverse.weight, 3)
(True, False, 0.141)

Private methods#

_summary_table()

Render as a table.