Source code for TimeSeriesSRC.basefunctions.uniChi

import numpy as np
from .xcorr import func_xcorr as xcorr
from .chisqrdf import func_chisqrdf as chisqrdf

[docs] def func_uniChi(pmod, y, k=20, alpha=0.05): """Box-Pierce portmanteau chi-square test on one-step-ahead residuals. Tests the null hypothesis that the residuals of a fitted model are white noise. Large values of the Q statistic (small p-values) indicate that the residuals are autocorrelated and the model does not adequately fit the data. Parameters ---------- pmod : pmodel Estimated prediction model (returned by :func:`estimate`). y : array-like 1-D desired output sequence used to compute residuals. k : int, optional Number of residual-ACF lags used in the Q statistic. Default 20. alpha : float, optional Significance level for the test (probability of Type I error). Default 0.05. Returns ------- passed : int 1 if the test is passed (residuals appear white), 0 otherwise. q : float Box-Pierce Q statistic. n : int Degrees of freedom (``k`` minus the number of free parameters). pval : float p-value of the Q statistic under the chi-square distribution. Examples -------- >>> import numpy as np >>> from scipy.signal import lfilter >>> from TimeSeriesSRC.Model.model import pmodel >>> from TimeSeriesSRC.Model.estimate import estimate >>> from TimeSeriesSRC.basefunctions.uniChi import func_uniChi >>> e = np.random.default_rng(0).standard_normal(500) >>> y = lfilter([1, 0.5], [1, -0.8], e) >>> pm = pmodel('arma', nc=[1], nd=[1], diff=[0], per=[]) >>> pm_est, trec, stat = estimate(pm, y, show_plot=False, show_output=False) >>> passed, q, n, pval = func_uniChi(pm_est, y) See Also -------- multiChi : Chi-square test for transfer function models (residual + cross-correlation). uniAnal : ACF/PACF/GPAC analysis for order identification. """ y_1d = np.asarray(y).ravel() # Compute residuals e = y_1d - pmod.predict(y_1d) # ACF of residuals at lags 0..k e_2d = e.reshape(1, -1) acf_full = xcorr(e_2d, e_2d, k, 'unbiased') # Keep positive lags (0..k), normalize by lag-0 value, drop lag-0 acf = acf_full[0, k:] # lags 0..k acf = acf / acf[0] # normalize → ρ_0 = 1 acf = acf[1:] # drop lag-0, now lags 1..k # Box-Pierce Q statistic q = len(y_1d) * np.sum(acf ** 2) # Degrees of freedom: lags minus number of free parameters X = pmod.getmX() num_para = len(X) n = k - num_para # Chi-square cumulative probability pr = chisqrdf(q, n) pval = 1.0 - pr passed = 1 if pval > alpha else 0 print('pval:', pval) print('alpha:', alpha) print('pr:',pr) print('q:',q) return passed, q, n, pval