learn-finance-with-phoebe / Practitioner session 5 of 10
Learn Finance with Phoebe · Practitioner session 5 of 10

The balance sheet and the tie

Session 1 wired net income into equity and the change in cash into the cash line, and left the tie sitting there as a fact about a working model. This one takes the sheet apart. Seven lines, each of which arrived from something the other two statements did, held equal by an identity that no convention chose. Marchmont's opening equity of £1,662,000 is not an input: it is solved, and the reason that is correct rather than convenient is worth twenty minutes. Then the part that only works if you do it: change one line in the engine so the sheet stops tying, watch the tie check report the exact size and the exact month of what you broke, and put it back.

🟢 Hands on Analysts who build the model Anyone reviewing somebody else's 45 min
0-4 · Welcome 4-32 · The position, and the solved opening 32-54 · Build-along: break it, then fix it 54-60 · Q&A
Part 0

Where this picks up

Session 1 named the two wires and ran the check. Session 3 produced the receivables, inventory and payables balances. Session 4 turned them into the bridge and landed on the change in cash. Every one of those outputs is a line on the sheet, so today is where the parts come back together and where the check earns its keep. Session 6 starts driving the model from its assumptions. The engine is assets/fin-live.js, loaded on this page.

Live = run together in the session Self-study = the full depth, after class 🔍 Every diagram zooms

★ What you walk out with today. Seven Marchmont lines and the activity that produced each one, so you can read a sheet as a record of what happened rather than a list of balances. The solved opening equity of £1,662,000, why solving is the honest option and what it costs you. The tie as a working check, with its measured result: 2.24e-8 worst error across the full canon set of 50 model runs, against a tolerance of 0.01. And two deliberate breaks, one that produces a constant error and one that produces a growing one, because the shape of a failure tells you what kind of mistake you made.

LiveA position, not a period4 min▶

The income statement and the cash flow statement both cover a stretch of time and are meaningless without one. The balance sheet is a single instant. Nothing on it happened during the month; everything on it is what was left standing at the end of it.

That is why the sheet has no subtotal you can call performance. It has a shape instead, and the shape is the whole argument: what the business controls on one side, and who has a claim on it on the other.

Real world

Marchmont's cash line at the end of month 10 is minus £7,432. Nothing about that figure says the month was bad. It says that on one particular evening, after ten months of profitable trading, the balance was below zero. The reason lives on the other two statements.

Self-studyThe fields the sheet is made of4 min▶

Each row the engine returns carries the whole sheet, plus the two totals and the difference between them. There is no separate balance sheet object, because the sheet is the row.

row fields used todaycash the bank balance at month end ar receivables: invoiced, not yet collected inventory instruments made, not yet sold netFixed fixed assets at cost less depreciation to date ap payables: received, not yet paid for equity the owners' claim, opening plus profits kept assets cash + ar + inventory + netFixed liabsEquity ap + debt + equity tieError assets - liabsEquity, computed per month

No credentials of any kind are involved. If an example ever needs one, the string is the word placeholder.

Part 1 · covers the position

Seven lines, and what put each one there

11 min live

Every balance on the sheet is the residue of an activity somewhere else. Reading it well means naming that activity for each line, which turns a list of balances into a history.

Each balance is the leftover of something the other two statements did. What Marchmont controls Who has a claim on it cash Moved by freeCF and by nothing else in the engine. ar, receivables Revenue invoiced and not yet collected. Set by DSO. inventory Instruments built and not yet sold. Set by DIO. netFixed Capex added, depreciation taken off, month after month. ap, payables Supplier costs received and not yet paid. Set by DPO. debt £300,000 throughout. Nothing drawn, nothing repaid. equity The owners' claim on whatever is left over. Opening: £1,662,000, solved rather than supplied. Then plus net income, every month, and nothing else. No dividend is paid, so no profit ever leaves. The two sides carry the same total at every month end. Not because anyone rounded them together. Everything owned was funded by somebody, so the claims must add to the same amount.
🔍 Click to zoom - three of the four left hand lines and one of the right hand ones are pure working capital, which is why session 3 was the session that decided the shape of this page.
LiveThe identity, and why it is not a rule4 min▶

Everything a business controls was paid for by somebody: a supplier waiting to be paid, a lender, or the owners, including through profits they left in the business. There is no fourth source. So the total of what it controls is the total of the claims on it, necessarily, not by agreement.

That is what makes the sheet usable as a test. A rule can be waived and a convention can be argued about. An identity cannot fail, so when the two sides differ the failure is in the recording, and the recording is the thing you can go and look at.

LiveEquity is the residual, and it behaves like one4 min▶

Payables and debt are claims for fixed amounts: a supplier is owed what the invoice says. Equity is whatever is left after those are satisfied, which means it absorbs every change that is not itself a claim. Profit raises it, a loss lowers it, and no one negotiates the figure.

In this engine that residual character is literal. Equity is the only balance on the sheet that no assumption drives directly. It opens as a solved number and then moves by net income, once a month, for as long as the model runs.

fin-live.jsvar equityNew = equity + netIncome; // the only write to equity after month 0
Self-studyNet fixed assets, the line that hides two movements4 min▶

One balance, two opposing flows. Capex adds to it and never touched the income statement. Depreciation takes off it and never touched the bank. A single netFixed figure therefore tells you nothing about either on its own, which is exactly why both appear separately on the cash flow statement.

fin-live.jsvar netFixedNew = netFixed + capex - depreciation;

Marchmont spent £180,310 and depreciated £102,025 over twelve months, so the line grew. A company whose net fixed assets shrink year after year is depreciating faster than it is investing, which is a fact about the future rather than the past.

Part 2 · covers the opening

£1,662,000 that nobody supplied

8 min live

Marchmont existed before month 1. It opens with customers who already owe it money, stock already on the shelf, suppliers already owed and a loan already drawn. Six of the seven opening balances are given. The seventh is worked out.

The opening sheet, and the one number nobody handed us. Owned at month 0 cash £250,000 receivables £1,000,000 inventory £464,000 net fixed assets £480,000 Owed at month 0 payables £232,000 debt £300,000 Everything owned, less everything owed, is by definition what the owners have in it. Opening equity, solved: £1,662,000 Six balances given, one worked out. The engine never asks for this figure and never reads an input for it. This is history, not a plug. It is every pound the owners ever put in and every pound of profit the business ever kept, which is not separately knowable from outside.
🔍 Click to zoom - the opening receivables, inventory and payables are set consistently with month 1 activity, which is also why the month 1 working capital movement is zero.
LiveWhy solving is correct rather than convenient4 min▶

Equity is not a measurement of anything. It is a definition: what is left when the claims of everybody else are met. Asking a modeller to supply it as an input is asking them to state a number that, if it disagrees with the other six, is simply wrong, because the other six describe things that physically exist and equity does not.

So the engine computes it once, at month 0, from the six balances that do describe real things.

fin-live.jsvar equity = (cash + ar + inv + netFixed) - (ap + debt); // £1,662,000 under the base assumptions

Session 1 set out the argument against this and it is a real one: a solved opening means month 0 cannot fail, so the tie is testing the forward mechanics rather than the opening data. The useful response is not to argue, it is to know precisely which half of the model the check covers.

LiveWhat a plug is, and why this is not one4 min▶

A plug is a figure inserted repeatedly to absorb a difference nobody has explained, usually every period, often with a name like other or adjustment. Its signature is that it moves when something unrelated changes and nobody can say why.

Marchmont's opening equity is computed once, from a definition, and never touched again. After month 0 it moves only by net income. If it were a plug, a change in the collection setting would move it; run { dso: 45 } and it does not, because collecting sooner rearranges cash and receivables on the same side of the sheet.

Self-studyTesting the opening data separately4 min▶

If the tie cannot test the opening position, something else has to. The honest substitute is a reasonableness check on the six given balances, which is a different kind of test and worth running by hand.

Opening receivables of £1,000,000 against month 1 revenue of £400,000 implies two and a half months of sales uncollected, which is the 75 day collection setting and is consistent. Opening inventory of £464,000 against a 60 day stock setting is two months of cost of sales, also consistent. A sheet whose opening receivables implied eight months of sales would tie perfectly and still be wrong, and only this check would catch it.

Part 3 · covers the check

The tie, measured across fifty runs

8 min live

One passing run proves almost nothing. Models fail on particular settings, and a check that has only ever been run on the base case is a check that has never been tested. The canon set is fifty runs.

Five growth rates, five collection settings, two horizons each. Every cell below is run to 24 months and again to 48. Fifty runs, fifty ties. days 30 45 60 75 90 growth 0% 2% 4% 6% 8% 24 ✓ 48 ✓ 24 ✓ 48 ✓ 24 ✓ 48 ✓ 24 ✓ 48 ✓ 24 ✓ 48 ✓ 24 ✓ 48 ✓ 24 ✓ 48 ✓ 24 ✓ 48 ✓ 24 ✓ 48 ✓ 24 ✓ 48 ✓ 24 ✓ 48 ✓ 24 ✓ 48 ✓ 24 ✓ 48 ✓ 24 ✓ 48 ✓ 24 ✓ 48 ✓ 24 ✓ 48 ✓ 24 ✓ 48 ✓ 24 ✓ 48 ✓ 24 ✓ 48 ✓ 24 ✓ 48 ✓ 24 ✓ 48 ✓ 24 ✓ 48 ✓ 24 ✓ 48 ✓ 24 ✓ 48 ✓ 24 ✓ 48 ✓ Worst error anywhere 2.24e-8 against a tolerance of 0.01 Two hundredths of a millionth of a penny. That is the arithmetic, not the accounting. ties() returns ok: true. The shaded row is the base case. The other twenty cells are why the result means anything. A check that has only been run where it was expected to pass has not been tested. Anything worse than tolerance is reported as broken, never plotted.
🔍 Click to zoom - the highlighted row is 4% growth, the base case. The base case is one of fifty, not the evidence.
LiveWhat the check actually reads4 min▶

Each row carries its own tieError, computed as assets - liabsEquity at the moment the row is built. ties walks all of them, keeps the largest absolute value and compares it to a tolerance that defaults to a penny.

fin-live.jstieError: assets - liabsEquity // stored on every row, one per month // and the walk: var e = Math.abs(result.rows[i].tieError); if (e > worst) worst = e; return { ok: worst <= tolerance, worst: worst };

Two consequences worth holding onto. The check reads a stored field rather than recomputing, so editing a row's balances without editing its tieError will not be caught. And it reports the worst month only, so a single failing month and a dozen failing months look identical until you inspect the rows.

LiveWhy the tolerance is not zero3 min▶

A computer adding decimal amounts does not land on exact zero, and the residue accumulates slightly with the number of months. Demanding an exact match would make the check fail on correct models, which trains everybody to ignore it.

A penny is the right order of magnitude because it is the smallest amount that could be a real accounting error. The measured worst across all fifty runs is 2.24e-8, which is roughly six orders of magnitude inside that, so the tolerance is not doing any work in practice and would not hide a genuine mistake.

Self-studyRunning the sweep yourself4 min▶
consoleconst growths = [0, 0.02, 0.04, 0.06, 0.08]; const dsos = [30, 45, 60, 75, 90]; let worst = 0, runs = 0; for (const growth of growths) { for (const dso of dsos) { for (const months of [24, 48]) { const r = MARCHMONT.run({ growth: growth, dso: dso }, months); const t = MARCHMONT.ties(r); runs += 1; if (!t.ok) throw new Error("no tie at " + growth + "/" + dso); if (t.worst > worst) worst = t.worst; } } } runs; // 50 worst; // the canon figure

The throw is the load bearing line. A sweep that records failures and keeps going will hand you a summary with a broken run inside it.

Part 4 · covers the failure

Break it on purpose, twice

7 min live

A check you have only ever seen pass is a check you do not understand. Two deliberate breaks, one that drops a single leg and one that cuts a wire for good, and the two failures look nothing like each other.

Same check, two failures, and the shape says which mistake you made. Break one: a single leg dropped flat at £38,356 month 7 net income, exactly Constant from month 7 on. One entry missed, and it never repeats. Break two: the wire cut for good £445,631 by month 12 the whole year's profit, never reaching equity Growing every month. The first non zero month is where you cut it. A flat error is a missing entry. A growing error is a broken rule. Reading the shape before you go looking saves the afternoon, because the two faults live in completely different parts of a model.
🔍 Click to zoom - both of these are produced by editing the engine and running it, not by drawing a plausible curve. The numbers are what the broken model reported.
LiveBreak one: drop a single leg4 min▶

In a copy of fin-live.js, stop equity rising in exactly one month and leave every other line alone. This is what recording an invoice against receivables and forgetting the revenue side looks like from the outside.

fin-live.js, deliberately broken// was: var equityNew = equity + netIncome; var equityNew = (m === 7) ? equity : equity + netIncome;

Run it and the tie error is zero for six months, becomes £38,356 in month 7, and then stays at £38,356 for every month after. It stays flat because later months add their own net income correctly; only the one leg is missing, forever. And £38,356 is month 7's net income, which is the whole point of the check. The failure names the transaction.

LiveBreak two: cut the wire and leave it cut4 min▶
fin-live.js, deliberately broken// was: var equityNew = equity + netIncome; var equityNew = equity;

Now profit never reaches equity at all. The tie error is non zero from month 1 and grows every month, reaching £445,631 by month 12, which is exactly twelve month net income. A rule has been broken rather than an entry missed, so the damage compounds.

Put the line back and re-run before doing anything else. The discipline that matters here is not the break, it is restoring the file and confirming ties returns ok again, because a broken engine left on disk is the one that gets used next week.

Self-studyBreaking a row without touching the engine3 min▶

If you would rather not edit the file, you can break a single row in memory. Because ties reads the stored tieError rather than recomputing it, the row's own total has to be updated too, which is itself the lesson.

consoleconst m = MARCHMONT.run({}, 12); m.rows[6].ar = m.rows[6].ar + 5000; // an invoice raised m.rows[6].assets = m.rows[6].assets + 5000; // the asset side moves m.rows[6].tieError = m.rows[6].assets - m.rows[6].liabsEquity; MARCHMONT.ties(m); // { ok: false, worst: 5000 }

Change only the first line and the check still passes, which is worth seeing once. A check that reads a stored result can only catch what the recording step recorded.

Part 5 · build-along

Read the sheet, then break it

22 min hands on

Six steps. The first three are in the console on this page. The last three need a copy of fin-live.js you are willing to damage.

Rebuild both totals by hand

Take rows[11] and add cash, ar, inventory and netFixed yourself. Then add ap, debt and equity. Compare each against the stored assets and liabsEquity. You are checking the engine's arithmetic, which is a reasonable thing to do once with any model you did not write.

Recover the opening equity

Take rows[0].equity and subtract rows[0].netIncome. You should land on £1,662,000. Confirm the same figure comes out of the six opening balances directly, and note that nothing in the assumptions supplied it.

Show that a working capital change does not move equity

Run the base case and { dso: 45 } side by side and compare month 12 equity. They should be identical, because collecting sooner moves money between two lines on the same side of the sheet. If equity had moved, the model would be claiming that collection terms change profit.

Drop one leg and read the error

In your copy, stop equity rising in one chosen month. Print every month's tieError. Confirm the error is zero before that month, equal to that month's net income from it onwards, and flat thereafter.

Cut the wire and read the shape

Now remove the net income addition entirely. Print the same column. Say in one sentence how you would tell these two failures apart if somebody handed you only the tieError column and no explanation.

Restore, and prove you restored it

Put the original line back and run the fifty run sweep. Anything other than ok across all fifty means something else is still edited. Finishing a deliberate break by proving the check passes again is the part people skip.

The habit to keep. Tie check any run before you read a single figure from it, including runs somebody else produced. It is one line, it cannot give a false pass on the mechanics it covers, and the alternative is interpreting a shape that came out of a broken model with complete confidence.

Check yourself

Three questions

Marchmont's opening equity of £1,662,000 is computed from the other six opening balances rather than supplied. What is that?

A plug is inserted repeatedly to absorb unexplained differences. This is computed once at month 0 from six balances that describe real things, and then moves only by net income. The real cost is that month 0 cannot fail, so the tie tests the forward mechanics rather than the opening data, and that is worth saying out loud.

A tie error is zero for six months, becomes £38,356 in month 7 and stays at exactly £38,356 for the rest of the run. What happened?

A flat error is a single missing entry: later months carry on correctly, so nothing adds to it. A rule that has been broken produces a growing error instead, which is the other deliberate break. The flat value is exactly month 7's net income, which is how the failure names the transaction.

Across the fifty run canon set the worst tie error is 2.24e-8 against a tolerance of 0.01. Why does the sweep matter rather than just the base case?

The canon set crosses five growth rates with five collection settings at two horizons precisely because a sign or an accumulation can break at one combination and nowhere else. More runs do not make the arithmetic more accurate; they make the passing result mean something.

Before session 6

Homework

Thirty minutes, in the console and on a copy of the engine.

Invent your own break

Choose any line in the engine other than the equity wire and break it so the sheet stops tying. Predict the shape of the error before you run it, then run it and see whether you were right. Being wrong is the useful outcome.

Reconcile the opening balances against the assumptions

Check that opening receivables, inventory and payables are each consistent with month 1 activity and the 75, 60 and 30 day settings. Write down what you would have to see to conclude the opening data was wrong even though the sheet tied. Session 6 starts changing those settings.

Covered today

What this session covers

✓The sheet as a positionA single instant, with no performance figure on it anywhere.
✓Seven lines and where each came fromCash, receivables, inventory, net fixed assets against payables, debt, equity.
✓The identity behind the balanceEverything controlled was funded by somebody, so the claims must add to the same total.
✓The solved opening equity£1,662,000, computed once from six given balances, and what solving it costs.
✓The tie measured across the canon set2.24e-8 worst across 50 runs, against a 0.01 tolerance.
✓Two deliberate breaks and their shapesFlat £38,356 for a dropped leg, growing to £445,631 for a cut wire.
◐Driving the sheet from the assumptionsPractitioner session 6, and the levers in session 7.
◐Breaking the model on a full benchPractitioner session 10.
○What the net assets are worthA different subject with different tools; not covered here.
○Statutory presentation and auditJurisdiction specific and not the point here.
Take this with you

Cheat sheet

A position, not a period. Nothing on the sheet happened during the month; it is what was left at the end of it.
The identity. assets = cash + ar + inventory + netFixed. liabsEquity = ap + debt + equity.
Equity is the residual. Solved once at £1,662,000, then plus net income and nothing else.
Not a plug. A plug is inserted repeatedly to absorb a difference nobody has explained.
What the tie covers. The forward mechanics. Not the opening data, which needs its own reasonableness check.
The measured result. 2.24e-8 worst across the 50 run canon set, tolerance 0.01.
Flat error. One entry missed. The amount is the leg you did not record.
Growing error. A rule broken. The first non zero month is where it started.