learn-value-investing-with-phoebe / Analyst session 2 of 10
Learn Value Investing with Phoebe · Analyst session 2 of 10

Normalising through a cycle

Last session ended with a list of years that jump. Exxon Mobil's owner earnings per share went from 1.47 dollars in fiscal 2020 to 14.60 two years later; Johnson & Johnson's fell to 1.33 in one year and bounced straight back. Any valuation that starts from a single year is held hostage by whichever year it picked. Tonight we average across five and ten years for the same four filers, learn to tell a business swinging through its cycle from an accounting event that happened once, and take a first look at what a hold-out test showed about which starting point misses least. No share prices anywhere.

🟡 Analyst Analysts, finance and data people who want a defensible starting number Python, standard library only, continuing Analyst session 1's reader 45 min
0-3 · Welcome 3-18 · Averages, cycle or event, the ladder 18-40 · Build-along: normalise four filers 40-45 · Q&A
Part 0

Where we start

In Analyst session 1 you built owner earnings per share, all-capex approximation, for Caterpillar, Exxon Mobil, Johnson & Johnson and Procter & Gamble, fifteen to nineteen fiscal years each. Every valuation in sessions 4 to 6 needs one starting number per company, and the choice of that number moves the answer more than most people expect. Normalising means choosing it on purpose: over a window long enough to hold a whole cycle, with every unusual year named rather than hidden.

🎫 Clear all three quiz questions to stamp your passport Live = presented in the 45 minutes Self-study = the full depth, after class ★ Build-along = everyone builds

★ What you walk out with tonight. Five- and ten-year owner earnings per share for four filers, computed from your own reader; a one-line rule that flags the years worth a second look; a sorting habit for those years, cycle or event; and the honest sentence about what the ladder showed, which is narrower and more useful than "averages work".

Part 1 · covers five- and ten-year averages

One year is a hostage

5 min live

Exxon Mobil's owner earnings per share were 1.84 dollars in fiscal 2015, 1.47 in fiscal 2020, 14.60 in fiscal 2022 and 6.15 in fiscal 2025. In fiscal 2020 its net income per share was minus 5.25. Pick any one of those years as "what the business earns" and you have picked a different company. An average over several years is the plainest way to stop one year from deciding everything.

EXXON MOBIL, OWNER EARNINGS PER SHARE, FY2011 TO FY2025 dollars, all-capex approximation · each line is a mean at FY2025, drawn over the years it averages 2022: inside the 5-yr mean 5-yr mean 8.87 10-yr mean 6.16 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 5.27 5.73 3.64 3.94 1.84 3.35 5.69 4.69 2.10 1.47 7.39 14.60 8.57 7.64 6.15 FY2020 net income per share was -5.25; owner earnings stayed positive because the write-downs sit inside D&A.
🔍 Click to zoom - the five-year mean sits above the ten-year mean because the boom year is inside its window
LiveWhy a cyclical business needs a whole cycle3 min▶

A cyclical business earns a lot in some years and very little in others because of things outside any single year's management: the price of what it sells, its customers' spending, the stage of an industry's investment cycle. What an owner gets over time is the average across those swings, not any one point on them. So the window you average over has to be long enough to contain at least one good stretch and one bad one. A window that holds only the good years overstates the business; one that holds only the bad years understates it.

Buffett's 1986 letter defends this kind of judgment over false precision: "I would rather be vaguely right than precisely wrong." A ten-year average is vague. A single year's figure, printed to the cent, is precise and, for Exxon, has ranged from 1.47 to 14.60 dollars in three years.

Self-studyA five-year average can include the boom3 min▶

Standing at fiscal 2025, Exxon's five-year mean owner earnings per share is 8.87 dollars and its ten-year mean is 6.16. The five-year window, fiscal 2021 to 2025, contains fiscal 2022 at 14.60 and no trough at all. The ten-year window, fiscal 2016 to 2025, also holds 2019 at 2.10 and 2020 at 1.47. Neither number is "right". The five-year number says what the last five years averaged; the ten-year number is closer to a whole cycle, and it is the more conservative of the two here.

The same check applies to every filer: before trusting a window, look at what is inside it. A window is only as good as the cycle it happens to contain, and you know which cycle that is only by printing the rows.

Real world

Exxon Mobil's capital spending ran ahead of its depreciation. Analyst session 1 showed Exxon's capex between about 1.5 and 2.2 times its depreciation every year from 2011 to 2015, the pattern Buffett's 1986 letter names for the oil industry. Over the last ten fiscal years the ratio was 0.82. A five-year window that sits in a heavy-spending stretch and one that sits in a lighter one can describe the same business very differently, before any judgment about growth.

Part 2 · covers cyclical swings versus one-off events

Cycle or one-off

5 min live

Not every jump is the cycle. Some years are the business swinging; some are an accounting event that happened once and will not repeat. They call for different treatment, so the first job with each unusual year is to sort it. Two tests do most of the work: does the next year snap back to trend, and does the 10-K note name a gain, a charge or a write-down?

SIX JUMPS, SORTED BY WHAT CAUSED THEM owner earnings per share, dollars · a cycle swings over years; an event is one year with a named cause CYCLE · the business swung EVENT · named in the note UNSORTED · read the note Caterpillar FY2016 · 3.18 trough: 4.56, then 12.74 next Exxon Mobil FY2022 · 14.60 a swing: 7.39, 14.60, 8.57 J&J FY2017 · 1.33 6.12, then 1.33, then 6.80 J&J FY2023 · 14.88 consumer health separation gain Exxon Mobil FY2020 · 1.47 trough, plus write-downs inside D&A P&G FY2019 · 1.33 numbers alone cannot say two tests 1 · next year snaps back 2 · the 10-K note names a gain, a charge or a write-down until then: keep it, say so Exxon FY2020 sits on the line: a cyclical trough and write-downs inside D&A, in the same year.
🔍 Click to zoom - sort every jump before averaging; one year can be a trough and an event at once
LiveWhat to do with an event year3 min▶

Keep it, note it, show the average with and without it, and never drop it silently. Dropping a year changes the number and hides the choice; leaving it in without a word hides it too. Showing both lets the reader of your figure see how much rides on the judgment.

Sometimes very little does. Johnson & Johnson's ten-year mean, fiscal 2016 to 2025, is 7.92 dollars per share with every year in; without fiscal 2017 and 2023 it is 7.87 over eight years, because one event pulled down and the other pushed up. Procter & Gamble's ten-year mean is 5.00 with fiscal 2019 and 5.41 without it, which is a bigger change, and the 10-K note decides whether the higher number is the fairer one. Both pairs are computed from the same engine the bench uses.

Exxon's fiscal 2020 shows why the sorting matters. Its D&A that year, 46,009 million dollars, included large write-downs, and owner earnings add D&A back, so owner earnings per share stayed at 1.47 while net income per share was minus 5.25. Part of that year is the cycle, which a normalised number should keep; part is a write-down, which the formula has already partly undone.

Self-studyRestatements change history2 min▶

A normalised number is built from the past, and the past is not fixed. Caterpillar's fiscal 2014 net income was 3,695 million dollars in the 10-K filed in 2015 and 2,452 million in later ones; fiscal 2015 moved from 2,102 to 2,512 million. Both changes came from the company restating earlier years. A ten-year average computed in 2015 and one computed today use different histories for the same years.

The reader from Analyst session 1 takes the latest filed value, so restatements win. That is a choice, and it belongs in the label: "ten-year mean owner earnings per share, all-capex approximation, latest filed values". A backtest that wants to know what was knowable at the time would need the original numbers instead.

Real world

Johnson & Johnson's two events. J&J's net income was 1,300 million dollars in fiscal 2017 and 35,153 million in fiscal 2023, the second including a gain from separating its consumer health business. Owner earnings per share were 1.33 and 14.88 dollars in those years, against 6.12 the year before 2017 and 6.80 the year after. Neither year describes what the remaining business earns in a normal year, and an average that holds only one of them is pulled in one direction.

Part 3 · covers the hold-out ladder

Where you start decides what you see

5 min live

Is a normalised number actually a better starting point than last year's? You can test that on the past. Stand at some year, forecast the years after it from what was known then, and measure the miss. The bench in Analyst session 10 does exactly this with four honest rungs: last year's net income per share, the five-year mean of owner earnings, the ten-year mean, and the ten-year mean growing at a fading rate. Here is the preview.

MEAN MISS BY RUNG, THREE HOLD-OUTS, FOUR FILERS brass = the rung that missed least in that row · lower is better hold-out 1 · last year 2 · five-year 3 · ten-year 4 · fade 3 years 39.7% 28.4% 41.8% 36.5% 4 years 26.8% 42.1% 47.9% 44.7% 5 years · default 70.4% 47.4% 50.2% 47.7% never the best Mean absolute miss across four filers. Every honest rung undershot: owner earnings rose sharply after 2020. The anti-lever, which compounds the best past year, missed by thousands of percent. Analyst session 10 runs it.
🔍 Click to zoom - the five-year mean missed least in two rows of three; nothing in the table saw the rise coming
LiveThe honest claim3 min▶

Hold out the last five fiscal years and the five-year mean missed by 47.4 percent on average against 70.4 percent for last year's net income. Hold out three and it wins again, 28.4 percent. Hold out four and last year's earnings win, 26.8 percent against 42.1, because that test starts from fiscal 2021, a strong year. The ten-year mean never had the smallest miss in any row.

So the honest sentence is narrow: on four filers and three hold-outs, a five-year normalised base missed less than last year's earnings in two of three tests, and every honest rung undershot. That is evidence about these companies over this stretch. It is not a law that averages beat single years, and the result changed when the starting year changed, which is the whole point of Part 3's title.

Self-studyWhy averages cannot see a boom coming3 min▶

Every honest rung is built from the past. If the years after your starting point are much better than the years before it, every average undershoots, and the longer the average, the more old, lower years it carries. At the five-year hold-out each rung's bias equals minus its mean miss: all four rungs guessed low for all four filers, because owner earnings for all four rose sharply after 2020.

Normalising protects you from mistaking one year for the business. It does not tell you where the business is going. That is a separate judgment, about growth and how long it lasts, and it is the work of Analyst sessions 7 and 8. The full ladder, including the anti-lever and its rebound-driven misses, runs in Analyst session 10, the intrinsic value bench.

Real world

Standing at Exxon Mobil's fiscal 2020. At the five-year hold-out the test stands at fiscal 2020 and forecasts the mean of fiscal 2021 to 2025, which turned out to be 8.87 dollars per share. Last year's net income per share was minus 5.25, a miss of 159.3 percent. The five-year mean of owner earnings was 3.46, a miss of 61.0 percent; the ten-year mean, 3.77, missed by 57.5. The averages were far better than the single year and still badly low.

Build-along

Normalise four filers

★ 22 min · everyone builds

Python 3, standard library only, continuing the reader from Analyst session 1. You need its owner_earnings(cik) function, which returns rows of fiscal year, net income per share and owner earnings per share. The printed figures below are the ones the bench computes from the same filings; if your reader's sieve differs, your numbers will differ, and the difference is worth finding.

ROWS TO AVERAGES, AND THE CHECK AFTER EACH STEP 1 · rows session 1's owner_earnings() 2 · slice last 5 rows, last 10 rows 3 · mean one per window 4 · flag 50% from 10-yr median check: the last year P&G ends at FY2026 check: window years a missing year shortens it check: five vs ten which is higher, and why? check: read each flag a question, not a verdict The rule flags boom years and a normal year too. It points you at the 10-K note; it cannot sort for you.
🔍 Click to zoom - the flag in brass is the step that needs a human; the code only says where to look

Step 1 · Load the rows for all four filers. One call per company to the reader you built in Analyst session 1, kept in a dictionary so every later step reuses them without fetching again.

★ Step 1 · rows from session 1's readerfrom statistics import mean, median FILERS = [("0000018230", "Caterpillar"), ("0000034088", "Exxon Mobil"), ("0000200406", "Johnson & Johnson"), ("0000080424", "Procter & Gamble")] ROWS = {name: owner_earnings(cik) for cik, name in FILERS} # [(fy, ni_ps, oe_ps), ...]

Step 2 · Check the windows before averaging. Print which fiscal years each window covers. P&G's year ends in June, so its last year is fiscal 2026 while the others end at fiscal 2025.

★ Step 2 · which years are insidefor name, rows in ROWS.items(): years = [r[0] for r in rows] print(f"{name:18} five-year FY{years[-5]}-FY{years[-1]} ten-year FY{years[-10]}-FY{years[-1]}") Caterpillar five-year FY2021-FY2025 ten-year FY2016-FY2025 Exxon Mobil five-year FY2021-FY2025 ten-year FY2016-FY2025 Johnson & Johnson five-year FY2021-FY2025 ten-year FY2016-FY2025 Procter & Gamble five-year FY2022-FY2026 ten-year FY2017-FY2026

Step 3 · Five- and ten-year means at the last fiscal year. These two numbers are rung 2 and rung 3 of the bench, the bases Analyst sessions 4 to 6 value.

★ Step 3 · normalise, and what it printeddef normalise(rows): oe = [r[2] for r in rows] return rows[-1][0], mean(oe[-5:]), mean(oe[-10:]) for name, rows in ROWS.items(): y, m5, m10 = normalise(rows) print(f"{name:18} FY{y} five-year {m5:6.2f} ten-year {m10:6.2f}") Caterpillar FY2025 five-year 17.94 ten-year 13.17 Exxon Mobil FY2025 five-year 8.87 ten-year 6.16 Johnson & Johnson FY2025 five-year 10.21 ten-year 7.92 Procter & Gamble FY2026 five-year 5.90 ten-year 5.00

Step 4 · Flag the years worth a second look. A simple rule: within the ten-year window, flag any year whose owner earnings per share sit more than 50 percent away from the window's median. The median is used because, unlike the mean, one wild year cannot drag it.

★ Step 4 · the flag rule, and what it printeddef flag_events(rows, window=10, band=0.5): recent = rows[-window:] med = median([oe for _, _, oe in recent]) return med, [(y, oe) for y, _, oe in recent if abs(oe - med) > band * abs(med)] for name, rows in ROWS.items(): med, flags = flag_events(rows) print(f"{name:18} median {med:5.2f} flagged: " + ", ".join(f"FY{y} {oe:.2f}" for y, oe in flags)) Caterpillar median 13.77 flagged: FY2016 3.18, FY2017 4.56, FY2023 21.19, FY2024 22.39 Exxon Mobil median 5.92 flagged: FY2019 2.10, FY2020 1.47, FY2022 14.60 Johnson & Johnson median 6.98 flagged: FY2017 1.33, FY2023 14.88, FY2025 12.13 Procter & Gamble median 5.57 flagged: FY2019 1.33

Step 5 · Sort each flag by hand. The rule flagged Caterpillar's fiscal 2023 and 2024 and J&J's fiscal 2025: those are years of a business that grew, not events. It did not flag Exxon's fiscal 2015 at 1.84, because 2015 is outside the ten-year window. Write one line per flag: cycle, event, or not yet known.

★ Step 5 · your sorting notes# one line per flag: cycle / event / not yet known, and the evidence # Caterpillar FY2016 ______________________________________________ # Exxon Mobil FY2020 ______________________________________________ # J&J FY2023 ______________________________________________ # P&G FY2019 ______________________________________________

Step 6 · Show the average with and without your event years. Never drop a year silently; print both and let the reader see what rides on the choice.

★ Step 6 · with and without, and what it printeddef with_without(rows, events, window=10): recent = rows[-window:] kept = [oe for y, _, oe in recent if y not in events] return mean(oe for _, _, oe in recent), mean(kept), len(kept) for name, events in [("Johnson & Johnson", {2017, 2023}), ("Procter & Gamble", {2019})]: w, wo, n = with_without(ROWS[name], events) print(f"{name:18} ten-year with {w:5.2f} without {wo:5.2f} ({n} years)") Johnson & Johnson ten-year with 7.92 without 7.87 (8 years) Procter & Gamble ten-year with 5.00 without 5.41 (9 years)

Keep the label with the number. A normalised figure travels as "ten-year mean owner earnings per share, all-capex approximation, latest filed values, event years kept (or: excluding FY2017 and FY2023)". The window, the treatment of events and the restatement choice are all part of the number.

Homework

Before Analyst session 3

30 min
  1. Normalise your fifth company from Analyst session 1's homework: print its five- and ten-year means and the years inside each window. Which window holds a whole cycle, if either does?
  2. Run the flag rule on it and sort every flag as cycle, event or not yet known. For each event, find the line in the 10-K note that names it.
  3. Change the band from 50 percent to 30 and to 70 for one of the four filers. Write one sentence on what the rule catches and misses at each setting.
  4. Write the label for your normalised figure: window, event treatment, restatement choice, and the with-and-without pair if you excluded anything.
Check yourself

Three questions

Clear all three and Analyst session 2 gets stamped in your passport.

1 · Why normalise owner earnings before valuing a cyclical business like Exxon Mobil?

A single year is a point on a swing. Averaging over a window that holds a whole cycle describes what an owner gets over time. It does not promise a better forecast, and it makes looking at the rows more important, not less.

2 · J&J's owner earnings per share were 6.12 in fiscal 2016, 1.33 in fiscal 2017 and 6.80 in fiscal 2018. What is the right first treatment of 2017?

A one-year collapse that recovers the next year is the signature of an event, not a cycle. The 10-K note names the cause. Keeping the year and printing both averages leaves the judgment visible; for J&J's ten-year mean it moves the number only from 7.92 to 7.87.

3 · What did the hold-out ladder preview show?

The result depends on where the test starts: from fiscal 2021, a strong year, last year's earnings won. Every honest rung guessed low because all four filers' owner earnings rose sharply after 2020. The claim is about these filers and these tests, not a law.

Sources covered

What this session teaches, and where it came from

✓Every filer figure: owner earnings per share by year, five- and ten-year means (17.94 / 13.17, 8.87 / 6.16, 10.21 / 7.92, 5.90 / 5.00), medians, flagged years, with-and-without means, Exxon FY2020 D&A, J&J FY2017 and FY2023 net income, Caterpillar's restatementsSEC EDGAR XBRL company facts, read from a public mirror after the SEC refused the build machine; computed with the bench's own engine
✓The hold-out ladder: mean miss by rung at three hold-outs, the undershoot, Exxon standing at fiscal 2020Computed from the same filings; two independent implementations agreed on every value
✓"Vaguely right than precisely wrong"; the oil industry as the case where capex exceeds D&ABuffett, W., Berkshire Hathaway shareholder letter, 1986, appendix (read at source)
◐The causes of P&G's fiscal 2019 and J&J's fiscal 2017 dropsNot read from the 10-K notes in this build; left for the learner to find, and taught as not yet known
◐Reading the three statements, cash versus profitTaught in Finance: Reading the Numbers; linked, not re-taught

Every fact on this page, and its verification tier, is recorded in the course's source map.

Analyst session 2 cheat sheet · pin this

One year is a hostageExxon went 1.47 to 14.60 a share in three years. Average across a cycle.
Look inside the windowA five-year window can hold the boom and no trough. Print the years.
Cycle or eventDoes next year snap back? Does the 10-K note name it? Then sort.
Never drop silentlyKeep it, note it, show the mean with and without.
A flag is a questionThe 50 percent rule also flags growth years. A human sorts.
The honest claimFive-year mean missed least in two of three tests; every rung undershot.