List Companies with over $1B in Market Cap on NASDAQ + NYSE using Python + Massive
Scan NASDAQ and NYSE stocks with Python and Massive to save companies with at least $1B in market cap.
In this tutorial, we are going to write a Python script that finds companies over $1B in market cap on the NYSE and NASDAQ. This is useful if you want to build a local list of large-cap stock tickers from Massive data.
This tutorial assumes you have Python installed and a basic understanding of programming. We are going to use Massive, which was previously Polygon.io.
Step 1: Create a Massive account
Sign up for a Massive account and find your API key. We are going to use the free tier for pulling the stock data.
This will not be an efficient way of finding these stocks because we will scan all stocks to disqualify them. I suggest finding a second attribute to filter by first and including that in the initial query to reduce the number of stocks you have to scan. For this tutorial, we will do it the brute-force way.
Step 2: Create the Python script
Create a file called main.py and add the following script:
import os
import time
import requests
from collections import deque
api_key = os.getenv('MASSIVE_API_KEY', '')
exchanges = ['XNAS', 'XNYS']
OUTPUT_FILE = 'billion_marketcap_tickers.txt'
MARKET_CAP_THRESHOLD = 1_000_000_000 # $1B
REQUESTS_PER_WINDOW = 5
REQUEST_WINDOW_SECONDS = 60
_request_times = deque()
def rate_limited_get(url, **kwargs):
"""Throttle outbound HTTP requests to keep us within API limits."""
while True:
now = time.monotonic()
# Drop old request timestamps outside the window
while _request_times and now - _request_times[0] > REQUEST_WINDOW_SECONDS:
_request_times.popleft()
if len(_request_times) < REQUESTS_PER_WINDOW:
_request_times.append(now)
break
sleep_time = REQUEST_WINDOW_SECONDS - (now - _request_times[0])
if sleep_time > 0:
time.sleep(sleep_time)
return requests.get(url, **kwargs)
def get_ticker_overview(ticker: str):
url = f'https://api.massive.com/v3/reference/tickers/{ticker}?apiKey={api_key}'
response = rate_limited_get(url)
if response.status_code > 299:
print(f'Error fetching overview for {ticker}: {response.status_code}')
return None
data = response.json()
return data.get('results')
def get_page_of_tickers(url: str):
response = rate_limited_get(url)
if response.status_code > 299:
print('Error fetching tickers: ' + str(response.status_code))
raise Exception('Error fetching tickers: ' + str(response.status_code))
data = response.json()
next_url = data.get('next_url')
results = data.get('results', [])
return results, next_url
def load_existing_tickers(path: str) -> set:
"""Load already-processed tickers from file so we don't double-process them."""
if not os.path.exists(path):
return set()
tickers = set()
with open(path, 'r') as f:
for line in f:
line = line.strip().upper()
if line:
tickers.add(line)
return tickers
def append_ticker_to_file(ticker: str, path: str):
"""Append a new ticker, one per line, to the output file."""
with open(path, 'a') as f:
f.write(ticker + '\n')
def find_large_caps_on_exchange(exchange: str, processed_tickers: set):
"""Find all tickers on an exchange with market cap >= $1B and save new ones."""
url = (
'https://api.massive.com/v3/reference/tickers'
f'?market=stocks&exchange={exchange}&active=true'
'&order=asc&limit=100&sort=ticker'
f'&apiKey={api_key}'
)
while True:
tickers, next_url = get_page_of_tickers(url)
if not tickers:
break
for ticker in tickers:
symbol = ticker.get('ticker')
if not symbol:
continue
# Avoid re-processing tickers we've already saved
if symbol in processed_tickers:
print(f'Skipping already processed ticker: {symbol}')
continue
overview = get_ticker_overview(symbol)
if not overview:
continue
market_cap = overview.get('market_cap')
if not isinstance(market_cap, (int, float)):
continue
if market_cap >= MARKET_CAP_THRESHOLD:
print(f'{symbol} has market cap {market_cap}, saving.')
append_ticker_to_file(symbol, OUTPUT_FILE)
processed_tickers.add(symbol)
else:
print(f'{symbol} market cap {market_cap} below threshold, skipping.')
if not next_url:
break
url = next_url
print(f'Finished page for exchange {exchange}, continuing to next page...')
def main():
# Load already-saved large cap tickers to avoid re-processing
processed_tickers = load_existing_tickers(OUTPUT_FILE)
print(f'Loaded {len(processed_tickers)} existing tickers from {OUTPUT_FILE}')
for exchange in exchanges:
print(f'Processing exchange: {exchange}')
find_large_caps_on_exchange(exchange, processed_tickers)
print('Done.')
if __name__ == '__main__':
main()
Step 3: Run the script
Run the script with your Massive API key:
MASSIVE_API_KEY='YOUR_API_KEY' python3 main.py
Step 4: Review the output
The console output will look like this:
Processing exchange: XNAS
AACB market cap 284222250.0 below threshold, skipping.
AACG market cap 39375594.88 below threshold, skipping.
AAL has market cap 8627330489.65, saving.
AAME market cap 61599628.56 below threshold, skipping.
AAOI has market cap 1427732458.08, saving.
AAON has market cap 7769113299.860001, saving.
AAPG has market cap 3130476376.7167, saving.
AAPL has market cap 4033205551350.0, saving.
AARD market cap 235586153.76 below threshold, skipping.
ABAT market cap 476339896.07 below threshold, skipping.
ABCL has market cap 1083592873.76, saving.
ABEO market cap 232291781.67000002 below threshold, skipping.
ABL market cap 632460971.85 below threshold, skipping.
ABLV market cap 39709497.288 below threshold, skipping.
ABNB has market cap 73483526929.64, saving.
ABOS market cap 109637899.25 below threshold, skipping.
ABP market cap 15726026.469999999 below threshold, skipping.
ABSI market cap 396980841.84000003 below threshold, skipping.
...
Any matching tickers will be saved to billion_marketcap_tickers.txt.
Conclusion
You now have a Python script that scans NASDAQ and NYSE tickers with Massive and saves companies with at least $1B in market cap.