Available Hire Me
← All Writing Fixed Income

Gross vs Post-Tax Yields — Modelling the 0/20/40/45% Income Tax Bands

Modelling post-tax gilt yields across the 0/20/40/45% tax bands — the arithmetic, tax-equivalent yields, and why a 45% taxpayer sees gilts differently.

Gross yield is the number in the headlines, and it is the wrong number for almost every actual investor. A 45% taxpayer holding a gilt is not earning the gross yield — they are earning what is left after income tax on the coupon. Because gilts have a special tax status — coupon taxed as income, capital gain exempt — the same bond can rank differently for different investors, and “what’s the best gilt to buy” does not have one answer: it has five, one per tax band. This post is the model behind the post-tax columns of the UK Gilt Daily Report: the band arithmetic, tax-equivalent yield, and why the rankings shift.

Why gross yield lies

Take a concrete gilt from the report: the 0 3/8% Treasury Gilt 2026. Its gross yield is 3.43%. But look at the same bond through the tax bands:

Band Net yield Tax-equivalent yield Rank
0% 3.43% 3.43% 70
20% 3.21% 4.02% 66
40% 2.99% 4.99% 54
45% 2.94% 5.34% 50

Three things jump out. The net yield falls as the band rises — unsurprising. But the ranking changes too: this gilt is only the 70th-best for a 0% taxpayer but the 50th-best for a 45% taxpayer. And the tax-equivalent yield — what a tax-free alternative would need to match it — rises to 5.34%. A 45% taxpayer comparing gilts against a cash ISA at 4.5% is comparing apples to oranges on gross numbers; the tax-equivalent column is the comparison done properly.

The tax treatment that makes this interesting

The model rests on one asymmetry: income is taxed, capital gains are not. For a gilt bought below par — like the 0 3/8% gilt at clean 99.48 — the redemption uplift back to 100 is a capital gain, and gilt capital gains are exempt from CGT. So a low-coupon gilt bought at a discount is tax-light: most of its return arrives as an untaxed capital gain, and only the small coupon is taxed. A high-coupon gilt is the opposite: a fat coupon taxed at the holder’s marginal rate. Two gilts with the same gross yield can have very different post-tax yields, and the divergence grows with the tax band.

That asymmetry is why the report’s header carries the full picture in one line — 0% / 20% / 40% / 45% / 0% — the bands plus the 0% CGT rate. The engine’s tax model is a statement of that asymmetry, applied per band.

The band model

The model itself is small — a tax band is a record with a rate, and the yield transform applies it to the income component while leaving the capital component untouched:

record TaxBand(String name, double rate) {
    static final List<TaxBand> UK = List.of(
        new TaxBand("0%", 0.0),
        new TaxBand("20%", 0.20),
        new TaxBand("40%", 0.40),
        new TaxBand("45%", 0.45));
}

record YieldView(double gross, double net, double taxEquivalent) {}

YieldView postTax(Gilt gilt, TaxBand band) {
    double income = gilt.runningYield();          // coupon part — taxed
    double capital = gilt.grossYield() - income;  // redemption gain — exempt
    double net = capital + income * (1.0 - band.rate());
    double taxEquivalent = band.rate() == 0.0
            ? gross(gilt)
            : net / (1.0 - band.rate());
    return new YieldView(gross(gilt), net, taxEquivalent);
}

The tax-equivalent yield is the honest comparison tool: it answers “what gross yield would a fully-taxable alternative need to beat this gilt for me?” — which is exactly the number to hold up against a savings account or a corporate bond. For a 0% band investor the tax-equivalent equals the gross yield, because nothing is being netted.

Why the rankings shift

The report ranks every gilt within each band, and the ranks are not the same. Two forces drive the shift:

  • Coupon level. Low-coupon gilts lose less to tax, so they rise in the rankings as the band rises. High-coupon gilts fall.
  • Price level. Gilts trading above par carry a capital loss to redemption — which is also untaxed, so a premium gilt’s tax disadvantage is muted compared with what the coupon alone suggests.

The practical consequence: a 45% taxpayer’s optimal gilt portfolio tilts toward low-coupon, below-par issues; a 0% taxpayer is indifferent to the coupon split and buys on gross yield alone. The rank columns make that visible without anyone having to run the arithmetic.

The edge cases

  • Band boundary moves — the 0%/20% boundary moves with the personal allowance, and the model reads the bands from configuration, not from code, so the engine survives a Budget.
  • Non-taxpayers — ISA and pension holders sit in the 0% band, and their tax-equivalent column is the gross yield: the report is honest that a tax-free wrapper changes nothing about the underlying bond, only about the holder’s view of it.
  • Index-linked gilts — the inflation uplift is treated as capital (exempt); only the real coupon is income. The same band model applies to the real yield.

The honest summary

Gross yield is the right number for comparing bonds ignoring who holds them. Post-tax yield is the right number for deciding what to hold. The gap between them is the holder’s tax band, and it is big enough to reorder an entire ranking — a 40% taxpayer and a 0% taxpayer looking at the same 104 gilts should not buy the same ones. The report computes all four views so the reader can see their own column instead of being sold a gross number that doesn’t apply to them.

If you’re building fixed-income tooling and want the tax band model handled properly, talk it through.

Samuel Jackson

Samuel Jackson

Senior Java Back End Developer & Contractor

Senior Java Back End Developer — Betfair Exchange API specialist, Spring Boot, AWS, and event-driven architecture. 25+ years delivering high-performance systems across betting, finance, energy, retail, and government. Available for Java contracting.