As a private investor, the amount of information you can find on the internet is rather daunting. With millions of companies and derivatives on the market, it is hard to understand what types of companies or ETFs are available. The most traded companies and ETFs are easy to find because they are known to the public (for example, Microsoft, Tesla, S&P 500 ETF or an All-World ETF), but what else is out there is often unknown.

This is why I created the Finance Database, a database featuring 300,000+ symbols containing Equities, ETFs, Funds, Indices, Currencies, Cryptocurrencies and Money Markets. It allows you to obtain a broad overview of sectors, industries, types of investments and much more, entirely for free. Everything is stored in CSV files that anyone can read and edit, so the database grows and improves through the community.

The database is explicitly not meant to provide up-to-date fundamentals or stock data, as those are easy to obtain (with the help of this database) through the Finance Toolkit. Instead, it shows which products exist in each country, industry and sector and gives the most essential information about each of them. With this information, you can analyze specific areas of the financial world or find a product that is otherwise hard to find. By using both, it is possible to do a fully-fledged competitive analysis with the tickers found in the Finance Database loaded into the Finance Toolkit.

Some key statistics of the database:

Equities
123,326
11 Sectors · 69 Industries · 118 Countries · 87 Exchanges
ETFs
44,429
605 Issuers · 34 Categories · 64 Exchanges
Funds
58,148
1,560 Fund Families · 71 Categories · 34 Exchanges
Indices
80,287
42 Categories · 63 Exchanges
Currencies
2,556
178 Currencies
Cryptocurrencies
3,378
352 Coins · 12 Quote Currencies
Money Markets
1,209
136 Fund Families · 2 Exchanges

Finance Database

Installation

Before installation, consider starring the project on GitHub which helps others find the project as well.

image

Installing the Finance Database only requires the following (Python 3.11 or newer):

pip install financedatabase -U

Then within Python use:

import financedatabase as fd

equities = fd.Equities()

No API key is needed. Each asset class is downloaded once and cached locally, see Questions & Answers for how the cache works.

Functionality

This section is an introduction to the Finance Database. The Getting Started Notebook contains many more examples, including the full output of each query.

Find the Getting Started Notebook

A basic example of how to use the Finance Database is shown below. Every code snippet in the sections that follow builds on this same equities instance. Initialization of each asset class is only required once, so save it to a variable to query the database much more quickly.

import financedatabase as fd

# Initialize the Equities database
equities = fd.Equities()

# Select all equities
equities.select()

A portion of the output is shown below. The tables in this section are cut off to five entries and a selection of the columns due to the sheer size of the database.

symbol name currency sector industry exchange market country market_cap isin
AAPL Apple Inc. USD Information Technology Technology Hardware, Storage & Peripherals NMS NASDAQ Global Select United States Mega Cap US0378331005
ASML.AS ASML Holding N.V. EUR Information Technology Semiconductors & Semiconductor Equipment AMS Euronext Amsterdam Netherlands Mega Cap NL0010273215
7203.T Toyota Motor Corporation JPY Consumer Discretionary Automobiles JPX Tokyo Stock Exchange Japan Mega Cap JP3633400001
NESN.SW Nestle S.A. CHF Consumer Staples Food Products EBS SIX Swiss Exchange Switzerland Mega Cap CH0038863350
SIE.DE Siemens Aktiengesellschaft EUR Industrials Machinery GER XETRA Germany Mega Cap DE0007236101

And below the actively listed equities are counted per sector.

Actively listed equities per sector Actively listed equities per sector

Each asset class has the same three functions: select to filter on the database’s categories, search to look for any text in any column and show_options to see which values a category can take. The asset classes are fd.Equities(), fd.ETFs(), fd.Funds(), fd.Indices(), fd.Currencies(), fd.Cryptos() and fd.Moneymarkets().

Three capabilities cut across all of them:

  • Lists of values. Every filter accepts a single value or a list, e.g. country=['Netherlands', 'Belgium'], returning the entries that match any of them.
  • only_primary_listing and exclude_delisted. A company is often listed on many exchanges. only_primary_listing=True keeps only its primary listing, and delisted symbols are left out by default (exclude_delisted=False to include them).
  • pandas or Polars. Queries run lazily with Polars and return a pandas DataFrame by default, or a Polars DataFrame with as_pandas=False.

Exploring the Options

With show_options, all possible options are given per column. This is useful as it doesn’t require loading the larger data files.

# Show the options of every column of the equities
options = fd.show_options("equities")

# Select the sectors
options["sector"]

This returns the eleven sectors used for equities, which approximate GICS:

['Communication Services', 'Consumer Discretionary', 'Consumer Staples',
 'Energy', 'Financials', 'Health Care', 'Industrials',
 'Information Technology', 'Materials', 'Real Estate', 'Utilities']

Once an asset class is loaded, show_options is also available on the class itself, where it shows the options that remain after filtering. For example, the industries of the financial companies in the Netherlands:

# Show the industries of financial companies in the Netherlands
equities.show_options(
    selection="industry",
    sector="Financials",
    country="Netherlands",
)

Which returns:

['Banks', 'Capital Markets', 'Consumer Finance',
 'Diversified Financial Services', 'Insurance']

And below the number of companies in each of these industries is shown. Each company is counted once, however many exchanges it is listed on: listings that share an ISIN, share class FIGI, website or the first word of their name (such as Aegon and its perpetual bonds) are combined.

Dutch financial companies per industry Dutch financial companies per industry

The options of every column can be shown this way, including currency, exchange, market, country and market_cap (Mega, Large, Mid, Small, Micro and Nano Cap). Find the Notebook here.

Selecting Equities

Given these options, it becomes possible to filter the database on the categories you are interested in. For example, the ‘Insurance’ companies in the ‘United States’, one row per company. The sector can be omitted here since the industry already implies ‘Financials’.

# Select the primary listings of insurance companies in the United States
equities.select(
    country="United States",
    industry="Insurance",
    only_primary_listing=True,
)

This returns about 180 companies, of which a few of the larger ones are shown below.

symbol name currency sector industry exchange market country market_cap
AFL Aflac Incorporated USD Financials Insurance NYQ New York Stock Exchange United States Large Cap
AJG Arthur J. Gallagher & Co. USD Financials Insurance NYQ New York Stock Exchange United States Large Cap
BRO Brown & Brown, Inc. USD Financials Insurance NYQ New York Stock Exchange United States Large Cap
CINF Cincinnati Financial Corporation USD Financials Insurance NMS NASDAQ Global Select United States Large Cap
PGR Progressive Corporation USD Financials Insurance NYQ New York Stock Exchange United States Large Cap

Without only_primary_listing=True, the same query returns about 450 listings on more than 20 exchanges, because every exchange a company trades on is shown by default. Progressive, for example, also appears as PGV.F (Frankfurt), PGV.SG (Stuttgart), PGR.MX (Mexico) and P1GR34.SA (B3). Primary listings are the symbols without an exchange suffix, which makes the option mostly useful for US companies. For companies elsewhere, filter on the exchange or market instead.

For the Netherlands, it makes sense to select the market “Euronext Amsterdam” (exchange “AMS”), here together with the market cap:

# Select the large insurance companies on Euronext Amsterdam
equities.select(
    country="Netherlands",
    industry="Insurance",
    market="Euronext Amsterdam",
    market_cap="Large Cap",
)

This gives the following three companies:

symbol name currency sector industry exchange market country market_cap isin
AGN.AS Aegon N.V. EUR Financials Insurance AMS Euronext Amsterdam Netherlands Large Cap BMG0112X1056
ASRNL.AS ASR Nederland N.V. EUR Financials Insurance AMS Euronext Amsterdam Netherlands Large Cap NL0011872643
NN.AS NN Group N.V. EUR Financials Insurance AMS Euronext Amsterdam Netherlands Large Cap NL0010773842

Every filter also accepts a list, so both queries can be combined into one with country=["Netherlands", "United States"] and market=["Euronext Amsterdam", "New York Stock Exchange", "NASDAQ Global Select"]. Equities can be selected on country, sector, industry_group, industry, currency, exchange, mic, market and market_cap. Find the Notebook here.

Searching the Database

If the categorization doesn’t lead to the results you are looking for, search filters on any column via a custom string. If the text is found anywhere in the column, the entry is returned. Searches are not case sensitive unless case_sensitive=True is set, index searches the symbol and, just like select, every argument accepts a list.

# Search for robotics or education companies with equipment on the Frankfurt Stock Exchange
equities.search(
    summary=["Robotics", "Education"],
    industry_group="Equipment",
    market="Frankfurt",
    index=".F",
)

This returns about 60 instruments listed on the Frankfurt Stock Exchange, in an industry group containing “Equipment” and with “Robotics” or “Education” in their summary. Filtering on index=".F" is an alternative way to find the exchange or market you are looking for.

symbol name currency sector industry exchange market country market_cap
089.F Cambium Networks Corporation EUR Information Technology Communications Equipment FRA Frankfurt Stock Exchange Cayman Islands Micro Cap
109.F Castlight Health, Inc. EUR Health Care Health Care Technology FRA Frankfurt Stock Exchange United States Small Cap
1KT.F Keysight Technologies Inc EUR Information Technology Electronic Equipment, Instruments & Components FRA Frankfurt Stock Exchange United States Large Cap
1N1.F Nanalysis Scientific Corp. EUR Information Technology Electronic Equipment, Instruments & Components FRA Frankfurt Stock Exchange Canada Nano Cap
1YO.F Yangtze Optical Fibre And Cable Joint Stock Limited Company EUR Information Technology Communications Equipment FRA Frankfurt Stock Exchange China Large Cap

And below the results are counted per industry.

Search results per industry Search results per industry

The search function works on every column of every asset class, including name, isin, cusip and figi. For example, equities.search(isin="US0378331005") returns Apple on each exchange it is listed on. Find the Notebook here.

Exploring Other Asset Classes

All of these functions are also available for the other asset classes. The only difference is the class name and the columns. For example, ETFs use fd.ETFs() and are selected on category_group, category and family instead.

# Initialize the ETFs database
etfs = fd.ETFs()

# Select the Fixed Income ETFs of Vanguard
etfs.select(
    category_group="Fixed Income",
    family="Vanguard Asset Management",
)

For example, see some of the Vanguard bond ETFs listed in Berlin below:

symbol name currency category_group category family exchange
0250.BE Vanguard Intermediate-Term Corporate Bond Index Fund ETF Shares EUR Fixed Income Corporate Bonds Vanguard Asset Management BER
0251.BE Vanguard Short-Term Corporate Bond Index Fund ETF Shares EUR Fixed Income Corporate Bonds Vanguard Asset Management BER
0252.BE Vanguard Total World Bond ETF EUR Fixed Income Investment Grade Bonds Vanguard Asset Management BER
025L.BE Vanguard Total International Bond Index Fund ETF Shares EUR Fixed Income Investment Grade Bonds Vanguard Asset Management BER
025N.BE Vanguard Long-Term Corporate Bond Index Fund ETF Shares EUR Fixed Income Corporate Bonds Vanguard Asset Management BER

The same applies to search, for example to find the funds that focus on pension plans:

# Initialize the Funds database
funds = fd.Funds()

# Search for funds with "Pension" in their summary
funds.search(summary="Pension")

Which returns over 600 funds, of which a few are shown below:

symbol name currency category_group category family exchange
0P000015HA.F Casermed Protección 6 PP EUR Equities Allocation Sa Nostra Seguros de Vida SA FRA
0P000015V5.F BK Revalorización Europa 2022 PP EUR Fixed Income Bonds Bankinter FRA
0P000015VC.F Bankia Protegido Renta 2023 PP EUR Fixed Income Bonds Bankia Fondos FRA
0P000017AE.F Santander Universidades RF Mixta PP EUR Fixed Income Bonds Santander Asset Management SGIIC FRA
0P000017AF.F OpenBank Monetario PP EUR Cash Money Market Instruments Santander Asset Management SGIIC FRA

And below all actively listed ETFs are divided over their category groups.

Actively listed ETFs per category group Actively listed ETFs per category group

The categories of each asset class can again be found with show_options, e.g. fd.Indices().show_options(selection="category") returns the 42 index categories, from ‘Corporate Bonds’ and ‘Emerging Markets’ to ‘Small Cap’ and ‘Value’. Cryptocurrencies are selected on cryptocurrency and currency, currencies on base_currency and quote_currency and money markets on currency and family. Find the Notebook here.

Combining with the Finance Toolkit

The Finance Database has a direct integration with the Finance Toolkit, making it possible to do financial analysis on the instruments you’ve found. Any selection can be loaded into the Finance Toolkit with to_toolkit.

To be able to get started, you need to obtain an API Key from FinancialModelingPrep. This gives access to 30+ years of financial statements, both annual and quarterly. Note that the Free plan is limited to 250 requests each day, 5 years of data and only features companies listed on US exchanges.

Obtain an API Key from FinancialModelingPrep

Returning to the three large insurance companies in the Netherlands:

# Select the large insurance companies on Euronext Amsterdam
dutch_insurance_companies = equities.select(
    country="Netherlands",
    industry="Insurance",
    market="Euronext Amsterdam",
    market_cap="Large Cap",
)

# Load them into the Finance Toolkit
toolkit = dutch_insurance_companies.to_toolkit(api_key="FINANCIAL_MODELING_PREP_KEY")

# Obtain historical market data for all tickers
historical_data = toolkit.get_historical_data()

# Select the results for ASR Nederland
historical_data.xs("ASRNL.AS", axis=1, level=1)

For example, a portion of the historical data for ASR Nederland is shown below.

date Open High Low Close Adj Close Volume Dividends Return Cumulative Return
2026-09-30 73.26 73.64 71.88 72.16 72.16 435324 0 -0.0118 3.608
2026-10-01 71.52 71.72 70.58 71 71 666582 0 -0.0161 3.55
2026-10-02 71.14 71.54 70.66 71.48 71.48 408475 0 0.0068 3.574
2026-10-05 71.5 72.36 71.4 72.16 72.16 375435 0 0.0095 3.608
2026-10-06 72.44 73.1 72.4 72.82 72.82 63282 0 0.0091 3.641

And below the cumulative returns of Aegon, ASR Nederland and NN Group are plotted, including the S&P 500 as benchmark.

Cumulative returns of Aegon, ASR Nederland and NN Group against the S&P 500 Cumulative returns of Aegon, ASR Nederland and NN Group against the S&P 500

Now let’s make it more advanced by calculating the profitability ratios for each company:

# Collect all Profitability Ratios for all tickers
profitability_ratios = toolkit.ratios.collect_profitability_ratios()

# Select the results for ASR Nederland
profitability_ratios.loc["ASRNL.AS"]

For example, see some of the profitability ratios of ASR Nederland below.

  2018 2019 2020 2021 2022 2023 2024 2025
Net Profit Margin 0.1055 0.116 0.0811 0.091 0.1666 0.0814 0.0427 0.024
Income Before Tax Profit Margin 0.1564 0.1515 0.1104 0.1231 0.2202 0.1089 0.0688 0.0328
Effective Tax Rate 0.2168 0.1983 0.2075 0.2233 0.2609 0.2181 0.2699 0.1882
Return on Assets 0.0107 0.0144 0.0083 0.0118 -0.0259 0.0098 0.0061 0.0036
Return on Equity 0.1118 0.16 0.0982 0.1305 -0.2591 0.1427 0.0969 0.0552

And below these and other profitability ratios of ASR Nederland, each with its latest value, the change over the period and its trend.

Profitability ratios of ASR Nederland Profitability ratios of ASR Nederland

This works for the other asset classes too. For example, Ethereum quoted in BTC, CAD, EUR, GBP and USD can be loaded with fd.Cryptos().select(cryptocurrency="ETH").to_toolkit(api_key="FINANCIAL_MODELING_PREP_KEY"), after which get_historical_data(period="quarterly") returns its quarterly returns in each currency. This is just a small snippet of what is available within the Finance Toolkit. For more information, see the Finance Toolkit page here or the example Notebook here.

MCP Server

The Finance Database MCP Server gives any AI assistant that supports the Model Context Protocol (MCP), such as Claude, Copilot, Cursor or Windsurf, direct access to the database. Ask in plain English for, say, every mid cap semiconductor company in Taiwan or the bond ETFs of a given issuer, and the assistant queries the database on your behalf. No API key is needed.

Connect to the hosted server at https://financedatabase.jeroenbouma.com/mcp with nothing to install, or run it locally with uvx --from "financedatabase[mcp]" financedatabase-mcp-setup, which adds the server to your client’s configuration automatically. Combine it with the Finance Toolkit MCP Server to go from a list of symbols to their financial statements, ratios and prices.

Explore the Finance Database MCP Server

Questions & Answers

This section includes frequently asked questions. If you have any questions that are not answered here, consider creating an Issue or reach out to me via the contact details below.

How is the data obtained?

The data is an aggregation of various publicly available sources. I strictly maintain the rule that all data in this database must be freely accessible to everyone. Data requiring API keys or paid subscriptions is never included. Information that companies charge for is typically owned and maintained by those companies, making public sharing of such data a violation of their Terms of Service (ToS). However, publicly available data can be freely shared (read more about the legality of web scraping here). This database will always remain completely free.

What categorization method is used?

The categorization for Equities is based on a loose approximation of GICS (Global Industry Classification Standard). This database attempts to reflect sectors and industries as accurately as possible through manual curation, without collecting any actual data from MSCI’s proprietary sources. The official GICS datasets curated by MSCI remain the most up-to-date, paid solution and were not used in developing any part of this database. All other categorizations in the database are independently developed and can be freely modified.

How can I find out which countries, sectors and/or industries exist within the database without needing to check the database manually?

For this you can use the show_options function, either for an asset class as a whole (fd.show_options("equities")), which doesn’t require any data to be loaded, or on a loaded asset class to see the options that remain after filtering. See Exploring the Options for more information.

When I try to collect data I notice that not all tickers return output, why is that?

Some tickers are merely holdings of companies and therefore do not really have any data attached to them. Therefore, it makes sense that not all tickers return data. If you are still in doubt, search the ticker on Google to see if there is really no data available. If you can’t find anything about the ticker, consider updating the database by visiting the Contributing Guidelines.

How does the database handle changes to companies over time, like symbol/exchange migration, mergers, bankruptcies, or symbols getting reused?

For American exchanges, the database automatically updates every Sunday using data from this repository. This process includes checks for market cap changes and updates asset classifications accordingly. Delisted tickers are intentionally retained for historical research purposes.

While professional financial data services like Bloomberg charge over $25,000 annually for comprehensive market data maintenance, this database relies on community contributions. When companies outside American exchanges undergo changes (migrations, mergers, bankruptcies), we depend on community members to identify and update these entries.

Most companies don’t change so rapidly that the database becomes obsolete. Major changes like Facebook’s rebrand to META are quickly incorporated. Even when companies go bankrupt, their ticker information remains valuable for historical analysis.

If you notice outdated information, please consider contributing through the Contributing Guidelines.

Is the data downloaded every time I use the package?

No. Each dataset is downloaded once and cached in your user cache folder (or the folder set in FINANCEDATABASE_CACHE_DIR). Once a day the package checks for a newer version and only downloads it when it changed; offline, the cached copy is used. Queries run lazily with Polars and return pandas by default, or Polars with as_pandas=False, e.g. equities.select(country="Canada", as_pandas=False).

Contributing

First of all, thank you for taking the time to contribute (or at least read the Contributing Guidelines)!

Find the Contributing Guidelines

The Finance Database serves the role of providing anyone with any type of financial product categorization entirely for free. To achieve this, it relies on community involvement to add, edit and remove tickers over time. This is made easy enough that anyone, even those with a lack of coding experience, can contribute because of the use of CSV files that can be manually edited with ease.

Below are those that made significant contributions to the project. Thank you!

User Contribution
dokson Made very significant contributions to the quality of the database in #138, #139, #140, #141, #142, #143, #144, #145, #146 and #147, added the MIC column (#149), enriched the FIGIs and added 709 missing tickers (#150, #151) and fixed the CI workflows (#154).
JonArnfred Built the identifier validation that now checks every pull request (#159), filled missing share class FIGIs (#158), made the database workflow preserve CSV values exactly as written (#166) and fixed the test suite (#160).
AlfaStake Added ISIN codes for ETFs (#124) and corrected and enriched 229 equity ISINs (#126).
pettijohn Added missing currencies and company names from SEC data (#135, #136).
desaijimmy Made changes to Equities dataset including the Split of Daimler to Mercedes-Benz and Daimler Trucks
nindogo Introduced a variety of new equities from the Nairobi Securities Exchange and introduced the country Kenya into the dataset.
colin99d Helped in the conversion of the Finance Database package to Object-Oriented, making the code much more efficient.

Contact

If you have any questions about the Finance Database or would like to share with me what you have been working on, feel free to reach out to me via:

If you’d like to support my efforts, either help me out via the Contributing Guidelines or Sponsor Me.

Star History Chart