Owner Earnings Yield: Buffett's Metric Backtested on 25 Years of US Stock Data

Growth of $10,000 invested in Owner Earnings Yield vs S&P 500 from 2000 to 2025. OE Yield grew to $180K, S&P 500 to $66K.

We screened for stocks with high Owner Earnings yield, strong profitability, and reasonable size across all US exchanges from 2000 to 2025. The strategy returned 12.25% annually vs 7.85% for the S&P 500. Zero cash periods, 23 stocks per rebalance on average, and a down capture ratio of 33.1%. The portfolio captured almost all of the market's upside while absorbing less than a third of its losses.

Contents

  1. Method
  2. What is Owner Earnings?
  3. The Signal
  4. The Screen (SQL)
  5. What We Found
  6. 25 years of data. 4.4% annual alpha over the S&P 500.
  7. Year-by-year returns
  8. The early 2000s: OE Yield's golden era
  9. The 2019 anomaly
  10. Where OE Yield struggles: post-2017 growth dominance
  11. Backtest Methodology
  12. Limitations
  13. Takeaway
  14. Part of a Series
  15. References
  16. Run This Screen Yourself

Method

Data source: Ceta Research (FMP financial data warehouse) Universe: All US exchanges (NYSE, NASDAQ, AMEX), market cap > $1B USD Period: 2000-2025 (25 years, 25 annual periods) Rebalancing: Annual (July, after FY filings + 45-day lag), equal weight top 30 Benchmark: S&P 500 Total Return (SPY) Execution: Next-day close (market-on-close after signal date) Cash rule: Hold cash if fewer than 10 stocks qualify Transaction costs: Size-tiered model (0.1-0.5% one-way based on market cap)

Owner Earnings computed from raw financial statements at each rebalance: Net Income + D&A - min(|Capex|, D&A). The min() function proxies maintenance capex. If a company spends less on capex than its depreciation, all capex is maintenance. If it spends more, the excess is treated as growth investment and excluded.


What is Owner Earnings?

Warren Buffett introduced Owner Earnings in his 1986 Berkshire Hathaway letter. He wanted a metric that answers one question: what does this business actually earn for its owners?

Owner Earnings = Net Income + D&A - Maintenance Capex

Standard free cash flow deducts all capital expenditure. Every dollar spent building a new factory gets the same treatment as a dollar replacing a broken machine. Owner Earnings only deducts the maintenance portion. It doesn't penalize companies for investing in growth.

Consider two companies with identical operations generating $500M in net income:

  • Company A spends $200M on maintenance. Owner Earnings: $300M. FCF: $300M. Same.
  • Company B spends $200M on maintenance and $400M building new capacity. Owner Earnings: $300M. FCF: -$100M. Dramatically different.

FCF makes Company B look like a money-losing operation. Owner Earnings shows both businesses have identical earning power from existing operations.

OE Yield = Owner Earnings / Market Cap

Higher yield means you're paying less per dollar of owner earnings. We screen for the cheapest stocks on this metric.


The Signal

Filter Threshold Rationale
OE Yield > 5% Less than 20x owner earnings
OE Yield < 50% Removes data artifacts
ROE > 10% Solid returns on shareholder equity
Operating Margin > 10% Genuine pricing power
Market Cap > $1B USD Liquidity filter

Top 30 by highest OE yield, equal weight. Annual rebalance in July (after FY filings become available, with a 45-day lag to prevent look-ahead bias).

The signal is deliberately simple. Four quality/value filters plus a size gate. Unlike our FCF Yield strategy, there's no interest coverage filter. This means more stocks qualify, particularly industrial and consumer companies that carry moderate debt but generate strong owner earnings.


The Screen (SQL)

WITH income_latest AS (
    SELECT symbol, netIncome, depreciationAndAmortization,
        ROW_NUMBER() OVER (PARTITION BY symbol ORDER BY date DESC) AS rn
    FROM income_statement
    WHERE period = 'FY'
      AND netIncome IS NOT NULL
      AND depreciationAndAmortization IS NOT NULL
),
cashflow_latest AS (
    SELECT symbol, capitalExpenditure,
        ROW_NUMBER() OVER (PARTITION BY symbol ORDER BY date DESC) AS rn
    FROM cash_flow_statement
    WHERE period = 'FY'
      AND capitalExpenditure IS NOT NULL
),
calculated AS (
    SELECT
        i.symbol,
        i.netIncome + i.depreciationAndAmortization
            - LEAST(ABS(c.capitalExpenditure), i.depreciationAndAmortization)
            AS owner_earnings
    FROM income_latest i
    JOIN cashflow_latest c ON i.symbol = c.symbol AND c.rn = 1
    WHERE i.rn = 1
)
SELECT
    calc.symbol,
    p.companyName,
    ROUND(calc.owner_earnings / k.marketCap * 100, 2) AS oe_yield_pct,
    ROUND(k.freeCashFlowYieldTTM * 100, 2) AS fcf_yield_pct,
    ROUND(k.returnOnEquityTTM * 100, 1) AS roe_pct,
    ROUND(f.operatingProfitMarginTTM * 100, 1) AS op_margin_pct,
    ROUND(k.marketCap / 1e9, 1) AS market_cap_billions
FROM calculated calc
JOIN key_metrics_ttm k ON calc.symbol = k.symbol
JOIN financial_ratios_ttm f ON calc.symbol = f.symbol
JOIN profile p ON calc.symbol = p.symbol
WHERE calc.owner_earnings > 0
  AND calc.owner_earnings / k.marketCap > 0.05
  AND calc.owner_earnings / k.marketCap < 0.50
  AND k.returnOnEquityTTM > 0.10
  AND f.operatingProfitMarginTTM > 0.10
  AND k.marketCap > 1e9
  AND p.exchange IN ('NYSE', 'NASDAQ', 'AMEX')
ORDER BY calc.owner_earnings / k.marketCap DESC
LIMIT 30

Run this query on Ceta Research


What We Found

Growth of $10,000 invested in Owner Earnings Yield vs S&P 500 from 2000 to 2025. OE Yield grew to $180K, S&P 500 to $66K.
Growth of $10,000 invested in Owner Earnings Yield vs S&P 500 from 2000 to 2025. OE Yield grew to $180K, S&P 500 to $66K.

25 years of data. 4.4% annual alpha over the S&P 500.

Metric OE Yield (US) S&P 500
CAGR 12.25% 7.85%
Total Return 1,698% 562%
Volatility 23.8% 16.6%
Max Drawdown -41.1% -38.0%
Sharpe Ratio 0.432 0.352
Sortino Ratio 0.943 0.628
Win Rate (annual) 56% -
Avg Stocks per Period 23.2 -
Cash Periods 0 of 25 -

OE Yield turned $10,000 into $179,750. The S&P 500 turned it into $66,170. The strategy was fully invested every single period.

The standout metric is down capture: 33.1%. The portfolio captured only 33 cents of every dollar the market lost. Up capture was 125%, meaning it participated in rallies and then some. That combination, more upside with less downside, drives the 4.4% excess CAGR.

Year-by-year returns

OE Yield vs S&P 500 annual returns from 2000 to 2024.
OE Yield vs S&P 500 annual returns from 2000 to 2024.

Year OE Yield S&P 500 Excess
2000 +26.3% -14.8% +41.1%
2001 +6.3% -22.4% +28.8%
2002 +14.2% +6.9% +7.3%
2003 +29.7% +14.9% +14.8%
2004 +25.6% +8.9% +16.7%
2005 +33.5% +8.0% +25.5%
2006 +25.0% +20.9% +4.0%
2007 -15.9% -15.2% -0.7%
2008 -29.9% -26.9% -3.0%
2009 +13.8% +16.0% -2.2%
2010 +27.1% +33.5% -6.4%
2011 +7.3% +4.2% +3.1%
2012 +43.4% +20.7% +22.7%
2013 +33.8% +24.7% +9.0%
2014 +8.4% +7.2% +1.2%
2015 -4.8% +2.7% -7.5%
2016 +37.5% +18.6% +18.9%
2017 +6.8% +14.3% -7.6%
2018 +0.2% +11.2% -11.0%
2019 -33.0% +7.4% -40.4%
2020 +74.6% +41.0% +33.6%
2021 -16.6% -10.7% -5.9%
2022 +12.0% +18.1% -6.1%
2023 +16.8% +25.4% -8.6%
2024 +26.7% +14.4% +12.3%

The early 2000s: OE Yield's golden era

Year OE Yield S&P 500 Excess
2000 +26.3% -14.8% +41.1%
2001 +6.3% -22.4% +28.8%
2002 +14.2% +6.9% +7.3%
Cumulative +53.3% -30.3% +83.6%

While the market cratered during the dot-com bust, OE Yield gained 53% over three years. The screen naturally avoids overvalued growth stocks. Companies trading at less than 20x owner earnings with 10%+ ROE and margins aren't dot-com highfliers. They're profitable, established businesses that happened to be cheap.

2003-2006 continued the run. The portfolio gained 29.7%, 25.6%, 33.5%, and 25.0% in four consecutive years. Value stocks dominated this era, and OE Yield was positioned perfectly.

The 2019 anomaly

The worst year was 2019: -33.0% while SPY gained 7.4%. That's a 40-point gap, the strategy's widest annual underperformance. This July 2019 to July 2020 period covers the start of the COVID crash. Small-cap value stocks were hit hard in late February and March 2020.

The bounce was equally dramatic. The 2020 period (July 2020 to July 2021) returned +74.6%, the strategy's single best year. The stocks that were beaten down in the crash recovered violently. Over the two periods combined, OE Yield returned +16.1% vs SPY's +51.4%. The strategy recovered but gave up ground to the benchmark in net terms.

Where OE Yield struggles: post-2017 growth dominance

From 2017 to 2023, OE Yield underperformed SPY in 5 of 7 years. Total return over those 7 years: OE Yield +57%, SPY +130%. The gap is growth-driven. Mega-cap tech companies with high P/E ratios and massive growth capex don't pass the OE Yield screen. NVIDIA, Microsoft, and Apple all fail multiple filters during their biggest runs.

This is the tradeoff. You get 4.4% annual alpha over 25 years, but you have to sit through extended periods of underperformance when growth leads the market.


Backtest Methodology

Parameter Choice
Universe NYSE + NASDAQ + AMEX, Market Cap > $1B USD
Signal OE Yield 5-50%, ROE > 10%, OPM > 10%
Portfolio Top 30 by OE Yield, equal weight
Rebalancing Annual (July)
Cash rule Hold cash if < 10 qualify
Benchmark S&P 500 Total Return (SPY)
Execution Next-day close (market-on-close)
Period 2000-2025 (25 annual periods)
Data Point-in-time (45-day lag for FY filings)
Transaction costs Size-tiered (0.1-0.5% one-way by market cap)

Full methodology details: backtests/METHODOLOGY.md


Limitations

Annual rebalancing only. We test July-to-July periods using the most recent FY filing. Quarterly or monthly rebalancing with TTM data might produce different results. We chose annual to match the data source (FY filings) and reduce turnover.

Maintenance capex is estimated. We use min(|Capex|, D&A) as a proxy. Companies with recently purchased assets have high depreciation but may need little maintenance. Companies that defer maintenance look artificially profitable. The proxy is standard in the literature but imperfect.

Recent underperformance. OE Yield trailed SPY from 2017-2023. Growth-dominated markets are the strategy's blind spot. Factor strategies are cyclical, and this one requires patience through multi-year stretches of relative weakness.

Survivorship bias. Exchange membership uses current company profiles. Delisted companies, M&A targets, and bankruptcies aren't fully captured in the historical universe.

Concentrated portfolio. 23 stocks on average. Higher concentration means more stock-specific risk than a broad index.

Benchmark currency mismatch. Returns and benchmark are both in USD for US exchanges. No adjustment needed. For regional blogs, currency differences apply.


Takeaway

OE Yield works on US stocks. 12.25% CAGR over 25 years, 4.4% alpha above the S&P 500, zero cash periods. The portfolio always found at least 10 qualifying stocks from the US universe.

The strategy's edge is asymmetric. 125% up capture, 33% down capture. It participates fully in rallies and absorbs a third of the losses. That asymmetry, not raw stock picking, drives the long-term alpha.

The cost is clear: multi-year stretches of underperformance during growth-led markets. 2017-2023 was tough. The next growth cycle will produce another dry spell. OE Yield rewards investors who can hold through those periods. The 25-year record shows the math works if you give it time.


Part of a Series

This analysis is part of our Owner Earnings Yield global exchange comparison. We tested the same screen on 13 exchanges worldwide: - OE Yield on Indian Stocks (BSE + NSE) - 17.2% CAGR, +5.1% vs Sensex - OE Yield on Hong Kong Stocks (HKSE) - 10.4% CAGR, +8.8% vs Hang Seng - OE Yield on Swedish Stocks (STO) - 9.6% CAGR, +7.0% vs OMX Stockholm 30 - OE Yield on Chinese Stocks (SHZ + SHH) - 9.6% CAGR, +7.2% vs SSE Composite - OE Yield: 13-Exchange Global Comparison - full comparison table


References

  • Buffett, W. (1986). "Berkshire Hathaway Annual Letter to Shareholders."
  • Greenwald, B., Kahn, J., Sonkin, P. & van Biema, M. (2001). Value Investing: From Graham to Buffett and Beyond. John Wiley & Sons.
  • Greenblatt, J. (2006). The Little Book That Beats the Market. John Wiley & Sons.

Run This Screen Yourself

Via web UI: Run the Owner Earnings Yield screen on Ceta Research. The query is pre-loaded. Hit "Run" and see what passes today.

Via Python:

import requests, time

API_KEY = "your_api_key"  # get one at cetaresearch.com
BASE = "https://tradingstudio.finance/api/v1"

resp = requests.post(f"{BASE}/data-explorer/execute", headers={
    "X-API-Key": API_KEY, "Content-Type": "application/json"
}, json={
    "query": """
        WITH income_latest AS (
            SELECT symbol, netIncome, depreciationAndAmortization,
                ROW_NUMBER() OVER (PARTITION BY symbol ORDER BY date DESC) AS rn
            FROM income_statement WHERE period = 'FY'
              AND netIncome IS NOT NULL AND depreciationAndAmortization IS NOT NULL
        ),
        cashflow_latest AS (
            SELECT symbol, capitalExpenditure,
                ROW_NUMBER() OVER (PARTITION BY symbol ORDER BY date DESC) AS rn
            FROM cash_flow_statement WHERE period = 'FY' AND capitalExpenditure IS NOT NULL
        ),
        calculated AS (
            SELECT i.symbol,
                i.netIncome + i.depreciationAndAmortization
                    - LEAST(ABS(c.capitalExpenditure), i.depreciationAndAmortization) AS owner_earnings
            FROM income_latest i JOIN cashflow_latest c ON i.symbol = c.symbol AND c.rn = 1
            WHERE i.rn = 1
        )
        SELECT calc.symbol, p.companyName,
            ROUND(calc.owner_earnings / k.marketCap * 100, 2) AS oe_yield_pct,
            ROUND(k.returnOnEquityTTM * 100, 1) AS roe_pct,
            ROUND(f.operatingProfitMarginTTM * 100, 1) AS op_margin_pct,
            ROUND(k.marketCap / 1e9, 1) AS market_cap_billions
        FROM calculated calc
        JOIN key_metrics_ttm k ON calc.symbol = k.symbol
        JOIN financial_ratios_ttm f ON calc.symbol = f.symbol
        JOIN profile p ON calc.symbol = p.symbol
        WHERE calc.owner_earnings > 0
          AND calc.owner_earnings / k.marketCap > 0.05
          AND calc.owner_earnings / k.marketCap < 0.50
          AND k.returnOnEquityTTM > 0.10
          AND f.operatingProfitMarginTTM > 0.10
          AND k.marketCap > 1e9
          AND p.exchange IN ('NYSE', 'NASDAQ', 'AMEX')
        ORDER BY calc.owner_earnings / k.marketCap DESC
        LIMIT 30
    """,
    "options": {"format": "json", "limit": 100}
})
task_id = resp.json()["taskId"]

while True:
    result = requests.get(f"{BASE}/tasks/data-query/{task_id}",
                          headers={"X-API-Key": API_KEY}).json()
    if result["status"] in ("completed", "failed"):
        break
    time.sleep(2)

for r in result["result"]["rows"][:10]:
    print(f"{r['symbol']:8s} OE Yield={r['oe_yield_pct']}% ROE={r['roe_pct']}% MCap=${r['market_cap_billions']}B")

Get your API key at cetaresearch.com. The full backtest code (Python + DuckDB) is on GitHub.


Data: Ceta Research, FMP financial data warehouse. Universe: NYSE + NASDAQ + AMEX. Annual rebalance (July), equal weight top 30, 2000-2025. Transaction costs included.

Read more