---
title: "US Fundamental Data"
description: "US Fundamental Data dataset from Morningstar."
canonical: https://www.quantconnect.com/docs/v2/writing-algorithms/datasets/morningstar/us-fundamental-data
markdown: https://www.quantconnect.com/docs/v2/writing-algorithms/datasets/morningstar/us-fundamental-data.md
language: python
source: https://github.com/QuantConnect/Documentation/tree/master/03%20Writing%20Algorithms/14%20Datasets/04%20Morningstar/01%20US%20Fundamental%20Data
modified: 2026-11-01
index: https://www.quantconnect.com/llms.txt
---

# US Fundamental Data

[Documentation](https://www.quantconnect.com/docs/v2.md) > [Writing Algorithms](https://www.quantconnect.com/docs/v2/writing-algorithms.md) > Datasets > [Morningstar](https://www.quantconnect.com/docs/v2/writing-algorithms/datasets/morningstar.md) > US Fundamental Data

> Code examples are shown in Python. Append `?lang=csharp` to this URL for the C# version of this page.

## Introduction

The US Fundamental Data by Morningstar tracks US Equity fundamentals. The data covers 8,000 US Equities, starts in January 1998, and is delivered on a daily frequency. The data does not include ETFs, ADRs, or OTC equities. This dataset is created by using a combination of string matching, Regular Expressions, and Machine Learning to gather the fundamental data published by companies.

For older symbols, the file date is approximated 45 days after the as of date. When a filing date is present on the Morningstar data, it is used. As we are a quant platform, all the data is loaded using "As Original Reported" figures. If there was a mistake reporting the figure, this will not be fixed later. The market typically responds quickly to these initially reported figures. Data is available for multiple periods depending on the property. Periods available include: 1 mo, 2 mo, 3 mo, 6 mo, 9 mo, 12 mo, 1 Yr, 2 Yr, 3 Yr, and 5 Yr. Morningstar symbols cover the NYSE, NASDAQ, AMEX, and BATS exchanges.

In live trading, Morningstar data is delivered to your algorithm at approximately 6 am each day. The majority of the fundamental data update occurs once per month. This includes updates to all of the key information for each security Morningstar supports. On top of this monthly update, there are daily updates of the financial ratios.

As Morningstar data arrives, it updates the master copy and is passed into your algorithm, similar to how TradeBars are fill-forwarded in your data feed. If there have been no updates for a day, you'll receive the same fundamental data.

This dataset depends on the [US Equity Security Master](https://www.quantconnect.com/datasets/quantconnect-us-equity-security-master) dataset because the US Equity Security Master dataset contains information on splits, dividends, and symbol changes.

QuantConnect/LEAN combines the data of this dataset with [US Coarse Universe](https://www.quantconnect.com/datasets/quantconnect-us-coarse-universe-constituents) data in runtime.

For more information about the US Fundamental Data dataset, including CLI commands and pricing, see the [dataset listing](https://www.quantconnect.com/datasets/morning-star-us-fundamentals).

## About the Provider

Morningstar was founded by Joe Mansueto in 1984 with the goal of empowering investors by connecting people to the investing information and tools they need. Morningstar provides access extensive line of products and services for individual investors, financial advisors, asset managers, and retirement plan providers. Morningstar provides data on approximately 525,000 investment offerings including stocks, mutual funds, and similar vehicles, along with real-time global market data on nearly 18 million equities, indexes, futures, options, commodities, and precious metals, in addition to foreign exchange and Treasury markets. Morningstar also offers investment management services through its investment advisory subsidiaries, with $244 billion in assets under advisement or management as of 2021.

## Getting Started

The following snippets demonstrate how to request data from the US Fundamental dataset:

- Direct Access using the Security object

```python
equity = self.add_equity("IBM")
ibm_fundamental = equity.fundamentals
```

- Direct Access using the Symbol object

```python
ibm = Symbol.create("IBM", SecurityType.EQUITY, Market.USA)
ibm_fundamental = self.fundamentals(ibm)
```

- Universe Selection

```python
def initialize(self) -> None:
    self._universe = self.add_universe(self.fundamental_filter_function)

def fundamental_filter_function(self, fundamental: List[Fundamental]):
    filtered = [f for f in fundamental if f.has_fundamental_data and f.price > 10 and not np.isnan(f.valuation_ratios.pe_ratio)]
    sorted_by_pe_ratio = sorted(filtered, key=lambda f: f.valuation_ratios.pe_ratio)
    return [f.symbol for f in sorted_by_pe_ratio[:10]]
```

## Data Summary

The following table describes the dataset properties:

| Property | Value |
| --- | --- |
| Start Date | January 1998 |
| Asset Coverage | 8,000 US Equities* |
| Corporate Indicators / Tracked Fields | 900 Fields |
| Data Density | Sparse |
| Resolution | Daily |
| Timezone | New York |

*The data does not include ETFs, ADRs, or OTC equities.

## Migration

Morningstar retired the Global Equity Data Feeds behind this dataset and replaced them with the Equity Data Feeds. From September 23, 2026, US fundamentals come from the new feeds for the whole history, not just for new data, so backtest results change.

- Of the values both generations carry, about one third differ. Most are figures Morningstar recalculated; the rest come from sign conventions and rounding. Where a value differs, it usually differs by more than 20%.
- Ratios, growth, per-share and average properties are dated by the filing that produced them instead of by the period end, a median of 63 days later. A backtest that reads them no longer sees a figure before it was public, which is what research and live trading already did.
- Price multiples update daily instead of monthly, so they move more often.
- Coverage grows from 8,717 to 9,705 companies. 535 properties are new and 1,251 of the old ones are gone, 358 of which were never populated. A retired property still compiles, but throws when you read it and names its replacement where one exists.

The previous data is deprecated and cannot be kept alongside the new data, so backtests run on it will not reproduce. For the full breakdown of what changed, see [Morningstar Migration](https://www.quantconnect.com/docs/v2/writing-algorithms/universes/equity/morningstar-migration.md).

## Requesting Data

You don't need any special code to request US Fundamental Data. You can access the current and historical fundamental data for any of the US Equities that this dataset includes.

```python
class MorningStarDataAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2021, 1, 1)
        self.set_end_date(2021, 7, 1)
        self.set_cash(100000)
        self.universe_settings.asynchronous = True

        # Option 1: Subscribe to individual US Equity assets
        self.add_equity("IBM")

        # Option 2A: Create a fundamental universe (classic version)
        self._universe = self.add_universe(self.fundamental_function)

        # Option 2B: Create a fundamental universe (framework version)
        self.add_universe_selection(FundamentalUniverseSelectionModel(self.fundamental_function))
```

For more information about universe settings, see [Settings](https://www.quantconnect.com/docs/v2/writing-algorithms/universes/settings.md).

## Accessing Data

If you add a [fundamental universe](https://www.quantconnect.com/docs/v2/writing-algorithms/universes/equity/fundamental-universes.md) to your algorithm, you can access fundamental data in the universe selection function.

```python
def fundamental_function(self, fundamental: List[Fundamental]) -> List[Symbol]:
    return [f.symbol for f in fundamental if f.price > 10 and f.valuation_ratios.pe_ratio > 30]
```

To get fundamental data for Equities in your algorithm, use the `fundamentals` property of the `Equity` objects. The fundamental data represent the corporate fundamentals for the current algorithm time.

```python
fundamentals = self.securities[symbol].fundamentals
```

To get fundamental data for Equities, regardless of whether or not you have subscribed to them in your algorithm, call the `fundamentals` method. If you pass one `Symbol`, the method returns a `Fundamental` object. If you pass a list of `Symbol` objects, the method returns a list of `Fundamental` objects.

```python
# Single asset
ibm = Symbol.create("IBM", SecurityType.EQUITY, Market.USA)
ibm_fundamental = self.fundamentals(ibm)

# Multiple assets
nb = Symbol.create("NB", SecurityType.EQUITY, Market.USA)
fundamentals = self.fundamentals([ nb, ibm ])
```

## Historical Data

You can get historical fundamental data in an algorithm and in the Research Environment.

### Historical Data in Algorithms

To get historical fundamental data in an algorithm, call the `history` method with `Fundamental` type and the Equity `Symbol` or the `Universe` object. If there is no data in the period you request, the history result is empty.

```python
ibm = Symbol.create("IBM", SecurityType.EQUITY, Market.USA)

# DataFrame object where the columns are the Fundamental attributes
asset_df_history = self.history(Fundamental, ibm, timedelta(30), flatten=True)

# Fundamental objects
fundamental_history= self.history[Fundamental](ibm, timedelta(30))

# Fundamentals objects for all US Equities (including delisted companies)
fundamentals_history = self.history[Fundamentals](timedelta(30))

# Multi-index Series objects where the values are lists of Fundamental objects
series_history = self.history(self.universe, 30, Resolution.DAILY)
for (universe_symbol, time), fundamentals in series_history.items():
    highest_market_cap = sorted(fundamentals, key=lambda x: x.market_cap)[-5:]
```

### Historical Data in the Research Environment

To get historical data in the Research Environment, call any of the preceding methods or call the `universe_history` method with the `Universe` object, a start date, and an end date. This method returns the filtered universe. Alternatively, call the `get_fundamental` method with the Equity `Symbol`, a `Fundamental` property, a start date, and an end date. If there is no data in the period you request, the history result is empty.

```python
# DataFrame object where the columns are the Fundamental attributes
universe_history_df = qb.universe_history(universe, qb.time-timedelta(30), qb.time, flatten=True)

# Multi-index Series objects where the values are lists of Fundamental objects
universe_history = qb.universe_history(universe, qb.time-timedelta(30), qb.time)
for (universe_symbol, time), fundamentals in universe_history.items():
    for fundamental in fundamentals:
        print(f"{fundamental.symbol} market cap at {fundamental.end_time}: {fundamental.market_cap}")

# DataFrame of a single Fundamental attribute
history = qb.get_fundamental(symbol, "ValuationRatios.pe_ratios", datetime(2021, 1, 1), datetime(2021, 7, 1))
```

For more information about historical US Equity fundamental data, see [Equity Fundamental Data](https://www.quantconnect.com/docs/v2/research-environment/datasets/equity-fundamental-data.md).

## Example Applications

The US Fundamentals dataset enables you to design strategies harnessing fundamental data points. Examples include the following strategies:

- Ranking a universe of securities by a value factor like the [Piotroski F-score](https://www.quantconnect.com/research/15728/piotroski-f-score-investing) and buying a subset of the universe with the best factor ranking
- Using the Morningstar asset classification to target specific industries or to ensure your strategy is diversified across several sectors
- Trading securities that recently performed an IPO

### Classic Algorithm Example

The following example algorithm creates a dynamic universe of US Equities. The first stage filter selects the 100 most liquid US Equities and the second stage filter selects the 10 assets with the greatest PE ratio. The algorithm then forms an equal-weighted portfolio with the 10 assets in the universe.

```python
from AlgorithmImports import *

class MorningStarDataAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2024, 9, 1)
        self.set_end_date(2024, 12, 31)
        self.set_cash(100000)
        # Seed the price of each asset with its last known price to avoid trading errors.
        self.settings.seed_initial_prices = True
        self.universe_settings.resolution = Resolution.DAILY
        self.universe_size = 10
        # Add universe selection to filter with fundamental data
        self.add_universe(self.fundamental_selection_function)

    def fundamental_selection_function(self, fundamental: List[Fundamental]) -> List[Symbol]:
        # Make sure fundamental data and PE ratio available
        # To avoid penny stocks with high volatility, set price above $1
        selected = [f for f in fundamental if f.has_fundamental_data and f.price > 1 and not np.isnan(f.valuation_ratios.pe_ratio)]
        # Filter the top 100 high dollar volume equities to ensure liquidity
        sorted_by_dollar_volume = sorted(selected, key=lambda f: f.dollar_volume, reverse=True)[:100]
        # Get the top 10 PE Ratio stocks to follow speculations of a large number of capital
        sorted_by_pe_ratio = sorted(sorted_by_dollar_volume, key=lambda f: f.valuation_ratios.pe_ratio, reverse=True)[:self.universe_size]
        return [ f.symbol for f in sorted_by_pe_ratio ]

    def on_data(self, slice: Slice) -> None:
        # if we have no changes, do nothing
        if self._changes is None or not slice.bars: return

        # liquidate removed securities, as not being the most popular stocks anymore
        for security in self._changes.removed_securities:
            if security.invested:
                self.liquidate(security.symbol)

        # we want 1/N allocation in each security in our universe to evenly dissipate risk
        for security in self._changes.added_securities:
            self.set_holdings(security.symbol, 1 / self.universe_size)

        self._changes = None

    def on_securities_changed(self, changes: SecurityChanges) -> None:
        self._changes = changes
```

### Framework Algorithm Example

The following example algorithm creates a dynamic universe of US Equities. The first stage filter selects the 100 most liquid US Equities and the second stage filter selects the 10 assets with the greatest PE ratio. The algorithm then forms an equal-weighted portfolio with the 10 assets in the universe.

```python
from AlgorithmImports import *

class MorningStarDataAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2024, 9, 1)
        self.set_end_date(2024, 12, 31)
        self.set_cash(100000)

        # Add universe selection to filter with fundamental data
        self.universe_settings.resolution = Resolution.DAILY
        self.set_universe_selection(CustomFundamentalUniverseSelectionModel())

        self.set_alpha(ConstantAlphaModel(InsightType.PRICE, InsightDirection.UP, timedelta(1)))

        # we want 1/N allocation in each security in our universe to evenly dissipate risk
        self.set_portfolio_construction(EqualWeightingPortfolioConstructionModel())

        self.add_risk_management(NullRiskManagementModel())

        self.set_execution(ImmediateExecutionModel())

class CustomFundamentalUniverseSelectionModel(FundamentalUniverseSelectionModel):

    def select(self, algorithm: QCAlgorithm, fundamental: List[Fundamental]) -> List[Symbol]:
        # Make sure fundamental data and PE ratio available
        # To avoid penny stocks with high volatility, set price above $1
        # Filter the top 100 high dollar volume equities to ensure liquidity
        sorted_by_dollar_volume = sorted([x for x in fundamental if x.price > 1 and not np.isnan(x.valuation_ratios.pe_ratio)],
            key=lambda x: x.dollar_volume, reverse=True)[:100]
        # Get the top 10 PE Ratio stocks to follow speculations of a large number of capital
        sorted_by_pe_ratio = sorted(sorted_by_dollar_volume, key=lambda x: x.valuation_ratios.pe_ratio, reverse=True)[:10]

        # Take the top entries from our sorted collection
        return [ x.symbol for x in sorted_by_pe_ratio ]
```

### Research Example

The following example selects the 100 most liquid US Equities and lists the 10 assets with the greatest PE ratio.:

```python
qb = QuantBook()

# Add Fundamental Universe Selection
def fundamental_selection_function(fundamentals):
    selected = [f for f in fundamentals if not np.isnan(f.valuation_ratios.pe_ratio)]
    sorted_by_dollar_volume = sorted(selected, key=lambda f: f.dollar_volume, reverse=True)[:100]

    sorted_by_pe_ratio = sorted(sorted_by_dollar_volume,
        key=lambda f: f.valuation_ratios.pe_ratio, reverse=True)[:10]
    return [ f.symbol for f in sorted_by_pe_ratio ]

universe = qb.add_universe(fundamental_selection_function)

# Historical Universe data
universe_history = qb.universe_history(universe, qb.time-timedelta(30), qb.time)
for (universe_symbol, time), fundamentals in universe_history.items():
    for fundamental in fundamentals:
        print(f"{fundamental.symbol} PE ratio volume at {fundamental.end_time}: {fundamental.valuation_ratios.pe_ratio}")
```

## Data Point Attributes

The US Fundamentals dataset provides `Fundamental` objects. To filter `Fundamental` objects, you can use one of the enumeration helpers.

### Fundamental Attributes

`Fundamental` objects have the following attributes:

*Members of `QuantConnect.Data.Fundamental.Fundamental` (JSON): https://www.quantconnect.com/services/inspector?type=T:QuantConnect.Data.Fundamental.Fundamental&language=python*

### MorningstarSectorCode Enumeration

Sectors are large super categories of data. To access the sector of an Equity, use the `MorningstarSectorCode` property.

```python
filtered_fundamentals = [x for x in fundamental
    if x.asset_classification.morningstar_sector_code == MorningstarSectorCode.TECHNOLOGY]
```

The `MorningstarSectorCode` enumeration has the following members:

*Members of `QuantConnect.Data.Fundamental.MorningstarSectorCode` (JSON): https://www.quantconnect.com/services/inspector?type=T:QuantConnect.Data.Fundamental.MorningstarSectorCode&language=python*

### MorningstarIndustryGroupCode Enumeration

Industry groups are clusters of related industries that tie together. To access the industry group of an Equity, use the `MorningstarIndustryGroupCode` property.

```python
filtered_fundamentals = [x for x in fundamental
    if x.asset_classification.morningstar_industry_group_code == MorningstarIndustryGroupCode.APPLICATION_SOFTWARE]
```

The `MorningstarIndustryGroupCode` enumeration has the following members:

*Members of `QuantConnect.Data.Fundamental.MorningstarIndustryGroupCode` (JSON): https://www.quantconnect.com/services/inspector?type=T:QuantConnect.Data.Fundamental.MorningstarIndustryGroupCode&language=python*

### MorningstarIndustryCode Enumeration

Industries are the finest classification level available and are the individual industries according to the Morningstar classification system. To access the industry group of an Equity, use the `MorningstarIndustryCode` property.

```python
filtered_fundamentals = [x for x in fundamental
    if x.asset_classification.morningstar_industry_code == MorningstarIndustryCode.SOFTWARE_APPLICATION]
```

The `MorningstarIndustryCode` enumeration has the following members:

*Members of `QuantConnect.Data.Fundamental.MorningstarIndustryCode` (JSON): https://www.quantconnect.com/services/inspector?type=T:QuantConnect.Data.Fundamental.MorningstarIndustryCode&language=python*

### StockType Enumeration

The Stock Type classification groups companies according to the underlying fundamentals of their business. It answers the question: "If I buy this stock, what kind of company am I buying?" The emphasis is on income statement, balance sheet, and cash-flow data—not price data or valuation multiples. To access the stock type of an Equity, use the `StockType` property.

```python
filtered_fundamentals = [x for x in fundamental
    if x.asset_classification.stock_type == StockType.AGGRESSIVE_GROWTH]
```

The `StockType` enumeration has the following members:

*Members of `QuantConnect.Data.Fundamental.StockType` (JSON): https://www.quantconnect.com/services/inspector?type=T:QuantConnect.Data.Fundamental.StockType&language=python*

### StyleBox Enumeration

The Morningstar Equity Style Box is a grid that provides a graphical representation of the investment style of stocks and portfolios. It classifies securities according to market capitalization (vertical axis) and value-growth scores (horizontal axis). For stocks, the central column represents the core style. To access the style box of an Equity, use the `StyleBox` property.

```python
filtered_fundamentals = [x for x in fundamental
    if x.asset_classification.style_box == StyleBox.LARGE_VALUE]
```

The `StyleBox` enumeration has the following members:

*Members of `QuantConnect.Data.Fundamental.StyleBox` (JSON): https://www.quantconnect.com/services/inspector?type=T:QuantConnect.Data.Fundamental.StyleBox&language=python*

### MorningstarEconomySphereCode Enumeration

Sectors are consolidated into three major economic spheres or Super Sectors: Cyclical, Defensive, and Sensitive. To access the economy sphere (Super Sector) of an Equity, use the `MorningstarEconomySphereCode` property.

```python
filtered_fundamentals = [x for x in fundamental
    if x.asset_classification.morningstar_economy_sphere_code == MorningstarEconomySphereCode.CYCLICAL]
```

The `MorningstarEconomySphereCode` enumeration has the following members:

*Members of `QuantConnect.Data.Fundamental.MorningstarEconomySphereCode` (JSON): https://www.quantconnect.com/services/inspector?type=T:QuantConnect.Data.Fundamental.MorningstarEconomySphereCode&language=python*

### Exchange ID Values

The exchange ID represents the exchange that lists the Equity. To access the exchange ID of an Equity, use the `PrimaryExchangeID` property.

```python
filtered_fundamentals = [x for x in fundamental
    if x.company_reference.primary_exchange_id == "NAS"]
```

The exchanges are represented by the following string values:

| String Representation | Exchange |
| --- | --- |
| NYS | New York Stock Exchange (NYSE) |
| NAS | NASDAQ |
| ASE | American Stock Exchange (AMEX) |
| TSE | Tokyo Stock Exchange |
| AMS | Amsterdam Internet Exchange |
| SGO | Santiago Stock Exchange |
| XMAD | Madrid Stock Exchange |
| ASX | Australian Securities Exchange |
| BVMF | B3 (stock exchange) |
| LON | London Stock Exchange |
| TKS | Istanbul Stock Exchange Settlement and Custody Bank |
| SHG | Shanghai Exchange |
| LIM | Lima Stock Exchange |
| FRA | Frankfurt Stock Exchange |
| JSE | Johannesburg Stock Exchange |
| MIL | Milan Stock Exchange |
| TAE | Tel Aviv Stock Exchange |
| STO | Stockholm Stock Exchange |
| ETR | Deutsche Boerse Xetra Core |
| PAR | Paris Stock Exchange |
| BUE | Buenos Aires Stock Exchange |
| KRX | Korea Exchange |
| SWX | SIX Swiss Exchange |
| PINX | Pink Sheets (OTC) |
| CSE | Canadian Securities Exchange |
| PHS | Philippine Stock Exchange |
| MEX | Mexican Stock Exchange |
| TAI | Taiwan Stock Exchange |
| IDX | Indonesia Stock Exchange |
| OSL | Oslo Stock Exchange |
| BOG | Colombia Stock Exchange |
| NSE | National Stock Exchange of India |
| HEL | Nasdaq Helsinki |
| MISX | Moscow Exchange |
| HKG | Hong Kong Stock Exchange |
| IST | Istanbul Stock Exchange |
| BOM | Bombay Stock Exchange |
| TSX | Toronto Stock Exchange |
| BRU | Brussels Stock Exchange |
| BATS | BATS Global Markets |
| ARCX | NYSE Arca |
| GREY | Grey Market (OTC) |
| DUS | Dusseldorf Stock Exchange |
| BER | Berlin Stock Exchange |
| ROCO | Taipei Exchange |
| CNQ | Canadian Trading and Quotation System Inc. |
| BSP | Bangko Sentral ng Pilipinas |
| NEOE | NEO Exchange |
