Growth Stock Screener

An automated stock screen which isolates top companies based on time-tested growth criteria.


Terminal
Stock Screener Terminal Window

Features

Iterations Icon
Five distinct screen iterations based on criteria for predicting super performance.
RS Ratings Icon
RS Ratings calculated using methodology from William O'Neil Securities.
Stage 2 Trend Icon
Stage-2 Trend derived from strategies of U.S. investing champions Mark Minervini and Oliver Kell.
Revenue Growth Icon
Revenue growth sourced directly from the SEC's EDGAR XBRL data APIs.
User Settings Icon
Customizable screen settings for fine-tuning and experimenting.
Output File Icon
Easy-to-access .csv outfiles storing screen results. Parsable .json outfiles for evaluation.

Getting Started

Growth Stock Screener is a web-scraping utility that screens all stocks listed on the NASDAQ Composite based on inputted criteria. It relies on AIOHTTP and asyncio for asynchronous web requests, and Selenium for browser automation when desired content is dynamically loaded.


Installation

First, ensure that you have Python 3.11+ and Firefox installed.

Note for Mac users: Python now includes its own private copy of OpenSSL and no longer uses Apple-supplied OpenSSL libraries. After installing Python, navigate to your Applications/Python X.XX/ folder and double-click Install Certificates.command.

Note for Linux users: the 'snap' version of Firefox that comes pre-installed may cause issues when running Selenium. To troubleshoot, follow these instructions to install Firefox via 'apt' (not snap).

Next, navigate to the directory where you would like to install the screener, and run the following commands in a terminal application:

  1. Clone the project repository:
Terminal
git clone https://github.com/starboi-63/growth-stock-screener.git
  1. Navigate to the root directory:
Terminal
cd growth-stock-screener
  1. Install Python dependencies:
Terminal
pip3 install -r requirements.txt

Usage

Running the screener

To run the screener, execute the following command in the project root directory:

Terminal
python3 growth_stock_screener/run_screen.py

Modifying settings

To customize screen settings, modify values in settings.py.

settings.py
1import multiprocessing
2
3# ITERATIONS (modify these values as desired)
4
5# Iteration 1: Relative Strength
6min_rs: int = 90  # minimum RS rating to pass (integer from 0-100)
7
8# Iteration 2: Liquidity
9min_market_cap: float = 1000000000  # minimum market cap (USD)
10min_price: float = 10               # minimum price (USD)
11min_volume: int = 100000            # minimum 50-day average volume
12
13# Iteration 3: Trend
14trend_settings = {
15    "Price >= 50-day SMA": True,               # set values to 'True' or 'False'
16    "Price >= 200-day SMA": True,              # ^
17    "10-day SMA >= 20-day SMA": True,          # ^ 
18    "20-day SMA >= 50-day SMA": True,          # ^
19    "Price within 50% of 52-week High": True,  # ^
20}
21
22# Iteration 4: Revenue Growth
23min_growth_percent: float = 25  # minimum revenue growth for a quarter compared to the same quarter 1 year ago (percentage)
24protected_rs: int = 97          # minimum RS rating to bypass revenue screen iteration (see README)
25
26# Iteration 5: Institutional Accumulation
27# (no parameters to modify)
28
29# THREADS (manually set the following value if the screener reports errors during the "Trend" or "Institutional Accumulation" iterations)
30# Recommended values are 1-10. Currently set to 3/4 the number of CPU cores on the system (with a max of 10)
31
32# Thread Pool Size
33threads: int = min(int(multiprocessing.cpu_count() * 0.75), 10)  # number of concurrent browser instances to fetch dynamic data (positive integer)

Viewing results

Screen results are saved in .csv format in the project root directory, and can be opened with software like Excel, Google Sheets, or Numbers.

Completed screen.

Screen Iterations

An initial list of stocks from which to screen is sourced from NASDAQ.

NASDAQ Listings.

Then, the following screen iterations are executed sequentially:

1. Relative Strength

The market's strongest stocks are determined by calculating a raw weighted average percentage price change over the last 1212 months of trading. A 40%40\% weight is attributed to the most recent quarter, while the previous three quarters each receive a weight of 20%20\%.

RS (raw)=0.2(Q1 %Δ)+0.2(Q2 %Δ)+0.2(Q3 %Δ)+0.4(Q4 %Δ) \begin{align*} \text{RS (raw)} = 0.2(Q_1\ \%\Delta) + 0.2(Q_2\ \%\Delta) + 0.2(Q_3\ \%\Delta) + 0.4(Q_4\ \%\Delta) \end{align*}

These raw values are then assigned a percentile rank from 01000\to 100 and turned into RS ratings. By default, only stocks with a relative strength rating greater than or equal to 9090 make it through this stage of screening.

2. Liquidity

All micro-cap companies and thinly traded stocks are filtered out based on the following criteria:

market cap$1 billionprice$1050-day average volume100,000 shares \begin{align*} \text{market cap} &\geq \$1\ \text{billion}\\ \text{price} &\geq \$10\\ 50\text{-day average volume} &\geq 100,000\ \text{shares} \end{align*}

3. Trend

All stocks which are not in a stage-two uptrend are filtered out. We define a stage-two uptrend as:

price50-day SMAprice200-day SMA10-day SMA20-day SMA50-day SMAprice50% of 52-week high \begin{align*} \text{price} &\geq 50\text{-day SMA}\\ \text{price} &\geq 200\text{-day SMA}\\ 10\text{-day SMA} &\geq 20\text{-day SMA} \geq 50\text{-day SMA}\\ \text{price} &\geq 50\%\ \text{of}\ 52\text{-week high} \end{align*}

4. Revenue Growth

Only the most rapidly growing companies with high revenue growth are allowed to pass this iteration of the screen. Specifically, the percent increase in the most recent reported quarterly revenue versus a year ago must be at least 25%25\%; if available, the percent increase in the prior period versus the same quarter a year ago must also be at least 25%25\%. Revenue data is extracted from XBRL from company 10-K and 10-Q SEC filings, which eliminates foreign stocks in the process.

The current market often factors in future revenue growth; historically, this means certain exceptional stocks have exhibited super-performance without having strong on-paper revenue growth (examples include NVDA, UPST, PLTR, AI, etc.). To ensure that these stocks aren't needlessly filtered out, a small exception to revenue criteria is added: stocks with an RS97\text{RS} \geq 97 can bypass revenue criteria and make it through this screen iteration.

5. Institutional Accumulation

Any stocks with a net-increase in institutional-ownership are marked as being under accumulation. Institutional-ownership is measured by the difference in total inflows and outflows in the most recently reported financial quarter.

Since this information lags behind the current market by a few months, no stocks are outright eliminated based on this screen iteration.


Troubleshooting Errors

By default, the screener attempts to calculate an ideal number of concurrent broswer instances to create based on the number of CPU cores present on your machine. In rare cases, this number may be too high.

If you notice failed stock symbols with errors such as Browsing context has been discarded, Tried to run command without establishing a connection, WebDriver session does not exist, or Failed to decode response from marionette during the trend or institutional-accumulation iterations, you are likely creating too many browser instances at once.

Consider decreasing the value of threads in settings.py to 1-3 if you are experiencing this.