Time Series Generator
foretools/tsgen/ts_gen.py provides a pedagogical synthetic time-series generator with explicit structural components. It is useful when you need data that is fully controlled, explainable, and easy to visualize.
Import path
python
from foretools.tsgen import TimeSeriesGeneratorWhat make() returns
df
A tidy dataframe with one row per timestamp per series.
Expected columns:
seriestimey- optional exogenous columns such as
x1,x2, ... - optional calendar columns such as
month,dayofweek,fourier_wk_sin,fourier_yr_cos
meta
A metadata dictionary that contains the ground truth behind the generated series.
Most useful keys:
meta["time_index"]: shared pandas time indexmeta["params"]: the configuration used to generate the datameta["components"]: arrays for trend, seasonality, cycle, noise, regime bias, and exogenous effectmeta["states"]: latent regime state path when regime switching is enabledmeta["missing_mask"]: missing-value mask if missingness was injectedmeta["splits"]: chronological split boundaries ifsplits=was requested
Supported component families
| Component | Main options | Notes |
|---|---|---|
| Trend | linear, poly, piecewise | piecewise uses knots and per-segment slopes |
| Seasonality | list of seasonal specs | each seasonal spec supports period, amplitude, phase, harmonics |
| Cycle | period, amplitude, freq_drift, phase | low-frequency oscillation separate from the main seasonal terms |
| Noise | ar, ma, sigma | ARMA-style base noise |
| Regime | n_states, transition matrix p, state_bias, state_sigma_scale | adds discrete state-dependent bias and volatility |
| Heteroskedasticity | {"type": "arch1", "alpha0": ..., "alpha1": ...} | replaces the base noise with ARCH-like noise |
| Outliers | prob, scale | injects heavy-tailed spikes |
| Missingness | prob, block_prob, block_max | applies missing values to y only |
| Exogenous inputs | n_features, types, beta | supported types are random_walk, seasonal, binary_event, noise |
| Multivariate mixing | n_factors, mix_strength | induces cross-series correlation after component synthesis |
| Calendar features | add_calendar=True | adds date parts and Fourier encodings |
Common examples
1. Fully observed structural series
Use this when you want clean series for plotting, teaching, or debugging a model's ability to recover trend and seasonality.
python
df, meta = gen.make(
n_series=2,
n_steps=400,
trend={"type": "linear", "slope": 0.03, "intercept": 5.0},
seasonality=[{"period": 7.0, "amplitude": 3.0, "harmonics": 2}],
cycle={"period": 160.0, "amplitude": 1.2},
noise={"ar": [0.5], "ma": [0.1], "sigma": 0.4},
return_components=True,
)2. Create a train/val/test split quickly
make_train_ready() pivots the generated data into wide format and reserves the last two horizons for validation and test.
python
dataset = gen.make_train_ready(
n_series=3,
n_steps=240,
horizon=24,
trend={"type": "linear", "slope": 0.02},
seasonality=[{"period": 24.0, "amplitude": 1.5}],
noise={"ar": [0.3], "sigma": 0.5},
)
train_df = dataset["train"]
val_df = dataset["val"]
test_df = dataset["test"]
meta = dataset["meta"]plot_series()shows the observedypath for a single series.plot_decompose()renders separate trend, seasonality, cycle, and noise plots.
Practical behavior to know
- Missingness is applied after the full signal is constructed, and only to the
ycolumn. - When
heterosked={"type": "arch1", ...}is enabled, the generator replaces the previously built base noise with ARCH-like noise for clarity. - Calendar features are shared across all series because they come from the common timestamp index.
- Multivariate factor mixing happens after the univariate structural components are combined, so it affects the final series rather than individual components.
return_components=Falsekeeps the dataframe output but omits the large component arrays frommeta.
Recommended workflow
- Start with
return_components=Trueso you can inspect the exact decomposition. - Keep missingness and outliers off for first-pass model debugging.
- Add regimes, exogenous drivers, and missingness only after the baseline workflow is working.
- Use
plot_series()andplot_decompose()when you want publication-style plots or teaching material.