---
title: "Legacy Fundamental Universes"
description: "This API for Universe Selection was deprecated on November 2023 but you can still use it."
canonical: https://www.quantconnect.com/docs/v2/writing-algorithms/universes/equity/legacy-fundamental-universes
markdown: https://www.quantconnect.com/docs/v2/writing-algorithms/universes/equity/legacy-fundamental-universes.md
language: python
source: https://github.com/QuantConnect/Documentation/tree/master/03%20Writing%20Algorithms/12%20Universes/03%20Equity/06%20Legacy%20Fundamental%20Universes
modified: 2026-10-31
index: https://www.quantconnect.com/llms.txt
---

# Legacy Fundamental Universes

[Documentation](https://www.quantconnect.com/docs/v2.md) > [Writing Algorithms](https://www.quantconnect.com/docs/v2/writing-algorithms.md) > Universes > [Equity](https://www.quantconnect.com/docs/v2/writing-algorithms/universes/equity.md) > Legacy Fundamental Universes

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

## Introduction

> Warning: This API for Universe Selection was deprecated on November 2023. Please refer to the [new Fundamental Universe API](https://www.quantconnect.com/docs/v2/writing-algorithms/universes/equity/fundamental-universes.md).

There are several ways to create an Equities universe. You can select a universe based on `CoarseFundamental` data or the constituents of an ETF, and then you can further filter your universe down with corporate fundamentals. The following sections explain each of these techniques in detail.

## Coarse Universe Selection

A coarse universe enables you pick a set of stocks based on their trading volume, price, or whether they have fundamental data. To add a coarse universe, in the `initialize` method, pass a filter function to the `add_universe` method. The coarse filter function receives a list of `CoarseFundamental` objects and must return a list of `Symbol` objects. The `Symbol` objects you return from the function are the constituents of the universe and LEAN automatically creates subscriptions for them. Don't call `add_equity` in the filter function.

```python
class MyCoarseUniverseAlgorithm(QCAlgorithm):
    def initialize(self) -> None:
        self.universe_settings.asynchronous = True
        self.add_universe(self._coarse_filter_function)

    def _coarse_filter_function(self, coarse: List[CoarseFundamental]) -> List[Symbol]:
        sorted_by_dollar_volume = sorted(coarse, key=lambda x: x.dollar_volume, reverse=True)
        return [c.symbol for c in sorted_by_dollar_volume[:100]]
```

`CoarseFundamental` objects have the following attributes:

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

The total number of stocks in the [US Equity Security Master dataset](https://www.quantconnect.com/datasets/quantconnect-us-equity-security-master) is 30,000 but your coarse filter function won't receive all of these at one time because the US Equity Security Master dataset is free of survivorship bias and some of the securities have delisted over time. The number of securities that are passed into your coarse filter function depends on the date of your algorithm. Currently, there are about 10,000 securities that LEAN passes into your coarse filter function.

## Fundamentals Selection

A fundamental universe lets you select stocks based on corporate fundamental data. This data is powered by [Morningstar®](https://www.quantconnect.com/datasets/morning-star-us-fundamentals) and includes approximately 8,100 tickers with 900 properties each. This universe doesn't include ETFs, ADRs, or OTC equities. Due to the sheer volume of information, fundamental selection is performed on the output of another universe filter. Think of this process as a 2-stage filter. An initial filter function selects a set of stocks and then a fine fundamental filter function selects a subset of those stocks.

![Fundamental selection process](https://cdn.quantconnect.com/docs/i/filters.png)

*QuantConnect Coarse and Fine Universe Selection*

To add a fundamental universe, in the `initialize` method, pass two filter functions to the `add_universe` method. The first filter function can be a [coarse universe filter](https://www.quantconnect.com/docs/v2/writing-algorithms/universes/equity/legacy-fundamental-universes.md#02-Coarse-Universe-Selection), [dollar volume filter](https://www.quantconnect.com/docs/v2/writing-algorithms/universes/equity/liquidity-universes.md), or an [ETF constituents filter](https://www.quantconnect.com/docs/v2/writing-algorithms/universes/equity/etf-constituents-universes.md). The second filter function receives a list of `FineFundamental` objects and must return a list of `Symbol` objects. The list of `FineFundamental` objects contains a subset of the `Symbol` objects that the first filter function returned. The `Symbol` objects you return from the second function are the constituents of the fundamental universe and LEAN automatically creates subscriptions for them. Don't call `add_equity` in the filter function.

Tip:

Only 8,100 assets have fundamental data. If your first filter function receives `CoarseFundamental` data, you should only select assets that have a true value for their `has_fundamental_data` property.

```python
class MyUniverseAlgorithm(QCAlgorithm):
    def initialize(self) -> None:
        self.universe_settings.asynchronous = True
        self.add_universe(self._coarse_filter_function, self._fine_fundamental_function)

    def _coarse_filter_function(self, coarse: List[CoarseFundamental]) -> List[Symbol]:
        # In addition to further coarse universe selection, ensure the security has fundamental data
        return [c.symbol for c in coarse if c.has_fundamental_data]

    def _fine_fundamental_function(self, fine: List[FineFundamental]) -> List[Symbol]:
        # Return a list of Symbols
        return []
```

`FineFundamental` objects have the following attributes:

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

### Example

The simplest example of accessing the fundamental object would be harnessing the iconic PE ratio for a stock. This is a ratio of the price it commands to the earnings of a stock. The lower the PE ratio for a stock, the more affordable it appears.

```python
# In Initialize:
self.universe_settings.asynchronous = True
self.add_universe(self._coarse_selection_function, self._fine_selection_function)

def _coarse_selection_function(self, coarse: List[CoarseFundamental]) -> List[Symbol]:
    sorted_by_dollar_volume = sorted(coarse, key=lambda x: x.dollar_volume, reverse=True)
    filtered = [x.symbol for x in sorted_by_dollar_volume if x.has_fundamental_data]
    return filtered[:50]

def _fine_selection_function(self, fine: List[FineFundamental]) -> List[Symbol]:
    sorted_by_pe_ratio = sorted(fine, key=lambda x: x.valuation_ratios.pe_ratio, reverse=False)
    return [x.symbol for x in sorted_by_pe_ratio[:10]]
```

### Asset Categories

In addition to valuation ratios, the [US Fundamental Data from Morningstar](https://www.quantconnect.com/datasets/morning-star-us-fundamentals) has many other data point attributes, including over 200 different categorization fields for each US stock. Morningstar groups these fields into sectors, industry groups, and industries.

Sectors are large super categories of data. To get the sector of a stock, use the `MorningstarSectorCode` property.

```python
tech = [x for x in fine if x.asset_classification.morningstar_sector_code == MorningstarSectorCode.TECHNOLOGY]
```

Industry groups are clusters of related industries that tie together. To get the industry group of a stock, use the `MorningstarIndustryGroupCode` property.

```python
ag = [x for x in fine if x.asset_classification.morningstar_industry_group_code == MorningstarIndustryGroupCode.AGRICULTURE]
```

Industries are the finest level of classification available. They are the individual industries according to the Morningstar classification system. To get the industry of a stock, use the `MorningstarIndustryCode`.

```python
coal = [x for x in fine if x.asset_classification.morningstar_industry_code == MorningstarSectorCode.COAL]
```

### Practical Limitations

Like coarse universes, fine universes allow you to select an unlimited universe of assets to analyze. Each asset in the universe consumes approximately 5MB of RAM, so you may quickly run out of memory if your universe filter selects many assets. If you backtest your algorithms in the Algorithm Lab, familiarize yourself with the RAM capacity of your [backtesting](https://www.quantconnect.com/docs/v2/cloud-platform/organizations/resources.md#02-Backtesting-Nodes) and [live trading nodes](https://www.quantconnect.com/docs/v2/cloud-platform/organizations/resources.md#04-Live-Trading-Nodes). To keep your algorithm fast and efficient, only subscribe to the assets you need.

## Live Trading Considerations

The live data for fundamental universe selection arrives at 6/7 AM Eastern Time (ET), so fundamental universe selection runs for live algorithms between 7 and 8 AM ET. This timing allows you to place trades before the market opens. Don't schedule anything for midnight because the universe selection data isn't ready yet.

## Examples

The legacy fundamental universe is deprecated. For examples of the new fundamental universe API, see [Examples](https://www.quantconnect.com/docs/v2/writing-algorithms/universes/equity/fundamental-universes.md#99-Examples).
