Run seat simulations from your latest forecast and explore decision-support outputs.
No run yet.
This document explains the modelling approach in plain language and gives step-by-step instructions for running a simulation.
This tool estimates how seats might be allocated in a 6-seat constituency using the D'Hondt method and closed lists. It does this by running many simulations rather than producing a single prediction. Each simulation is a plausible election outcome based on your base forecast and a set of assumptions about uncertainty and shared swings between parties.
Key ideas in simple terms:
This gives you answers like:
1) The base forecast is the starting point
- The values in forecast.yaml are the best estimate of vote shares.
- They should add up to 100% (the tool will renormalize if they do not).
2) Shared swings happen within blocs - Lists are grouped into a left bloc and a right bloc. - Before each simulation, the model applies a shared swing to the left bloc and a shared swing to the right bloc. - This captures the idea that parties in the same bloc often move together.
3) There is additional random variation around the swung forecast - After the bloc swing, the model draws a random vote share around that new forecast using a standard probability distribution (Dirichlet). - This accounts for noise and day-to-day uncertainty in polling or turnout.
4) Seats are allocated using D'Hondt - Each simulated vote share is converted into seats using the D'Hondt method. - The seat allocation is deterministic given the simulated vote shares.
All key settings live in forecast.yaml:
base_shares: The expected vote share for each list.sims: Number of simulations (higher = smoother results, slower).concentration: Think of this as "how steady is the forecast day to day?"swing_sd: Think of this as "how big could a bloc-wide swing be?"swing_rho: Think of this as "do blocs move in opposite directions or
together?"left_bloc / right_bloc: Which lists move together.1) Install dependencies (first time only)
bash
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
2) Edit the forecast
forecast.yaml and update base_shares and other parameters.3) Run the simulation
bash
python -m btnforecast simulate --config forecast.yaml --out outputs
4) View outputs
outputs/summary.json for the headline probabilities.outputs/seat_outcomes.csv and outputs/seat_probs.csv for raw results.outputs/expected_seats.png, outputs/seat_distribution.png,
outputs/seat_prob_dots.png for charts.outputs/sensitivity.csv for how sensitive expected seats are to small
vote-share changes.outputs/pc_targeting.txt for a model-based ranking of which single-party
vote transfers would most increase PC's expected seats.Hosted deployment: https://btnforecast.onrender.com/
1) Start the server
bash
AUTH_TOKEN=your-shared-token uvicorn app:app --reload --host 0.0.0.0 --port 8000
2) Open the UI
http://localhost:8000.The hosted UI requires a shared token. Paste it into the "Shared token" field in the web interface before running a simulation. This value should have been provided to you by the service owner or team lead.
sims) for stable comparisons between scenarios.sensitivity.csv to see which lists are most affected by small swings.