Price-to-Sales Below 1 in South Africa: 8.53% CAGR, Marginal Edge Over SPY

Growth of ZAR 10,000 invested in P/S value screen South Africa (JNB) vs S&P 500 from 2006 to 2025. Marginal outperformance over SPY in USD terms.

We screened JSE-listed stocks for low price-to-sales ratios with qualifying margins and profitability, then backtested the resulting portfolio from 2000 to 2025. The strategy returned 8.53% annually vs 8.02% for the S&P 500. That's +0.51% annual outperformance. The Sharpe ratio is -0.022, the win rate against SPY is 46.6%, and the first six years were entirely in cash.

Contents

  1. Method
  2. The Screen
  3. JSE P/S Screen (SQL)
  4. What We Found
  5. The headline numbers
  6. The Sharpe ratio explanation
  7. Cash periods: 2000-2005 in the dark
  8. Year-by-year returns
  9. 2008: the JSE held up far better than the S&P 500
  10. 2009: a strong recovery, not a near-double
  11. 2017-2020: four years of underperformance
  12. 2022: commodity boom, clear advantage
  13. Crisis performance summary
  14. Backtest Methodology
  15. Limitations
  16. Takeaway
  17. Part of a Series
  18. References
  19. Run This Screen Yourself

The honest summary: this screen barely beats the global benchmark on raw return, doesn't beat South African government bonds on a risk-adjusted basis, and wins against SPY in fewer than half of invested years. The 2008 protection was real. The long-run case is thin.

Data: FMP financial data warehouse, 2000–2025. Updated March 2026.


Method

Data source: Ceta Research (FMP financial data warehouse) Universe: JNB (Johannesburg Stock Exchange), market cap > ZAR 1B Period: 2000-2025 (25 years total; effectively 20 years invested from 2006) Rebalancing: Quarterly (January, April, July, October), equal weight, top 30 by lowest P/S Benchmark: S&P 500 Total Return (SPY) Cash rule: Hold cash if fewer than 10 stocks qualify

Popularized by Kenneth Fisher in Super Stocks (1984). 45-day lag on financial data to prevent look-ahead bias.


The Screen

Signal filters:

Criterion Metric Threshold
Cheap relative to revenue Price-to-Sales < 1.0
Business quality Gross Margin > 20%
Operational efficiency Operating Margin > 5%
Capital returns ROE > 10%

Size filter: Market cap > ZAR 1B

Selection: Top 30 by lowest P/S among qualifying stocks.

JSE P/S Screen (SQL)

SELECT
    f.symbol,
    p.companyName,
    p.exchange,
    p.sector,
    ROUND(f.priceToSalesRatioTTM, 3) AS ps_ratio,
    ROUND(f.grossProfitMarginTTM * 100, 1) AS gross_margin_pct,
    ROUND(f.operatingProfitMarginTTM * 100, 1) AS op_margin_pct,
    ROUND(k.returnOnEquityTTM * 100, 1) AS roe_pct,
    ROUND(k.marketCap / 1e9, 2) AS mktcap_b
FROM financial_ratios_ttm f
JOIN key_metrics_ttm k ON f.symbol = k.symbol
JOIN profile p ON f.symbol = p.symbol
WHERE f.priceToSalesRatioTTM > 0
  AND f.priceToSalesRatioTTM < 1
  AND f.grossProfitMarginTTM > 0.20
  AND f.operatingProfitMarginTTM > 0.05
  AND k.returnOnEquityTTM > 0.10
  AND k.marketCap > 1000000000
  AND p.exchange IN ('JNB')
QUALIFY ROW_NUMBER() OVER (PARTITION BY f.symbol ORDER BY f.priceToSalesRatioTTM ASC) = 1
ORDER BY f.priceToSalesRatioTTM ASC
LIMIT 30

Run this query on Ceta Research


What We Found

Growth of $10,000 invested in P/S value screen South Africa vs S&P 500 from 2006 to 2025. South Africa (ZAR) outperformed SPY in USD terms.
Growth of $10,000 invested in P/S value screen South Africa vs S&P 500 from 2006 to 2025. South Africa (ZAR) outperformed SPY in USD terms.

The headline numbers

Metric P/S Screen (JNB) S&P 500
CAGR 8.53% 8.02%
Excess Return +0.51%
Max Drawdown -43.91% -43.86%
Sharpe Ratio -0.022 0.361
Win Rate vs SPY 46.6%
Avg Stocks per Period 23.6 (when invested)
Cash Periods 25 of 100

The Sharpe ratio explanation

The Sharpe formula is: (Portfolio Return - Risk-Free Rate) / Volatility

South Africa's risk-free rate is approximately 9%, reflecting local government bond yields. The portfolio returned 8.53% CAGR. That means the numerator is negative: 8.53% - 9% = -0.47%. A negative Sharpe ratio.

This isn't just a presentation issue. It means the strategy literally didn't beat South African government bonds on a risk-adjusted basis over 25 years. A domestic investor could have held SA bonds and come out ahead without taking equity risk. The +0.51% excess over SPY is a real global comparison, but it doesn't survive local risk-free rate scrutiny.

The win rate of 46.6% adds more context: this screen beats SPY in fewer than half of invested years. That's not the profile of a durable strategy with consistent alpha.

Cash periods: 2000-2005 in the dark

25 of 100 quarterly periods were in cash. The first 24 were consecutive (2000-2005), when FY financial data for JSE-listed companies wasn't available in sufficient coverage. The screen couldn't find 10 qualifying stocks, so the cash rule triggered every quarter.

This matters for the CAGR calculation. The 8.53% CAGR covers all 25 years including those cash years. From 2006 onward (when the strategy was actually invested), the returns are higher. But even accounting for the cash drag, the long-run result is only marginally above SPY.

Year-by-year returns

JNB P/S screen vs S&P 500 annual returns 2000 to 2025. Strategy in cash 2000-2005. Strong 2008 protection. Mixed results across invested years.
JNB P/S screen vs S&P 500 annual returns 2000 to 2025. Strategy in cash 2000-2005. Strong 2008 protection. Mixed results across invested years.

Year JNB P/S S&P 500 Excess
2000 0.0% (cash) -10.5%
2001 0.0% (cash) -9.17%
2002 0.0% (cash) -19.92%
2003 0.0% (cash) +24.12%
2004 0.0% (cash) +10.24%
2005 0.0% (cash) +7.17%
2006 +24.69% +13.65% +11.04%
2007 +25.46% +4.40% +21.06%
2008 -19.44% -34.31% +14.87%
2009 +31.90% +24.73% +7.16%
2010 +26.99% +14.31% +12.68%
2011 +30.15% +2.46% +27.69%
2012 +50.30% +17.09% +33.20%
2013 -11.30% +27.77% -39.07%
2014 +14.23% +14.50% -0.27%
2015 -10.80% -0.12% -10.68%
2016 +51.62% +14.45% +37.16%
2017 +2.36% +21.64% -19.29%
2018 -7.47% -5.15% -2.32%
2019 -2.11% +32.31% -34.43%
2020 -11.11% +15.64% -26.75%
2021 +35.43% +31.26% +4.17%
2022 +4.77% -18.99% +23.76%
2023 +5.35% +26.00% -20.65%
2024 +14.78% +25.28% -10.50%
2025 +2.77% +15.47% -12.70%

2008: the JSE held up far better than the S&P 500

While the S&P 500 lost -34.31% in 2008, this screen returned -19.44%. That's nearly a 15-point advantage in the worst year of the financial crisis. JSE-listed companies with P/S below 1 and positive operating margins were less exposed to the credit market destruction that drove US financials down. South African banks, while not immune, didn't hold the same toxic mortgage exposure as US counterparts. This is the screen's genuine bright spot.

2009: a strong recovery, not a near-double

The portfolio gained +31.90% in 2009 against SPY's +24.73%. That's a solid 7-point advantage. The commodity-heavy JSE composition helped as raw materials recovered, and quality names that survived 2008 with intact margins rebounded. But this isn't the "near-double" story of the original data. +31.90% is a good year, not an outlier. Context matters here because 2013 tells the other side: -11.30% while SPY returned +27.77%, a -39 point gap that was one of the worst relative years of the entire dataset.

2017-2020: four years of underperformance

The strategy underperformed in four consecutive years from 2017 to 2020. South Africa's political uncertainty (land reform debate, Zuma-era policy drift, cabinet reshuffles), combined with weak commodity prices and currency pressure, dragged the equity market. The rand weakened, reducing USD returns for foreign investors. The P/S screen couldn't offset structural macro headwinds at the country level.

This is the weak point of any single-country strategy: concentrated political and currency risk doesn't diversify away.

2022: commodity boom, clear advantage

The strategy returned +4.77% in 2022 while the S&P 500 fell -18.99%. A 24-point gap. South Africa's commodity exposure (gold, platinum group metals, iron ore, coal) turned into a tailwind when global inflation drove raw material prices higher. This, along with 2008, is the screen's most compelling case.

Crisis performance summary

Event JNB P/S S&P 500 Gap
Financial Crisis (2008) -19.44% -34.31% +14.87%
COVID (2020) -11.11% +15.64% -26.75%
2022 Inflation Bear +4.77% -18.99% +23.76%

The screen protects well against financial-sector and inflation crises. It suffers badly during growth-driven recoveries where US tech dominance is the main driver. That's an honest characterization: the strategy has a specific regime where it works, and it doesn't work consistently outside of that regime.


Backtest Methodology

Parameter Choice
Universe JNB (Johannesburg), Market Cap > ZAR 1B
Signal P/S < 1.0, Gross Margin > 20%, Operating Margin > 5%, ROE > 10%
Portfolio Top 30 by lowest P/S, equal weight
Rebalancing Quarterly (January, April, July, October)
Cash rule Hold cash if < 10 qualify
Benchmark S&P 500 Total Return (SPY)
Period 2000-2025 (25 years, 100 periods; invested from 2006)
Data Point-in-time (45-day lag for financial statements)

Limitations

Negative Sharpe ratio. At -0.022, the strategy's 8.53% return falls below South Africa's 9% risk-free rate. This isn't a presentation artifact. It means the strategy didn't compensate for equity risk relative to domestic bonds over 25 years.

Win rate below 50%. The strategy beats SPY in 46.6% of invested years. Most strategies in this global series clear 50%. The South Africa screen doesn't.

Currency risk is significant. Returns are in ZAR. The rand has depreciated meaningfully against the USD and EUR over 25 years. A foreign investor's realized returns in home currency could be materially lower than the ZAR-denominated CAGR.

Six years in cash. The 2000-2005 data gap is a real limitation. The 8.53% CAGR includes those cash years, which compresses the apparent return. The strategy's actual performance when invested is higher than the headline, but the long-run case remains marginal.

Political and policy risk. South Africa carries elevated country-specific risk (currency controls, land reform uncertainty, infrastructure challenges). These aren't priced into a simple backtest.

Commodity concentration. The JSE is heavily weighted toward mining and resources. The P/S screen will tend to pull from these sectors. Sector concentration is persistent.

Survivorship bias. Exchange membership uses current profiles, not historical. Delistings aren't tracked.

Transaction costs not included. With quarterly rebalancing and roughly 24 stocks, cost drag is approximately 0.3-0.5% annually.


Takeaway

The South Africa P/S screen returns 8.53% annually over 25 years, +0.51% above the S&P 500. That's a thin margin. The six cash years drag on the headline CAGR, but even adjusting for them, the result is modest.

The Sharpe of -0.022 is the clearest verdict: the strategy's return was below South Africa's 9% risk-free rate. A domestic investor holding government bonds over the same period did better on a risk-adjusted basis without taking equity risk. For an international investor comparing against SPY, the picture is slightly better, but a 46.6% win rate means SPY won in more invested years than the screen did.

The 2008 performance is genuine. Losing -19.44% while SPY fell -34.31% is a real protective feature, and the 2022 commodity tailwind (+4.77% vs SPY -18.99%) is similarly real. The strategy works in specific regimes: financial crises and commodity booms. It doesn't work consistently outside of those regimes.

The currency and political risk are real. Any foreign investor allocating to JSE needs to factor in ZAR exposure and a higher required return than they'd demand from a developed market.


Part of a Series

This analysis is part of our P/S value screen global exchange comparison. We tested the same four-factor screen across 14 exchanges worldwide: - P/S Value Screen on US Stocks - P/S Value Screen on Indian Stocks - P/S Value Screen on Canadian Stocks - P/S Value Screen on Swedish Stocks - P/S Value Screen on German Stocks (XETRA) - P/S Value Screen on Japanese Stocks - P/S Value Screen: 13-Exchange Global Comparison


References

  • Fisher, K. (1984). Super Stocks. Dow Jones-Irwin.
  • Barbee, W., Mukherji, S. & Raines, G. (1996). "Do Sales-Price and Debt-Equity Explain Stock Returns Better than Book-Market and Firm Size?" Financial Analysts Journal, 52(2), 56-60.
  • Gray, W. & Vogel, J. (2012). "Analyzing Valuation Measures: A Performance Horse Race over the Past 40 Years." Journal of Portfolio Management, 39(1), 112-121.
  • Novy-Marx, R. (2013). "The Other Side of Value: The Gross Profitability Premium." Journal of Financial Economics, 108(1), 1-28.

Run This Screen Yourself

Via web UI: Run the P/S 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": """
        SELECT
            f.symbol,
            p.companyName,
            ROUND(f.priceToSalesRatioTTM, 3) AS ps_ratio,
            ROUND(f.grossProfitMarginTTM * 100, 1) AS gross_margin_pct,
            ROUND(f.operatingProfitMarginTTM * 100, 1) AS op_margin_pct,
            ROUND(k.returnOnEquityTTM * 100, 1) AS roe_pct,
            ROUND(k.marketCap / 1e9, 2) AS mktcap_b
        FROM financial_ratios_ttm f
        JOIN key_metrics_ttm k ON f.symbol = k.symbol
        JOIN profile p ON f.symbol = p.symbol
        WHERE f.priceToSalesRatioTTM > 0
          AND f.priceToSalesRatioTTM < 1
          AND f.grossProfitMarginTTM > 0.20
          AND f.operatingProfitMarginTTM > 0.05
          AND k.returnOnEquityTTM > 0.10
          AND k.marketCap > 1000000000
          AND p.exchange IN ('JNB')
        QUALIFY ROW_NUMBER() OVER (
            PARTITION BY f.symbol ORDER BY f.priceToSalesRatioTTM ASC
        ) = 1
        ORDER BY f.priceToSalesRatioTTM ASC
        LIMIT 30
    """,
    "options": {"format": "json", "limit": 30}
})
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"]:
    print(f"{r['symbol']:10s} P/S={r['ps_ratio']:.3f}  GM={r['gross_margin_pct']:.1f}%  ROE={r['roe_pct']:.1f}%")

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


Data: Ceta Research, FMP financial data warehouse. Universe: JNB (Johannesburg). Returns in ZAR. Quarterly rebalance, equal weight, 2006-2025 invested.