Blog » Metric Design

Seasonality in a KPI Tree: Fix the Comparison, Not the Node

· 12 min read

Seasonally adjusted drivers do not sum to the adjusted total. The worked months show a flat tree and a 20.42 percent fall on the same source rows.

One Dataset, One Flat Month and One Collapse

Seasonality in a KPI tree is usually handled by deseasonalizing the numbers before they enter the tree. That single choice breaks the tree's arithmetic, and it breaks it quietly, because every node still looks correct.

Take one consumer business with two revenue lines, gift and subscription, across December and January.

December raw revenue was 7,200,000 dollars of gift and 3,600,000 of subscription, a total of 10,800,000. January was 1,440,000 and 3,672,000, a total of 5,112,000. Raw, the total fell 5,688,000 dollars: gift minus 5,760,000, subscription plus 72,000, summing to the total exactly. The answer is Christmas, which nobody needed a tree to learn.

So the analyst deseasonalizes. Each line carries multiplicative seasonal factors fitted on its own history: gift at 2.00 in December and 0.40 in January, subscription at 1.00 and 1.02. Dividing through, both lines sit at 3,600,000 dollars in December and 3,600,000 in January. Adjusted, the business was flat.

The same analyst also deseasonalizes the total, using factors fitted on the total's own history, 1.35 and 0.803. That gives 8,000,000 dollars in December and 6,366,127.02 in January, a fall of 20.42 percent.

Same two months, same rows, both adjustments sound. One says flat. One says the business lost a fifth of its run rate.

The adjusted drivers summed to 7,200,000 dollars in both months, a change of zero. The adjusted total moved from 8,000,000 to 6,366,127.02, a fall of 20.42 percent. No driver in the tree accounts for the 1,633,872.98.

Why a Total's Seasonal Factor Is Not the Average of Its Children's

The gap has one cause, and it is arithmetic rather than estimation error.

A multiplicative factor divides. Raw revenue for a line equals its adjusted revenue multiplied by its factor. Sum across lines and the raw total equals the sum of each line's adjusted revenue multiplied by that line's own factor. Divide both sides by the adjusted total and the total's factor falls out: the average of the children's factors, weighted by each child's share of the adjusted total.

Run it on December. Both lines sit at 3,600,000 dollars adjusted, so each weighs 0.50. The weighted factor is 0.50 times 2.00 plus 0.50 times 1.00, which is 1.50, and 10,800,000 divided by 1.50 is 7,200,000, the figure the children already produced.

Run it on January. The weights are unchanged, the factors are 0.40 and 1.02, so the weighted factor is 0.71, and 5,112,000 divided by 0.71 is 7,200,000 again.

The total's own fitted factors were 1.35 and 0.803 because the history behind them had gift at 35 percent of adjusted December revenue, not 50. Check it: 0.35 times 2.00 plus 0.65 times 1.00 is 1.35, and 0.35 times 0.40 plus 0.65 times 1.02 is 0.803. Those factors are not stale. They are correct for the old mix.

A total's seasonal factor is the share-weighted average of its children's factors. Move the mix and the total's factor moves, even when no child's seasonality has changed at all.

Should a KPI Tree Use Seasonally Adjusted Numbers?

No. A KPI tree is an accounting identity over summable quantities, and seasonal adjustment is a non-additive operation fitted series by series. Adjust the children and the parent is already implied. Adjust the parent as well and the two disagree. Keep raw quantities in the nodes and handle seasonality in the choice of comparison period instead.

There are only two ways to put adjusted numbers into a tree, and both cost something.

Adjust the children and sum. The tree reconciles, because the parent is defined as the sum. What you lose is the headline: this total will not match the adjusted total anyone else quotes, including the one the finance system prints.

Adjust the total as well. Now the headline matches and the children no longer explain it. The residual is not a driver and has no owner, so the review spends its time on an artifact of the weighting.

The adjustment is also an estimate rather than a reading. A seasonal factor comes out of a model fitted to one series, carries standard errors, revises as history extends, and depends on options somebody chose. A KPI tree exists to end an argument about which driver moved, and a node holding a revisable estimate starts a different one.

Why Do Seasonally Adjusted Drivers Not Sum to the Adjusted Total?

Because each series is adjusted on its own history and the aggregate is adjusted on the aggregate's history. The US Census Bureau puts it plainly: under most circumstances the direct and indirect adjustments of an aggregate series are not identical. Agreement requires very limited conditions, and a multiplicative decomposition makes those conditions more restrictive still.

The two routes have names. Adjusting the components and summing them is the indirect adjustment of the aggregate. Adjusting the aggregate's own series is the direct adjustment.

Hood and Findley, writing for the US Census Bureau, define the indirect route as summing adjusted component series "to get a seasonally adjusted aggregate series", and the direct route as "applying the seasonal adjustment procedure directly to the aggregate data".¹ Their finding is unambiguous: "Under most circumstances, the direct and indirect adjustments for an aggregate series are not identical."¹ The limited cases where the two could coincide arise "particularly if the adjustments are additive", and for a multiplicative decomposition "the conditions required for identical adjustments are even more restrictive".¹ Revenue seasonality is almost always modeled multiplicatively, which puts a business tree in the harder case.

The UK's Office for National Statistics states the tradeoff from the other side. Indirect estimation "maintains the 'adding up' feature that occurs in non-adjusted CPI/CPIH", while direct estimation "generally leads to the best possible seasonal adjustment of each price index, including the all-item figures".²

That is the whole choice. Additivity, or the best headline. Not both.

Forecasters named the same constraint. Numbers across a hierarchy are coherent when, as Aikawa and co-authors write, "the forecast value of each parent series exactly matches the sum of the forecast values of its child series".³ Their fixes, from bottom-up summation to the minimum-trace method, all do one thing: change the numbers so they add up.³ A tree on raw additive quantities never needs that step, because coherence holds by construction.

What the Statistical Agencies Do With the Same Problem

The agencies that publish adjusted aggregates have argued about this for decades, and their working papers are the cheapest education available on it.

The ONS paper to the Advisory Panel on Consumer Prices, dated June 2025, proposes adjustment across "84 to 87 4-digit series and over 60 aggregates" using "the X-13 ARIMA-SEATS method".² That program, documented by the Census Bureau's Time Series Research Staff, fits a model to each series separately.⁴ The ONS recommends direct estimation initially, with NIESR preferring direct "due to its simplicity".² The cost is quantified: adding the adjusted 4-digit series up to all-items CPIH leaves "a maximum difference of around 1.5%".²

On the worked months above, 1.5 percent of a 7,200,000 dollar adjusted total is 108,000 dollars of residual with no driver behind it. That is the floor, on a national index with roughly ninety components and stable weights. A two-line business whose mix moved from 35 percent to 50 percent produced 800,000 dollars of divergence in December and 833,872.98 in January, in opposite directions.

Eurostat's ESS guidelines, endorsed by the ESS Committee in November 2014, give direct and indirect approaches a section of their own.⁵ The ONS adds that there is "no clear consensus on a preferred approach across other National Statistics Institutes".² Teams who assume their BI tool settled it have not read the question.

Four Ways to Handle Seasonality, and What Each Costs

Four approaches cover the field, and only the fourth leaves a tree reconciling without a non-additive step inside it.

The second row is where most reporting sits, because it is what the finance system prints. The third is where analysts go once told the second cannot be decomposed. None of the four removes seasonality from the business. They differ in where the seasonal assumption sits: in the nodes, in the headline, or in the two periods compared.

ApproachWhat goes in the nodesWhat it answersWhere it fails
Raw month on monthRaw summable quantitiesWhat moved since last monthSeasonality dominates every driver, so the answer is the calendar
Direct adjustment of the totalOne adjusted aggregateWhether the headline sits above or below trendThe drivers cannot be reconciled to it, and a mix shift moves the factor
Indirect adjustment of the childrenAdjusted children, summedWhich driver moved net of its own seasonThe headline differs from the adjusted total everyone else quotes
Raw same period prior yearRaw summable quantitiesWhich driver moved against a comparable seasonA changed pattern, a moved holiday or an extra trading day leaks into the drivers

What Is the Right Comparison Period for a KPI Tree?

The same period one year earlier, on raw quantities. January against January holds the season roughly constant without applying a non-additive step to any node, so the tree still reconciles. Each driver's contribution becomes the difference of two raw sums, and those differences add to the total change exactly, with no factor anywhere in the arithmetic.

Run the same business January against January.

The prior January booked 1,200,000 dollars of gift and 3,570,000 of subscription, a total of 4,770,000. This January booked 1,440,000 and 3,672,000, a total of 5,112,000.

Gift contributed 240,000 dollars, a rise of 20.00 percent. Subscription contributed 102,000, a rise of 2.86 percent. The total rose 342,000 dollars, or 7.17 percent, and 240,000 plus 102,000 is 342,000.

That is the decomposition the business needed. Gift grew seven times faster than subscription and supplied 70 percent of the growth, which is also why the total's seasonal factor had moved in the first place.

No seasonal factor appears anywhere in that paragraph. December's 2.00 and January's 0.40 are still true of the gift line, and they cancel because both Januaries carry the same one. Seasonality has not been removed. It has been held constant, and holding a term constant is cheaper and more auditable than estimating it. The same logic governs a comparable sales base, where the question is which stores belong in the comparison rather than which months.

Where Like-for-Like Still Leaks

The cancellation is approximate, and a post claiming otherwise would be selling something.

The pattern can change. A factor cancels across two Januaries only if it is the same in both. A business that moved its clearance sale from January to February changed the pattern, and the whole shift lands in the drivers as if it were performance.

The calendar is not periodic. A 53-week retail year, Easter crossing a quarter boundary, Chinese New Year moving between January and February, and an extra trading day all break the assumption that two same-named months are comparable units.

Not every line is seasonal. The ONS found that "Between one fifth and one quarter of series were found to be 'non-seasonal'", and would adjust only series showing seasonal patterns under standard statistical tests.² A blanket rule applied to every node is wrong on a quarter of them.

One question a tree cannot answer at all: whether the seasonal pattern itself changed. That is a question about many periods, and a decomposition of two holds no information about it. When that is live, a model fitted to the full history is the right instrument and the tree is not.

Four Tests Before a Seasonal Number Enters a Tree

Review capacity is the scarce resource. The AFP's 2026 benchmarking survey of 332 FP&A and finance professionals across 54 countries reports the average budgeting cycle still takes nearly nine weeks, unchanged over three years.⁶ Four tests are cheaper than one argument.

1. Additivity. Can the node be summed across every dimension in the tree without a weight? A quantity passes. A rate, an index and an adjusted series do not.

2. One operation, one level. If an adjustment is applied, apply it at exactly one level and derive the others from it. Fitting a factor at two levels guarantees a residual.

3. Mix stability. Compare each child's share of the total in the base period and the current period. A share that moved more than a few points means any aggregate factor fitted on history is wrong for this period.

4. Base-period comparability. Count weeks, trading days and moved holidays in both periods before trusting the comparison. If they differ, say so in the report rather than inside a node.

The same discipline applies to error metrics, where an unweighted average of ratios misleads for the same weighting reason. Testing a tree for MECE catches classification failures, and a deseasonalized node survives those tests.

Building This in kpitree.io

kpitree.io is a self-service KPI tree builder that takes uploaded CSV data and produces interactive driver trees for root cause analysis. CSV upload is the only data path, and a tree refreshes when a new file is uploaded.

The relevant mechanism is the node arithmetic. Every identity in the tree is addition or subtraction, and no row stores a ratio. Derived KPIs are computed inside the tree by dividing two summable columns at the level being read, so a rate is never summed and never averaged.

That has one consequence for seasonality. There is no place in the tree for a per-series adjustment to sit, so a tree that reconciles cannot silently be carrying one. The seasonal decision moves to where it belongs: which rows get uploaded, and which two periods get compared.

The smallest useful version takes one CSV with a period column, a segment column and two value columns.

Seasonality in a KPI Tree: Common Questions

Can a year-over-year growth rate go on every node instead?

No. Growth rates are ratios and do not sum across siblings. Decompose the change in dollars or units, which does sum, then express the total as a rate once, at the top.

What if finance only publishes seasonally adjusted figures?

Report both. Run the tree on raw like-for-like quantities to attribute the move, and quote the published adjusted headline separately as the level. Do not try to make the tree reconcile to a number produced by different arithmetic.

Is quarter against prior-year quarter better than month against prior-year month?

Quarters are more stable, because within-quarter timing effects cancel, and they are slower. Use the quarter for the decision and the month for the early signal, expecting the month to be noisier rather than wrong.

How large does a mix shift have to be before the aggregate factor is unusable?

There is no universal threshold. Apply the weighting identity to your own numbers: recompute the share-weighted factor for the current period and compare it to the fitted one. The difference is the error, in your units.

Closing: Compare the Same Month

The instinct to deseasonalize before decomposing is a good instinct applied in the wrong order. Seasonality is real and it does swamp a month-on-month tree. The fix is not to rework the nodes, because that arithmetic is non-additive and additivity is the only property the tree provides.

The fix is to change what the tree compares. Hold the season constant against the same period a year earlier, keep raw summable quantities in every node, test both base periods for calendar comparability, and check the mix before trusting any aggregate factor you did not compute yourself.

Do that and the arithmetic in this article never arises. The parts add to the total, and the review argues about the business instead of the adjustment.

Upload one CSV, pick the metric your last monthly review stalled on, and decompose it against the same month last year.

Sources