Finding ICE intercommodity spreads
Overview
In this example we'll use the Historical client 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 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.
We'll request the definition schema 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
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
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