Skip to main content

Unofficial IBD-style Relative Strength Rating for 4,600+ US stocks

Project description

RS Rating

IBD-Style Relative Strength Rating

Unofficial IBD-style RS Rating for 4,600+ US stocks, updated daily.

The only open-source project that provides true percentile-ranked RS Ratings (1-99) — not just weighted returns.

PyPI Daily Update Stocks Python License: MIT

Installation · Quick Start · API Reference · How It Works


Why This Project?

IBD's Relative Strength (RS) Rating is one of the most powerful tools for momentum investing — used by William O'Neil, Mark Minervini, and thousands of growth investors. But IBD doesn't provide it for free, and existing open-source alternatives only calculate weighted returns without the crucial percentile ranking step.

This project solves that. We calculate true RS Ratings (1-99) for 4,600+ US stocks daily:

  • RS 99 = outperforming 99% of all stocks over the past year
  • RS 50 = median performer
  • RS 1 = bottom 1%
from rs_rating import RS

rs = RS()
rs.get("NVDA")
# {'ticker': 'NVDA', 'date': '2026-03-19', 'rs_raw': 0.1666, 'rs_rating': 70}

No API key needed. No rate limits. Just pip install and go.


Installation

pip install ibd-rs-rating

Zero dependencies — uses only Python standard library (urllib, json).


Quick Start

from rs_rating import RS

rs = RS()

# Get latest RS Rating for a stock
rs.get("AAPL")
# {'ticker': 'AAPL', 'date': '2026-03-19', 'rs_raw': 0.2841, 'rs_rating': 72}

# Get RS Rating for a specific date
rs.get("AAPL", date="2026-03-01")

# Top 10 stocks by RS Rating
rs.top(10)
# [{'ticker': 'MU', 'rs_rating': 99, 'rs_raw': 1.99}, ...]

# RS Rating history (last 30 days)
rs.history("NVDA")
# [{'date': '2026-03-19', 'rs_raw': 0.17, 'rs_rating': 70}, ...]

# Compare multiple stocks
rs.compare(["NVDA", "AMD", "AVGO", "INTC"])
# [{'ticker': 'AVGO', 'rs_rating': 85}, {'ticker': 'NVDA', 'rs_rating': 70}, ...]

# Filter: stocks with RS ≥ 90
rs.filter(min_rating=90)
# Returns all stocks in the top 10%

# SPY & QQQ benchmark RS (raw score, not ranked)
rs.reference()
# [{'ticker': 'SPY', 'rs_raw': 0.049}, {'ticker': 'QQQ', 'rs_raw': 0.063}]

# Stocks with biggest RS Rating improvement (last 5 trading days)
rs.movers(days=5, n=10)
# [{'ticker': 'XYZ', 'rs_rating': 85, 'prev_rating': 60, 'change': 25}, ...]

# Biggest RS losers
rs.movers(days=5, n=10, direction="down")

# Available date range
rs.dates()
# {'first': '2025-03-21', 'last': '2026-03-19'}

# Sector & Industry analysis
rs.sector_ranking()                    # Which sectors are strongest?
rs.industry_top("Semiconductors", 5)   # Top 5 semiconductor stocks
rs.sector_top("Energy", 10)            # Top 10 energy stocks

Available Stocks

4,600+ US-listed stocks are tracked and updated daily. See the full list with current RS ratings:

data/tickers.csv


API Reference

RS(url=None, key=None)

Create a client instance. No arguments needed — connects to the public API by default.

.get(ticker, date=None) → dict | None

Get RS rating for a single ticker. Returns latest if no date specified.

Parameter Type Description
ticker str Stock symbol (case-insensitive)
date str Optional. "YYYY-MM-DD" format

.history(ticker, start=None, end=None, days=30) → list

Get RS rating history for a ticker.

Parameter Type Description
ticker str Stock symbol
start str Start date "YYYY-MM-DD"
end str End date "YYYY-MM-DD"
days int Recent days (default: 30, ignored if start is set)

.top(n=20, date=None) → list

Get top N stocks ranked by RS Rating.

.bottom(n=20, date=None) → list

Get bottom N stocks ranked by RS Rating.

.filter(min_rating=None, max_rating=None, date=None) → list

Filter stocks by RS Rating range.

# Stocks with RS between 80 and 95
rs.filter(min_rating=80, max_rating=95)

.compare(tickers, date=None) → list

Compare RS ratings for a list of tickers, sorted by rating descending.

rs.compare(["AAPL", "MSFT", "GOOG", "AMZN", "META"])

.reference(date=None) → list

Get RS raw scores for benchmark indices (SPY, QQQ). These are not percentile-ranked — they provide a baseline to compare individual stocks against the market.

.movers(days=5, n=20, direction="up") → list

Get stocks with the biggest RS Rating change over recent trading days. Perfect for finding emerging momentum leaders.

Parameter Type Description
days int Lookback period in trading days (default: 5)
n int Number of results (default: 20)
direction str "up" for gainers, "down" for losers
rs.movers(days=5, n=10, direction="up")
# [{'ticker': 'XYZ', 'rs_rating': 85, 'prev_rating': 60, 'change': 25}, ...]

.dates() → dict

Get the available date range for RS data.

rs.dates()
# {'first': '2025-03-21', 'last': '2026-03-19'}

.sectors() → list

List all available sectors.

.industries(sector=None) → list

List all available industries, optionally filtered by sector.

rs.industries("Technology")
# ['Communication Equipment', 'Computer Hardware', 'Consumer Electronics', ...]

.sector_ranking(date=None) → list

Rank sectors by average RS Rating. Shows which sectors have the strongest momentum.

rs.sector_ranking()
# [{'sector': 'Energy', 'avg_rs': 78.7, 'count': 210}, ...]

.industry_ranking(date=None, sector=None) → list

Rank industries by average RS Rating. O'Neil's research shows ~50% of a stock's move is driven by its industry group.

rs.industry_ranking()
# [{'industry': 'Oil & Gas Drilling', 'sector': 'Energy', 'avg_rs': 92.0, 'count': 15}, ...]

.sector_top(sector, n=20, date=None) → list

Get top N stocks within a specific sector.

rs.sector_top("Technology", n=5)
# [{'ticker': 'AXTI', 'rs_rating': 99, 'rs_raw': 14.79, 'industry': 'Semiconductor Equipment'}, ...]

.industry_top(industry, n=20, date=None) → list

Get top N stocks within a specific industry.

rs.industry_top("Semiconductors", n=5)
# [{'ticker': 'MU', 'rs_rating': 98, 'rs_raw': 1.99}, ...]

How It Works

The Formula

RS Rating follows IBD's reverse-engineered methodology:

RS Raw = 0.4 × ROC(63) + 0.2 × ROC(126) + 0.2 × ROC(189) + 0.2 × ROC(252)

Where ROC(n) = cumulative price return over the last n trading days.

This gives 5x more weight to the most recent quarter compared to the oldest quarter — designed to catch stocks with accelerating momentum.

Quarter Effective Weight
Most recent (0-3 months) 100%
2nd quarter (3-6 months) 60%
3rd quarter (6-9 months) 40%
Oldest (9-12 months) 20%

The raw score is then percentile-ranked across all ~4,600 stocks to produce a rating from 1 to 99.

Data Pipeline

Finviz Screener → Ticker list (~4,600 stocks)
       ↓
yfinance → Daily close prices (2 years history)
       ↓
RS calculation → Vectorized pandas computation
       ↓
Supabase PostgreSQL → Stored & served via REST API
       ↓
GitHub Actions → Automated daily update (weekdays, after market close)

Universe

  • ~4,600 US-listed stocks (NYSE, NASDAQ, AMEX)
  • Market cap > $50M (micro-cap and above)
  • Excludes ETFs and shell companies (SPACs)
  • Includes ADRs (BABA, TSM, etc.)
  • SPY & QQQ tracked as reference benchmarks

Self-Hosting

Want to run your own instance? The calculation engine is included.

git clone https://github.com/your-username/IBD-RS-Rating.git
cd IBD-RS-Rating
pip install -e ".[pg]"

# Local mode (SQLite)
python -m ibd_rs init      # Download 2yr data + calculate RS (~30 min)
python -m ibd_rs update    # Daily update (~3 min)
python -m ibd_rs top 20    # View top stocks

# Cloud mode (Supabase)
export DATABASE_URL="postgresql://..."
python -m ibd_rs init      # Loads data into Supabase

CLI Commands

Command Description
python -m ibd_rs init Initial setup: download data + compute RS
python -m ibd_rs update Daily update: new prices + RS recalc
python -m ibd_rs top [N] Top N stocks by RS Rating
python -m ibd_rs lookup TICKER RS history for a ticker
python -m ibd_rs status Database statistics
python -m ibd_rs export Export to CSV

Accuracy

Compared against actual IBD MarketSmith RS Ratings:

Range Accuracy Notes
RS 90+ ±1-3 points Near-exact match for top performers
RS 60-90 ±5-10 points Systematic offset due to universe size difference
RS < 30 ±3-6 points Both agree stock is weak

Ranking order is consistent — the same stocks appear at the top. The absolute values may differ slightly because IBD's exact formula and universe are proprietary.


Disclaimer

This project is not affiliated with Investor's Business Daily (IBD) or William O'Neil + Co. RS Ratings are calculated using a reverse-engineered approximation of IBD's methodology. For official ratings, subscribe to IBD MarketSmith.

This tool is for educational and research purposes. It is not financial advice.


License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ibd_rs_rating-0.3.1.tar.gz (33.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ibd_rs_rating-0.3.1-py3-none-any.whl (23.8 kB view details)

Uploaded Python 3

File details

Details for the file ibd_rs_rating-0.3.1.tar.gz.

File metadata

  • Download URL: ibd_rs_rating-0.3.1.tar.gz
  • Upload date:
  • Size: 33.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for ibd_rs_rating-0.3.1.tar.gz
Algorithm Hash digest
SHA256 91d0c549e7b41fce51117b2a65db60293b0bc01d079f709a8ecc6f6fcb5686d4
MD5 12db6260d4fbd401fea728ae5e513704
BLAKE2b-256 33689287cfdb8cf062a1a88909325c1a6b5cbb6b27eda30759dd1f5dd2740352

See more details on using hashes here.

File details

Details for the file ibd_rs_rating-0.3.1-py3-none-any.whl.

File metadata

  • Download URL: ibd_rs_rating-0.3.1-py3-none-any.whl
  • Upload date:
  • Size: 23.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for ibd_rs_rating-0.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 077b6af4472d5a426e6f0eadc9eaabcfe3803bee35d77b245ff60af9f85545c1
MD5 5f68c81fd9044d4de960a5926b49b0aa
BLAKE2b-256 933bdcb0e069e8742c229a027a1cefa11eb56cc99d3bd3bf066cbc5f526510dd

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page