clark_west#

cultivars.forecast.comparison.clark_west(realized, restricted, unrestricted, *, horizon=1)[source]#

Clark-West (2007) test that a nesting model forecasts better than the model it nests.

Under the null that the smaller model is true, the larger one’s extra parameters are estimated noise, so its mean squared prediction error is expected to exceed the smaller one’s and Diebold-Mariano is biased against it. Clark and West subtract the noise term (f_r - f_u)**2 from the loss differential,

\[\hat f_t = e_{r,t}^2 - e_{u,t}^2 + (\hat y_{r,t} - \hat y_{u,t})^2, \qquad \mathrm{CW} = \frac{\bar{\hat f}}{\sqrt{\hat\sigma^2_{LR}(\hat f) / T}},\]

and test what remains with a one-sided normal reference, which is approximately correctly sized in the recursive and rolling schemes a backtest runs.

Parameters:
  • realized (ArrayLike) – (T,) outcomes.

  • restricted (ArrayLike) – (T,) point forecasts of the nested model.

  • unrestricted (ArrayLike) – (T,) point forecasts of the nesting model, aligned origin by origin – BacktestResult.point[:, h - 1, j] from two backtests on the same schedule.

  • horizon (int) – The forecast horizon behind the series; sets the long-run variance’s Bartlett window.

Return type:

ClarkWestTest

Returns:

The ClarkWestTest.

Raises:

Note

Nesting is the caller’s claim; the function cannot check that the restricted model is a special case of the unrestricted one, and on two non-nested forecasts the adjustment simply rewards the forecast that differs more from the other. For non-nested forecasts use ForecastComparison. The test takes point forecasts and outcomes rather than losses because the adjustment needs the forecasts themselves.

See also

References

Clark, T. E., & West, K. D. (2007). Approximately normal tests for equal predictive accuracy in nested models. Journal of Econometrics, 138(1), 291-311.

Example

A predictor with real content against the no-change forecast it nests; the raw MSPEs favor it too, but on a null predictor they would not, and the adjustment is what keeps the test honest:

>>> import numpy as np
>>> rng = np.random.default_rng(0)
>>> x = rng.standard_normal(200)
>>> y = 0.5 * x + rng.standard_normal(200)
>>> verdict = clark_west(y, np.zeros(200), 0.5 * x)
>>> bool(verdict.pvalue < 0.01)
True
>>> verdict.nobs, verdict.horizon
(200, 1)
>>> bool(verdict.mspe_unrestricted < verdict.mspe_restricted)
True
>>> clark_west(y, np.zeros(200), 0.5 * x, horizon=150)
Traceback (most recent call last):
    ...
cultivars.exceptions.SpecificationError: a horizon of 150 needs more than 300 ...