Skip to main content

tsfm provides an easy interface to use TimeSeries Foundational Models.

Project description

TSFM Logo

Time Series Forecasting Models (TSFM)

A unified Python framework for time series forecasting that makes it easy to switch between classical statistical models and modern foundation models with just a single line of code.

Why TSFM?

Forecasting time series data shouldn't require rewriting your entire pipeline when you want to try a different model. TSFM provides:

  • One Interface, Multiple Models: Switch from autoregressive models to state-of-the-art foundation models (Moirai, Chronos) by changing just the model name
  • Works With Any Frequency: Automatically detects whether your data is monthly, quarterly, weekly, or daily - no manual configuration needed
  • Batteries Included: Built-in metrics (RMSFE, MAE, ME), visualizations, and prediction intervals out of the box
  • Production Ready: Consistent API across all models makes it easy to integrate into your workflow

Quick Start

Installation

Create a dedicated conda environment:

conda create -n tsfm python==3.12 ipykernel
conda activate tsfm
pip install tsfmecb
# Optional: register Jupyter kernel if you work within a notebook environment
python -m ipykernel install --user --name=tsfm --display-name "tsfm"

Your First Forecast

from tsfm import Model, generator

# Generate some sample data (or use your own DataFrame)
df = generator()

# Build a model - try "armodel", "moirai", "moirai2", "chronos", or "chronos2"
mdl = Model.build(name="moirai2")

# Generate forecasts
yhs = mdl.pred(df, y="y", ctx_len=12, horizon=6, oos_start="2005-01-31")

# View results
yhs.summary()  # See metrics
yhs.plot_actual_vs_pred(horizon=1)  # Visualize forecasts

That's it! The model automatically:

  • Detects your data frequency
  • Handles the forecasting
  • Computes accuracy metrics
  • Provides prediction intervals

Try Different Models

The beauty of TSFM is how easy it is to compare models:

# Classical autoregressive model
mdl_ar = Model.build(name="armodel")
yhs_ar = mdl_ar.pred(df, y="y", ctx_len=12, horizon=6, oos_start="2005-01-31")

# Salesforce Moirai foundation model
mdl_moirai = Model.build(name="moirai2")
yhs_moirai = mdl_moirai.pred(df, y="y", ctx_len=12, horizon=6, oos_start="2005-01-31")

# Amazon Chronos foundation model
mdl_chronos = Model.build(name="chronos2")
yhs_chronos = mdl_chronos.pred(df, y="y", ctx_len=12, horizon=6, oos_start="2005-01-31")

# Compare accuracy
print(f"AR RMSFE: {yhs_ar.rmsfe.values.mean():.3f}")
print(f"Moirai RMSFE: {yhs_moirai.rmsfe.values.mean():.3f}")
print(f"Chronos RMSFE: {yhs_chronos.rmsfe.values.mean():.3f}")

Works With Any Frequency

Have quarterly data? No problem:

# Resample to quarterly
df_quarterly = df.resample('Q').mean()

# Same code works - frequency is detected automatically
mdl = Model.build(name="moirai2")
yhs = mdl.pred(df_quarterly, y="y", ctx_len=4, horizon=2, oos_start="2005Q1")

# horizon=1 now means "next quarter" (not next month!)
yhs.plot_actual_vs_pred(horizon=1)

Supports monthly (M), quarterly (Q), weekly (W), daily (D), and any pandas frequency.

Available Models

Model Type Covariates Speed
armodel Classical AR ⚡⚡⚡
moirai Foundation (Salesforce 1.1) ⚡⚡
moirai2 Foundation (Salesforce 2.0) ⚡⚡
chronos Foundation (Amazon Bolt) ⚡⚡
chronos2 Foundation (Amazon 2.0) ⚡⚡

What You Get

Every forecast returns a ForecastOutput object with:

  • Predictions: Full DataFrame with actuals vs predictions by horizon and quantile
  • Metrics: RMSFE, MAE, ME computed automatically
  • Visualization: Built-in plotting with prediction intervals
  • Uncertainty: Quantile forecasts (10th, 50th, 90th percentiles, etc.)
# Access predictions
yhs.df_preds  # MultiIndex DataFrame

# Get metrics by horizon
yhs.rmsfe  # Root Mean Squared Forecast Error
yhs.mae    # Mean Absolute Error
yhs.me     # Mean Error

# Quick summary
yhs.summary()

# Plot with uncertainty bands
yhs.plot_actual_vs_pred(horizon=1)

Learn More

Check out the tutorial notebook for:

  • Data format requirements
  • Model selection guidance
  • Uncertainty quantification
  • Troubleshooting tips
  • Advanced usage examples

Technical Documentation

Architecture Overview

TSFM is a unified time series forecasting framework that supports multiple frequencies (monthly, quarterly, etc.) with automatic frequency inference. It provides a consistent interface across classical statistical models and modern foundation models.

Key Features

  • Automatic Frequency Inference: No need to specify data frequency - it's detected from the DataFrame's DatetimeIndex
  • Multiple Model Support: Classical AR models and state-of-the-art foundation models (Moirai, Chronos)
  • Unified API: Consistent interface across all models with pred() method
  • Frequency-Aware Metrics: Horizons adapt to your data frequency (horizon=1 means next period, regardless of frequency)
  • Rich Outputs: Built-in metrics (RMSFE, MAE, ME) and visualization with prediction intervals

UML Diagram

classDiagram
    %% Exceptions
    class TSFMError {
        <<Exception>>
    }
    
    class InvalidInputError {
        <<Exception>>
        +__init__(message: str)
    }
    
    Exception <|-- TSFMError
    TSFMError <|-- InvalidInputError
    
    %% Output Classes
    class ForecastOutput {
        -df_preds: DataFrame
        -meta: dict[str, Any]
        +rmsfe: DataFrame
        +mae: DataFrame
        +me: DataFrame
        +metric(name: Literal) DataFrame
        +summary(digits: int) None
        +plot_actual_vs_pred(horizon: int, ax: Axes, start: Timestamp, end: Timestamp, return_ax: bool) Axes
        -_agg_mean(s: Series, name: str, post: Callable) DataFrame
        -_summary(digits: int) str
    }
    
    %% Base Model (Abstract)
    class Model {
        <<Abstract>>
        +registry: ClassVar[dict]
        +name: property
        +__init_subclass__(cls, name: str, **kwargs)
        +build(name: str, **kwargs) Model
        +get_backbone() Any*
        +_pred(df: DataFrame, y: str, X: list, ctx_len: int, horizon: int, oos_start: str)* DataFrame
        +pred(df: DataFrame, y: str, X: list, ctx_len: int, horizon: int, oos_start: str) ForecastOutput
    }
    
    ABC <|-- Model
    
    %% ARModel
    class ARModel {
        +get_backbone() None
        +_pred(df: DataFrame, y: str, X: list, ctx_len: int, horizon: int, oos_start: str) DataFrame
    }
    
    Model <|-- ARModel : name="armodel"
    ARModel ..> InvalidInputError : raises
    ARModel ..> ForecastOutput : creates
    
    %% Moirai Model
    class Moirai {
        +get_backbone() MoiraiModule
        +get_model(ctx_len: int, horizon: int, n_covariates: int) MoiraiForecast
        +_pred(df: DataFrame, y: str, X: list, ctx_len: int, horizon: int, oos_start: str) DataFrame
    }
    
    Model <|-- Moirai : name="moirai"
    Moirai ..> ForecastOutput : creates
    
    %% Moirai2 Model
    class Moirai2 {
        +get_backbone() Moirai2Module
        +get_model(ctx_len: int, horizon: int, n_covariates: int) Moirai2Forecast
        +_pred(df: DataFrame, y: str, X: list, ctx_len: int, horizon: int, oos_start: str) DataFrame
    }
    
    Model <|-- Moirai2 : name="moirai2"
    Moirai2 ..> ForecastOutput : creates
    
    %% Chronos Model
    class Chronos {
        +get_backbone() BaseChronosPipeline
        +_pred(df: DataFrame, y: str, X: list, ctx_len: int, horizon: int, oos_start: str) DataFrame
    }
    
    Model <|-- Chronos : name="chronos"
    Chronos ..> ForecastOutput : creates
    
    %% Chronos2 Model
    class Chronos2 {
        +get_backbone() Chronos2Pipeline
        +_pred(df: DataFrame, y: str, X: list, ctx_len: int, horizon: int, oos_start: str) DataFrame
    }
    
    Model <|-- Chronos2 : name="chronos2"
    Chronos2 ..> ForecastOutput : creates
    
    %% Data Module Functions
    class DataModule {
        <<module: data.py>>
        +infer_freq(df: DataFrame) str
        +generator(n: int, phi: float, beta0: float, beta1: float, sigma: float, trend: float, season_period: int, season_ampl: float, seed: int) DataFrame
        +split_is_oos(df: DataFrame, test_frac: float) tuple[DataFrame, DataFrame]
    }
    
    %% ARModel Helper Functions
    class ARModelHelpers {
        <<module: armodel.py>>
        +create_lags(var: Series, lags: int) DataFrame
        +get_design_matrix(ys: Series, y_lags: int, horizon: int) tuple[Series, DataFrame]
        +fit(ys: Series, y_lags: int, horizon: int) RegressionResultsWrapper
        +pred(ys: Series, y_lags: int, horizon: int, oos_start: str) Series
        +build_oos_panel(ys: Series, y_lags: int, horizon: int, oos_start: str, freq: str) DataFrame
        -_to_period_end(idx: Index, freq: str) DatetimeIndex
    }
    
    ARModel ..> ARModelHelpers : uses
    
    %% Moirai Helper Functions
    class MoiraiHelpers {
        <<module: moirai.py>>
        +make_fc_df(forecasts: list, y_true_series: Series, freq: str) DataFrame
        +prepare_data(df: DataFrame, y: str, X: list, horizon: int, oos_start: str, freq: str) TestData
        +MODEL_ID: str
    }
    
    Moirai ..> MoiraiHelpers : uses
    
    %% Moirai2 Helper Functions
    class Moirai2Helpers {
        <<module: moirai2.py>>
        +make_fc_df(forecasts: list, y_true_series: Series, freq: str) DataFrame
        +prepare_data(df: DataFrame, y: str, X: list, horizon: int, oos_start: str, freq: str) TestData
        +MODEL_ID: str
    }
    
    Moirai2 ..> Moirai2Helpers : uses
    
    %% Chronos Helper Functions
    class ChronosHelpers {
        <<module: chronos.py>>
        +prepare_data(df: DataFrame, y: str, X: list, ctx_len: int, oos_start: str, freq: str) DataFrame
        +make_fc_df(forecasts: DataFrame, y_true: DataFrame, horizon: int, freq: str) DataFrame
        +BOLT_MODEL_ID: str
    }
    
    Chronos ..> ChronosHelpers : uses
    
    %% Chronos2 Helper Functions
    class Chronos2Helpers {
        <<module: chronos2.py>>
        +prepare_data(df: DataFrame, y: str, X: list, ctx_len: int, oos_start: str, freq: str) DataFrame
        +make_fc_df(forecasts: DataFrame, y_true: DataFrame, horizon: int, freq: str) DataFrame
        +MODEL_ID: str
    }
    
    Chronos2 ..> Chronos2Helpers : uses
    
    %% Output Helper Functions
    class OutputHelpers {
        <<module: outputs.py>>
        +get_horizon_groupby(df: DataFrame, freq: str) Index
    }
    
    ForecastOutput ..> OutputHelpers : uses
    
    %% Relationships with external libraries
    Model ..> ForecastOutput : returns
    Model ..> DataModule : uses infer_freq
    
    %% Package level
    class TSFMPackage {
        <<module: __init__.py>>
        +ARModel
        +Model
        +Moirai
        +Moirai2
        +Chronos
        +Chronos2
        +generator
    }
    
    TSFMPackage ..> ARModel : exports
    TSFMPackage ..> Model : exports
    TSFMPackage ..> Moirai : exports
    TSFMPackage ..> Moirai2 : exports
    TSFMPackage ..> Chronos : exports
    TSFMPackage ..> Chronos2 : exports
    TSFMPackage ..> DataModule : exports generator

    %% Notes
    note for Model "Registry pattern:\nSubclasses auto-register\nby name parameter\nAuto-infers frequency from data"
    
    note for ForecastOutput "Contains forecast results\nwith MultiIndex[cutoff, oos_date]\nFrequency-aware metrics\nand visualization"
    
    note for ARModel "Autoregressive model\nusing statsmodels OLS\nwith HAC standard errors\nNo covariate support"
    
    note for Moirai "Pretrained foundation model\nfrom Salesforce\nmodel: moirai-1.1-R-small\nSupports covariates"
    
    note for Moirai2 "Pretrained foundation model\nfrom Salesforce\nmodel: moirai-2.0-R-small\nuses uni2ts library\nSupports covariates"
    
    note for Chronos "Amazon Chronos-Bolt model\nchronos-bolt-small\nNo covariate support\nFrequency-aware"
    
    note for Chronos2 "Amazon Chronos 2.0 model\namazon/chronos-2\nSupports covariates\nFrequency-aware"
    
    note for DataModule "infer_freq:\nAuto-detects frequency\nfrom DatetimeIndex\nSupports M, Q, W, D, etc."

Class Descriptions

Core Classes

  1. Model (Abstract Base Class)

    • Registry pattern for dynamic model creation
    • All models inherit from this class
    • Defines interface: get_backbone() (abstract), _pred() (abstract), and pred() (concrete)
    • Registry allows building models by name: Model.build(name="armodel")
    • Automatically infers frequency from DataFrame and passes to ForecastOutput
  2. ARModel

    • Autoregressive time series model using classical statistical methods
    • Uses statsmodels for OLS regression with HAC standard errors
    • Does not support covariates (raises InvalidInputError)
    • Implements expanding window forecasting
    • Frequency-aware: automatically adapts to monthly, quarterly, or other frequencies
  3. Moirai

    • Wrapper for Salesforce's Moirai 1.1 foundation model (moirai-1.1-R-small)
    • Supports covariates via past_feat_dynamic_real
    • Uses GluonTS for data preparation
    • Generates 1,000 samples for probabilistic forecasting with quantile outputs
    • Frequency-aware with automatic normalization of timestamps
  4. Moirai2

    • Wrapper for Salesforce's Moirai 2.0 foundation model (moirai-2.0-R-small)
    • Supports covariates
    • Uses uni2ts library for inference
    • Quantile-based forecasting (median as point forecast)
    • Frequency-aware with automatic normalization of timestamps
  5. Chronos

    • Amazon Chronos-Bolt model (chronos-bolt-small)
    • Fast inference with quantile predictions
    • Does not support covariates
    • Frequency-aware with dynamic offset calculations
    • Returns quantile predictions (0.1 through 0.9)
  6. Chronos2

    • Amazon Chronos 2.0 model (amazon/chronos-2)
    • Supports covariates via DataFrame columns
    • Uses predict_df() interface for batch predictions
    • Frequency-aware with dynamic offset calculations
    • Returns quantile predictions and point forecasts

Data Structures

  1. ForecastOutput
    • Dataclass containing forecast results
    • MultiIndex DataFrame: (cutoff, oos_date)
    • Cached properties for metrics: RMSFE, MAE, ME
    • Frequency-aware metrics (stored in meta['freq'])
    • Methods for summary statistics and plotting
    • plot_actual_vs_pred(): Visualize forecasts with prediction intervals
    • Horizon parameter adapts to data frequency (horizon=1 = next period)

Exceptions

  1. TSFMError

    • Base exception for the package
  2. InvalidInputError

    • Raised when input validation fails (e.g., covariates not supported)

Utility Modules

  1. DataModule (data.py)

    • infer_freq(): Automatically detects frequency from DataFrame's DatetimeIndex
    • generator(): Simulates time series with AR, trend, seasonality
    • split_is_oos(): Splits data into train/test
  2. Helper Functions

    • ARModel helpers: lag creation, design matrix, OLS fitting, frequency-aware period alignment
    • Moirai helpers: forecast formatting with frequency parameter, GluonTS data preparation
    • Moirai2 helpers: forecast formatting with frequency parameter, uni2ts data preparation
    • Chronos helpers: rolling window data preparation, frequency-aware offset handling
    • Chronos2 helpers: DataFrame-based data preparation, frequency-aware offset handling
    • Output helpers: horizon grouping with frequency awareness

Architecture Patterns

  • Registry Pattern: Models self-register via __init_subclass__ enabling dynamic instantiation
  • Template Method: Base Model.pred() calls abstract _pred() and handles common logic
  • Dataclass: ForecastOutput with cached properties for lazy metric computation
  • Facade: Simple interface (pred()) over complex forecasting logic
  • Frequency Inference: Automatic detection and propagation of time series frequency throughout the pipeline

Frequency Support

All models automatically detect and adapt to your data's frequency:

  • Monthly (M): Standard month-end dates
  • Quarterly (Q): Quarter-end dates
  • Weekly (W): Week-end dates
  • Daily (D): Daily dates
  • Custom: Any pandas frequency string

The frequency is:

  1. Inferred from the DataFrame's DatetimeIndex using pd.infer_freq()
  2. Passed through the prediction pipeline
  3. Stored in ForecastOutput.meta['freq']
  4. Used for horizon calculations, metrics, and plotting

Detailed API Usage

Monthly Data Example

from tsfm import Model, generator

# Generate monthly data (frequency auto-detected)
df = generator()

# Build and use any model
mdl = Model.build(name="moirai2")
yhs = mdl.pred(df, y="y", ctx_len=12, horizon=6, oos_start="2005-01-31")

# View metrics
yhs.summary()

# Plot forecasts (horizon=1 means next month)
yhs.plot_actual_vs_pred(horizon=1)

Quarterly Data Example

# Resample to quarterly (frequency auto-detected as 'Q')
df_quarterly = df.resample('Q').mean()

# Use the same interface - frequency is handled automatically
mdl = Model.build(name="chronos2")
yhs = mdl.pred(df_quarterly, y="y", ctx_len=4, horizon=2, oos_start="2005Q1")

# horizon=1 now means next quarter (not next 3 months!)
yhs.plot_actual_vs_pred(horizon=1)

Model Selection

# Classical statistical model
mdl = Model.build(name="armodel")

# Foundation models from Salesforce
mdl = Model.build(name="moirai")   # Moirai 1.1
mdl = Model.build(name="moirai2")  # Moirai 2.0

# Foundation models from Amazon
mdl = Model.build(name="chronos")   # Chronos-Bolt
mdl = Model.build(name="chronos2")  # Chronos 2.0

Accessing Metrics and Predictions

# Individual metrics
rmsfe = yhs.rmsfe  # Root Mean Squared Forecast Error by horizon
mae = yhs.mae      # Mean Absolute Error by horizon
me = yhs.me        # Mean Error by horizon

# Or use the metric method
yhs.metric("mae")

# Access raw predictions
yhs.df_preds  # MultiIndex DataFrame with y_true, y_pred, quantiles

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tsfmecb-0.1.5.tar.gz (13.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tsfmecb-0.1.5-py3-none-any.whl (19.7 kB view details)

Uploaded Python 3

File details

Details for the file tsfmecb-0.1.5.tar.gz.

File metadata

  • Download URL: tsfmecb-0.1.5.tar.gz
  • Upload date:
  • Size: 13.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.8.23

File hashes

Hashes for tsfmecb-0.1.5.tar.gz
Algorithm Hash digest
SHA256 42a6a8b02aa0051ff13ed878429249d78a6f5da5fa9fb1f7e89dddb25f0958f9
MD5 93a06fe32b5d6359d8fe2e1993a80e73
BLAKE2b-256 ef8f2bbdead29b14317dd5803a9a68ed7958877934f08e25fb59c8dc72221a22

See more details on using hashes here.

File details

Details for the file tsfmecb-0.1.5-py3-none-any.whl.

File metadata

  • Download URL: tsfmecb-0.1.5-py3-none-any.whl
  • Upload date:
  • Size: 19.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.8.23

File hashes

Hashes for tsfmecb-0.1.5-py3-none-any.whl
Algorithm Hash digest
SHA256 fb2d43292e5eb357c8c169c3e182c5891b3e353e6b5c9e222a5e78915006a880
MD5 cce363c1e518403ec0f7aeb78757af01
BLAKE2b-256 28325b0f9c37597062a2a4b05bae3431ba74ed5b4338ed30a34360acecc89a26

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page