Source: https://databento.com/docs/examples/basics-historical/requesting


# Request a large number of symbols

> **Info**
>
> If you're new to Databento, see the [Quickstart guide](https://databento.com/docs/quickstart.md) for a walkthrough on setting up our live and historical APIs.
>
Databento supports several ways for you to get multiple symbols in a single request.

If you're interested in a large universe of symbols, we recommend you use any of these supported approaches and filter the symbols on client side as opposed to requesting one symbol at a time. This minimizes the number of requests, which will usually give you better performance.

## Getting all symbols with `"ALL_SYMBOLS"`

The simplest way to do this is to get all symbols of a given dataset. Passing in `"ALL_SYMBOLS"` as the `symbols` argument will give you every listed symbol.

```python
import databento as db

client = db.Historical("$YOUR_API_KEY")

data = client.timeseries.get_range(
    dataset="XNAS.ITCH",
    schema="trades",
    symbols="ALL_SYMBOLS",
    start="2024-05-21T15:00",
    end="2024-05-21T15:01",
)

df = data.to_df()

print(f"{len(df):,d} trade(s) for {len(df['instrument_id'].unique()):,d} instrument(s)")
```
```plaintext
31,405 trade(s) for 2,854 instrument(s)
```
This works for live subscriptions as well, which gives you a firehose subscription to all symbols:

```python
import databento as db

client = db.Live("$YOUR_API_KEY")

client.subscribe(
    dataset="XNAS.ITCH",
    schema="ohlcv-1s",
    symbols="ALL_SYMBOLS",
)
```
Our live data gateways are capable of delivering every book event on most venues--like a direct feed, except over internet. You'll usually run into bandwidth limitations long before our gateway runs into other practical limits. If your application requires real-time data of all symbols at the granularity of the `trades` schema or more, we recommend you to look into our supported options for [dedicated connectivity](https://databento.com/docs/architecture/dedicated-connectivity-guide.md).

## Getting multiple, specific symbols

If you're only interested in a subset of specific symbols, you can pass in a list of symbols--this works for all symbology types. We support a maximum of 2,000 symbols in a single request.

```python
import databento as db

client = db.Historical("$YOUR_API_KEY")

data = client.timeseries.get_range(
    dataset="XNAS.ITCH",
    schema="trades",
    symbols=["AAPL", "MSFT", "NVDA"],
    start="2024-05-21T15:00",
    end="2024-05-21T15:01",
)
```
Likewise, this works for live subscriptions as well:

```python
import databento as db

client = db.Live("$YOUR_API_KEY")

client.subscribe(
    dataset="XNAS.ITCH",
    schema="ohlcv-1s",
    symbols=["AAPL", "MSFT", "NVDA"],
)
```
If you need more than 2,000 symbols in a single request, you can split your symbol list and dispatch multiple requests, but in such situations we usually encourage you to fetch all symbols and discard unwanted symbols on client side, even if it may cost more.

There's a practical reason for this recommendation and why we limit to the number of symbols you can specify in this manner. While it may seem unintuitive, selecting specific symbols is usually a much slower operation than requesting all symbols, because our servers have to validate your symbol list, resolve any parent symbols into their child instruments, and inspect each event if it qualifies your selection.

## Getting all child instruments using parent symbology

For futures and options data, there's often a need to get all symbols with the same underlying or all symbols that share the same product root. We allow you to reference such a product or cluster of symbols with the same underlying using a **parent symbol**.

To specify a parent symbol for futures, you can pass in `"parent"` as the input symbology argument, `stype_in`. You must append the `.FUT` suffix to the symbol:

> **See also**
>
> For more on parent symbology, see the [Symbology](https://databento.com/docs/conventions/symbology.md#parent) guide.

```python
import databento as db

client = db.Historical("$YOUR_API_KEY")

data = client.timeseries.get_range(
    dataset="GLBX.MDP3",
    schema="trades",
    stype_in="parent",
    symbols=["ES.FUT", "NQ.FUT"],
    start="2024-05-21T15:00",
    end="2024-05-21T15:01",
)

df = data.to_df()

print(f"{len(df):,d} trade(s) for {len(df['instrument_id'].unique()):,d} instrument(s)")
```
```plaintext
1,101 trade(s) for 4 instrument(s)
```
We can also use parent symbology for options with the `.OPT` suffix:

```python
import databento as db

client = db.Historical("$YOUR_API_KEY")

data = client.timeseries.get_range(
    dataset="OPRA.PILLAR",
    schema="trades",
    stype_in="parent",
    symbols=["QQQ.OPT", "VIX.OPT"],
    start="2024-05-21T15:00",
    end="2024-05-21T15:01",
)

df = data.to_df()

print(f"{len(df):,d} trade(s) for {len(df['instrument_id'].unique()):,d} instrument(s)")
```
```plaintext
1,021 trade(s) for 146 instrument(s)
```
Common use cases of parent symbology include fetching [option chains](https://databento.com/docs/examples/options/equity-options-introduction.md#using-parent-symbology-to-fetch-an-option-chain), all outrights and expirations of a futures product, or all maturities of a fixed income product.

> **See also**
>
> See the [0DTE symbols](https://databento.com/docs/examples/options/zero-dte-options.md) example on how to filter instruments based on `expiration`.


# Request a large number of symbols

> **Info**
>
> If you're new to Databento, see the [Quickstart guide](https://databento.com/docs/quickstart.md) for a walkthrough on setting up our live and historical APIs.
>
Databento supports several ways for you to get multiple symbols in a single request.

If you're interested in a large universe of symbols, we recommend you use any of these supported approaches and filter the symbols on client side as opposed to requesting one symbol at a time. This minimizes the number of requests, which will usually give you better performance.

## Getting all symbols with `Symbols::All`

The simplest way to do this is to get all symbols of a given dataset.
Passing in `Symbols::All` as the `symbols` argument will give you every listed symbol.

```rust
use std::collections::HashSet;

use databento::{
    HistoricalClient, Symbols,
    dbn::{Dataset, Schema, TradeMsg},
    historical::timeseries::GetRangeParams,
};
use time::macros::datetime;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let mut client = HistoricalClient::builder().key_from_env()?.build()?;

    let mut data = client
        .timeseries()
        .get_range(
            &GetRangeParams::builder()
                .dataset(Dataset::XnasItch)
                .schema(Schema::Trades)
                .symbols(Symbols::All)
                .date_time_range(datetime!(2024-05-21 15:00 UTC)..datetime!(2024-05-21 15:01 UTC))
                .build(),
        )
        .await?;
    let trades = data.decode_records::<TradeMsg>().await?;
    let instruments = trades
        .iter()
        .map(|trade| trade.hd.instrument_id)
        .collect::<HashSet<_>>();
    println!(
        "{} trades for {} instruments",
        trades.len(),
        instruments.len()
    );
    Ok(())
}
```
```plaintext
31405 trades for 2854 instruments
```
This works for live subscriptions as well, which gives you a firehose subscription to all symbols:

```rust
use databento::{
    LiveClient, Symbols,
    dbn::{Dataset, Schema},
    live::Subscription,
};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let mut client = LiveClient::builder()
        .key_from_env()?
        .dataset(Dataset::XnasItch)
        .build()
        .await?;

    client
        .subscribe(
            Subscription::builder()
                .symbols(Symbols::All)
                .schema(Schema::Ohlcv1S)
                .build(),
        )
        .await?;

    Ok(())
}
```
Our live data gateways are capable of delivering every book event on most venues--like a direct feed, except over internet.
You'll usually run into bandwidth limitations long before our gateway runs into other practical limits.
If your application requires real-time data of all symbols at the granularity of the `Trades` schema or more, we recommend you to look into our supported options for [dedicated connectivity](https://databento.com/docs/architecture/dedicated-connectivity-guide.md).

## Getting multiple, specific symbols

If you're only interested in a subset of specific symbols, you can pass in a list of symbols--this works for all symbology types.
We support a maximum of 2,000 symbols in a single request.

```rust
use databento::{
    HistoricalClient,
    dbn::{Dataset, Schema},
    historical::timeseries::GetRangeParams,
};
use time::macros::datetime;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let mut client = HistoricalClient::builder().key_from_env()?.build()?;

    let _data = client
        .timeseries()
        .get_range(
            &GetRangeParams::builder()
                .dataset(Dataset::XnasItch)
                .schema(Schema::Trades)
                .symbols(["AAPL", "MSFT", "NVDA"])
                .date_time_range(datetime!(2024-05-21 15:00 UTC)..datetime!(2024-05-21 15:01 UTC))
                .build(),
        )
        .await?;
    Ok(())
}
```
Likewise, this works for live subscriptions as well:

```rust
use databento::{
    LiveClient,
    dbn::{Dataset, Schema},
    live::Subscription,
};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let mut client = LiveClient::builder()
        .key_from_env()?
        .dataset(Dataset::XnasItch)
        .build()
        .await?;

    client
        .subscribe(
            Subscription::builder()
                .symbols(["AAPL", "MSFT", "NVDA"])
                .schema(Schema::Ohlcv1S)
                .build(),
        )
        .await?;

    Ok(())
}
```
If you need more than 2,000 symbols in a single request, you can split your symbol list and dispatch multiple requests, but in such situations we usually encourage you to fetch all symbols and discard unwanted symbols on client side, even if it may cost more.

There's a practical reason for this recommendation and why we limit to the number of symbols you can specify in this manner.
While it may seem unintuitive, selecting specific symbols is usually a much slower operation than requesting all symbols, because our servers have to validate your symbol list, resolve any parent symbols into their child instruments, and inspect each event if it qualifies your selection.

## Getting all child instruments using parent symbology

For futures and options data, there's often a need to get all symbols with the same underlying or all symbols that share the same product root.
We allow you to reference such a product or cluster of symbols with the same underlying using a **parent symbol**.

To specify a parent symbol for futures, you can pass in `SType::Parent` as the input symbology argument, `stype_in`. You must append the `.FUT` suffix to the symbol:

> **See also**
>
> For more on parent symbology, see the [Symbology](https://databento.com/docs/conventions/symbology.md#parent) guide.

```rust
use std::collections::HashSet;

use databento::{
    HistoricalClient,
    dbn::{Dataset, SType, Schema, TradeMsg},
    historical::timeseries::GetRangeParams,
};
use time::macros::datetime;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let mut client = HistoricalClient::builder().key_from_env()?.build()?;

    let mut data = client
        .timeseries()
        .get_range(
            &GetRangeParams::builder()
                .dataset(Dataset::GlbxMdp3)
                .schema(Schema::Trades)
                .stype_in(SType::Parent)
                .symbols(["ES.FUT", "NQ.FUT"])
                .date_time_range(datetime!(2024-05-21 15:00 UTC)..datetime!(2024-05-21 15:01 UTC))
                .build(),
        )
        .await?;
    let trades = data.decode_records::<TradeMsg>().await?;
    let instruments = trades
        .iter()
        .map(|trade| trade.hd.instrument_id)
        .collect::<HashSet<_>>();
    println!(
        "{} trades for {} instruments",
        trades.len(),
        instruments.len()
    );
    Ok(())
}
```
```plaintext
1101 trades for 4 instruments
```
We can also use parent symbology for options with the `.OPT` suffix:

```rust
use std::collections::HashSet;

use databento::{
    HistoricalClient,
    dbn::{Dataset, SType, Schema, TradeMsg},
    historical::timeseries::GetRangeParams,
};
use time::macros::datetime;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let mut client = HistoricalClient::builder().key_from_env()?.build()?;

    let mut data = client
        .timeseries()
        .get_range(
            &GetRangeParams::builder()
                .dataset(Dataset::OpraPillar)
                .schema(Schema::Trades)
                .stype_in(SType::Parent)
                .symbols(["QQQ.OPT", "VIX.OPT"])
                .date_time_range(datetime!(2024-05-21 15:00 UTC)..datetime!(2024-05-21 15:01 UTC))
                .build(),
        )
        .await?;
    let trades = data.decode_records::<TradeMsg>().await?;
    let instruments = trades
        .iter()
        .map(|trade| trade.hd.instrument_id)
        .collect::<HashSet<_>>();
    println!(
        "{} trades for {} instruments",
        trades.len(),
        instruments.len()
    );
    Ok(())
}
```
```plaintext
1021 trades for 146 instruments
```
Common use cases of parent symbology include fetching [option chains](https://databento.com/docs/examples/options/equity-options-introduction.md#using-parent-symbology-to-fetch-an-option-chain), all outrights and expirations of a futures product, or all maturities of a fixed income product.
