Synthetic Data Generator¶
generator
¶
Pure example-data generator — no I/O.
Deterministic panel math: each series is a sum of readable components —
trend + short-cycle & yearly seasonality + holiday bumps + AR(1) noise — then shaped by
an archetype (smooth-seasonal, intermittent, trending, promo-spiky, noisy) that applies
intermittency, level shifts, and promo spikes. Seasonality is measured in steps (via the
shared seasonality maps), so the panel is coherent at any freq — daily, weekly,
monthly, hourly — and daily output is byte-for-byte the same as day-count math. Every series
draws its parameters from an rng seeded by its own index, so:
- series
iis byte-for-byte identical no matter which partition produced it — hencegenerate_panel(n)equals the union of any partitioning ofrange(n)(the property the Spark seed job relies on), and - one master
seedreproduces the whole 100k dataset on every deployment.
The five archetypes deliberately favor different models — that's what makes the ensemble and straggler contrasts visible downstream. The golden test fixture is a tiny call into this same code, so tests and shipped data share one path.
Public surface: GenConfig, generate_partition, generate_panel.
Archetype
dataclass
¶
Archetype(
name,
base,
trend_frac,
weekly_amp,
yearly_amp,
noise_frac,
ar1_rho,
holiday_frac,
zero_inflation,
spike_rate,
spike_mult,
level_shift_prob,
)
One series "personality". Each field is a (low, high) range the per-series rng
samples uniformly, or a scalar probability. Distinct profiles make distinct models win.
GenConfig
dataclass
¶
GenConfig(
history=1460,
freq="D",
start="2021-01-01",
holidays=("US",),
with_exog=False,
with_hierarchy=False,
)
How to shape each series — not how many. The count is the caller's id_range /
n (a partition of series ids), which keeps the partition-union invariant orthogonal
to the per-series knobs. Pure parameters — no source/sink here (that's seed_spark.py).
generate_panel
¶
Generate the full panel of the first n series — generate_partition(range(n)).
Because each series is seeded by its own index, this is exactly the union of any
partitioning of range(n) (the invariant the distributed seed job depends on), and
subsetting to the first k series (data.series_limit) is just a prefix of this.
Source code in src/scale_forecasting/data_gen/generator.py
generate_partition
¶
Generate the long-format panel for a set of series ids.
id_range is any iterable of integer series indices (a partition of the full range in
the Spark seed job). Returns a frame with columns ts_id, archetype, ds, y (plus
region, category when cfg.with_hierarchy or cfg.with_exog, and
promo_flag, price_index, temperature when cfg.with_exog), sorted by ts_id
then ds. Pure and deterministic: identical output for identical (id, cfg, seed).
Source code in src/scale_forecasting/data_gen/generator.py
is_holiday_flags
¶
Boolean holiday flags for a sequence of dates — the public view of the panel's calendar.
The generator applies holidays as a numeric bump on y (it emits no holiday column),
but the source_series table carries an is_holiday column the models read. This
derives that flag from the same holidays calendar the bump uses, so the shipped
is_holiday agrees with the effect baked into y (parity). Pure — used by
the Spark seed transform (data_gen.seed_spark).
ds is any date-like sequence (a column of generate_partition output, a list of
date/Timestamp); holidays is the country codes (e.g. ("US",)). Returns a
bool array aligned to ds.