Source: https://databento.com/docs/examples/instrument-definitions/ice-crack-spreads


# Finding ICE intercommodity spreads

## Overview

In this example we'll use the [Historical client](https://databento.com/docs/api-historical/client/historical.md) to find ICE intercommodity futures spreads, where the legs do not all belong to the same asset.
Crack spreads are a specific type of intercommodity spread.
ICE's [Strategy Code Reference Manual](https://www.ice.com/publicdocs/technology/ICE_Strategy_Code_Reference_Manual.pdf) describes `CRACK` as an exchange-defined spread between two products where one leg is a refined product and the other is an unrefined product.
ICE also lists concrete crack spread contracts such as [RBOB Gasoline/Brent Crack Spread](https://www.ice.com/products/2634472/RBOB-Gasoline-Brent-Crack-Spread).

We'll request the [definition schema](https://databento.com/docs/schemas/instrument-definitions.md) for all symbols in `IFEU.IMPACT`, filter to instruments with `instrument_class` equal to `FUTURE_SPREAD`, and use the leg definition fields to inspect each spread's legs.
For each leg, we'll join `leg_instrument_id` back to the definitions to recover the leg instrument's `asset`.

The example prints the `raw_symbol` of every futures spread where at least one leg has the target asset `BRN`, and the set of leg assets contains more than one asset.

## Example

```python
import databento as db

# Create a historical client
client = db.Historical("$YOUR_API_KEY")

# Set parameters
dataset = "IFEU.IMPACT"
target_asset = "BRN"
date = "2026-05-26"

# Download definition data for all symbols
data = client.timeseries.get_range(
    dataset=dataset,
    symbols="ALL_SYMBOLS",
    schema="definition",
    start=date,
)

# Convert to a DataFrame
df = data.to_df()

# Map each instrument_id to its asset. This lets us look up the asset for each
# leg_instrument_id in a spread definition.
latest_defs = df.drop_duplicates("instrument_id", keep="last")
asset_by_instrument_id = latest_defs.set_index("instrument_id")["asset"]

# In the definition schema, each spread has one row for each leg. The primary
# fields identify the spread, while fields beginning with leg_ identify the leg.
spread_legs = df[
    (df["instrument_class"] == db.InstrumentClass.FUTURE_SPREAD) & (df["leg_count"] > 0)
].copy()
spread_legs = spread_legs.drop_duplicates(
    ["instrument_id", "leg_index"],
    keep="last",
)
spread_legs["leg_asset"] = spread_legs["leg_instrument_id"].map(
    asset_by_instrument_id,
)
spread_legs = spread_legs.dropna(subset=["leg_asset"])

def matches_asset_and_is_intercommodity(legs):
    leg_assets = set(legs["leg_asset"])
    return target_asset in leg_assets and len(leg_assets) > 1

matches = spread_legs.groupby("instrument_id").filter(
    matches_asset_and_is_intercommodity,
)
raw_symbols = matches.drop_duplicates("instrument_id")["raw_symbol"].sort_values()

print(raw_symbols)
```
## Result

```plaintext
ts_recv
2026-05-26 00:00:00+00:00                ADM FMF0027-BRN FMF0027
2026-05-26 00:00:00+00:00                ADM FMG0027-BRN FMG0027
2026-05-26 00:00:00+00:00                ADM FMH0027-BRN FMH0027
2026-05-26 00:00:00+00:00                ADM FMJ0027-BRN FMJ0027
2026-05-26 00:00:00+00:00                ADM FMK0027-BRN FMK0027
                                            ...
2026-05-26 00:00:00+00:00    WBS FYF0028.Z0028-BRN FYF0028.Z0028
2026-05-26 00:00:00+00:00    WBS FYF0029.Z0029-BRN FYF0029.Z0029
2026-05-26 00:00:00+00:00    WBS FYF0030.Z0030-BRN FYF0030.Z0030
2026-05-26 00:00:00+00:00    WBS FYF0031.Z0031-BRN FYF0031.Z0031
2026-05-26 00:00:00+00:00    WBS FYF0032.Z0032-BRN FYF0032.Z0032
Name: raw_symbol, Length: 436, dtype: str
```
