Skip to main content
Tool Comparisons

How to Use Create a Stock Screener With Python for Better Investment Decisions [Tutorial]

JS
Written by Javier Sanz
7 min read
Share:

To create a stock screener with Python, you need three things: a data source, a filtering function, and an output format. This tutorial covers all three. By the end, you will have a working script that pulls fundamental data, applies value and quality filters, and returns a ranked shortlist of stocks.

Python is not the fastest path to a screener. A tool like the ValueMarkers screener runs the same filters across 73 global exchanges in seconds without writing a single line of code. But building one yourself teaches you exactly how screening logic works, which makes you a more precise user of any screener afterward.

Key Takeaways

  • Python screeners work by pulling fundamental data via an API or library, applying conditional filters with pandas, and returning the surviving stocks.
  • The most common data sources are yfinance (free, limited), Financial Modeling Prep (FMP), and Alpha Vantage. Each has different rate limits and data depth.
  • A minimal working screener needs a ticker list, a data-fetch loop, and a filter function. The whole thing fits in under 80 lines of Python.
  • Debt-to-equity, ROE, and ROIC are the three filters that most reliably separate quality businesses from mediocre ones in historical backtests.
  • Once you build a Python screener, compare its output to a professional screener to verify data accuracy. Discrepancies usually trace back to the data source, not your logic.
  • Automating the script with a cron job or GitHub Actions lets you receive weekly results without manual runs.

What You Need Before Writing Code

You need Python 3.9 or later and four libraries: pandas, yfinance, requests, and openpyxl (for Excel output if you want it). Install them with a single pip command.

pip install pandas yfinance requests openpyxl

You also need a list of tickers to screen. For a U.S.-only screen, the S&P 500 constituent list is a reasonable starting universe. A CSV of current S&P 500 tickers is available on Wikipedia via the pandas.read_html() function, which pulls it directly without manual downloading.

Step 1: Pull the Ticker Universe

Start by fetching your ticker universe programmatically. Using the S&P 500 Wikipedia table keeps your list current without manual maintenance.

import pandas as pd

url = "https://en.wikipedia.org/wiki/List_of_S%26P_500_companies"
table = pd.read_html(url)[0]
tickers = table["Symbol"].str.replace(".", "-", regex=False).tolist()
print(f"Universe: {len(tickers)} tickers")

The .replace(".", "-") call converts tickers like BRK.B to BRK-B, which is the format yfinance expects. For international markets, you need either a manually maintained list or a paid API that provides constituent data per exchange.

Step 2: Fetch Fundamental Data

With your ticker list ready, fetch fundamental data for each ticker. The yfinance .info dictionary contains the fields you need for a basic value and quality screen.

import yfinance as yf
import time

records = []

for ticker in tickers[:50]: # Start with 50 to test
 try:
 info = yf.Ticker(ticker).info
 records.append({
 "ticker": ticker,
 "name": info.get("longName", ""),
 "sector": info.get("sector", ""),
 "pe_ratio": info.get("trailingPE"),
 "pb_ratio": info.get("priceToBook"),
 "roe": info.get("returnOnEquity"),
 "debt_to_equity": info.get("debtToEquity"),
 "dividend_yield": info.get("dividendYield"),
 "market_cap": info.get("marketCap"),
 "eps_growth": info.get("earningsGrowth"),
 })
 time.sleep(0.3) # Respect rate limits
 except Exception as e:
 print(f"Failed: {ticker} - {e}")

df = pd.DataFrame(records)

The time.sleep(0.3) call prevents yfinance from rate-limiting your requests. Removing it will get you blocked quickly. For the full 500-ticker universe, expect this loop to take 3 to 5 minutes.

A critical limitation: yfinance does not provide ROIC directly. You can calculate it from operating income and total invested capital if you pull the balance sheet separately, but that requires additional API calls. For ROIC at scale, the ValueMarkers screener or a paid data provider like Financial Modeling Prep is more reliable.

Step 3: Apply Your Filters

Once you have a DataFrame with fundamental data, filtering is straightforward with pandas boolean indexing.

df_clean = df.dropna(subset=["pe_ratio", "roe", "debt_to_equity"])

filtered = df_clean[
 (df_clean["pe_ratio"] > 0) &
 (df_clean["pe_ratio"] < 20) &
 (df_clean["roe"] > 0.12) &
 (df_clean["debt_to_equity"] < 80) # yfinance reports D/E as percentage
]

filtered = filtered.sort_values("pe_ratio", ascending=True)
print(filtered[["ticker", "name", "sector", "pe_ratio", "roe", "debt_to_equity"]].head(20))

Note that yfinance returns the debt-to-equity ratio as a percentage in some versions (80 means 0.8x), while other data sources return it as a decimal. Always check one known company to confirm the scale before applying thresholds.

The filters above mirror a simple value-quality screen: P/E under 20, ROE above 12%, and debt at a conservative level. This is the same logical structure used by the value preset in the ValueMarkers screener, just expressed in Python instead of a UI.

Step 4: Score and Rank the Results

Filtering produces a binary pass/fail list. Ranking adds nuance. A composite score that weights multiple metrics lets you see which survivors look best on the combined criteria, not just the ones that barely cleared each threshold.

from scipy.stats import rankdata

df_filtered = filtered.copy()

df_filtered["pe_score"] = rankdata(-df_filtered["pe_ratio"]) # Lower P/E = better
df_filtered["roe_score"] = rankdata(df_filtered["roe"]) # Higher ROE = better
df_filtered["de_score"] = rankdata(-df_filtered["debt_to_equity"]) # Lower D/E = better

df_filtered["composite_score"] = (
 df_filtered["pe_score"] * 0.4 +
 df_filtered["roe_score"] * 0.4 +
 df_filtered["de_score"] * 0.2
)

df_final = df_filtered.sort_values("composite_score", ascending=False)

The weights (40% P/E, 40% ROE, 20% D/E) are arbitrary starting points. Adjust them to reflect what your investment framework prioritizes. If financial health is your primary concern, increase the D/E weight.

Step 5: Export the Results

Save the output to a CSV or Excel file so you can review it without re-running the script.

df_final[["ticker", "name", "sector", "pe_ratio", "roe", "debt_to_equity", "composite_score"]].to_csv(
 "screener_output.csv", index=False
)

# Or to Excel with formatting

![create a stock screener with python — chart and analysis](/blog-images/create-a-stock-screener-with-python-hero.svg)

df_final.to_excel("screener_output.xlsx", index=False, sheet_name="Results")

For a more automated workflow, pipe the output directly to a Slack message, an email via the smtplib module, or a Google Sheet via the Sheets API. The Python screener then runs as a weekly cron job and delivers results without any manual steps.

Comparing Your Python Screen to Professional Data

FactorPython (yfinance)ValueMarkers Screener
Data freshnessEnd-of-day, 1-day lagReal-time + end-of-day
Indicator coverage30-40 basic metrics120+ indicators
Exchange coverageU.S. and some international73 global exchanges
ROIC availabilityRequires manual calculationDirect filter
Setup time30-60 minutes2 minutes
CostFree (yfinance)Subscription
CustomizationUnlimitedUI-bounded

The Python route wins on customization and cost. The ValueMarkers screener wins on speed, coverage, and data quality. Many investors use both: the screener for weekly shortlists and Python for custom research pipelines.

Limitations of a Python Screener

Data gaps. yfinance often returns None for metrics on smaller companies or international tickers. Your filter will exclude those companies by default (via dropna), which means you may miss valid candidates.

Calculation differences. ROE calculated from yfinance data can differ from the figure on a financial site because of differences in averaging periods, extraordinary items, and fiscal year alignment. Always verify a few known values against a trusted source.

No historical fundamental data in the free tier. yfinance provides current and some trailing-twelve-month data. Point-in-time historical fundamentals, the data you need for true backtesting, require a paid source like Sharadar, Tiingo, or Financial Modeling Prep.

Maintenance burden. APIs change. yfinance has broken field names and response structures multiple times. A Python screener you build today may need fixes in six months.

For investors who want reliable, maintained data without debugging API changes, running a Python screen and then cross-checking its top outputs against the ValueMarkers screener is a practical workflow.

Why python stock screener Matters

This section anchors the discussion on python stock screener. The detailed treatment, formula, and worked examples appear in the body of this article above. The points below summarize the most important takeaways for value investors who want to apply python stock screener in real portfolio decisions. ValueMarkers exposes the underlying data on every covered ticker via the screener and stock profile pages, so the concepts in this article translate directly into actionable filters.

Key inputs for python stock screener

See the main discussion of python stock screener in the sections above for the full treatment, including the inputs, the calculation methodology, the typical sector benchmarks, and the most common pitfalls to avoid. The ValueMarkers screener lets value investors filter the full universe of 100,000+ stocks across 73 exchanges using python stock screener alongside the rest of the 120-indicator composite, with sector percentiles and historical trends shown on every stock profile.

Sector benchmarks for python stock screener

See the main discussion of python stock screener in the sections above for the full treatment, including the inputs, the calculation methodology, the typical sector benchmarks, and the most common pitfalls to avoid. The ValueMarkers screener lets value investors filter the full universe of 100,000+ stocks across 73 exchanges using python stock screener alongside the rest of the 120-indicator composite, with sector percentiles and historical trends shown on every stock profile.

Frequently Asked Questions

what happens if the stock market crashes

When the stock market crashes, your Python screener's output changes significantly as prices fall. The P/E thresholds you set will capture more companies at lower prices, and the filtered list will grow. This is actually the desired behavior: a well-tuned screen becomes most useful in a downturn when valuations compress and quality businesses trade at discounts.

what time does the stock market open

U.S. markets open at 9:30 a.m. Eastern Time. yfinance downloads end-of-day data after market close at 4:00 p.m. Eastern. If you run your Python screener before market close, you are working with the prior day's prices. For most fundamental screens this is fine, since earnings, debt levels, and margins change quarterly, not daily.

are stock markets closed today

U.S. markets observe 10 federal holidays annually. yfinance handles this automatically by returning the last available trading day's data when you request a date that falls on a holiday or weekend. Your screener does not need special holiday logic for this reason, but be aware that the data you fetch on a Monday morning reflects Friday's close.

what time does the stock market close

The U.S. market closes at 4:00 p.m. Eastern Time. After-hours trading continues until 8:00 p.m. Eastern, but yfinance does not include after-hours prices in its standard download. If you are scheduling your Python screener to run automatically, set it to execute after 5:00 p.m. Eastern to ensure it captures the complete trading day's final prices.

when does the stock market open

The U.S. market opens at 9:30 a.m. Eastern Time. If your Python screener targets international markets, each exchange has its own session hours: London opens at 8:00 a.m. GMT, Hong Kong at 9:30 a.m. HKT, Tokyo at 9:00 a.m. JST. Schedule international data pulls accordingly, and expect yfinance data for non-U.S. exchanges to have a longer lag than U.S. data.

why is the stock market down today

Markets decline for many reasons, from Federal Reserve rate decisions to earnings misses to macro events. Your Python screener responds to these declines by returning more candidates as prices fall through valuation thresholds. The most useful posture is to have your screen running before the downturn and review the new entries, rather than adjusting the script reactively during volatile periods.


Build the script, run it against a 50-ticker test universe, compare the output to what you see on the ValueMarkers screener, and calibrate from there. The screener does the heavy lifting on 73 exchanges with 120 indicators while your Python script handles any custom logic the UI cannot express.

Written by Javier Sanz, Founder of ValueMarkers. Last updated April 2026.


Ready to find your next value investment?

ValueMarkers tracks 120+ fundamental indicators across 100,000+ stocks on 73 global exchanges. Run the methodology above in seconds with our stock screener, or see today's top-ranked names on the leaderboard.

Related tools: DCF Calculator · Methodology · Compare ValueMarkers

Disclaimer: This content is for informational and educational purposes only and does not constitute investment advice, a recommendation, or an offer to buy or sell any security. Past performance does not guarantee future results. Consult a licensed financial advisor before making investment decisions.

Key Metrics Mentioned

Related Articles

Tool Comparisons

How to Use Create Custom Stock Screener for Better Investment Decisions [Tutorial]

Learn how to create custom stock screener filters that match your investment strategy, with step-by-step setup using real indicators and data.

9 min read

Tool Comparisons

Everything You Need to Know About What is Morningstar Rating [FAQ]

The Morningstar rating is a backward-looking star system that scores mutual funds and ETFs on risk-adjusted returns. Here is exactly what it measures, what it misses, and how.

5 min read

Tool Comparisons

Wisesheets Alternative: Why ValueMarkers Offers More

If you use Wisesheets to pull stock data into Excel or Google Sheets, you already understand its fundamental appeal: custom functions automatically...

9 min read

Tool Comparisons

Gurufocus Undervalued Stocks: What the Data Tells Value Investors

Gurufocus undervalued stocks flags use the GF Value metric to surface potential discounts. This analysis explains what the data actually shows, which signals hold up historically.

8 min read

Tool Comparisons

Free Advanced Stock Screener: A Step-by-Step Tutorial for Investors

A step-by-step tutorial on using a free advanced stock screener. Covers Piotroski F-Score, EV/EBITDA, ROIC, and multi-factor filter logic for serious fundamental analysis.

8 min read

Tool Comparisons

Analyzing Marketwatch Watchlist: Data-Driven Insights for Investors

A data-driven breakdown of the Marketwatch watchlist feature, how it compares to alternatives, and what the numbers behind your tracked stocks actually tell you.

10 min read

Weekly Stock Analysis - Free

5 undervalued stocks, fully modeled. Every Monday. No spam.

Cookie Preferences

We use cookies to analyze site usage and improve your experience. You can accept all, reject all, or customize your preferences.