Overview and Workflow

Use the scenario planner when you want to compare whole plans rather than run a single low-level optimisation call.

The planner combines typed scenario specifications, a Python comparison service and retained evidence bundles. Use abacus.scenarios for new scenario code. Application wrappers are separate projects.

If you need the low-level optimiser instead, see Budget Optimisation.

For the supported entry points and current limits, see Supported Surface.

What the planner compares

The retained planner supports three scenario types:

Scenario typePurposePublic spec
CurrentUse observed history as a reference planCurrentScenarioSpec
Manual allocationSimulate a user-defined future planManualAllocationScenarioSpec
Fixed-budget optimisedOptimise a future plan at a fixed budgetFixedBudgetOptimizedScenarioSpec

FE and CRE support historical and manual scenarios for complete fitted-unit panels. Fixed-budget optimisation remains unavailable for these presets. See the estimator support matrix.

Planner units versus optimiser units

The most important distinction is budget units.

SurfacePublic budget contract
PanelBudgetOptimizerWrapperPer-period spend
abacus.scenarios.ScenarioPlannerTotal spend over the whole scenario horizon

For example, if a four-period scenario has a total budget of 900_000, the planner converts that to per-period units internally before it calls the wrapper or response sampler.

Requested and evaluated windows

Each scenario has a requested window from start_date to end_date.

For simulated scenarios, the evaluated window can be longer than the requested window when you set include_carryover=True. AMMM3 extends the synthetic future path so lagged adstock effects can continue after the requested end date.

The planner reports both windows in the metadata output.

Historical overlap for current scenarios

CurrentScenarioSpec is strict about history.

Its requested window must overlap observed data. AMMM3 does not reinterpret a future-only window as “use the latest history instead”.

Typical workflow

The common workflow is:

  1. Fit PanelMMM.
  2. Build one or more scenario specs.
  3. Run abacus.scenarios.ScenarioPlanner.compare(...) or a versioned scenario recipe against the fitted run directory.
  4. Inspect the comparison tables, save workspaces, and export the planning outputs you need.

Minimal example

from abacus.scenarios import (
    CurrentScenarioSpec,
    ManualAllocationScenarioSpec,
    ScenarioPlanner,
)

planner = ScenarioPlanner(mmm)

comparison = planner.compare(
    [
        CurrentScenarioSpec(
            name="Current baseline",
            start_date="2025-01-06",
            end_date="2025-02-24",
        ),
        ManualAllocationScenarioSpec(
            name="Manual plan",
            start_date="2025-03-03",
            end_date="2025-03-24",
            noise_level=0.0,
            include_carryover=False,
            allocation={
                "channel_1": 420_000.0,
                "channel_2": 280_000.0,
                "channel_3": 200_000.0,
            },
        ),
    ]
)

For the full API, see Python API.

How the planner differs from post-model summaries

The scenario planner does not reuse mmm.summary tables directly. Instead, it builds comparison tables that are specific to planning:

  • totals
  • channels
  • contributions_over_time
  • allocations
  • metadata

See Comparison Outputs.

Common pitfalls

  • Mixing up total horizon spend and per-period spend
  • Using a future-only window in CurrentScenarioSpec
  • Forgetting that carryover can extend the evaluated window