Revenue, net income, and margins on the income statement
Revenue is what customers were billed. Net income is what's left after every cost the accountants could find, including several that never moved any cash. A margin is one of those numbers divided by revenue, and which cost line you stop at decides what the ratio is telling you.
Two real ones. In the quarter ended 10 May 2026, Costco booked net sales of $69.154 billion against merchandise costs of $61.519 billion. Gross margin: 11.0 percent. In the quarter ended 30 June 2026, Microsoft booked revenue of $90.007 billion against cost of revenue of $29.525 billion. Gross margin: 67.2 percent. Neither figure is a grade. They describe two different ways of getting a product to a customer, and reading them as good and bad is the fastest way to misuse the income statement.
This series has been building the vocabulary our theses use, one statement at a time. An earlier piece laid out how the three statements fit together. This one walks down the middle statement, top line to bottom.
Top line to bottom line, on a filing you can open
Costco's quarterly income statement is a short document. Here are its main lines for the twelve weeks ended 10 May 2026, straight off the release:
- Net sales: $69,154 million
- Membership fees: $1,373 million
- Total revenue: $70,527 million
- Merchandise costs: $61,519 million
- Selling, general and administrative: $6,193 million
- Operating income: $2,815 million
- Interest expense: $32 million
- Interest income and other, net: $155 million
- Provision for income taxes: $746 million
- Net income: $2,192 million
Revenue isn't one thing here. Costco's top line has two sources with completely different economics: merchandise, which carries $61.519 billion of cost right underneath it, and membership fees, which carry no merchandise cost at all. Any ratio you build on "revenue" is averaging across those.
And there's no gross profit line. The statement goes from total revenue straight to merchandise costs to SG&A. Gross profit is a subtotal you compute, and plenty of filers never print it. Small fact, large consequence, and we'll come back to it.
What gross margin actually measures
Gross margin is revenue minus cost of revenue, over revenue. Cost of revenue (also called cost of goods sold) is what it costs to deliver the thing itself: the merchandise, the manufacturing, the servers running the customer's workload. Everything else lives below that line. Salespeople, R&D, the head office, interest, tax.
So gross margin answers a narrow question. Of every dollar that comes in, how much survives the cost of producing what was sold?
For Costco that's $69,154 million minus $61,519 million, or $7,635 million, over net sales: 11.0 percent. For Microsoft it's $60,482 million of gross margin on $90,007 million of revenue: 67.2 percent. Six times the ratio, and the reason is structural. Costco bought the pallet. The second copy of a software license costs about nothing to produce, though the cloud half of Microsoft's business puts real hardware and datacenter depreciation into cost of revenue, which is what keeps the ratio well short of where a pure licensing business would sit.
Costco's thin merchandise margin is the strategy, not a symptom. Membership fees of $1,373 million sit against operating income of $2,815 million, so just under half of the quarter's operating profit arrived on a revenue line with no merchandise cost against it. Sell the goods near cost, charge for the door. A rule that rejects low gross margins would throw this company out for executing its plan correctly.
Net margin, and why it can move the other way
Net margin is net income over revenue, and everything is in it: production costs, operating costs, interest, taxes, gains on asset sales, restructuring charges, the lot. Costco's quarter comes to $2,192 million on $70,527 million of total revenue, or 3.1 percent. Microsoft's comes to $35,766 million on $90,007 million, or 39.7 percent.
Over the same year, Microsoft's two margins moved in opposite directions. The prior-year column shows revenue of $76,441 million, cost of revenue of $24,014 million, gross margin of $52,427 million and net income of $27,233 million. That's a gross margin of 68.6 percent and a net margin of 35.6 percent. A year later: gross margin 67.2 percent, net margin 39.7 percent. One down, one up.
The arithmetic behind it is plain. Revenue grew 18 percent while gross margin dollars grew about 15, so the percentage had to fall. Below the gross line, costs grew slower than revenue, and the bottom line widened anyway. A reader watching only net margin would conclude the business got more profitable per dollar of sales. A reader watching only gross margin would conclude the opposite. Both readings are arithmetically correct and both are incomplete.
The same release also reports the bottom line two ways: net income "increased 31% on a GAAP basis, and was $35.3 billion and increased 22% on a non-GAAP basis". That gap is the company telling you some of the reported profit isn't the operating business repeating itself, which is exactly the problem a one-off creates for a value rule. Net income is also the number most stuffed with estimates, which is why it drifts from the cash the business actually collected.
The level is the fingerprint; the trend is the signal
Comparing Costco's 11 percent to Microsoft's 67 percent tells you what industry each is in. It doesn't rank them. What ranks a company is its own history.
Costco a year earlier: $61,965 million of net sales, $54,996 million of merchandise costs, a gross margin of 11.2 percent, and a net margin of 3.0 percent. So merchandise margin slipped two tenths of a point and net margin ticked up a tenth. Microsoft, over its own year, gave up 1.4 points of gross margin. Small moves in both cases, and neither release explains them.
A gross margin can fall because input costs rose, because the company cut prices to defend share, because a lower-margin product grew faster than the rest of the mix, or because a cost got reclassified above the line. Those are four different companies wearing the same number. A rule can flag the change; the management discussion section of the filing is where the explanation lives, if there is one.
One discipline makes the comparison usable: compare a quarter against the same fiscal quarter a year earlier, never the quarter before it. Retail earns its year in the December quarter, and a sequential margin comparison across that boundary measures the calendar. It's the same reason our theses read trailing numbers and lag by four periods before they compare anything.
What your data actually carries
Gross margin is the more diagnostic of the two ratios, and it's the harder one to put in a rule. The reason is a data problem, and it's worth knowing before you write the rule.
Revenue and net income have been in the point-in-time fundamentals table since the beginning. gross_profit and cost_of_revenue are in the DSL vocabulary and fresh SEC ingests populate both, but those columns landed after early lakes were built, so older rows can sit NULL until a re-pull backfills them. Coverage on recent filings is fine. Coverage a decade back depends on when your lake was first built.
That's why the bundled Piotroski F-Score template ships eight of the paper's nine signals, and says so in the header comments at the top of the file:
# - EIGHT of the nine signals. The gross-margin signal (ΔGM > 0) is DROPPED:
# gross_profit/cost_of_revenue landed in fundamentals_pit after lakes were
# first populated (see PIT_BACKFILL_COLUMNS), so older rows can be NULL
# until a re-pull/backfill. Add the signal once coverage is dependable.
A signal computed from a column that sits null across long stretches of your history introduces a bias. Names with good coverage get scored, names without get dropped, and coverage correlates with size and recency, which are exactly the dimensions a value screen is trying to be neutral about. Leaving the signal out costs you information. Averaging over the hole costs you the result.
Costco supplies the other half of the warning. Its statement has no gross profit subtotal, so any gross profit figure you see attributed to it was computed by somebody from the cost line. Do the subtraction yourself and at least you know which denominator went in: net sales, or net sales plus membership fees. Those give 11.0 percent and 10.8 percent for the same quarter. Two tenths of a point is small until it's sitting next to a threshold.
Writing a margin rule
Of the five bundled templates, only Buffett Quality Value scores a margin, and it uses the net one:
rev_ttm: ttm(revenue)
ni_ttm: ttm(net_income)
net_margin: if(rev_ttm > 0, ni_ttm / rev_ttm, null)
The guard matters. A pre-revenue biotech has a net income and no revenue, and the right output there is null. Without the guard you get a crash, or a number that means nothing and looks like it means something. Notice also that net_margin never stands alone in that template. It's a second condition stacked on return on equity: full marks need both roe >= $roe_strong and net_margin >= 0.08. High return on equity with a thin margin is a business running on turnover, and high return on equity with a fat margin is a different claim about the world. The margin is there to tell those apart.
If you want to score the trend as well as the level, the shape is short. This one is illustrative and the bundled templates are the reference for exact field names:
# "Margin holding up, and priced like it isn't" - illustrative
params:
margin_floor: 0.08 # net margin that counts as a real cushion
slip_tolerance: 0.01 # year-over-year erosion treated as noise
features:
rev_ttm: ttm(revenue)
ni_ttm: ttm(net_income)
net_margin: if(rev_ttm > 0, ni_ttm / rev_ttm, null)
rev_q: newest(revenue)
rev_q_prior: lag(revenue, 4)
nm_q: if(rev_q > 0, newest(net_income) / rev_q, null)
nm_q_prior: if(rev_q_prior > 0, lag(net_income, 4) / rev_q_prior, null)
criteria:
margin_level:
rules:
- { when: "is_null(net_margin)", score: 0, flag: no_revenue }
- { when: "net_margin >= $margin_floor", score: 2 }
- { when: "net_margin > 0", score: 1 }
- { else: 0 }
margin_trend:
rules:
- { when: "is_null(nm_q_prior)", score: 0, flag: no_year_ago_filing }
- { when: "nm_q >= nm_q_prior", score: 2 }
- { when: "nm_q >= nm_q_prior - $slip_tolerance", score: 1 }
- { else: 0 }
gate:
- rev_ttm > 0
Both criteria open on the null case, because a missing filing should cost a company its score instead of inheriting a default.
The argument worth having is the floor. Setting margin_floor at 8 percent excludes grocers, distributors, airlines and most of retail by construction. If your thesis is about durable pricing power, that exclusion is doing its job. If your thesis is about mispricing, you've just deleted the part of the market where thin margins on fast turnover are the normal way to make money, including the company we opened with. The way to settle it is to write both versions and run both, then read the two survivor lists side by side. The DSL reference has the full field vocabulary, including the gross-margin fields if your lake's coverage supports them.
What the ratio buys you
Revenue and net income are the two ends of one statement, and a margin is the entire middle compressed into a single number. That compression is what makes margins comparable across the whole market in one pass, and it's also why a margin can't tell you whether it fell because prices dropped, costs rose, or the mix changed underneath.
What you get is a fingerprint and a direction, computed from two lines on a document anyone can open. Build the rule, look at what it catches, then go read three of those filings and find out whether the margin was pointing at anything.
Next in the series: what EBITDA measures, and what it leaves out.
Research tooling, not investment advice. Nothing here is a recommendation to buy, sell, or hold any security. Screens, scores, and backtests are informational only; backtested results are hypothetical, exclude costs such as commissions and slippage, and do not guarantee future results. Verify against primary filings and make your own decisions.
Want to try this on your own rules? Quantery is free for 14 days: the full app, no card required.
← All articles