Support

Join options with underlying prices

Info
Info

This example builds off the Join schemas on instrument ID example.

Overview

In this example we will request trades data for all front month outright options and join them with the most recent quote for the underlying future.

Example

import databento as db
import pandas as pd

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

# Set parameters
dataset = "GLBX.MDP3"
symbol = "CL.c.0"
start = "2023-04-03T13:00:00"
end = "2023-04-03T13:10:00"

# Get symbol mapping for the continuous contract
symbol_map = client.symbology.resolve(
    dataset=dataset,
    symbols=symbol,
    stype_in="continuous",
    stype_out="instrument_id",
    start_date="2023-04-03",
)

# Get instrument ID for the front month future
front_month_id = int(symbol_map["result"][symbol][0]["s"])

# Get all option definitions, starting from Sunday
def_data = client.timeseries.get_range(
    dataset=dataset,
    schema="definition",
    symbols=["LO.OPT"],
    stype_in="parent",
    start="2023-04-02",
)

# Convert to DataFrame
def_df = def_data.to_df()

# Filter for options on the front month future
opt_def_df = def_df[
    (def_df["user_defined_instrument"] == db.UserDefinedInstrument.NO) &
    (def_df["instrument_class"].isin((db.InstrumentClass.CALL, db.InstrumentClass.PUT))) &
    (def_df["underlying_id"] == front_month_id)
]

# Get trades data for options on the front month future
opt_trades_df = client.timeseries.get_range(
    dataset=dataset,
    schema="trades",
    symbols=opt_def_df["instrument_id"].to_list(),
    stype_in="instrument_id",
    start=start,
    end=end,
).to_df()

# Get MBP-1 data for the front month future
fut_mbp_df = client.timeseries.get_range(
    dataset=dataset,
    schema="mbp-1",
    symbols=front_month_id,
    stype_in="instrument_id",
    start=start,
    end=end,
).to_df()
fut_mbp_df = fut_mbp_df[["bid_px_00", "ask_px_00"]]
fut_mbp_df = fut_mbp_df.sort_index()

# Join options with their definitions
opt_df = opt_trades_df.merge(
    opt_def_df,
    on="instrument_id",
    how="inner",
    suffixes=("", "_def"),
).set_index("ts_event")
opt_df = opt_df.sort_index()

# Join most recent underlying bid/ask with options trades
df = pd.merge_asof(
    opt_df,
    fut_mbp_df,
    left_index=True,
    right_index=True,
    direction="backward",
)

# Rename the columns
df = df.rename(
    columns={
        "ask_px_00": "underlying_ask",
        "bid_px_00": "underlying_bid",
    },
)

print(df[["strike_price", "instrument_class", "price", "underlying_bid", "underlying_ask"]].head())

Result

                                     strike_price instrument_class  price  underlying_bid  underlying_ask
ts_event
2023-04-03 13:00:05.464491127+00:00          75.5                P   0.81           80.24           80.25
2023-04-03 13:00:10.275423815+00:00          80.0                P   2.26           80.22           80.24
2023-04-03 13:00:30.917505675+00:00          72.0                P   0.34           80.19           80.20
2023-04-03 13:00:30.927198369+00:00          72.0                P   0.34           80.18           80.19
2023-04-03 13:01:15.044222777+00:00          75.0                P   0.75           80.01           80.03