# Exploring Availability of Market Data for CME (Derivatives)

{% embed url="<https://www.youtube.com/watch?v=kiiuqkptxZU>" %}

{% embed url="<https://github.com/coinmetrics/demo/blob/master/cme_exploration.py>" %}

### Instructions

The notebook linked above shows how to explore data from CME (Chicago Mercantile Exchange), one of the big derivatives exchanges. Options on derivatives are probably the most complicated market instruments available on Coin Metrics, so this may be particularly interesting!

This notebook linked above is in [Marimo](https://marimo.io/) format. The code below is more readable, but does not preserve the cell breaks. We recommend using Marimo as new, modern Jupyter environment.

```python
from coinmetrics.api_client import CoinMetricsClient
import os
import marimo as mo
from datetime import datetime, timedelta, time, timezone
import matplotlib.pyplot as plt
import pandas as pd

client = CoinMetricsClient(os.getenv('CM_API_KEY'))

end_time = datetime.now(tz=timezone.utc)
start_time = end_time - timedelta(days=60)


cme = client.reference_data_markets(exchange='cme').to_dataframe()
cme


cme.loc[(cme.pair=='btc-usd') & (cme.expiration >= end_time)].groupby(['expiration', 'pair', 'type', 'contract_size'], observed=True).agg({
    'strike': ['count', 'min', 'max'],
    'market': ['count', 'first']
})


my_markets = cme.loc[(cme.symbol.apply(len)==5) 
    & (cme.expiration >= end_time)
    & (cme.size_asset.isin(['btc', 'eth']))
    ].sort_values(['expiration', 'size_asset']).loc[:, ['expiration', 'symbol', 'market']]
my_markets.set_index('symbol')


client.catalog_market_candles_v2(markets=list(my_markets.market)).to_dataframe().set_index(['market', 'frequency'])

df = client.get_market_candles(markets=['cme-BTCM5-future',  ],
                         start_time=start_time,
                         frequency='1d').to_dataframe() # 'cme-BTCK5-future', 'cme-BTCM5-future',




# Ensure we have a datetime index or 'time' column
if not isinstance(df.index, pd.DatetimeIndex):
    if 'time' in df.columns:
        _df_time = pd.to_datetime(df['time'])
    else:
        raise ValueError("No datetime index or 'time' column found.")
else:
    _df_time = df.index

# Cumulative sum of volume per day, starting at midnight
_df = df.copy()
_df['__date'] = _df_time.dt.date
_df['vol_current_day_'] = _df.groupby(['market','__date'])['volume'].cumsum()
_df = _df.drop(columns='__date')

_df



import plotly.graph_objs as go

candles_90 = df.sort_index().iloc[-90:].copy()
# If the index is not a DatetimeIndex, reset and use time column if available
if not isinstance(candles_90.index, pd.DatetimeIndex):
    if 'time' in candles_90.columns:
        candles_90['time'] = pd.to_datetime(candles_90['time'])
    else:
        # fallback to numeric index as x axis
        candles_90['time'] = candles_90.index

# Candle chart
fig = go.Figure()

fig.add_trace(go.Candlestick(
    x=candles_90.get('time', candles_90.index),
    open=candles_90['price_open'],
    high=candles_90['price_high'],
    low=candles_90['price_low'],
    close=candles_90['price_close'],
    name="Price",
    increasing_line_color='green',
    decreasing_line_color='red',
))

fig.add_trace(go.Bar(
    x=candles_90.get('time', candles_90.index),
    y=candles_90['volume'],
    name='Volume',
    marker_color='steelblue',
    opacity=0.35,
    yaxis='y2',
))

# Layout for dual y-axis
fig.update_layout(
    title="CME Candle Chart with Volume (BTCM5=June 2025 epxiry)",
    yaxis_title="Price",
    xaxis_title="Time",
    yaxis2=dict(title='Volume', overlaying='y', side='right', showgrid=False),
    xaxis_rangeslider_visible=False,
    height=500,
    legend=dict(orientation='h', yanchor="bottom", y=1.02, xanchor="right", x=1)
)

fig



client.catalog_market_contract_prices_v2(exchange='cme').to_dataframe()

client.catalog_market_open_interest_v2(exchange='cme').to_dataframe()

client.catalog_market_implied_volatility_v2(exchange='cme').to_dataframe()

client.catalog_market_funding_rates_v2(exchange='cme').to_dataframe()

client.catalog_market_greeks_v2(exchange='cme').to_dataframe()

ob = client.catalog_market_orderbooks_v2(markets=list(my_markets.market),
                         ).to_list()
ob[0]

unpack = []

for m in ob:
    for de in m['depths']:
        unpack.append(
            {
                "market": m['market'],
                "depth": de['depth'],
                "min_time": de['min_time'],
                "max_time": de['max_time'],
            }
        )
pd.DataFrame(unpack)

EAM = client.catalog_exchange_asset_metrics_v2().to_dataframe()

EAM.loc[(EAM.metric.str.contains('future')) & (EAM.exchange_asset.str.startswith('cme-'))]

EAM.loc[(EAM.metric.str.contains('option')) & (EAM.exchange_asset.str.startswith('cme-'))]

import plotly.express as px

# Prepare data
metric_name = "volume_reported_option_notional_usd_1d"
exchange_asset = "cme-usd"
freq = "1d"
series_px = client.get_exchange_asset_metrics(
    metrics=[metric_name], 
    frequency=freq, 
    exchange_assets=[exchange_asset],
).to_dataframe().reset_index()
series_px['time'] = pd.to_datetime(series_px['time'])

# Find top 3
top3 = series_px.nlargest(3, metric_name)

# Plot
fig_px = px.line(
    series_px,
    x='time',
    y=metric_name,
    title="CME Reported Option Notional Volume (Top 3 Labeled)",
    labels={
        "time": "Time",
        metric_name: "Option Notional Volume (USD)"
    },
    markers=True
)

# Add explicit text labels for top 3 values
for _, row in top3.iterrows():
    fig_px.add_annotation(
        x=row['time'],
        y=row[metric_name],
        text=f"{row['time'].date().isoformat()}/{row[metric_name]/1e6:,.0f} mUSD",
        showarrow=True,
        arrowhead=2,
        ay=-40,
        font=dict(color="crimson", size=13)
    )

fig_px.update_traces(line_color="indigo", marker=dict(size=7))
fig_px.update_layout(yaxis_title="Option Notional Volume (USD)", xaxis_title="Time")
fig_px
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://gitbook-docs.coinmetrics.io/tutorials-and-examples/tutorials/exploring-availability-of-market-data-for-cme-derivatives.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
