Analyzing historical stock market data is essential for backtesting trading strategies, identifying tradable edges, and conducting in-depth financial research. However, gathering comprehensive datasets, especially those that include delisted stocks (i.e., stocks that no longer trade due to acquisitions, mergers, buyouts, or bankruptcy) can be challenging. This is where Norgate Data comes in—offering a powerful solution that provides not only data for active stocks but also for delisted ones. It also includes vital metadata like index membership and sector classifications, allowing a quant researcher to build a comprehensive database on which to run their backtests.
In this guide, we’ll walk you through how to use Python with the Norgate Data API to download U.S. stock market data—both listed and delisted. We’ll start with some well-known tickers to get familiar with how Norgate Data integrates with Python, and then expand to downloading the entire U.S. stock market data.
By the end of this tutorial, you will be able to:
- Set up a connection to Norgate Data and retrieve stock data using Python.
- Download historical price data for individual tickers.
- Enrich the data with company names and sector information.
- Check index membership to see whether a stock was part of a major index like the S&P 500, Russell 3000 or other.
- Retrieve both active and delisted stock symbols for broader historical analysis.
- Download complete market data for both listed and delisted stocks.
To make the process accessible to everyone, we’ve provided a Jupyter Notebook that you can run locally. This step-by-step approach ensures that even beginners can follow along and build a complete market-wide dataset.
Setting Up Norgate Data
Before we dive into the code, there are a few steps to follow to ensure you can access the data using Python:
- Create a Norgate Data account – Norgate offers a 21-day free trial with access to two years’ worth of historical data. You can sign up here.
- Install Norgate Data Updater – Download and install the Norgate Data Updater from here. This software connects to the Norgate servers and allows you to download financial data. You must have this application running in the background to use the Python API.

Ensure Database is Downloaded and Active
Once Norgate Data Updater is installed, you must ensure that the necessary databases are downloaded and active before proceeding with the Python integration.

After logging into the Norgate Data Updater, navigate to the Database section and ensure that the following databases are marked as Active:
- US Equities
- US Equities Delisted
If any databases are missing, select the checkbox next to them and click the Download button at the bottom of the window. Make sure these databases are fully active before proceeding with the Python integration.
Disclaimer
This tutorial is for educational purposes only. We are not affiliated with or sponsored by Norgate Data.
Let’s Dive In!
With the Norgate Data Updater set up and running, you’re now ready to start retrieving U.S. stock market data using Python. We will begin by downloading data for specific tickers (like AAPL, TSLA, and GOOG) to understand how the Norgate Data API works. Once that’s clear, we’ll move on to downloading the entire U.S. stock market data, including both active and delisted stocks.
Here are the steps we will cover in this guide:
Step 1: Import Required Libraries and Set Up Logging
We will start by importing the necessary Python libraries, including norgatedata
, and set up logging to track the progress of data downloads and transformations.
Step 2: Download Historical Stock Data for Known Tickers (AAPL, TSLA, GOOG)
We will download daily stock market data for a few well-known companies to get comfortable with using the Norgate Data API.
Step 3: Add Company Names to the Downloaded Data
We’ll enrich the downloaded data by adding the full company names using Norgate’s company name information.
Step 4: Add Sector Information
We will add sector classifications (e.g., Technology, Consumer Discretionary) to the data to make the dataset more insightful.
Step 5: Check Index Constituency (S&P 500, Russell 3000)
We’ll check if the stocks were part of major indices such as the S&P 500 or the Russell 3000 at any given point in time and add that information to our dataset.
Step 6: Download Active and Delisted Market Symbols
We will retrieve the list of symbols for both active and delisted U.S. equities to expand our dataset to the entire market.
Step 7: Filter for Stocks Only
After downloading all symbols, we’ll filter out non-equity instruments (like ETFs and funds) to focus on stocks only.
Step 8: Download Complete Stock Data (Listed and Delisted)
Finally, we will download the complete dataset, which includes both active and delisted stocks, for the entire U.S. stock market.
Step 9: Add Company Names to the Entire Market Data
We will enrich the entire market dataset (both active and delisted stocks) by adding the full company names using Norgate’s company name information.
Step 10: Add Sector Information to the Entire Market Data
We will add sector classifications (e.g., Technology, Consumer Discretionary) to the entire market dataset to categorize stocks into industry groups.
Step 11: Check Index Constituency for the Entire Market (S&P 500, Russell 3000)
We will check if each stock in the entire market (both active and delisted) was part of major indices such as the S&P 500 or the Russell 3000 at any given point in time, and add that information to the dataset.
Step 12: Merge Active and Delisted Stocks into One Dataset
In this step, we merge the data for all active and delisted stocks into a single dataset. This ensures that our database contains a complete record of all stocks, whether they are still trading or have been delisted. The merged dataset is then sorted by date to maintain chronological order, and finally, it is saved as a .parquet
file for efficient storage and retrieval.
Steps Overview and Explanation
Let’s go through each step in more detail, explaining the code that will be used and showing how to handle the data.
Step 1: Import Required Libraries and Set Up Logging
The first step is to import the necessary libraries. We’ll need norgatedata
to interface with Norgate Data, pandas
for handling and manipulating the data, and logging
to monitor the process.
Also, you have to install norgatedata and pandas if they are not already installed by using the following commands:
Explanation: This imports the necessary libraries. Logging will help track the progress and debug any issues during data downloading and processing.
Step 2: Download Historical Stock Data for Known Tickers (AAPL, TSLA, GOOG)
Now, let’s download the daily stock price data for Apple (AAPL), Tesla (TSLA), and Google (GOOG) to understand how the Norgate Data API works.
Explanation: This function downloads the historical price data for the given symbol (AAPL, TSLA, GOOG) over the specified date range. We use total return adjusted price data, which accounts for dividends and stock splits.

Step 3: Add Company Names to the Downloaded Data
Next, we’ll add the full company name for each stock using Norgate’s security_name
function.
Explanation: We fetch the full company name for each ticker (AAPL, TSLA, GOOG) and add it as a new column (Security_Name
) in the data.

Security_Name
Step 4: Add Sector Information
We can further enrich our data by adding the GICS sector classification for each stock.
Explanation: This step adds each stock’s sector using the GICS (Global Industry Classification Standard), which categorizes stocks by industry.

Sector
Step 5: Check Index Constituency (S&P 500, Russell 3000)
In this step, we check whether a stock (e.g., AAPL, TSLA, GOOG) was part of major indices such as the S&P 500 or Russell 3000 at any point in time. We use Norgate Data’s index_constituent_timeseries
function to fetch the relevant data and append it to our existing DataFrame with clearly named columns.
Explanation:
- Loop Over Indices: We check for S&P 500 and Russell 3000 membership in this example, but you can add or remove indices as needed.
- Fetch Data from Norgate: We use
norgatedata.index_constituent_timeseries
to get whether the stock was a constituent of the index. - Column Renaming: The column
Index Constituent
is renamed based on the index being checked (e.g.,In_S&P_500
,In_Russell_3000
).

Step 6: Download Active and Delisted Market Symbols
Once we understand how to retrieve stock data for a few specific tickers, we can scale up by downloading all active and delisted symbols from Norgate Data. This is crucial for retrieving comprehensive stock market data that includes not just the current active stocks, but also companies that have been delisted.
Explanation:
get_all_market_symbols
: This function retrieves symbols from the US Equities (active) and US Equities Delisted databases provided by Norgate Data.

Step 7: Filter for Stocks Only
Now that we have a complete list of symbols, we want to filter out non-equity instruments (such as ETFs or REITs) so that we’re left with only stocks.
Explanation:
We use norgatedata.subtype1(symbol)
to filter out anything that is not classified as an equity (e.g., ETFs, REITs). This ensures we’re only dealing with stock data.

Step 8: Download Complete Stock Data (Listed and Delisted)
In this step, we move from working with individual tickers to downloading the complete U.S. stock market data, including both active and delisted stocks. This gives us a full dataset of the market, allowing for comprehensive analysis and backtesting across historical and current equities.
Explanation:
- Function Overview:
download_all_stock_data(symbols, start_date, end_date)
loops over the provided symbols (both active and delisted), downloading historical data for each one over the specified date range.- The data for each stock is appended to a list,
all_data
, and then combined into a single DataFrame withDate
as the index (Norgate’s default behavior).
- For Each Symbol:
- The function iterates through the
symbols
list (this could be either active or delisted stocks). - For each stock symbol, it calls
download_stock_data
to fetch the historical price data. - After fetching the data for each stock, it adds a new column called
Symbol
so that when all the data is combined, each row is labeled with the corresponding stock symbol.
- The function iterates through the
- Combining the Data:
- The data for all stocks is combined into a single DataFrame using
pd.concat
. Since the default behavior from Norgate is to return theDate
as the index, we maintain that structure by not resetting the index.
- The data for all stocks is combined into a single DataFrame using
- Downloading Active and Delisted Data:
- First, we download the data for active stocks (
all_active_data
), then for delisted stocks (all_delisted_data
). - After downloading, the code prints how many unique stocks were downloaded in each category (based on the specified dates). If no data was downloaded, it prints a message indicating that.
- First, we download the data for active stocks (

In case you print out all_active_data, you will see the following:

Step 9: Adding Security Names to the Data
In this step, we will add the security names for each stock in the dataset
Explanation:
- Unique Symbols: We extract the unique symbols from the
Symbol
column usingdata['Symbol'].unique()
. This ensures that we only need to fetch the security name for each stock once. - Fetching Security Name: For each symbol, we fetch the security name from Norgate using the
norgatedata.security_name(symbol)
function. This is stored in a dictionary (security_names
) for faster lookup. - Mapping the Names: We map the security names back to the DataFrame using the
map()
function. This operation ensures that theDate
index remains unchanged.

Step 10: Adding Sector Information to the Data
In this step, we will add the sector classification for each stock.
Explanation:
- Unique Symbols: Similar to the security names step, we extract the unique symbols and iterate over them to fetch the sector classification for each stock.
- Fetching Sector Information: For each symbol, we fetch the sector classification using the
norgatedata.classification_at_level(symbol, 'GICS', 'Name', level=1)
function. The fetched sectors are stored in a dictionary for faster mapping. - Mapping the Sectors: The sectors are mapped back to the DataFrame using the
map()
function, ensuring that theDate
index remains unchanged.

Step 11: Checking Index Constituency for Active and Delisted Stocks
In this step, we will check whether each stock was part of major indices like the S&P 500 or the Russell 3000.
Explanation:
- Check Index Membership: We loop through each stock symbol in the active and delisted datasets and check if they were part of the S&P 500 or Russell 3000 indices. For each symbol, we add a corresponding column (e.g.,
In_S&P_500
,In_Russell_3000
) indicating index membership. - Combining Data: After processing all active and delisted symbols separately, we concatenate the results back into
all_active_data
andall_delisted_data
.

Step 12: Merge Active and Delisted Stocks into One Dataset
In this step, we combine active and delisted stock data into one dataset and export it as a .parquet
file.
Explanation:
- Merge datasets: We concatenate active and delisted stock data to create a comprehensive dataset.
- Sort by date: The merged data is sorted by the ‘Date’ index to ensure proper chronological order.
- Export to
.parquet
: The final dataset is saved in.parquet
format for efficient storage and retrieval.

.parquet
fileConclusion
Now we have successfully constructed a comprehensive, survivorship bias-free database of both listed and delisted stocks for the specified period, from start_date
to end_date
. This database can be used for various types of financial analysis, backtesting trading strategies, and academic research while ensuring that delisted stocks are not excluded, providing a more accurate reflection of historical market performance.
With this database, you can avoid the common pitfall of survivorship bias, which often leads to overly optimistic results in research that focuses only on active companies. Including both listed and delisted stocks allows for a more balanced, real-world view of the stock market, making your analysis much more robust.
You can download the full Jupyter Notebook for this process by clicking here and easily adapt it for your own research or projects
For further assistance, feel free to contact us.