Support

Displaying fractional prices

Overview

CME quotes its grain and treasury products in fractions rather than decimals. A 10-year treasury note trading at 108.578125 is quoted as 108'185, i.e. 108 3764, and corn trading at 498.25 is quoted as 498'2, i.e. 498 28. In this example we will use the Historical client to retrieve instrument definitions and daily bars for several of these products, then render each close price the way the exchange does.

Definition schema

The definition schema describes the convention with three fields, which CME documents under fractional pricing.

Field Description
main_fraction The denominator of the main fraction. 255 when unused.
sub_fraction The denominator of a fraction of one unit of the main fraction. 255 when unused.
price_display_format The number of digits printed to the right of the tick mark.

sub_fraction subdivides one unit of the main fraction, so the product of the two fields give the finest fraction the venue displays. For example, a main_fraction of 32 with a sub_fraction of 2 displays halves of a 32nd, or 64ths. When sub_fraction is unset, the main fraction is the finest unit.

Product main_fraction sub_fraction price_display_format Decimal price Quoted Interpretation
Corn (ZCZ6) 8 unset 1 498.25 498'2 498 28
30-year bond (ZBZ6) 32 unset 2 109.5625 109'18 109 1832
10-year note (ZNZ6) 32 2 3 108.578125 108'185 108 1832 plus half a 32nd, or 108 3764
2-year note (ZTZ6) 32 8 3 102.9453125 102'302 102 3032 plus a quarter of a 32nd, or 102 242256

price_display_format is the total number of digits printed after the tick mark ('), including one digit for the subdivision when sub_fraction is set. The last digit is a decimal rendering of the subdivision rather than its numerator, which is why half of a 32nd prints as 5 in 108'185. That digit is truncated rather than rounded, so a price of 102.9609375, which is 102 and 30 68 32nds, renders as 102'307 and not 102'308.

The finest displayed fraction can be finer than the instrument's tick. Corn futures have a min_price_increment of 0.25, or two eighths, so only even digits appear in their final position.

Products quoted in decimals, such as E-mini S&P 500 futures, leave all three fields unset.

Info
Info

These three fields carry venue-specific meanings. This example applies to GLBX.MDP3, and other datasets may populate them differently, so check the venue documentation before reusing this logic elsewhere.

Example

import databento as db

# The instruments to display. ESU6 is included to show a decimal-quoted product
symbols = ["ZCZ6", "ZBZ6", "ZNZ6", "ZTZ6", "ESU6"]

dataset = "GLBX.MDP3"
date = "2026-08-19"

# Value when unset or null
UNSET = 255


def display_price(price, main_fraction, sub_fraction, price_display_format):
    """Render a price in the venue's own quoting convention, such as 108'185."""
    if main_fraction == UNSET or price_display_format == UNSET:
        return f"{price:g}"

    whole = int(price)

    # The number of main fractions, such as 32nds, in the remainder. Fractional
    # prices land on a power-of-two grid, so this arithmetic is exact
    ticks = (price - whole) * main_fraction
    main = int(ticks)

    if sub_fraction == UNSET:
        return f"{whole}'{main:0{price_display_format}d}"

    # The last digit is the single-digit decimal of the leftover fraction of one main
    # fraction, so a half prints as 5 and three quarters as 7
    digits = max(price_display_format - 1, 0)
    leftover = int((ticks - main) * 10)
    return f"{whole}'{main:0{digits}d}{leftover}"


# First, create a historical client
client = db.Historical(key="YOUR_API_KEY")

# Next, retrieve the instrument definitions
definitions_data = client.timeseries.get_range(
    dataset=dataset,
    schema="definition",
    symbols=symbols,
    start=date,
)

# And extract the three fields that describe the display convention
definitions_df = definitions_data.to_df()
definitions_df = definitions_df.loc[definitions_df["instrument_class"] == db.InstrumentClass.FUTURE, :]
conventions = definitions_df.drop_duplicates("raw_symbol").set_index("instrument_id")[
    ["raw_symbol", "main_fraction", "sub_fraction", "price_display_format"]
]

# Then, request daily bars
ohlcv_data = client.timeseries.get_range(
    dataset=dataset,
    schema="ohlcv-1d",
    symbols=symbols,
    start=date,
)

# And join the bars with the display convention of each instrument
df = ohlcv_data.to_df().join(conventions, on="instrument_id").sort_values("raw_symbol")

# Finally, render each closing price in the venue's convention
df["decimal_close"] = df["close"]
df["display_close"] = df.apply(
    lambda row: display_price(
        row["close"],
        row["main_fraction"],
        row["sub_fraction"],
        row["price_display_format"],
    ),
    axis=1,
)

print(
    df[[
        "raw_symbol",
        "decimal_close",
        "main_fraction",
        "sub_fraction",
        "price_display_format",
        "display_close",
    ]],
)

Result

                          raw_symbol  decimal_close  main_fraction  sub_fraction  price_display_format display_close
ts_event
2026-08-19 00:00:00+00:00       ESU6    7740.000000            255           255                   255          7740
2026-08-19 00:00:00+00:00       ZBZ6     109.562500             32           255                     2        109'18
2026-08-19 00:00:00+00:00       ZCZ6     498.250000              8           255                     1         498'2
2026-08-19 00:00:00+00:00       ZNZ6     108.578125             32             2                     3       108'185
2026-08-19 00:00:00+00:00       ZTZ6     102.945312             32             8                     3       102'302