Skip to main content

TSIGenerator

Bases: BaseGenerator Generate series by composing randomized Trend, Seasonality and Irregularity components. The component-based construction is based on Bahrpeyma et al. (2021), “A Methodology for Validating Diversity in Synthetic Time Series Generation,” https://doi.org/10.1016/j.mex.2021.101459. SynForecast’s component families, sampling distributions, and stability guards are its own extensions rather than a reproduction of that paper’s generator. Every series draws a fresh random configuration: a trend type from trend_types, 0-3 seasonal harmonics with periods from seasonal_periods (integer and non-integer, so multiple harmonics are incommensurate), and an irregular (noise) process from irregular_types. The components are combined additively, or multiplicatively with probability multiplicative_prob when the trend base can be kept positive:
where c caps the relative seasonal swing so the factor stays positive. Trend shapes are normalized so their total movement over the series is drawn from trend_slope_range regardless of length; harmonic amplitudes are log-uniform; the noise scale is a log-uniform fraction of the structural signal’s standard deviation, so the pool spans signal-dominated through noise-dominated series. A per-series level and log-uniform scale spread series across magnitudes. Degenerate or exploding draws (non-finite, |y| >= 1e8, or constant) are redrawn a bounded number of times. Parameters:

TSIGenerator.generate_single_series

Generate values for a single TSI-composed time series. Parameters: Returns:

TCMGenerator

Bases: BaseGenerator Generate series from a random temporal structural causal model (SCM). Each series gets a freshly sampled SCM over n_vars latent variables: a sparse dependency graph over the (variable x lag) space is drawn, each edge is assigned a random edge function, and the system is rolled out autoregressively. Node i evolves as
with per-edge functions f_e(x) in
The temporal-SCM framing follows the overview in Runge et al. (2023), “Causal inference for time series,” https://doi.org/10.1038/s43017-023-00431-y. The particular graph sampler, edge-function mixture, stability rescaling, and guards here are original SynForecast design choices; this is not a reproduction of a named TCM generator from that paper or from Chronos-2. where x' is a second randomly-paired parent (product interaction) and tau a random threshold. Saturating kinds carry a log-uniform softness scale s and contribute c*s*tanh(x/s) (slope c near 0, bounded output). The returned univariate series is node 0 (nodes are exchangeable by construction); the remaining nodes act as latent parents, i.e. realistic exogenous-looking drivers. This produces genuine causal temporal structure — autocorrelation at sampled lags, lead-lag effects, nonlinear/regime-like dynamics — that component mixing cannot. Diversity is shaped per series: edge kinds follow a random Dirichlet mixture over edge_kinds (some series linear-dominated, others nonlinearity-dominated), coefficient magnitudes decay geometrically with lag (short-lag dominance), and, when ‘linear’ is in the pool, every node gets a positive linear self lag-1 edge so the observed node carries its own persistence. Stability: the linear-gain part (linear/tanh/relu edges) is assembled into VAR companion form and its coefficients are rescaled toward a per-series spectral-radius target below stability_margin — drawn near the margin with probability 0.22 (persistent, spectrally peaked series) and well below it otherwise (noise-like series); bounded-output edges cannot destabilize the core and keep their coefficients. During rollout every state is additionally soft-clamped via clamp * tanh(x / clamp) so nonlinear feedback cannot diverge. If a trajectory still fails the finiteness/scale guard, the SCM is redrawn (up to 5 times), then a guaranteed-stable linear AR(1) is used. The counters _redraw_total / _fallback_total and the last accepted SCM _last_scm are exposed for introspection on direct generate_single_series calls. Multivariate mode: with multivariate=True, generate(n_series) samples a single SCM (with at least n_series variables — the lower bound of n_vars_range is clamped up as needed) and one shared length, rolls the system out once, and returns the first n_series nodes as separate series in the long-format output (one unique_id per node, following VARGenerator). Because the nodes share one causal graph, they are genuinely cross-dependent at the sampled lags. The default multivariate=False keeps the univariate behavior: n_series independent SCMs, one observed node each. Parameters:

TCMGenerator.generate_single_series

Generate values for a single TCM series. Samples a fresh random SCM, rolls it out (with burn-in), and returns the target node. Redraws the SCM on guard failure, falling back to a stable linear AR(1) after _MAX_REDRAWS redraws. Parameters: Returns:

TCMGenerator.generate

Generate n_series time series from temporal causal models. With multivariate=False (default) this is the base behavior: n_series independent SCMs, one observed node each. With multivariate=True the n_series series are the first n_series nodes of one shared SCM, sharing a single length (following VARGenerator); generation is inherently joint, so n_jobs has no effect in that mode. Parameters: Returns:

KernelSynthGenerator

Bases: BaseGenerator Generate series by sampling from randomly composed Gaussian-process kernels. This adapts the KernelSynth recipe introduced for pretraining the Chronos forecasting models (Ansari et al. 2024, “Chronos: Learning the Language of Time Series”, https://arxiv.org/abs/2403.07815) and its Apache-2.0-licensed reference implementation (https://github.com/amazon-science/chronos-forecasting/blob/main/scripts/kernel-synth.py). For each series the generator draws 1..max_kernels base kernels (with replacement) from a fixed bank, folds them together with randomly chosen binary operators (+ or *), and samples one path from the resulting GP prior on the normalized grid x = linspace(0, 1, length). Kernel addition mixes behaviors (e.g. trend + seasonality); kernel multiplication modulates them (e.g. locally periodic, amplitude-varying seasonality). SynForecast makes the bank configurable, expresses seasonal periods in time steps on a normalized grid, and adds bounded retries, divergence guards, and optional standardization. Base kernels (r = |x_i - x_j|, all on the normalized grid):
  • rbf: exp(-r^2 / (2 l^2)) — smooth, length-scale l
  • rational_quadratic: (1 + r^2 / (2 a))^(-a) — scale mixture of RBFs, shape a
  • periodic (ExpSineSquared): exp(-2 sin^2(pi r / p_norm)) with p_norm = period / length so period is expressed in time steps
  • linear (DotProduct): s^2 + x_i x_j — trend / drift
  • white: w on the diagonal — independent noise
  • constant: a constant offset
Because a composed kernel can be near-degenerate or produce an exploding scale, non-finite, near-constant, or |y| >= 1e8 draws are redrawn a bounded number of times before falling back to Gaussian noise. Parameters:

KernelSynthGenerator.generate_single_series

Generate one KernelSynth series. Parameters: Returns:

MARGenerator

Bases: BaseGenerator Generate GRATIS-style mixtures of autoregressive components. The mixture autoregressive model is due to Wong and Li (2000, “On a mixture autoregressive model”, Journal of the Royal Statistical Society Series B 62(1), https://doi.org/10.1111/1467-9868.00222). This generator adapts the MAR simulation used for diverse series by GRATIS (Kang, Hyndman, and Li, 2020, “GRATIS: GeneRAting TIme Series with diverse and controllable characteristics”, https://arxiv.org/abs/1903.02787). At each step a component k is drawn from the mixture weights, then y_t = c_k + sum_i phi[k, i] y[t-i] + sigma_k eps_t. The parameter sampling, partial-autocorrelation reparameterization via Durbin-Levinson, defaults, and stability guards are SynForecast’s own design rather than a reproduction of the reference gratis R package. Random mode samples one to max_components components for every series; seasonal_period only affects random mode, where it enables a seasonal AR factor for a random subset of components. Fixed mode supplies all four of weights, ar_coefficients, intercepts, and noise_scales and is used by feature targeting. Every fixed component must be stationary, and the mixture must be second-order stationary (Wong and Li 2000). The numerical mixture check handles effective AR orders through 32, using covariance contraction certificates and a NumPy dense eigenvalue fallback. Solver failures are rejected. Validation results are cached. Larger mixtures are accepted when all components are identical and stable, or every component’s sum of absolute AR coefficients is below one. Other large mixtures raise an error because stationarity could not be verified; this conservative policy can reject valid mixtures. Trailing zero coefficients do not count toward effective order. A fixed model that fails the finite, bounded, non-constant output guards raises a ValueError at generation time instead of silently substituting noise. Moment handling is explicit: standardize=True (the default) maps every accepted multi-observation draw to zero mean and unit standard deviation, rather than retaining the MAR model’s component-implied level and scale. Set standardize=False to preserve those raw simulated moments. This output normalization is SynForecast’s own design and is not source-series moment matching. Bulk :meth:generate calls use the native Rust batch path; :meth:generate_single_series remains the Python reference path, so their seeded RNG streams are not bit-for-bit equivalent.

MARGenerator.generate_single_series

Generate one finite MAR series of exactly length observations. Random mode falls back to standard normal noise after _MAX_RETRIES rejected draws. Fixed mode raises ValueError instead.

MARGenerator.tune_to_features

Tune fixed MAR parameters toward requested GRATIS-style features. Supported names are spectral_entropy, trend_strength, seasonal_strength, and acf1, as defined by :func:synforecast._features.compute_targeting_features. This implements GRATIS feature-targeted generation (Kang et al. 2020, https://arxiv.org/abs/1903.02787) as a seeded evolutionary search over MAR parameters. The elitism, PACF-space Gaussian mutation, and minimal feature set are SynForecast’s own design rather than a reproduction of the GRATIS genetic algorithm. Candidate draw lengths are spaced evenly across min_length..max_length so the result targets the configured length range rather than one endpoint. The default budget evaluates at most 15 * 30 * 3 series; the search stops early once the best L2 feature distance is at or below tolerance. Infeasible targets return the best candidate after the fixed budget. Candidates whose mixture is not second-order stationary, or whose simulation fails the output guards, receive infinite fitness. The returned generator’s tuning_diagnostics records the best observed distance, whether tolerance was reached, generations run, and candidates evaluated. Each generation scores its valid candidates together in native Rust, parallelized across candidates. Failed simulations affect only their own candidate. n_jobs=-1 uses the default Rayon pool; a positive value selects the worker count. Results are independent of worker count. This native search uses a different seeded stream from the former Python simulation loop. Lengths are limited to 1,000,000 observations. Additional generator options are forwarded to candidate evaluation and the returned generator: standardize, burn_in, innovation_distribution, innovation_params, engine, alias, id_col, time_col, target_col, and start_datetime. Search-owned model parameters and pattern injection options are rejected.

MARGenerator.tuning_diagnostics

Search distance, convergence, and budget used, or None if untuned. best_distance is the selected candidate’s observed training fitness, not a guarantee about new draws. The returned dictionary is a copy.