def test_conformal_historical_forecasts(self, config):
        """Tests historical forecasts output naive conformal model with last points only, covariates, stride,
        different horizons and overlap end.
        Tests that the returned dimensions, lengths and start / end times are correct.
        """
        (
            use_covs,
            last_points_only,
            overlap_end,
            stride,
            horizon,
            use_int_idx,
            use_multi_series,
            ocs,
        ) = config
        q = [0.1, 0.5, 0.9]
        pred_lklp = {"num_samples": 1, "predict_likelihood_parameters": True}
        # compute minimum series length to generate n forecasts
        icl = 3
        ocl = 5
        horizon_ocs = horizon + ocs
        min_len_val_series = icl + horizon_ocs + int(not overlap_end) * horizon_ocs
        n_forecasts = 3
        # get train and val series of that length
        series = self.ts_pass_val[: min_len_val_series + n_forecasts - 1]
        if use_int_idx:
            series = TimeSeries.from_values(
                values=series.all_values(),
                columns=series.columns,
            )
        # check that too short input raises error
        series_too_short = series[:-n_forecasts]

        # optionally, generate covariates
        if use_covs:
            pc = tg.gaussian_timeseries(
                start=series.start_time(),
                end=series.end_time() + max(0, horizon - ocl) * series.freq,
                freq=series.freq,
            )
            fc = tg.gaussian_timeseries(
                start=series.start_time(),
                end=series.end_time() + (max(ocl, horizon) + ocs) * series.freq,
                freq=series.freq,
            )
        else:
            pc, fc = None, None

        # first train the ForecastingModel
        model_kwargs = (
            {}
            if not use_covs
            else {"lags_past_covariates": icl, "lags_future_covariates": (icl, ocl)}
        )
        forecasting_model = LinearRegressionModel(
            lags=icl, output_chunk_length=ocl, output_chunk_shift=ocs, **model_kwargs
        )
        forecasting_model.fit(series, past_covariates=pc, future_covariates=fc)

        # add an offset and rename columns in second series to make sure that conformal hist fc works as expected
        if use_multi_series:
            series = [
                series,
                (series + 10).shift(1).with_columns_renamed(series.columns, "test_col"),
            ]
            pc = [pc, pc.shift(1)] if pc is not None else None
            fc = [fc, fc.shift(1)] if fc is not None else None

        # conformal model
        model = ConformalNaiveModel(forecasting_model, quantiles=q)

        hfc_kwargs = dict(
            {
                "retrain": False,
                "last_points_only": last_points_only,
                "overlap_end": overlap_end,
                "stride": stride,
                "forecast_horizon": horizon,
            },
            **pred_lklp,
        )
        # cannot perform auto regression with output chunk shift
        if ocs and horizon > ocl:
            with pytest.raises(ValueError) as exc:
                _ = model.historical_forecasts(
                    series=series,
                    past_covariates=pc,
                    future_covariates=fc,
                    **hfc_kwargs,
                )
            assert str(exc.value).startswith("Cannot perform auto-regression")
            return

        # compute conformal historical forecasts
        hist_fct = model.historical_forecasts(
            series=series, past_covariates=pc, future_covariates=fc, **hfc_kwargs
        )
        # raises error with too short target series
        with pytest.raises(ValueError) as exc:
            _ = model.historical_forecasts(
                series=series_too_short,
                past_covariates=pc,
                future_covariates=fc,
                **hfc_kwargs,
            )
        assert str(exc.value).startswith(
            "Could not build the minimum required calibration input with the provided `series`"
        )

        if not isinstance(series, list):
            series = [series]
            hist_fct = [hist_fct]

        for (
            series_,
            hfc,
        ) in zip(series, hist_fct):
            if not isinstance(hfc, list):
                hfc = [hfc]

            n_preds_with_overlap = (
                len(series_)
                - icl  # input for first prediction
                - horizon_ocs  # skip first forecasts to avoid look-ahead bias
                + 1  # minimum one forecast
            )
            if not last_points_only:
                # last points only = False gives a list of forecasts per input series
                # where each forecast contains the predictions over the entire horizon
                n_pred_series_expected = n_preds_with_overlap
                n_pred_points_expected = horizon
                first_ts_expected = series_.time_index[icl] + series_.freq * (
                    horizon_ocs + ocs
                )
                last_ts_expected = series_.end_time() + series_.freq * horizon_ocs
                # no overlapping means less predictions
                if not overlap_end:
                    n_pred_series_expected -= horizon_ocs
            else:
                # last points only = True gives one contiguous time series per input series
                # with only predictions from the last point in the horizon
                n_pred_series_expected = 1
                n_pred_points_expected = n_preds_with_overlap
                first_ts_expected = series_.time_index[icl] + series_.freq * (
                    horizon_ocs + ocs + horizon - 1
                )
                last_ts_expected = series_.end_time() + series_.freq * horizon_ocs
                # no overlapping means less predictions
                if not overlap_end:
                    n_pred_points_expected -= horizon_ocs

            # no overlapping means less predictions
            if not overlap_end:
                last_ts_expected -= series_.freq * horizon_ocs

            # adapt based on stride
            if stride > 1:
                if not last_points_only:
                    n_pred_series_expected = n_pred_series_expected // stride + int(
                        n_pred_series_expected % stride
                    )
                else:
                    n_pred_points_expected = n_pred_points_expected // stride + int(
                        n_pred_points_expected % stride
                    )
                first_ts_expected = hfc[0].start_time()
                last_ts_expected = hfc[-1].end_time()

            cols_excpected = likelihood_component_names(
                series_.columns, quantile_names(q)
            )
            # check length match between optimized and default hist fc
            assert len(hfc) == n_pred_series_expected
            # check hist fc start
            assert hfc[0].start_time() == first_ts_expected
            # check hist fc end
            assert hfc[-1].end_time() == last_ts_expected
            for hfc_ in hfc:
                assert hfc_.columns.tolist() == cols_excpected
                assert len(hfc_) == n_pred_points_expected
Tests historical forecasts output naive conformal model with last points only, covariates, stride,
        different horizons and overlap end.
        Tests that the returned dimensions, lengths and start / end times are correct.
        
darts/tests/utils/historical_forecasts/test_historical_forecasts.py