Analyses avancées
La méthodologie de Poliwave
Un compte rendu détaillé de la construction de chaque projection, depuis les données historiques brutes jusqu'à la prévision finale réconciliée.
15
Stages every constituency passes through
4
Levels you can set targets at, national down to sub-region
40,000
Monte Carlo draws per formal projection
47
Elections the formula was backtested against
01En clair
Vous fournissez à Poliwave un ensemble de cibles. Ce peut être des résultats de sondages, des scénarios hypothétiques ou un mélange des deux. Vous pouvez fixer ces cibles à quatre niveaux : pays entier (général), région (par exemple Canada atlantique), province (subnational) ou sous-région plus petite (subrégional, par exemple Calgary).
Pour l'élection que vous souhaitez projeter, Poliwave charge le résultat de l'élection précédente tenue sous les frontières actuelles des circonscriptions (même redistribution, identifiée par rep_order dans la base de données). Cette unique élection antérieure sert de référence par circonscription. Les élections plus anciennes n'interviennent que via l'étape de reconstruction historique, qui complète les références pour les partis qui ne s'étaient pas présentés lors de ce cycle précédent.
Poliwave applique ensuite une formule de swing à chaque circonscription. Elle calcule deux prédictions classiques, les multiplie et prend la racine carrée, c'est-à-dire la moyenne géométrique. Le résultat se situe toujours entre les deux et penche vers la plus petite, ce qui empêche de descendre une circonscription sous zéro lorsque le parti perd, et laisse aux circonscriptions intermédiaires la marge nécessaire pour bondir lorsqu'il gagne.
Après le swing, le modèle peut ajouter d'autres effets : transferts de voix entre partis, vote tactique dans les courses serrées, ajustements démographiques et corrections régionales manuelles. La plupart sont optionnels. Le vote tactique est notamment désactivé par défaut dans les projections officielles publiées sur le site (le comportement réel des électeurs est trop désordonné pour être déduit de règles); il sert surtout d'option dans le simulateur interactif. À la fin, le modèle redimensionne chaque circonscription pour que les moyennes géographiques restent proches de vos cibles. Si vos chiffres se contredisent (par exemple une cible nationale qui ne correspond pas à la moyenne de vos cibles régionales), la cible la plus large l'emporte.
Pour les projections officielles publiées sur le site, nous exécutons en plus une simulation Monte-Carlo afin d'obtenir des probabilités de victoire et des intervalles de confiance. Une exécution prend environ cinq minutes, donc le simulateur interactif ne la lance pas sur vos scénarios; vous n'obtenez que l'estimation ponctuelle.
La suite de la page détaille chaque élément.
02Le modèle en un paragraphe
Poliwave fait passer chaque circonscription par un pipeline en quinze étapes. Chaque étape a un seul rôle : lire le résultat précédent, combler les candidats manquants, appliquer le swing, déplacer des voix entre partis, ajouter les ajustements démographiques et géographiques, puis redimensionner l'ensemble pour respecter vos cibles. La formule de swing au milieu est le cœur mathématique, mais elle ne suffirait pas à elle seule. Ce sont les étapes périphériques qui transforment un sondage national en une prévision crédible par circonscription.
03Core projection formula
There are two classical ways to convert a national swing into a constituency-level projection, and each one breaks in a different way.
Proportional swing multiplies every constituency by the same ratio. If a party doubles nationally, every constituency doubles too. This is fine most of the time but breaks during big swings in either direction. A party that was already at 55% in a constituency has nowhere to go when you double it, and the formula tries to push it past 100%. More damagingly, when a party collapses nationally (think NDP 2025 going from 17.8% to 6%), pure proportional brutalises strongholds, Edmonton Strathcona's 60.7% gets scaled down to 20% even though incumbent personal vote and local brand strength should preserve much more than that.
Uniform swing adds the same number of points to every constituency. If the party drops 10 points nationally, every constituency drops 10 points. This breaks the other way: a party at 3% in a constituency drops to negative 7%, which is not a thing. Pure uniform also has the opposite collapse problem: a constituency where the party had almost no presence keeps a non-zero share that's basically noise.
Poliwave's projection formula takes the geometric mean of both, it multiplies the two predictions together and takes the square root. The proportional prediction is computed in log-odds space instead of by plain multiplication, which is the part that stops a stronghold from being pushed past 100% when a small party surges nationally (more on that below). Each prediction is floored at zero first so the inputs to the square root can't be negative:
The geometric mean is the natural average for percentages. It always sits between the two predictions, and it gets pulled toward whichever one is smaller. That single mathematical property fixes both classical failure modes at once: when proportional runs high, the smaller uniform value pulls the answer down; when uniform crashes to zero, geometric mean returns zero too (because square root of anything-times-zero is zero), which is the correct answer for a constituency where the party has effectively vanished.
The proportional component uses log-odds so it can never break past 100%. Plain proportional swing multiplies a seat's share by the national ratio, so if a small party doubles or triples across the country, a seat where it was already strong gets multiplied straight off the chart (a 40% Green seat scaled by a tripling would land at 120%, which is not a real result). Log-odds works on a curved scale that has 0% and 100% as walls you can approach but never cross. We measure how far the national share moved on that curved scale, shift the seat by the same amount, and convert back. The seat still climbs when the party surges, it just climbs toward the 100% wall and flattens instead of shooting through it.
Variable definitions
- The party's projected vote share in this constituency. This is the output. Later pipeline steps adjust it further.
- What the party got in this constituency in the previous election. Normally the model uses only this one prior election. Earlier elections come in only via the historical-reconstruction step when this number is missing or unreliable.
- Your input target for the party (from polls or scenarios), picked at the most specific level that applies to this constituency. The model checks subregional input first, then subnational, then regional, then the general (national) input.
- The matching baseline. If the current input is regional, the baseline is what the party got in that same region in the last election. The two have to be at the same geographic level; otherwise the swing ratio means nothing.
04The fifteen-stage pipeline
Every constituency goes through the same ordered set of steps. The swing formula above is one of them. The others clean up the input to the formula and make the output line up with everything else the model has to respect.
- Input parsing. The model loads each constituency's previous result,
the geographic hierarchy (which constituency belongs to which sub-region, province, region),
and any referendum results for the target election's redistribution (
rep_order). Your hierarchical input is flattened into a lookup so each constituency picks the most specific target that applies to it. - Historical normalisation. Missing or unreliable prior results get filled in. A party that did not nominate a candidate at all (a recent Canadian example: Conservatives in Québec Centre, 2025), or that ran so far below its own national share for the cycle that the result reads as a late-withdrawal residue rather than a real campaign, gets rebuilt by one of three methods described in the next section. This step runs on whatever prior-cycle baseline the database holds for the constituency, including transposed results from older boundaries (a 2025 federal projection's main baseline is the 2021 result transposed onto the 2023 rep_order, for instance).
- Swing projection. The core formula runs on every constituency and every party. Special cases handle brand-new parties and parties running nationally but absent from this constituency.
- Simple normalisation. The constituency's projected percentages are rescaled to add up to 100%. Anything negative is set to zero.
- Vote flow. Loss-only redistribution. When a party is projected to lose share, the lost share is handed to other parties according to a flow matrix you supply.
- Vote intake. Vote transfers that don't depend on whether a party is winning or losing. The formula is in the redistribution section below.
- Tactical voting. Strategic defection in FPTP races, scaled by how close the local race is. Two rule types: block-target voting (anti-X coordination) and the top-two squeeze (wasted-vote logic). This stage is off by default in the formal projections published on the site and is enabled only when you turn it on in the interactive simulator.
- Regional adjustments. Manual knobs. You give the model two tables, one for additive shifts and one for percent multipliers, organised by level (subregional, subnational, regional) and by party. Each cell is the change you want applied at that level for that party. The model just applies what you wrote; nothing is auto-computed here.
- Demographics. Per-category adjustments scaled to the party's existing support. You set a boost for a (party, demographic) pair; the model multiplies it by how far the constituency deviates from the national average for that demographic and by the party's current vote share in the constituency, so the effect can't blow past what the party actually has to move.
- Incumbent boost. An automatic multiplicative boost goes to the party of any candidate identified as a running incumbent in the constituency (sitting MP seeking re-election). A symmetric deboost of the same size goes to the previous-winner party when the sitting MP is known to be retiring or otherwise not on the ballot. Both magnitudes are calibrated from a backtest sweep across 38 Canadian elections since 2000; see the dedicated section below.
- Constituency boosts. Per-constituency manual overrides, either additive or multiplicative. Useful for unusually strong or weak local candidates beyond the auto-incumbent effect, well-known local figures, or one-off scenario tweaks. User boosts stack on top of the auto-incumbent boost.
- Hierarchical normalisation. The rescaling step. Every constituency is rescaled level by level (subregional first, general last) so the vote-weighted average at each level matches your input for that level. The general (national) level runs last and is the binding rule the result has to respect.
- Threshold capping. Damps any party that's running hot in a constituency compared to its cohort. When the projected share exceeds a set multiple of the regional or national average, the excess gets reduced by a set rate. Both the multiple and the rate are configurable. The constituency is then renormalised to 100%, and hierarchical normalisation is re-run so the capping doesn't break the geographic totals. This isn't a small-party squelch; it applies to any party that runs hot.
- Aggregation. Constituency winners are picked, seat totals are added up by party, and geographic summary tables are built for each level of the hierarchy.
- Output. Everything is packaged into the JSON response used by the website and by the Monte Carlo layer further down this page.
05Historical reconstruction
Inside that history window, the most important prep step is filling in missing or unreliable prior results. A naive model would take "the party got 0% here" at face value and project from that. Poliwave does not, for two reasons.
The first reason is candidate withdrawal. A party might just not have nominated a candidate at all in the last cycle. There are real Canadian cases: the Conservatives did not run a candidate in Québec Centre in 2025, so the prior result is structurally zero, and treating it as a real voter preference would be wrong.
The second reason is late withdrawals that still leave a name on the ballot. The 2019 Brexit Party stand-down in Conservative-held UK seats is the classic example, but the same thing happens in Canada when a candidate withdraws after the nomination deadline. The resulting tenths of a percent look like a vote share, but they don't reflect a real campaign. Either way, this needs to be cleaned up before the swing formula sees the baseline.
When the model has to fill a baseline in, it picks one of three branches depending on what data is available. Note that transposed prior results (for example the 2021 federal result mapped onto the 2023 rep_order) are treated as the real prior result for the constituency and go through this stage like any other baseline. They're the main input the projection runs on, not an exceptional case.
Branch 1: footprint-matched proportional swing
The default. The missing value is filled by taking the most-specific available geographic average for the party and applying proportional swing from the historical version of that average to the current version. The averages on both sides of the swing ratio only count constituencies where the party ran in both the old and the new cycle. That restriction kills off a whole class of errors. If you didn't restrict it, a party that stood down in a region last cycle but is running fully this cycle would produce a huge swing ratio against a tiny prior denominator, and the rebuilt number would blow past 100%.
The "level" in the formula is picked most-specific-first: subregional, then subnational, then regional, then general (national). This matches the same hierarchy the user-input lookup uses elsewhere in the pipeline. The reasoning is the same too: a constituency's behaviour is better predicted by its actual local cohort than by a national rollup.
Branch 2: zero-swing fall-through
When the party has a historical result for the constituency but no current-cycle average at any level (usually because the party isn't running this cycle), the swing ratio is zero and the rebuilt baseline collapses to zero. The constituency gets a clean zero instead of some arbitrary leftover.
Branch 3: regional-average fallback
When there's no historical result at all (the party is genuinely new), the constituency gets a damped version of the current-cycle regional average. The damping factor is set so brand-new parties start meaningfully below their headline regional number, which leaves room for the swing formula to grow them in surge constituencies and shrink them where they don't catch on.
Rebuilt baselines are not treated as if they were real. Each baseline carries a confidence weight depending on where it came from: a real result from the database is trusted fully, a branch-1 reconstruction less, and the branch-3 regional fallback least of all. Before the swing formula reads the baseline, low-confidence baselines get pulled toward the regional mean by a weighted average:
The effect is a careful pull toward the average. When the model trusts the baseline, it respects the constituency's individual character. When it doesn't, the constituency behaves more like its regional cohort. That keeps a single noisy or guessed number from contaminating the rest of the pipeline.
06Three families of vote redistribution
Voters move between parties in three different ways, and Poliwave handles each one separately. The three run in order, with each one working on what the previous one produced.
Vote flow (only when a party is losing)
When a party is projected to lose share in a constituency compared to its previous result, the lost share gets handed out to other parties using a flow matrix you supply. Each row tells the model, for one source party, what fraction of its losses go to each other party. The rows don't have to add up to 100%; whatever's left over is treated as abstention or as going to parties outside the projection.
Vote intake (always-on transfer)
Vote intake exists for cases where the "only when losing" condition of vote flow doesn't apply. A party can be gaining nationally and still be drained locally by a new entrant. Each row in the intake matrix tells the model, for one receiving party, what fraction of each source party's current share it pulls in:
This is the case vote intake was built for. Imagine you want to model a new right-wing party (call it Restore) taking voters from Reform UK. Vote flow can't handle this if your projection has Reform gaining or holding steady nationally, because vote flow only fires when the source is losing. But Reform can be up nationally and still bleed support locally to a fresh competitor on the same side of the spectrum. Vote intake lets you say "for every constituency, Restore takes a fixed fraction of Reform's current share" regardless of whether Reform itself is up or down. That's why the formula has no loss-condition: it works in both directions.
Within a single constituency, all the rules look at the same starting snapshot, so the order of rules in the matrix doesn't matter. Multiple targets pulling from the same source add up. If the total drain would take the source below zero, the rules are scaled down proportionally so the source ends at zero instead of negative.
Tactical voting (close-race-sensitive)
In first-past-the-post systems, voters often abandon their first-choice party when it has no real chance of winning the local seat. Poliwave models this directly. There are two rule types. A block-target rule names a party that tactical voters want to keep out, a pool of parties whose supporters will defect, and a list of acceptable alternatives. The rule fires in a constituency only if the target is in the top two; the pool's voters then move to whichever named blocker is strongest locally. A top-two squeeze rule doesn't name a target. It just drains every party below third place toward the top two, with the destination split decided by the squeezed party's own vote-flow preferences.
Both rule types are damped by how close the race is. The effect scales linearly with the local margin and disappears at a cutoff you can set:
This is what keeps safe seats from moving while close seats get realistic tactical-voting behaviour. The model penalises parties below second place exactly in proportion to how much the local race matters.
07Demographic adjustments
Demographic effects in real elections are relative, not absolute. If a party does ten points better with renters, that doesn't mean it picks up ten points everywhere. It picks up ten points in constituencies that have a lot more renters than the national average, almost nothing in average constituencies, and loses ten points in constituencies with way fewer renters than average. Poliwave handles this directly. For each (party, demographic) boost you set, the model multiplies your boost by how far the constituency deviates from the national average for that demographic, and by the party's current support in that constituency:
The deviation term is what makes the adjustment relative. Above-average constituencies get a push proportional to how far above average they are; average constituencies barely move; below-average constituencies get pushed the opposite way. Multiplying by the party's current support is what keeps the formula honest: a party with no vote share in a constituency gets no demographic shift (a 0% party times anything is still 0), and a party already strong in the constituency has more vote share available to move. A party sitting at 3% can drift by a few tenths of a point per category; a party at 30% shifts ten times more in absolute terms but the same in relative terms. That self-bounding shape is what stops a small input ever amplifying into an unintended seat flip downstream.
08Incumbent boost
Incumbent candidates outperform their party's swing. The pattern is robust across systems and shows up in almost every academic study of personal-vote effects: name recognition, constituency casework, media presence during the prior term, and a ready-made local volunteer base all add up to a few percentage points of advantage that pure party-level swing math will miss. The flip side is sophomore-surge loss: when a sitting MP retires, the same seat loses the personal vote that helped prop it up, and the party usually slips back toward its normal baseline.
Poliwave applies both effects directly. After demographics and before any user-supplied constituency overrides, the model classifies every constituency into one of three states and adjusts the projected vote share of the relevant party:
- Incumbent running. A multiplicative boost to the incumbent's party.
- Incumbent retiring. A multiplicative deboost of the same magnitude to the previous-winner party. The seat may still be safe, but the personal vote is gone.
- No prior history available. No adjustment.
In the formula, is party 's raw baseline result in constituency , so picks out the previous winner; is that party's currently-projected share after the swing and all the redistribution steps above. The boost factor (1 ± b/100) is positive for running incumbents and negative for retiring ones. The constituency is then renormalised back to 100% so the within-constituency shares still sum cleanly, and the broader hierarchical reconciliation downstream re-anchors regional and national vote-weighted averages to the user's input, so the boost shifts the within-region distribution, not the regional totals.
Identifying the incumbent
Each constituency is classified by walking a priority cascade. The model looks at the election we're projecting to (when its candidate data is in the database) and tags each constituency using the first signal that fires:
- Explicit incumbent flag. The target-election row carries an incumbent flag, set when a sitting MP appears on the next ballot. Boost their party.
- Candidate-name match. If no flag was set, compare candidate names between the baseline election and the target. A target candidate whose name also appears in the same constituency's baseline ballot is treated as an incumbent. Catches cases where the flag was missed during data entry.
- Retiring fallback. When the baseline winner's candidate name does NOT appear in the target's candidate list, the seat is marked as a retiring-incumbent case and gets the negative deboost.
- Baseline-winner heuristic. When no target candidate data is available at all (live forward projection of an upcoming race), the model falls back on the party of the baseline winner and applies the positive boost only. Without target data the model can't tell running from retiring, so the deboost arm is disabled for these runs.
Parties classified as "Other," independent, or Speaker are excluded. The first is a mathematical lump rather than a real party with a sitting MP, and the latter two have their own special-case handling elsewhere in the pipeline.
Manual constituency boosts in the next step stack on top of this. If you know a specific candidate is exceptionally strong or unusually weak beyond what the party-level incumbency boost captures, you can add a per-constituency additive or multiplicative adjustment that runs after the automatic step. The two stack rather than override: the auto-boost lifts (or trims) the projected winner first, your manual boost adjusts further on top.
09Hierarchical reconciliation
Every projection has to answer a question you asked, like "what does the country look like if the Liberals are at 26% nationally and the Bloc is at 30% in Quebec?" The reconciliation step is what makes those targets actually stick. For each geographic group at each level, the model takes the current vote-weighted average of the group, compares it to your target for that group, and multiplies every constituency in the group by one correction factor:
The in the formula is the constituency's total vote count. It weighs each constituency's contribution to the group average, so larger constituencies have more influence. The four levels run in this fixed order: subregional first, then subnational, then regional, then general (national) last.
This top-down setup has a useful property. The geographic variation that earlier steps built in is preserved, because every rescale is just multiplication: if a constituency was double its regional average before reconciliation, it's still double afterwards. Only the absolute level changes. That's what lets the model honour any national target without flattening the constituency-by-constituency texture that makes the projection useful. It also means that if you genuinely want one province at 10% while the country is at 50%, you have to drop one of the inputs. The two don't agree with each other, and the model trusts the broader target.
This also matters when pollsters get their regional weighting wrong. A pollster's regional crosstabs don't always weight back up to the national headline they reported. If you fed those inconsistent regional numbers in as hard ceilings, the national total in the projection would drift away from the topline. Because Poliwave runs the national level last and rescales whatever the regions produced, the topline you trust the most stays the binding number, and a regionally mis-weighted poll still produces a sensible projection.
10Scrutin à deux tours (législatives françaises et systèmes similaires)
Pour les scrutins à deux tours comme les législatives françaises, la projection n'a calculé jusqu'ici que les parts de vote du premier tour. Une seconde étape du pipeline reprend ces résultats et projette le second tour de chaque circonscription en déterminant quels candidats se qualifient et comment les électeurs des candidats éliminés se répartissent entre eux. Toute cette section ne s'exécute que lorsque l'élection est marquée comme à deux tours. Le scrutin uninominal majoritaire, le MMP, la proportionnelle, le STV et les autres systèmes la sautent entièrement.
Sélection des qualifiés
La loi française permet à tout candidat qui dépasse 12,5% des inscrits au premier tour de se présenter au second. Les deux premiers passent toujours, même si moins de deux franchissent ce seuil. Nous appliquons la même règle : le seuil de qualification d'un candidat correspond à 12,5% du nombre d'inscrits dans la circonscription, converti en pourcentage équivalent des suffrages exprimés en utilisant la participation propre à chaque circonscription. Ainsi, dans une circonscription comptant 87 000 inscrits pour 60 000 votes valides (environ 69% de participation), un candidat a besoin d'environ 18% des suffrages exprimés pour passer le seuil, et non de 12,5%. Cette conversion produit un mélange réaliste de duels et de triangulaires ; appliquer 12,5 % directement aux suffrages exprimés ferait passer trois fois plus de candidats et rendrait les quadrangulaires bien plus fréquentes qu’elles ne le sont en pratique.
Si un candidat dépasse 50% des suffrages exprimés au premier tour, la circonscription est décidée immédiatement et le second tour est sauté pour ce siège.
Report des voix entre les tours
Les électeurs de chaque parti éliminé se répartissent entre les qualifiés selon une matrice de report. Chaque case de la matrice est l'affinité des électeurs d'un parti envers un autre, sur une échelle de 0 à 100. Les cases sont initialisées à partir de la distance idéologique selon
où sont les scores idéologiques des partis source et destination sur une échelle de -10 à +10, et est une constante de décroissance (3,0 par défaut). Deux partis de même idéologie obtiennent une affinité de 100; deux partis distants de 7 points obtiennent environ 10. Les utilisateurs peuvent remplacer une case individuelle dans l'onglet Matrice de report, et ces modifications manuelles priment sur la valeur idéologique automatique. Pour chaque parti éliminé d'une circonscription donnée, le modèle ne retient que les cases correspondant aux qualifiés réels de cette circonscription, les normalise, les multiplie par la part de premier tour du bloc source et ajoute le résultat au total de second tour de chaque qualifié. Les cases pour les non-qualifiés sont ignorées : une règle comme « les électeurs NFP n'aiment pas LR » ne compte que dans une circonscription où LR est effectivement passé au second tour.
Abstention par source
Tous les électeurs d'un candidat éliminé ne se présentent pas au second tour. Un électeur dont le premier choix était un candidat d'extrême gauche placé devant un duel extrême gauche contre extrême droite a une bonne option et la plupart d'entre eux votent. Le même électeur face à un duel centre contre extrême droite n'a aucune bonne option et l'abstention monte fortement. Le modèle capture cela avec un taux d'abstention par source
est le plancher, qui s'applique même quand le qualifié préféré de l'électeur est sur le bulletin, et le second terme est la sensibilité à la course, qui contrôle la hausse d'abstention quand aucun qualifié ne séduit. Les deux sont paramétrables. Le report de chaque source vers chaque qualifié est ensuite multiplié par (1 − abstention) avant d'être ajouté à la part de second tour du qualifié. Une fois tous les reports appliqués, les parts des qualifiés sont renormalisées pour sommer à 100% afin de coller aux tableaux de résultats français du second tour (la part abstenue n'apparaît pas comme un point de pourcentage d'un parti, comme dans les vraies tabulations).
Les deux paramètres sont exposés comme des curseurs dans l'onglet Matrice de report du simulateur.
Agrégation en deux passes
L'étape d'agrégation s'exécute deux fois. D'abord sur les parts projetées de premier tour, ce qui produit la vue pré-ballottage (qui gagnerait chaque circonscription au scrutin majoritaire à un tour, qui mène dans chaque région au premier tour). Ensuite les valeurs du premier tour sont sauvegardées dans des champs round1_* et le modèle remplace projected_percentages par le résultat de second tour, relance l'agrégation et l'enregistre comme résumé du tour final. La bascule R1/R2 sur les onglets Résumé, Carte et Tableau de résultats du simulateur ne fait qu'échanger l'ensemble de champs affichés.
C'est pour cette raison que les circonscriptions où le leader du premier tour perd le second (le classique front républicain où un candidat d'extrême droite mène à la pluralité mais perd quand le centre et la gauche se réunissent contre lui) apparaissent avec un badge « FLIP » dans l'onglet Reports par circonscription.
11Uncertainty and scenario probabilities
Getting a single point estimate is the easy part of a forecast. The hard part is what could happen around it. For formal projections, Poliwave runs Monte Carlo on top of the base projection (40,000 draws by default, more if set higher via the CLI) using a correlated error model. Polling error is split into three pieces: a national piece that moves every constituency the same way, a regional piece that moves constituencies inside one region together, and a per-constituency piece that's independent and whose size depends on the constituency's population.
The split exists because real polling misses aren't independent across constituencies. They're usually systemic and regional. If you treated every constituency as an independent draw, the confidence intervals would be way too narrow and the seat distributions would be too tight around the centre. The correlated split gives back the realistic spread an honest forecast needs.
The third piece, the per-constituency term, has its variance scaled inversely by the constituency's elector count. A small northern constituency with 35,000 electors really is noisier than a Toronto-area constituency with 110,000, because a smaller electorate gives more leverage to single events (a popular local candidate, a scandal, a local issue):
is the calibrated noise level at the reference population (the median constituency size in the jurisdiction), and is the constituency's own elector count. This is what gives small constituencies wider win-probability ranges than large ones, and any honest forecast model has to behave this way.
What the simulation actually produces:
- Per-constituency win probabilities and 95% confidence intervals for every party.
- Seat distributions at the regional and national level.
- Government formation probabilities: majority, minority, plurality, hung. Each gets its own simulated frequency, based on your inputs and the correlated error structure above.
12Does it work?
Methodology is only as good as the track record it produces. On the 2025 Canadian federal election, Poliwave produced the closest absolute seat-count projection among Canadian forecasters: the smallest total gap between projected and actual seats for the top four parties. On constituency-level accuracy (the share of seats where the model picked the right winner), Poliwave landed within one percentage point of the long-established national benchmark, despite being a much newer project run by one person instead of an institutional team.
Performance on every prior election the project has covered is published in full on the accuracy page: projected seats next to actual seats, no curation, no cherry-picking.
One caveat worth stating plainly: those results, including the 2025 federal projection, were produced with the Excel model that preceded this website. The first interactive web simulator went live in August 2025, after all of them. The pipeline described on this page is a direct descendant of that model and follows the same approach, but it has not yet been scored against a general election of its own.
+In summary
Geometric-mean swing
Every projection combines proportional and uniform swing by taking the geometric mean, multiply both predictions, square-root the product. No tuning parameters. Naturally pulls toward whichever component is smaller, which fixes both classical failure modes at once: runaway proportional projections get damped, near-zero parties cleanly zero out. Wins more elections than it loses against every other formula tested in head-to-head backtests across 47 CA elections since 2000.
Footprint-matched historical averaging
When the model needs a prior baseline for a party whose footprint changed between cycles, it only compares constituencies the party ran in both times. That kills off the distortion that would otherwise happen when a party stood down one cycle and runs fully the next.
Three-family vote redistribution
Loss-only flows, always-on intakes, and close-race tactical defection are three separate pipeline steps that add up cleanly without double-counting. Real voters move in different ways, and the model handles each one separately.
Margin-sensitive tactical voting
How much tactical voting happens depends on how close the local race is. A safe seat sees none; a tight seat sees the full effect. The cutoff and the pool of defecting voters are both user-configurable, so the same engine handles anti-Conservative coordination, anti-Reform coordination, or any future strategic alignment without code changes. Off by default in the formal projections; available as a knob in the interactive simulator.
Demographic integration
Each (party, demographic) boost is applied as a deviation-weighted adjustment scaled by the party's current vote share, so the size depends both on how far the constituency is from the national average and on how much support the party has to move. Above-average constituencies get a positive shift; below-average constituencies the opposite; a party at 0% gets nothing because there's nothing to multiply. Relative, not absolute.
Symmetric incumbent boost
Running incumbents get a multiplicative boost; retiring incumbents trigger a symmetric deboost of the same size to the previous-winner party. Incumbency is read from the target election's incumbent flag, falling back to candidate-name matches and finally to the baseline winner when no target candidate data exists. Both magnitudes were tuned by backtest sweeps across 38 Canadian elections since 2000.
Vote-weighted hierarchical reconciliation
The final stage rescales every constituency so that the vote-weighted averages at each geographic level land as close as possible to the user's input. Clamping at 0 and 100, two-decimal rounding, and single-constituency-group skips mean the match is approximate rather than exact; the broadest target acts as the binding constraint and everything upstream provides the per-constituency shape the rescale preserves.
Correlated-error Monte Carlo
Polling error is split into national, regional, and per-constituency pieces. This captures the fact that polling misses are usually systemic, not random, and produces realistic seat distributions instead of the implausibly tight ones you get from treating every constituency as independent.
Boundary-matched historical foundation
Every projection is anchored on the prior election held under today’s constituency boundaries. Earlier cycles can be brought in when their results have been mathematically transposed onto current boundaries by the database upload scripts. No constituency gets a generic baseline; each one starts from its own political history under the boundaries it has today.
Cette page décrit la construction du modèle et les équations qu'il utilise. Les chiffres de calibration spécifiques, le réglage juridiction par juridiction et les détails opérationnels restent internes.