code: def breaks_cusumolsresid(resid, ddof=0):
      """
      Cusum test for parameter stability based on ols residuals.
  
      Parameters
      ----------
      resid : ndarray
          An array of residuals from an OLS estimation.
      ddof : int
          The number of parameters in the OLS estimation, used as degrees
          of freedom correction for error variance.
  
      Returns
      -------
      sup_b : float
          The test statistic, maximum of absolute value of scaled cumulative OLS
          residuals.
      pval : float
          Probability of observing the data under the null hypothesis of no
          structural change, based on asymptotic distribution which is a Brownian
          Bridge
      crit: list
          The tabulated critical values, for alpha = 1%, 5% and 10%.
  
      Notes
      -----
      Tested against R:structchange.
  
      Not clear: Assumption 2 in Ploberger, Kramer assumes that exog x have
      asymptotically zero mean, x.mean(0) = [1, 0, 0, ..., 0]
      Is this really necessary? I do not see how it can affect the test statistic
      under the null. It does make a difference under the alternative.
      Also, the asymptotic distribution of test statistic depends on this.
  
      From examples it looks like there is little power for standard cusum if
      exog (other than constant) have mean zero.
  
      References
      ----------
      Ploberger, Werner, and Walter Kramer. “The Cusum Test with OLS Residuals.”
      Econometrica 60, no. 2 (March 1992): 271-285.
      """
      resid = np.asarray(resid).ravel()
      nobs = len(resid)
      nobssigma2 = (resid**2).sum()
      if ddof > 0:
          nobssigma2 = nobssigma2 / (nobs - ddof) * nobs
      # b is asymptotically a Brownian Bridge
      b = resid.cumsum() / np.sqrt(nobssigma2)  # use T*sigma directly
      # asymptotically distributed as standard Brownian Bridge
      sup_b = np.abs(b).max()
      crit = [(1, 1.63), (5, 1.36), (10, 1.22)]
      # Note stats.kstwobign.isf(0.1) is distribution of sup.abs of Brownian
      # Bridge
      # >>> stats.kstwobign.isf([0.01,0.05,0.1])
      # array([ 1.62762361,  1.35809864,  1.22384787])
      pval = stats.kstwobign.sf(sup_b)
      return sup_b, pval, crit
  
imports: from statsmodels.compat.pandas import deprecate_kwarg
  from collections.abc import Iterable
  import numpy
  import pandas
  from scipy import stats
  from statsmodels.regression.linear_model import OLS, RegressionResultsWrapper
  from statsmodels.stats._adnorm import anderson_statistic, normal_ad
  from statsmodels.stats._lilliefors import kstest_exponential, kstest_fit, kstest_normal, lilliefors
  from statsmodels.tools.validation import array_like, bool_like, dict_like, float_like, int_like, string_like
  from statsmodels.tsa.tsatools import lagmat
label_desc: Use image node_id 21 for calling a global function with example usage: breaks_cusumolsresid(resid, ddof) and returns: sup_b,  pval,  crit