Multi-Period Budget Optimisation
This guide explains AMMM V2 multi-period optimisation, including seasonality adjustments and ramp constraints.
What This Guide Covers
Section titled “What This Guide Covers”- Enabling multi-period mode from
runme.py - Interpreting
70_optimisation/multi-period artefacts - Constraint design (
ramp-abs,ramp-pct, JSON ramp config) - Common failure modes and practical mitigation
1. When to Use Multi-Period Mode
Section titled “1. When to Use Multi-Period Mode”Use multi-period optimisation when:
- planning budgets across several future periods (for example 13 weeks);
- seasonal effects materially change channel efficiency over time;
- you need period-level allocation, not a single aggregate recommendation.
Use single-period mode when:
- you need a fast first-pass allocation;
- planning horizon detail is not required.
2. Enable From CLI
Section titled “2. Enable From CLI”# Default multi-period run (13 periods)python runme.py --multiperiod
# Custom horizonpython runme.py --multiperiod --multiperiod-weeks 26
# Disable seasonality adjustmentspython runme.py --multiperiod --no-seasonalityImportant:
--use-adstockis not compatible with--multiperiodinrunme.py.
3. Objective and Constraints
Section titled “3. Objective and Constraints”AMMM allocates spend by period and channel:
$$ \max_{{S_{p,i}}} \sum_{p=1}^{P}\sum_{i=1}^{n} w_{p,i} , C_i(S_{p,i}) $$
Subject to:
- total budget constraint;
- per-channel bounds;
- optional per-period limits;
- optional ramp constraints between consecutive periods.
4. Ramp Constraints
Section titled “4. Ramp Constraints”Uniform constraints from CLI
Section titled “Uniform constraints from CLI”# Absolute ramp limitpython runme.py --multiperiod --ramp-abs 20000
# Percentage ramp limitpython runme.py --multiperiod --ramp-pct 0.25
# Bothpython runme.py --multiperiod --ramp-abs 20000 --ramp-pct 0.25Per-channel constraints from JSON
Section titled “Per-channel constraints from JSON”python runme.py --multiperiod --ramp-config constraints.jsonpython runme.py --multiperiod --ramp-config constraints.json --strict-ramp-configRelated flags:
--ramp-epsfor safe percentage denominators;--round-incrementfor rounded budget recommendations.
5. Seasonality Controls
Section titled “5. Seasonality Controls”Seasonality multipliers can be clipped:
python runme.py --multiperiod --seasonality-clip-min 0.7 --seasonality-clip-max 1.3These clips help avoid extreme multiplier-driven allocations.
6. Output Artefacts
Section titled “6. Output Artefacts”All files below are written to 70_optimisation/:
multiperiod_optimization_results.csvmultiperiod_budget_heatmap.pngmultiperiod_contribution_over_time.pngmultiperiod_seasonal_patterns.png(when seasonality is used)multiperiod_period_comparison.pngmultiperiod_budget_vs_contribution.png
CSV schema (multiperiod_optimization_results.csv)
Section titled “CSV schema (multiperiod_optimization_results.csv)”Typical columns:
periodperiod_datechannelbudgetcontributionseasonal_multiplierroi
7. Validation Before Business Use
Section titled “7. Validation Before Business Use”Review diagnostics first:
50_diagnostics/convergence_report.json(converged)50_diagnostics/calibration_report.json(well_calibrated)50_diagnostics/pareto_k_summary.json(ok)
Then inspect multi-period outputs for operational plausibility.
8. Common Failure Modes
Section titled “8. Common Failure Modes”Convergence failures in optimisation
Section titled “Convergence failures in optimisation”Symptoms:
- solver does not converge;
- infeasible or unstable allocation pattern.
Mitigations:
- Reduce horizon (
--multiperiod-weeks 4as a smoke test). - Use a single ramp type first (
--ramp-absor--ramp-pct). - Relax very tight ramps.
- Reduce optional constraints, then reintroduce incrementally.
Flat allocations across periods
Section titled “Flat allocations across periods”Likely causes:
- seasonality disabled (
--no-seasonality); - weak seasonal variation in learned baseline.
Overly volatile allocations
Section titled “Overly volatile allocations”Likely causes:
- no ramp constraints;
- overly broad seasonality clips.
9. Python API Example
Section titled “9. Python API Example”import src as ammmfrom driver import MMMBaseDriverV2
driver = MMMBaseDriverV2( config_filename="data-config/demo_config.yml", input_filename="data-config/demo_data.csv", holidays_filename="data-config/holidays.csv", results_filename="results",)driver.main()
ammm.optimize_marketing_budget( model=driver.model, data=driver.processed_data, config=driver.config, results_dir=driver.results_dir, multiperiod_mode=True, n_time_periods=13, use_seasonality=True, frequency="W",)10. Practical Workflow
Section titled “10. Practical Workflow”- Fit and validate model diagnostics.
- Run
--multiperiodwith a short horizon first. - Add ramps conservatively.
- Scale to full horizon after stable solver behaviour.
- Review period-level outputs with business constraints.