Shuffler
Turn quantiles of marginal distribution forecasts returned by any model into sample paths from a joint forecast distribution using Shuffler.
A limitation of most probabilistic time series (foundation) models is that they return forecasts in the form of quantiles of marginal distributions, only. While this suffices to answer some questions, many use cases require a joint distribution over the forecast horizon to answer more complex questions, such as…
- “What is the probability that half of the product’s inventory will be consumed over the next 12 days?”
- “What is the probability that electricity prices will be higher than 200€/MWh for a period of six hours in the next 24 hours?”
Shuffler implements the copula-based approach by Baron et al. (2025), which injects an auto-correlation structure estimated from past observations into samples from the marginal distribution forecasted by any model, resulting in sample paths from a joint distribution forecast. The sample paths can then be aggregated to answer arbitrary questions.
Install Shuffler
Install Shuffler from Github. Use either pip…
pip install "git+https://github.com/timradtke/shuffler"
… or use uv:
uv pip install "git+https://github.com/timradtke/shuffler"
Get Started
Shuffler postprocesses quantile forecasts into sample paths. Therefore, you first forecast quantiles with some model and then you draw sample paths using Shuffler given the quantile forecasts. For the example here we’ll use Chronos-2, but you can use any model that returns its forecasts in the form of marginal quantiles.
Start by importing some helper libraries and defining the quantile levels to forecast. Use as many as make sense given your model. Chronos-2 is trained to forecast 21 quantiles (see section 3.2 in Chronos-2: From Univariate to Universal Forecasting), so use all of them.
import numpy as np
import shuffler as sf
# The following aren't dependencies of shuffler:
import pandas as pd
import matplotlib.pyplot as plt
from chronos import Chronos2Pipeline
Then reproduce the example from Chronos’s documentation, forecasting the next 24 hours of German electricity prices using some covariates.
horizon = 24
quantile_levels = [
0.01, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45,
0.5,
0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 0.99,
]
context_df = pd.read_parquet("train.parquet")
test_df = pd.read_parquet("test.parquet")
future_df = test_df.drop(columns="target")
pipeline = Chronos2Pipeline.from_pretrained(
"amazon/chronos-2",
device_map="cpu"
)
pred_df = pipeline.predict_df(
context_df,
future_df=future_df,
prediction_length=horizon,
quantile_levels=quantile_levels,
id_column="id",
timestamp_column="timestamp",
target="target",
)
Applying Shuffler is model-agnostic. Take the quantile forecasts (here we need to separate them from the other information in pred_df) and pass them to Shuffler’s workhorse function, draw_sample_paths(). Given past observations of the target time series, it fits a copula to that turns the marginal distributions specified by the provided quantile forecasts into a joint distribution over the forecast horizon. The returned object is a numpy array of sample paths drawn from the joint distribution, of shape (n_samples, horizon).
# Extract the quantile forecasts from `pred_df`, then
# reshape them to a numpy array with shape
# (len(quantile_levels), horizon).
quantile_column_names = [str(x) for x in quantile_levels]
quantile_forecasts = \
pred_df[quantile_column_names].to_numpy().transpose()
# Fit a copula to learn a joint forecast distribution.
sample_paths = sf.draw_sample_paths(
quantile_forecasts=quantile_forecasts,
# Same as for Chronos:
quantile_forecast_levels=np.array(quantile_levels),
# Provide past observations:
y=context_df["target"].to_numpy(),
horizon=horizon,
size=n_samples,
seed=128,
)
Finally, visualize the first three sample paths along with the observed data. Note the sample paths’ smooth behavior, reminiscent of the observed data. Shuffler’s copula injects auto-correlation structure into the sample paths to ensure a realistic joint distribution even though we started from only marginal quantile forecasts.

Refer to the extended tutorial notebook for more details.
References
Shuffler is an implementation of the copula-based approach to transform marginal quantile forecasts into sample paths described in Efficiently Generating Correlated Sample Paths from Multi-step Time Series Foundation Models (Baron et al., 2025).
The approach relies on interpolating and extrapolating arbitrary quantiles of a given marginal distribution given only a limited number of its quantiles (in the above example, only 21 quantiles of the marginal distribution were known, not the full marginal distribution). Shuffler (just like Baron et al. (2025)) follows the inter/extrapolation approach described in section 3.2 of Learning Quantile Functions without Quantile Crossing for Distribution-free Time Series Forecasting (Park et al., 2021).