Add holiday effects
The YAML builder can prepare CSV-driven holiday effects for ordinary MMM models. Choose the representation because it matches the modelling question, rather than because a calendar variable improves in-sample fit.
| Mode | Representation |
|---|---|
event | Smooth effects for uniquely named event rows |
pooled_control | A binary any-holiday indicator |
prophet_component | A frozen target-fitted Prophet component with an MMM coefficient |
holidays:
enabled: true
mode: prophet_component
path: holidays.csv
countries: [UK]
prefix: holiday
Preparing a new Prophet component requires the holidays extra. Its weights
are estimated from the scaled training target, then retained without pickling
a Prophet object. Loading and prediction reuse the saved profile. Because the
weights were estimated in an earlier stage, their uncertainty is not fully
propagated as a joint Bayesian fit. Refit this feature inside each training
split; preparing it once from all outcomes leaks holdout information.
Accepted CSV schemas are name,start_date,end_date and
ds,holiday,country,year. Catalogue dates are day-first; UK and GB are
aliases. Aggregate models default to US when countries are omitted, so specify
them explicitly. Geo panels require multiple country codes corresponding to
their geo coordinates. pooled_control does not support panel dimensions;
FE and CRE reject these holiday effects altogether.
A configured relative path resolves from the YAML directory. Without a path, the builder uses the packaged calendar snapshot. Check its country and year coverage rather than assuming a current universal calendar. Holiday ranges are inclusive and assigned to the model periods they overlap; model dates label period starts. The final period uses the inferred observed interval.
The canonical calendar and fitted profile are persisted, so future predictions do not depend on the original CSV remaining in place. A changed calendar is a new input requiring model review and refitting. A holiday coefficient remains conditional on the model and adjustment assumptions, not a causal effect solely because it is named after a calendar event.
Build from a small calendar
Save this illustrative calendar as sandbox/holidays.csv; its two events fall
inside the Python quickstart’s training dates. Event dates are inclusive.
name,start_date,end_date
winter_event,2025-02-10,2025-02-10
spring_event,2025-04-14,2025-04-20
This continuation constructs a fresh ordinary model and attaches an event effect
before building. It requires the prepared X and y from the quickstart and
uses the calendar file just shown.
from pathlib import Path
from ammm.mmm import MMM, GeometricAdstock, LogisticSaturation
from ammm.mmm.builders.schema import HolidaysConfig
from ammm.mmm.builders.holidays import apply_holidays_from_config, load_holiday_calendar
calendar_path = Path("sandbox/holidays.csv").resolve()
calendar = load_holiday_calendar(calendar_path, countries=("UK",))
print(calendar.data)
print(calendar.provenance.source_sha256)
holiday_model = MMM(
date_column="date", channel_columns=["tv", "social"],
adstock=GeometricAdstock(l_max=1), saturation=LogisticSaturation(),
)
apply_holidays_from_config(
holiday_model,
HolidaysConfig(mode="event", path=str(calendar_path), countries=("UK",)),
model_dates=X["date"],
)
holiday_model.build_model(X, y)
For YAML stored in sandbox/model.yml, the matching block is
holidays: {enabled: true, mode: event, path: holidays.csv, countries: [UK]}.
Check the retained resolved path, source SHA-256, input schema, effective countries
and coverage years against the intended calendar; the canonical rows and
provenance fields come from src/ammm/mmm/builders/holidays.py:194.
No-overlap warnings indicate a zero component for the observations, not successful
holiday adjustment (src/ammm/mmm/builders/holidays.py:356).
Implementation reference at 7cb7f20: src/ammm/mmm/builders/holidays.py:194, src/ammm/mmm/holidays.py:27.