Skip to content

timecopilot.forecaster

TimeCopilotForecaster

TimeCopilotForecaster(
    models: list[Forecaster],
    fallback_model: Forecaster | None = None,
)

Bases: Forecaster

Unified forecaster for multiple time series models.

This class enables forecasting and cross-validation across a list of models from different families (foundational, statistical, machine learning, neural, etc.) using a single, consistent interface. It is designed to handle panel (multi-series) data and to aggregate results from all models for easy comparison and ensemble workflows.

The unified API ensures that users can call forecast or cross_validation once, passing a list of models, and receive merged results for all models.

Initialize the TimeCopilotForecaster with a list of models.

Parameters:

Name Type Description Default
models list[Forecaster]

List of instantiated model objects from any supported family (foundational, statistical, ML, neural, etc.). Each model must implement the forecast and cross_validation methods with compatible signatures.

required
fallback_model Forecaster

Model to use as a fallback when a model fails.

None

Raises:

Type Description
ValueError

If duplicate model aliases are found in the models list.

Source code in timecopilot/forecaster.py
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
def __init__(
    self,
    models: list[Forecaster],
    fallback_model: Forecaster | None = None,
):
    """
    Initialize the TimeCopilotForecaster with a list of models.

    Args:
        models (list[Forecaster]):
            List of instantiated model objects from any supported family
            (foundational, statistical, ML, neural, etc.). Each model must
            implement the `forecast` and `cross_validation` methods with
            compatible signatures.
        fallback_model (Forecaster, optional):
            Model to use as a fallback when a model fails.

    Raises:
        ValueError: If duplicate model aliases are found in the models list.
    """
    self._validate_unique_aliases(models)
    self.models = models
    self.fallback_model = fallback_model

forecast

forecast(
    df: DataFrame,
    h: int,
    freq: str | None = None,
    level: list[int | float] | None = None,
    quantiles: list[float] | None = None,
) -> DataFrame

Generate forecasts for one or more time series using all models.

This method produces point forecasts and, optionally, prediction intervals or quantile forecasts. The input DataFrame can contain one or multiple time series in stacked (long) format.

Parameters:

Name Type Description Default
df DataFrame

DataFrame containing the time series to forecast. It must include as columns:

- "unique_id": an ID column to distinguish multiple series.
- "ds": a time column indicating timestamps or periods.
- "y": a target column with the observed values.
required
h int

Forecast horizon specifying how many future steps to predict.

required
freq str

Frequency of the time series (e.g. "D" for daily, "M" for monthly). See Pandas frequency aliases for valid values. If not provided, the frequency will be inferred from the data.

None
level list[int | float]

Confidence levels for prediction intervals, expressed as percentages (e.g. [80, 95]). If provided, the returned DataFrame will include lower and upper interval columns for each specified level.

None
quantiles list[float]

List of quantiles to forecast, expressed as floats between 0 and 1. Should not be used simultaneously with level. When provided, the output DataFrame will contain additional columns named in the format "model-q-{percentile}", where {percentile} = 100 × quantile value.

None

Returns:

Type Description
DataFrame

pd.DataFrame: DataFrame containing forecast results. Includes:

- point forecasts for each timestamp, series and model.
- prediction intervals if `level` is specified.
- quantile forecasts if `quantiles` is specified.

For multi-series data, the output retains the same unique identifiers as the input DataFrame.

Source code in timecopilot/forecaster.py
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
def forecast(
    self,
    df: pd.DataFrame,
    h: int,
    freq: str | None = None,
    level: list[int | float] | None = None,
    quantiles: list[float] | None = None,
) -> pd.DataFrame:
    """
    Generate forecasts for one or more time series using all models.

    This method produces point forecasts and, optionally, prediction
    intervals or quantile forecasts. The input DataFrame can contain one
    or multiple time series in stacked (long) format.

    Args:
        df (pd.DataFrame):
            DataFrame containing the time series to forecast. It must
            include as columns:

                - "unique_id": an ID column to distinguish multiple series.
                - "ds": a time column indicating timestamps or periods.
                - "y": a target column with the observed values.

        h (int):
            Forecast horizon specifying how many future steps to predict.
        freq (str, optional):
            Frequency of the time series (e.g. "D" for daily, "M" for
            monthly). See [Pandas frequency aliases](https://pandas.pydata.org/
            pandas-docs/stable/user_guide/timeseries.html#offset-aliases) for
            valid values. If not provided, the frequency will be inferred
            from the data.
        level (list[int | float], optional):
            Confidence levels for prediction intervals, expressed as
            percentages (e.g. [80, 95]). If provided, the returned
            DataFrame will include lower and upper interval columns for
            each specified level.
        quantiles (list[float], optional):
            List of quantiles to forecast, expressed as floats between 0
            and 1. Should not be used simultaneously with `level`. When
            provided, the output DataFrame will contain additional columns
            named in the format "model-q-{percentile}", where {percentile}
            = 100 × quantile value.

    Returns:
        pd.DataFrame:
            DataFrame containing forecast results. Includes:

                - point forecasts for each timestamp, series and model.
                - prediction intervals if `level` is specified.
                - quantile forecasts if `quantiles` is specified.

            For multi-series data, the output retains the same unique
            identifiers as the input DataFrame.
    """
    return self._call_models(
        "forecast",
        merge_on=["unique_id", "ds"],
        df=df,
        h=h,
        freq=freq,
        level=level,
        quantiles=quantiles,
    )

cross_validation

cross_validation(
    df: DataFrame,
    h: int,
    freq: str | None = None,
    n_windows: int = 1,
    step_size: int | None = None,
    level: list[int | float] | None = None,
    quantiles: list[float] | None = None,
) -> DataFrame

This method splits the time series into multiple training and testing windows and generates forecasts for each window. It enables evaluating forecast accuracy over different historical periods. Supports point forecasts and, optionally, prediction intervals or quantile forecasts.

Parameters:

Name Type Description Default
df DataFrame

DataFrame containing the time series to forecast. It must include as columns:

- "unique_id": an ID column to distinguish multiple series.
- "ds": a time column indicating timestamps or periods.
- "y": a target column with the observed values.
required
h int

Forecast horizon specifying how many future steps to predict in each window.

required
freq str

Frequency of the time series (e.g. "D" for daily, "M" for monthly). See Pandas frequency aliases for valid values. If not provided, the frequency will be inferred from the data.

None
n_windows int

Number of cross-validation windows to generate. Defaults to 1.

1
step_size int

Step size between the start of consecutive windows. If None, it defaults to h.

None
level list[int | float]

Confidence levels for prediction intervals, expressed as percentages (e.g. [80, 95]). When specified, the output DataFrame includes lower and upper interval columns for each level.

None
quantiles list[float]

Quantiles to forecast, expressed as floats between 0 and 1. Should not be used simultaneously with level. If provided, additional columns named "model-q-{percentile}" will appear in the output, where {percentile} is 100 × quantile value.

None

Returns:

Type Description
DataFrame

pd.DataFrame: DataFrame containing the forecasts for each cross-validation window. The output includes:

- "unique_id" column to indicate the series.
- "ds" column to indicate the timestamp.
- "y" column to indicate the target.
- "cutoff" column to indicate which window each forecast
  belongs to.
- point forecasts for each timestamp, series and model.
- prediction intervals if `level` is specified.
- quantile forecasts if `quantiles` is specified.
Source code in timecopilot/forecaster.py
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
def cross_validation(
    self,
    df: pd.DataFrame,
    h: int,
    freq: str | None = None,
    n_windows: int = 1,
    step_size: int | None = None,
    level: list[int | float] | None = None,
    quantiles: list[float] | None = None,
) -> pd.DataFrame:
    """
    This method splits the time series into multiple training and testing
    windows and generates forecasts for each window. It enables evaluating
    forecast accuracy over different historical periods. Supports point
    forecasts and, optionally, prediction intervals or quantile forecasts.

    Args:
        df (pd.DataFrame):
            DataFrame containing the time series to forecast. It must
            include as columns:

                - "unique_id": an ID column to distinguish multiple series.
                - "ds": a time column indicating timestamps or periods.
                - "y": a target column with the observed values.

        h (int):
            Forecast horizon specifying how many future steps to predict in
            each window.
        freq (str, optional):
            Frequency of the time series (e.g. "D" for daily, "M" for
            monthly). See [Pandas frequency aliases](https://pandas.pydata.
            org/pandas-docs/stable/user_guide/timeseries.html#offset-aliases)
            for valid values. If not provided, the frequency will be inferred
            from the data.
        n_windows (int, optional):
            Number of cross-validation windows to generate. Defaults to 1.
        step_size (int, optional):
            Step size between the start of consecutive windows. If None, it
            defaults to `h`.
        level (list[int | float], optional):
            Confidence levels for prediction intervals, expressed as
            percentages (e.g. [80, 95]). When specified, the output
            DataFrame includes lower and upper interval columns for each
            level.
        quantiles (list[float], optional):
            Quantiles to forecast, expressed as floats between 0 and 1.
            Should not be used simultaneously with `level`. If provided,
            additional columns named "model-q-{percentile}" will appear in
            the output, where {percentile} is 100 × quantile value.

    Returns:
        pd.DataFrame:
            DataFrame containing the forecasts for each cross-validation
            window. The output includes:

                - "unique_id" column to indicate the series.
                - "ds" column to indicate the timestamp.
                - "y" column to indicate the target.
                - "cutoff" column to indicate which window each forecast
                  belongs to.
                - point forecasts for each timestamp, series and model.
                - prediction intervals if `level` is specified.
                - quantile forecasts if `quantiles` is specified.
    """
    return self._call_models(
        "cross_validation",
        merge_on=["unique_id", "ds", "cutoff"],
        df=df,
        h=h,
        freq=freq,
        n_windows=n_windows,
        step_size=step_size,
        level=level,
        quantiles=quantiles,
    )

detect_anomalies

detect_anomalies(
    df: DataFrame,
    h: int | None = None,
    freq: str | None = None,
    n_windows: int | None = None,
    level: int | float = 99,
) -> DataFrame

Detect anomalies in time-series using a cross-validated z-score test.

This method uses rolling-origin cross-validation to (1) produce adjusted (out-of-sample) predictions and (2) estimate the standard deviation of forecast errors. It then computes a per-point z-score, flags values outside a two-sided prediction interval (with confidence level), and returns a DataFrame with results.

Parameters:

Name Type Description Default
df DataFrame

DataFrame containing the time series to detect anomalies.

required
h int

Forecast horizon specifying how many future steps to predict. In each cross validation window. If not provided, the seasonality of the data (inferred from the frequency) is used.

None
freq str

Frequency of the time series (e.g. "D" for daily, "M" for monthly). See Pandas frequency aliases for valid values. If not provided, the frequency will be inferred from the data.

None
n_windows int

Number of cross-validation windows to generate. If not provided, the maximum number of windows (computed by the shortest time series) is used. If provided, the number of windows is the minimum between the maximum number of windows (computed by the shortest time series) and the number of windows provided.

None
level int | float

Confidence levels for z-score, expressed as percentages (e.g. 80, 95). Default is 99.

99

Returns:

Type Description
DataFrame

pd.DataFrame: DataFrame containing the forecasts for each cross-validation window. The output includes:

- "unique_id" column to indicate the series.
- "ds" column to indicate the timestamp.
- "y" column to indicate the target.
- model column to indicate the model.
- lower prediction interval.
- upper prediction interval.
- anomaly column to indicate if the value is an anomaly.
    an anomaly is defined as a value that is outside of the
    prediction interval (True or False).
Source code in timecopilot/forecaster.py
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
def detect_anomalies(
    self,
    df: pd.DataFrame,
    h: int | None = None,
    freq: str | None = None,
    n_windows: int | None = None,
    level: int | float = 99,
) -> pd.DataFrame:
    """
    Detect anomalies in time-series using a cross-validated z-score test.

    This method uses rolling-origin cross-validation to (1) produce
    adjusted (out-of-sample) predictions and (2) estimate the
    standard deviation of forecast errors. It then computes a per-point z-score,
    flags values outside a two-sided prediction interval (with confidence `level`),
    and returns a DataFrame with results.

    Args:
        df (pd.DataFrame):
            DataFrame containing the time series to detect anomalies.
        h (int, optional):
            Forecast horizon specifying how many future steps to predict.
            In each cross validation window. If not provided, the seasonality
            of the data (inferred from the frequency) is used.
        freq (str, optional):
            Frequency of the time series (e.g. "D" for daily, "M" for
            monthly). See [Pandas frequency aliases](https://pandas.pydata.
            org/pandas-docs/stable/user_guide/timeseries.html#offset-aliases)
            for valid values. If not provided, the frequency will be inferred
            from the data.
        n_windows (int, optional):
            Number of cross-validation windows to generate.
            If not provided, the maximum number of windows
            (computed by the shortest time series) is used.
            If provided, the number of windows is the minimum
            between the maximum number of windows
            (computed by the shortest time series)
            and the number of windows provided.
        level (int | float):
            Confidence levels for z-score, expressed as
            percentages (e.g. 80, 95). Default is 99.

    Returns:
        pd.DataFrame:
            DataFrame containing the forecasts for each cross-validation
            window. The output includes:

                - "unique_id" column to indicate the series.
                - "ds" column to indicate the timestamp.
                - "y" column to indicate the target.
                - model column to indicate the model.
                - lower prediction interval.
                - upper prediction interval.
                - anomaly column to indicate if the value is an anomaly.
                    an anomaly is defined as a value that is outside of the
                    prediction interval (True or False).
    """
    return self._call_models(
        "detect_anomalies",
        merge_on=["unique_id", "ds", "cutoff"],
        df=df,
        h=h,  # type: ignore
        freq=freq,
        n_windows=n_windows,
        level=level,  # type: ignore
        quantiles=None,
    )

plot staticmethod

plot(
    df: DataFrame | None = None,
    forecasts_df: DataFrame | None = None,
    ids: list[str] | None = None,
    plot_random: bool = True,
    max_ids: int | None = 8,
    models: list[str] | None = None,
    level: list[float] | None = None,
    max_insample_length: int | None = None,
    plot_anomalies: bool = False,
    engine: str = "matplotlib",
    palette: str | None = None,
    seed: int | None = None,
    resampler_kwargs: dict | None = None,
    ax: Axes | ndarray | Figure | None = None,
)

Plot forecasts and insample values.

Parameters:

Name Type Description Default
df DataFrame

DataFrame with columns [unique_id, ds, y]. Defaults to None.

None
forecasts_df DataFrame

DataFrame with columns [unique_id, ds] and models. Defaults to None.

None
ids list[str]

Time Series to plot. If None, time series are selected randomly. Defaults to None.

None
plot_random bool

Select time series to plot randomly. Defaults to True.

True
max_ids int

Maximum number of ids to plot. Defaults to 8.

8
models list[str]

Models to plot. Defaults to None.

None
level list[float]

Prediction intervals to plot. Defaults to None.

None
max_insample_length int

Maximum number of train/insample observations to be plotted. Defaults to None.

None
plot_anomalies bool

Plot anomalies for each prediction interval. Defaults to False.

False
engine str

Library used to plot. 'plotly', 'plotly-resampler' or 'matplotlib'. Defaults to 'matplotlib'.

'matplotlib'
palette str

Name of the matplotlib colormap to use for the plots. If None, uses the current style. Defaults to None.

None
seed int

Seed used for the random number generator. Only used if plot_random is True. Defaults to 0.

None
resampler_kwargs dict

Keyword arguments to be passed to plotly-resampler constructor. For further custumization ("show_dash") call the method, store the plotting object and add the extra arguments to its show_dash method. Defaults to None.

None
ax matplotlib axes, array of matplotlib axes or plotly Figure

Object where plots will be added. Defaults to None.

None
Source code in timecopilot/models/utils/forecaster.py
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
@staticmethod
def plot(
    df: pd.DataFrame | None = None,
    forecasts_df: pd.DataFrame | None = None,
    ids: list[str] | None = None,
    plot_random: bool = True,
    max_ids: int | None = 8,
    models: list[str] | None = None,
    level: list[float] | None = None,
    max_insample_length: int | None = None,
    plot_anomalies: bool = False,
    engine: str = "matplotlib",
    palette: str | None = None,
    seed: int | None = None,
    resampler_kwargs: dict | None = None,
    ax: plt.Axes | np.ndarray | plotly.graph_objects.Figure | None = None,
):
    """Plot forecasts and insample values.

    Args:
        df (pd.DataFrame, optional): DataFrame with columns
            [`unique_id`, `ds`, `y`]. Defaults to None.
        forecasts_df (pd.DataFrame, optional): DataFrame with
            columns [`unique_id`, `ds`] and models. Defaults to None.
        ids (list[str], optional): Time Series to plot. If None, time series
            are selected randomly. Defaults to None.
        plot_random (bool, optional): Select time series to plot randomly.
            Defaults to True.
        max_ids (int, optional): Maximum number of ids to plot. Defaults to 8.
        models (list[str], optional): Models to plot. Defaults to None.
        level (list[float], optional): Prediction intervals to plot.
            Defaults to None.
        max_insample_length (int, optional): Maximum number of train/insample
            observations to be plotted. Defaults to None.
        plot_anomalies (bool, optional): Plot anomalies for each prediction
            interval. Defaults to False.
        engine (str, optional): Library used to plot. 'plotly', 'plotly-resampler'
            or 'matplotlib'. Defaults to 'matplotlib'.
        palette (str, optional): Name of the matplotlib colormap to use for the
            plots. If None, uses the current style. Defaults to None.
        seed (int, optional): Seed used for the random number generator. Only
            used if plot_random is True. Defaults to 0.
        resampler_kwargs (dict, optional): Keyword arguments to be passed to
            plotly-resampler constructor. For further custumization ("show_dash")
            call the method, store the plotting object and add the extra arguments
            to its `show_dash` method. Defaults to None.
        ax (matplotlib axes, array of matplotlib axes or plotly Figure, optional):
            Object where plots will be added. Defaults to None.
    """
    df = ensure_time_dtype(df, time_col="ds")
    if forecasts_df is not None:
        forecasts_df = ensure_time_dtype(forecasts_df, time_col="ds")
        if any("anomaly" in col for col in forecasts_df.columns):
            df = None
            models = [
                col.split("-")[0]
                for col in forecasts_df.columns
                if col.endswith("-anomaly")
            ]
            forecasts_df = ufp.drop_columns(
                forecasts_df,
                [f"{model}-anomaly" for model in models],
            )
            lv_cols = [
                c.replace(f"{model}-lo-", "")
                for model in models
                for c in forecasts_df.columns
                if f"{model}-lo-" in c
            ]
            level = [float(c) if "." in c else int(c) for c in lv_cols]
            level = list(set(level))
            plot_anomalies = True
    return plot_series(
        df=df,
        forecasts_df=forecasts_df,
        ids=ids,
        plot_random=plot_random,
        max_ids=max_ids,
        models=models,
        level=level,
        max_insample_length=max_insample_length,
        plot_anomalies=plot_anomalies,
        engine=engine,
        resampler_kwargs=resampler_kwargs,
        palette=palette,
        seed=seed,
        id_col="unique_id",
        time_col="ds",
        target_col="y",
        ax=ax,
    )