code: def check_backtesting_input(
      forecaster: object,
      steps: int,
      metric: Union[str, Callable, list],
      y: Optional[pd.Series] = None,
      series: Optional[pd.DataFrame] = None,
      initial_train_size: Optional[int] = None,
      fixed_train_size: bool = True,
      gap: int = 0,
      allow_incomplete_fold: bool = True,
      refit: Optional[Union[bool, int]] = False,
      interval: Optional[list] = None,
      alpha: Optional[float] = None,
      n_boot: int = 500,
      random_state: int = 123,
      in_sample_residuals: bool = True,
      n_jobs: Optional[Union[int, str]] = "auto",
      verbose: bool = False,
      show_progress: bool = True,
  ) -> None:
      """
      This is a helper function to check most inputs of backtesting functions in
      modules `model_selection`, `model_selection_multiseries` and
      `model_selection_sarimax`.
  
      Parameters
      ----------
      forecaster : object
          Forecaster model.
      steps : int, list
          Number of future steps predicted.
      metric : str, Callable, list
          Metric used to quantify the goodness of fit of the model.
      y : pandas Series
          Training time series for uni-series forecasters.
      series : pandas DataFrame
          Training time series for multi-series forecasters.
      initial_train_size : int, default `None`
          Number of samples in the initial train split. If `None` and `forecaster`
          is already trained, no initial train is done and all data is used to
          evaluate the model.
      fixed_train_size : bool, default `True`
          If True, train size doesn't increase but moves by `steps` in each iteration.
      gap : int, default `0`
          Number of samples to be excluded after the end of each training set and
          before the test set.
      allow_incomplete_fold : bool, default `True`
          Last fold is allowed to have a smaller number of samples than the
          `test_size`. If `False`, the last fold is excluded.
      refit : bool, int, default `False`
          Whether to re-fit the forecaster in each iteration. If `refit` is an integer,
          the Forecaster will be trained every that number of iterations.
      interval : list, default `None`
          Confidence of the prediction interval estimated. Sequence of percentiles
          to compute, which must be between 0 and 100 inclusive.
      alpha : float, default `None`
          The confidence intervals used in ForecasterSarimax are (1 - alpha) %.
      n_boot : int, default `500`
          Number of bootstrapping iterations used to estimate prediction
          intervals.
      random_state : int, default `123`
          Sets a seed to the random generator, so that boot intervals are always
          deterministic.
      in_sample_residuals : bool, default `True`
          If `True`, residuals from the training data are used as proxy of prediction
          error to create prediction intervals.  If `False`, out_sample_residuals
          are used if they are already stored inside the forecaster.
      n_jobs : int, 'auto', default `'auto'`
          The number of jobs to run in parallel. If `-1`, then the number of jobs is
          set to the number of cores. If 'auto', `n_jobs` is set using the fuction
          skforecast.utils.select_n_jobs_fit_forecaster.
          **New in version 0.9.0**
      verbose : bool, default `False`
          Print number of folds and index of training and validation sets used
          for backtesting.
      show_progress: bool, default `True`
          Whether to show a progress bar.
  
      Returns
      -------
      None
  
      """
  
      forecasters_uni = [
          "ForecasterAutoreg",
          "ForecasterAutoregCustom",
          "ForecasterAutoregDirect",
          "ForecasterSarimax",
          "ForecasterEquivalentDate",
      ]
      forecasters_multi = [
          "ForecasterAutoregMultiSeries",
          "ForecasterAutoregMultiSeriesCustom",
          "ForecasterAutoregMultiVariate",
      ]
  
      forecaster_name = type(forecaster).__name__
  
      if forecaster_name in forecasters_uni:
          if not isinstance(y, pd.Series):
              raise TypeError("`y` must be a pandas Series.")
          data_name = "y"
          data_length = len(y)
  
      if forecaster_name in forecasters_multi:
          if not isinstance(series, pd.DataFrame):
              raise TypeError("`series` must be a pandas DataFrame.")
          data_name = "series"
          data_length = len(series)
  
      if not isinstance(steps, (int, np.integer)) or steps < 1:
          raise TypeError(
              f"`steps` must be an integer greater than or equal to 1. Got {steps}."
          )
      if not isinstance(gap, (int, np.integer)) or gap < 0:
          raise TypeError(
              f"`gap` must be an integer greater than or equal to 0. Got {gap}."
          )
      if not isinstance(metric, (str, Callable, list)):
          raise TypeError(
              (
                  f"`metric` must be a string, a callable function, or a list containing "
                  f"multiple strings and/or callables. Got {type(metric)}."
              )
          )
  
      if forecaster_name == "ForecasterEquivalentDate" and isinstance(
          forecaster.offset, pd.tseries.offsets.DateOffset
      ):
          pass
      elif initial_train_size is not None:
          if not isinstance(initial_train_size, (int, np.integer)):
              raise TypeError(
                  (
                      f"If used, `initial_train_size` must be an integer greater than the "
                      f"window_size of the forecaster. Got type {type(initial_train_size)}."
                  )
              )
          if initial_train_size >= data_length:
              raise ValueError(
                  (
                      f"If used, `initial_train_size` must be an integer smaller "
                      f"than the length of `{data_name}` ({data_length})."
                  )
              )
          if initial_train_size < forecaster.window_size:
              raise ValueError(
                  (
                      f"If used, `initial_train_size` must be an integer greater than "
                      f"the window_size of the forecaster ({forecaster.window_size})."
                  )
              )
          if initial_train_size + gap >= data_length:
              raise ValueError(
                  (
                      f"The combination of initial_train_size {initial_train_size} and "
                      f"gap {gap} cannot be greater than the length of `{data_name}` "
                      f"({data_length})."
                  )
              )
          if data_name == "series":
              for serie in series:
                  if np.isnan(
                      series[serie].to_numpy()[:initial_train_size]
                  ).all():
                      raise ValueError(
                          (
                              f"All values of series '{serie}' are NaN. When working "
                              f"with series of different lengths, make sure that "
                              f"`initial_train_size` has an appropriate value so that "
                              f"all series reach the first non-null value."
                          )
                      )
      else:
          if forecaster_name == "ForecasterSarimax":
              raise ValueError(
                  (
                      f"`initial_train_size` must be an integer smaller than the "
                      f"length of `{data_name}` ({data_length})."
                  )
              )
          else:
              if not forecaster.fitted:
                  raise NotFittedError(
                      (
                          "`forecaster` must be already trained if no `initial_train_size` "
                          "is provided."
                      )
                  )
              if refit:
                  raise ValueError(
                      "`refit` is only allowed when `initial_train_size` is not `None`."
                  )
  
      if not isinstance(fixed_train_size, bool):
          raise TypeError(
              "`fixed_train_size` must be a boolean: `True`, `False`."
          )
      if not isinstance(allow_incomplete_fold, bool):
          raise TypeError(
              "`allow_incomplete_fold` must be a boolean: `True`, `False`."
          )
      if not isinstance(refit, (bool, int, np.integer)) or refit < 0:
          raise TypeError(
              f"`refit` must be a boolean or an integer greater than 0. Got {refit}."
          )
      if not isinstance(n_boot, (int, np.integer)) or n_boot < 0:
          raise TypeError(
              f"`n_boot` must be an integer greater than 0. Got {n_boot}."
          )
      if (
          not isinstance(random_state, (int, np.integer))
          or random_state < 0
      ):
          raise TypeError(
              f"`random_state` must be an integer greater than 0. Got {random_state}."
          )
      if not isinstance(in_sample_residuals, bool):
          raise TypeError(
              "`in_sample_residuals` must be a boolean: `True`, `False`."
          )
      if not isinstance(n_jobs, int) and n_jobs != "auto":
          raise TypeError(
              f"`n_jobs` must be an integer or `'auto'`. Got {n_jobs}."
          )
      if not isinstance(verbose, bool):
          raise TypeError(
              "`verbose` must be a boolean: `True`, `False`."
          )
      if not isinstance(show_progress, bool):
          raise TypeError(
              "`show_progress` must be a boolean: `True`, `False`."
          )
  
      if interval is not None or alpha is not None:
          check_interval(interval=interval, alpha=alpha)
  
      if (
          not allow_incomplete_fold
          and data_length - (initial_train_size + gap) < steps
      ):
          raise ValueError(
              (
                  f"There is not enough data to evaluate {steps} steps in a single "
                  f"fold. Set `allow_incomplete_fold` to `True` to allow incomplete folds.\n"
                  f"    Data available for test : {data_length - (initial_train_size + gap)}\n"
                  f"    Steps                   : {steps}"
              )
          )
  
      return
  
imports: from typing import Union, Any, Optional, Tuple, Callable
  import warnings
  import importlib
  import joblib
  import numpy
  import pandas
  import sklearn
  import sklearn.pipeline
  import sklearn.linear_model
  from sklearn.compose import ColumnTransformer
  from sklearn.exceptions import NotFittedError
  import inspect
  from copy import deepcopy
  import skforecast
  from ..exceptions import MissingValuesExogWarning
  from ..exceptions import DataTypeWarning
  from ..exceptions import IgnoredArgumentWarning
  from ..exceptions import SkforecastVersionWarning
label_desc: Use image node_id 25 for calling a global function with example usage: check_backtesting_input(forecaster, steps, metric, y, series, initial_train_size, fixed_train_size, gap, allow_incomplete_fold, refit, interval, alpha, n_boot, random_state, in_sample_residuals, n_jobs, verbose, show_progress) without return types