Source: https://databento.com/docs/datasets/glbx-mdp3


# CME Globex MDP 3.0

**Dataset ID**: [GLBX.MDP3]($PLATFORM_HOSTNAME/catalog/cme/GLBX.MDP3)

The CME Group disseminates full depth-of-book data for CME, CBOT, NYMEX, and COMEX through their MDP 3.0 feed, which Databento receives over UDP multicast in our DC3 datacenter.
Databento provides full coverage of all futures and options on futures beginning in June 2010.

In May 2017, CME introduced MDP 3.0, which provides full granularity for every order event (MBOFD) in addition to providing aggregated depth at a limited number of price levels (MBP).

Before May 2017, data was based on the legacy FIX/FAST protocol.

CME makes the specifications of their MDP 3.0 feed available [on their website here](https://www.cmegroup.com/confluence/display/EPICSANDBOX/CME+MDP+3.0+Market+Data).

### Timestamps

CME MDP 3.0 messages received by Databento will generally include two timestamps with nanosecond precision.
As with all of our datasets, we also collect a `ts_recv` timestamp when the packet was received by our capture server.

| Databento Field | MDP 3.0 Tag | Description |
| `ts_recv` | N/A | The capture-server-received timestamp. |
| `ts_event` | 60-TransactTime | The matching-engine-received timestamp. |
| `ts_in_delta` | 52-SendingTime | The matching-engine-sending timestamp. |

More details about our timestamps are available in our [timestamping guide](https://databento.com/docs/architecture/timestamping-guide.md).

### MBO normalization

**`F_LAST` flag in MBO**

When interpreting MBO data, the `F_LAST` [flag](https://databento.com/docs/conventions/common-fields-enums-types.md#flags) (`0x80`, 128) is used to mark the last record in a single event for each `instrument_id`.
This flag is based on CME's "End of event" flag in tag 5799-MatchEventIndicator.
However, CME only sets this flag on one single message, even if the event spanned multiple instruments.
Instead, we set the `F_LAST` flag on the last record for _each_ instrument, so that the data can be interpreted consistently with any subset of instruments.
Records with `action` **N**one may carry `F_LAST`.

Across all of Databento's feeds, it is important to use the `F_LAST` flag when calculating the best bid and offer, like our MBP-1 schema.
Between records *without* the `F_LAST` flag, the book is in the process of updating, and the apparent best bid and offer may have already been traded.

This is accounted for when we construct our other schemas, such as MBP-1 and Trades.
Outside of MBO, this flag can be ignored.

**Order events**

Records in the [MBO schema](https://databento.com/docs/schemas/mbo.md) with **A**dd, **M**odify, and **C**ancel actions are normalized from [Market Data Incremental Refresh - MBOFD](https://www.cmegroup.com/confluence/display/EPICSANDBOX/MDP+3.0+-+Market+Data+Incremental+Refresh+-+MBOFD),
and records with **T**rade and **F**ill actions are normalized from [Market Data Incremental Refresh - Trade Summary](https://www.cmegroup.com/confluence/display/EPICSANDBOX/MDP+3.0+-+Market+Data+Incremental+Refresh+-+Trade+Summary) messages,
and records with the clea**R** action are normalized from [Market Data Incremental Refresh - Channel Reset](https://www.cmegroup.com/confluence/display/EPICSANDBOX/MDP+3.0+-+Market+Data+Incremental+Refresh+-+Channel+Reset) messages.

**Trade events**

The MBO schema includes detailed information about both sides of the trade by normalizing [Market Data Incremental Refresh - Trade Summary](https://www.cmegroup.com/confluence/display/EPICSANDBOX/MDP+3.0+-+Market+Data+Incremental+Refresh+-+Trade+Summary) messages from CME into **T**rade and **F**ill actions.
The [MBP-n and trades schemas](https://databento.com/docs/schemas/mbp-1.md) include **T**rade records, but do not include **F**ill detail records.

Each CME MDP 3.0 [Market Data Incremental Refresh - Trade Summary](https://www.cmegroup.com/confluence/display/EPICSANDBOX/MDP+3.0+-+Market+Data+Incremental+Refresh+-+Trade+Summary) message from CME contains two repeating groups: a set of *trade summaries*, followed by a set of *order ID entries*.
Each trade summary in the message is normalized into one **T**rade record.
If there is a defined aggressor for the trade, its corresponding order ID entry from the second set is used to populate the `order_id` field.
This commonly happens when an incoming order partially executes, leaving the remaining quantity to rest on the book.

Following each **T**rade record, the remaining (passive) order ID entries are normalized into **F**ill records.
These records correspond to resting orders in the order book, but **do not** modify the orders.

If the aggressing order existed on the book, then a **F**ill record will be emitted for it.
This can happen if a resting order was modified to cross the book.
If the aggressing order did not already exist on the book then its **F**ill record is suppressed, however its order ID is still reported in the **T**rade record as described above.

**Side**

[Implied trades](https://www.cmegroup.com/confluence/display/EPICSANDBOX/MDP+3.0+-+Implied+Book) may not have an aggressing side set.
These trades will be normalized with [side](https://databento.com/docs/conventions/common-fields-enums-types.md#side) set to **N**one.

**Order Priority**

Although Databento does not expose tag 37707-MDOrderPriority in the MBO schema, first in, first out priority (FIFO) can be determined from message order.
Messages for a single `instrument_id` are never reordered, even if they have the same timestamps.
Our daily MBO snapshots also preserve FIFO order priority.

**CME MBO snapshot**

At the beginning of the weekly trading session, CME publishes a MBO order snapshot.
This snapshot contains any orders that persisted from the previous trading session, such as Good 'Till Cancelled orders.
The event timestamp (`ts_event`) for these orders corresponds to the time the snapshot is generated by CME.
It does not reflect the original time the order was entered or last modified.

These orders are not published by CME in priority order.
As Databento does not expose tag 37707-MDOrderPriority, if these MBO records were published by Databento in the same order they were sent from CME, it would not be possible to determine the correct order priority.
In order to publish the records in priority order, Databento buffers the orders from the first CME event of the trading session, per instrument.

Once the End of Event is reached, Databento sorts the records in priority order and then publishes them.

Therefore, the order priority is correctly reflected by the order of publishing.

The `ts_recv` for these records will be set to the `ts_recv` of the final record of the event.
As the records have been slightly delayed and the `ts_recv` of the initial records may not match the original `ts_recv`, the flag `F_BAD_TS_RECV` is set on these records.

The `F_SNAPSHOT` flag is also set on these records to indicate that they are from the CME snapshot.

**Weekly Sessions**

Although CME pauses trading daily, the market follows a weekly session structure with most instruments accepting orders from Sunday night to Friday night (local time).
To make it easier to work with historical MBO data, Databento includes an [order book snapshot](https://databento.com/docs/conventions/mbo-snapshot.md) at 00:00:00 UTC each weekday (Monday-Friday).

Before the trading session begins, or during the daily pause, it is normal for order books to be locked or crossed: CME will accept orders but won't execute any trades until the opening uncrossing.

Details about the trading hours and sessions for each product group are available on the [Trading hours](https://www.cmegroup.com/trading-hours.html) page of CME's website.

### Implied book

In futures and options markets, implied depth allows for extra liquidity beyond what's visible in the order book for a specific instrument. It is derived from the relationships between different instruments, such as between outrights, spreads, or multi-leg options. CME's matching engine uses implied depth to construct liquidity, ensuring that even if a direct order isn't placed, the system can infer potential liquidity from other related contracts.

CME's MDP3 feed has support for implied orders over their MBP feed. The MBP feed provides up to 10 levels of real liquidity and 2 levels of implied liquidity.
Databento combines the real and implied books, publishing the merged top-of-book on the [CMBP-1](https://databento.com/docs/schemas/mbp-1.md#consolidated-market-by-price-cmbp-1) schema. Databento also provides subsampled views of the merged top-of-book on the [CBBO-1s and CBBO-1m](https://databento.com/docs/schemas/bbo.md#consolidated-bbo-on-interval-cbbo) schemas.

CME provides [documentation and examples](https://cmegroupclientsite.atlassian.net/wiki/spaces/EPICSANDBOX/pages/457095346/Implied+Orders) for the implied book.

### Statistics normalization

Databento normalizes the following daily statistics from [Market Data Incremental Refresh - Daily Statistics](https://www.cmegroup.com/confluence/display/EPICSANDBOX/MDP+3.0+-+Market+Data+Incremental+Refresh+-+Daily+Statistics):

- Settlement price
- Cleared volume
- Open interest
- Fixing price

The exact times these statistics are published will vary.
Cleared volume and open interest statistics will normally publish on the following UTC date, unless they are for Friday's session, in which case they will be published on the following Sunday.
Settlement price statistics will first publish shortly after the [settlement window](https://cmegroupclientsite.atlassian.net/wiki/spaces/EPICSANDBOX/pages/457085528/Daily+Settlement+Time+Details) for an instrument.
The CME does not publish settlement prices on their MDP feed for instruments without open interest or volume.

Databento normalizes the following session statistics from [Market Data Incremental Refresh - Session Statistics](https://www.cmegroup.com/confluence/display/EPICSANDBOX/MDP+3.0+-+Market+Data+Incremental+Refresh+-+Session+Statistics):

- Opening and indicative opening price
- Trading session high and low price
- Trading session highest bid and lowest offer

These statistics are published throughout the trading session as the values change.

**Price limits**

Databento normalizes the `HighLimitPrice` and `LowLimitPrice` fields of the Limits Banding message into upper price limit and lower price limit statistics.
Both statistics are published on every limits banding update, using tag 60-TransactTime as `ts_event`.

**Reference timestamp (`ts_ref`)**

CME includes tag 5796-TradingReferenceDate, the trading session date, with daily statistics.
This field is normalized to `ts_ref` as a nanosecond-precision UNIX timestamp for consistency with other timestamps.
Because the source only has date precision, users should avoid localizing `ts_ref` to their time zone.

**Multiple records for the same date**

CME often publishes multiple messages for the same trading session date (indicated by `ts_ref`) and daily statistic.
The initial messages indicate preliminary values, and the final message for the trading session date indicates the final value.
The final message is always the most accurate and the one you should use, when available.

**Stat flags**

Settlement price statistics normalize the [bit field](https://en.wikipedia.org/wiki/Bit_field) [tag 731-SettlPriceType](https://www.cmegroup.com/confluence/display/EPICSANDBOX/MDP+3.0+-+Settlement+Price) to the `stat_flags` field.

| Value | Decimal | Description |
| `1 << 0` | 1 | Whether the settlement price is final, as opposed to preliminary. |
| `1 << 1` | 2 | Whether the settlement price is actual, as opposed to theoretical. |
| `1 << 2` | 4 | Some products have a different trading tick size than their clearing tick size. 1 if settling at the trading tick and 0 if at the clearing tick. |
| `1 << 3` | 8 | Whether the price is an intraday settlement price and disseminated before the official end-of-day settlement calculation. |

[The CME documentation on settlement prices](https://www.cmegroup.com/confluence/display/EPICSANDBOX/Settlement+Prices#SettlementPrices-SettlementatTradingTick/SettlementatClearingTick) expands on the meaning of each flag value.
Settlement prices before 2015-11-20 follow different rules, described under [MDP 2 data](https://databento.com/docs/datasets/glbx-mdp3.md#mdp-2-data).

### Symbology

Databento normalizes the `asset` field from tag 6937-Asset of the [Market Data Security Definition](https://cmegroupclientsite.atlassian.net/wiki/spaces/EPICSANDBOX/pages/457672532/MDP+3.0+-+Security+Definition) message.
The `asset` field is used when requesting data with [parent symbology](https://databento.com/docs/conventions/symbology.md#parent).

Databento normalizes the `raw_symbol` field from tag 55-Symbol of the Security Definition message.
This symbol contains the product code, followed by the [month code](https://www.cmegroup.com/month-codes.html), followed by the year.
Previously, this field would only contain a 1-digit year, e.g. `ESZ3` for the E-mini S&P 500 December 2023 contract.
In some recently listed contracts, CME has begun using a 2-digit year, e.g. `NGN25` for the Henry Hub Natural Gas July 2025 contract.

### Definition normalization

**FX spots**

CME lists foreign exchange spot instruments alongside futures.
Databento sets `instrument_class` to `X` (FX spot) for instruments whose CFI code begins with `IF`.
The `cfi` and `security_type` fields are passed through from CME unchanged.

**Instrument attributes**

CME publishes a [bit field](https://en.wikipedia.org/wiki/Bit_field) of instrument attributes in tag 872-InstAttribValue, normalized to the `inst_attrib_value` field.

| Value | Description |
| `1 << 0` | Whether the instrument is eligible for electronic matching. |
| `1 << 1` | Whether the instrument is eligible for order cross. |
| `1 << 2` | Whether the instrument is eligible for block trades. |
| `1 << 3` | Whether the instrument is EFP eligible. |
| `1 << 4` | Whether the instrument is EBF eligible. |
| `1 << 5` | Whether the instrument is EFS eligible. |
| `1 << 6` | Whether the instrument is EFR eligible. |
| `1 << 7` | Whether the instrument is OTC eligible. |
| `1 << 8` | Whether the instrument is eligible for iLink indicative mass quoting. |
| `1 << 9` | Whether the instrument may have a negative strike price. |
| `1 << 10` | Whether the outright instrument may have a negative price. |
| `1 << 11` | Whether prices for the instrument are displayed as fractions. |
| `1 << 12` | Whether the option is quoted in volatility. |
| `1 << 13` | Whether the instrument is eligible for RFQ cross. |
| `1 << 14` | Whether the outright instrument may have a price of zero. |
| `1 << 15` | Whether the product is a decaying product. |
| `1 << 16` | Whether the product is a variable product. |
| `1 << 17` | Whether the product is a daily product. |
| `1 << 18` | Whether the instrument accepts good-til orders. |
| `1 << 19` | Whether the instrument is eligible for implied matching. |
| `1 << 20` | Whether the instrument is eligible for triangulation. |
| `1 << 21` | Whether the instrument is eligible for a variable cabinet price. |
| `1 << 22` | Whether the instrument's book is inverted. |
| `1 << 23` | Whether the instrument is all-or-none. |
| `1 << 24` | Whether the instrument is SEF regulated. |
| `1 << 25` | Whether the instrument is MTF regulated. |
| `1 << 26` | Whether the instrument is an EFIX instrument. |
| `1 << 27` | Whether the instrument is a hedge instrument. |

[The CME MDP 3.0 documentation](https://www.cmegroup.com/confluence/display/EPICSANDBOX/CME+MDP+3.0+Market+Data) expands on the meaning of each attribute.

`1 << 11` pertains to how a price is displayed and marks instruments CME quotes in the exchange's [fractional convention](https://cmegroupclientsite.atlassian.net/wiki/spaces/EPICSANDBOX/pages/457092591/Fractional+Pricing), and pairs with the `main_fraction`, `sub_fraction`, and `price_display_format` fields.
The [Displaying fractional prices](https://databento.com/docs/examples/instrument-definitions/fractional-prices.md) example renders prices using these fields.

### Spreads and combos

In addition to futures and options on futures, this dataset also contains data for both exchange-listed spreads and [user-defined spreads (UDS)](https://www.cmegroup.com/confluence/display/EPICSANDBOX/User+Defined+Spread+-+UDS).

Spreads and combinations consisting only of futures (such as exchange-listed calendar spreads) are considered part of the futures [parent symbols](https://databento.com/docs/conventions/symbology.md#parent).
For example, `ESH4-ESZ4` is a calendar spread contained in `ES.FUT`.
These spreads can have negative prices.

Spreads and combinations containing options (such as butterfly or covered spreads) are considered part of the option [parent symbols](https://databento.com/docs/conventions/symbology.md#parent).
For example, `UD:1V: VT 2533938` is a vertical option spread contained in `ES.OPT`.

[The CME documentation on spreads and combinations](https://www.cmegroup.com/confluence/display/EPICSANDBOX/Spreads+and+Combinations+Available+on+CME+Globex) contains an exhaustive list of the different spread types.
The `instrument_class` field in the definition schema can be used to identify spread instruments generically.
The `SecuritySubType` field in the exchange documentation is normalized to the `secsubtype` field in the `definition` schema and can be used to identify the exchange-specific spread type.

To identify the parent symbol of strategies and user-defined spreads, the `asset` field in the definition schema should be used.

**Leg definitions**

Databento publishes one definition record per leg of a spread or combination.
The records for an instrument are identical apart from the fields beginning with `leg_`, which describe a single leg.
`leg_count` is the number of legs and `leg_index` is the 0-based index of the leg the record describes.

| Databento field | MDP 3.0 tag | Description |
| `leg_count` | 555-NoLegs | The number of legs in the spread. |
| `leg_index` | N/A | The 0-based index of the leg within the spread. |
| `leg_instrument_id` | 602-LegSecurityID | The instrument ID of the leg instrument. |
| `leg_side` | 624-LegSide | The side taken for the leg when buying the spread. |
| `leg_ratio_qty_numerator` | 623-LegRatioQty | The quantity of the leg instrument per unit of the spread. |
| `leg_ratio_qty_denominator` | N/A | Always 1 for this dataset. |
| `leg_price` | 566-LegPrice | The tied price of the leg, used for hedged strategies. |
| `leg_delta` | 1017-LegOptionDelta | The delta of the leg, used for hedged strategies. |
| `leg_raw_symbol` | N/A | Taken from the leg instrument's own definition. |
| `leg_instrument_class` | N/A | Taken from the leg instrument's own definition. |
| `leg_underlying_id` | N/A | Taken from the leg instrument's own definition. |

The `leg_ratio_price_numerator` and `leg_ratio_price_denominator` fields are not populated for this dataset.

CME can publish the definition of a spread before the definitions of its legs.
Until the leg instrument's own definition arrives, the fields taken from it are unset.
Databento then republishes the affected leg records with `security_update_action` set to **M**odify.

### Status normalization

Status records are normalized from [Market Data Security Status](https://cmegroupclientsite.atlassian.net/wiki/x/JbtAGw) messages.
A single status message from CME may update the status of all instruments in a `group`, all instruments in a `group` and `asset`, or an individual instrument.
To support requesting data for individual instruments, Databento normalizes all these messages into instrument-level status messages.
When requesting status schema data for multiple instruments in the same `group` or `asset`, there will be status records that are identical minus the `instrument_id`.

The state fields of the status schema: `is_trading`, `is_quoting`, and `is_short_sell_restricted` are based solely on the status updates from CME.
Group-level status updates generate a status record for each instrument with a definition, regardless of activation or expiration.
As a result, the status state fields (`is_trading` and `is_quoting`) may be incorrect before activation or after expiration.

### Matching Algorithms

CME implements various [matching algorithms](https://databento.com/docs/schemas/instrument-definitions.md#matching-algorithm) across its universe of products, with **F**IFO being the most common.

Specific details on the different algorithms can be found on the [Supported Matching Algorithms page](https://cmegroupclientsite.atlassian.net/wiki/spaces/EPICSANDBOX/pages/457218479/Supported+Matching+Algorithms) on the CME website.

### Flags normalization

The `F_PUBLISHER_SPECIFIC` flag provides no additional meaning in this dataset and can be safely ignored.

### MDP 2 data

On 2017-05-21, CME introduced full granularity for every order event (MBOFD).
Data prior to this date is based on the MDP 2, level-aggregated FIX protocol.
This leads to some differences in the data.

**Timestamps**

MDP 2 data is sourced from FIX flat files.
Because of this, capture timestamps (commonly available as `ts_recv`) are not available.
The `ts_recv` field on all MDP 2 data is set to the same value as `ts_event`.

Because of this, all records on MDP 2 data have the `F_BAD_TS_RECV` flag set.
This is normal and expected.

Nanosecond-resolution timestamps have been introduced by CME on 2015-11-20.
Timestamps prior to that date are limited to millisecond resolution.

| Databento Field | CME Tag | Description |
| `ts_recv` | 52-SendingTime | The matching-engine-sending timestamp. |
| `ts_event` | 52-SendingTime | The matching-engine-sending timestamp. |

**MBO format**

MDP 2 data predates the introduction of full-depth MBO by CME.
Because of this, the MBO schema is not available.
The highest granularity schema available for MDP 2 data is MBP-10.

**CMBP-1 format**

The CMBP-1, CBBO-1s, and CBBO-1m schemas are not available for MDP 2 data.

**Settlement prices**

Before 2015-11-20, CME sent the settlement price type in tag 286-OpenCloseSettlFlag instead of tag 731-SettlPriceType.

For products not subject to settlement price rounding, a `stat_flags` value of 4 marks an unrounded preliminary price rather than settlement at the trading tick.

Final settlement prices before 2015-11-20 come from the weekly security definition replay CME sent each Sunday, which covers the last trading session of the week.
From 2015-11-20, CME sent tag 731-SettlPriceType on daily updates, which include final settlement prices.

**Status schema**

There's significantly less status data prior to 2015; this is expected.
Before November 2015, status changes from the normal trading schedule did not result in a status message.
