Support

Computing tick value and contract notional

Overview

The value of a tick and the notional value of a contract can be derived from the contract and tick size in the definition schema. E-mini S&P 500 futures are quoted in index points, crude oil in dollars per barrel, lean hogs in cents per pound, and corn in cents per bushel. In this example we will use the Historical client to derive this information from the definition schema and convert daily closes into contract values.

Definition schema

Field Description
unit_of_measure The unit the contract is measured in, such as BBL for barrels or LBS for pounds.
unit_of_measure_qty The contract size, in the unit_of_measure.
min_price_increment The minimum tick size, in price units.
min_price_increment_amount The value of one tick, with the display factor applied.
display_factor The multiplier from the venue's display price to the conventional price.
Warning
Warning

CME lists tag 1146, which carries min_price_increment_amount, as under development and permits a null value. Treat the tick value and notional below as a first pass and confirm them against the contract specification for instruments you trade.

Three steps take you from these fields to a tick value and a contract value.

scale      = (min_price_increment_amount / display_factor) / (min_price_increment * unit_of_measure_qty)
tick_value = min_price_increment * unit_of_measure_qty * scale
notional   = close * unit_of_measure_qty * scale

scale is the multiplier that turns close * unit_of_measure_qty into the currency named by currency. A value of 1 means the price is already in that currency's major unit per unit of measure, as for E-mini S&P 500 futures at 7740.00 index points with a contract size of 50, giving a notional of 387,000 USD. A value of 0.01 means the price is in hundredths, as for lean hogs at 81.50 cents per pound with a contract size of 40,000 pounds, giving 32,600 USD. The formula for scale reconciles CME's published tick value against the contract terms. When the two agree it gives a power of ten.

Info
Info

A scale of 0.01 reads as cents when unit_of_measure is a physical unit, and as percent of par when it is a currency, as it is for treasuries.

Fractionally quoted products

CME does not publish a usable min_price_increment_amount for the products it quotes in fractions. Corn reports 1.0 against a real tick value of 12.50 USD, and the 10-year note reports 0.001 against 15.625 USD.

These products have fractional pricing, and they are quoted in hundredths: grains are cents per bushel and treasuries are percent of par, so a scale of 0.01 applies to both. Taking that value gives the correct tick value and notional for both.

All fractionally-priced products in CME are listed on CBOT (exchange=XCBT), but there are many non-fractionally priced future assets on CBOT.

Products with a contradictory tick value

For some products, CME publishes a min_price_increment_amount that contradicts the contract size it accompanies. Silver futures (SI.FUT) report 5.00 USD, the tick value of the 1,000-ounce contract (SIL.FUT), against a unit_of_measure_qty of 5,000 ounces. min_price_increment and unit_of_measure_qty are correct here. They give a tick value of 25.00 and a notional of 339,275 USD at a close of 67.855.

Info
Info

A scale reached this way is an inference. Exact reconciliation shows that the amount and the contract terms agree, not that either is right. Check tick values against the venue's contract specifications.

Validating the result

price_scale returns None when the tick amount is missing, or too far from the contract terms to reconcile. The example covers outright futures, and options and spreads need separate handling. A tick size can change during the day. Other datasets populate the field differently, so check the venue documentation before reusing this logic.

Example

import math
import databento as db

# A mix of products quoted in the currency's major unit and in cents
symbols = [
    "ESU6", "CLV6", "GCZ6", "6EU6", "HEV6", "ZLZ6",
    "MZCZ6", "ZCZ6", "ZNZ6", "SIZ6",
]

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

# Value when unset or null
UNSET = 255


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

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

# And extract the fields that describe the contract size and the tick
definitions = definitions.loc[
    definitions["instrument_class"] == db.InstrumentClass.FUTURE
]
contracts = definitions.drop_duplicates("raw_symbol").set_index("instrument_id")[
    [
        "raw_symbol",
        "unit_of_measure",
        "unit_of_measure_qty",
        "main_fraction",
        "min_price_increment",
        "min_price_increment_amount",
        "display_factor",
    ]
]

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

# And join the bars with the contract terms of each instrument
df = bars.join(contracts, on="instrument_id").sort_values("raw_symbol")


# Prices arrive in the currency's major unit or in hundredths of it
CONVENTIONS = (1.0, 0.01)


def nearest_convention(scale):
    """Return the convention nearest scale, or None when it is over ten times off."""
    convention = min(CONVENTIONS, key=lambda c: abs(math.log10(scale / c)))
    if abs(math.log10(scale / convention)) >= 1:
        return None
    return convention


def price_scale(
    main_fraction,
    min_price_increment,
    min_price_increment_amount,
    display_factor,
    unit_of_measure_qty,
):
    """Return the multiplier from price * unit_of_measure_qty to the currency, or None."""
    # Fractionally quoted products are priced in hundredths
    if main_fraction != UNSET:
        return 0.01

    # A scale needs a positive tick, contract size, and tick amount
    terms = (min_price_increment, unit_of_measure_qty, min_price_increment_amount)
    if not all(term > 0.0 for term in terms):
        return None

    tick_value = min_price_increment_amount / display_factor
    contract_tick = min_price_increment * unit_of_measure_qty

    # One tick moves the contract by one tick value
    scale = tick_value / contract_tick

    exponent = round(math.log10(scale))
    if math.isclose(scale, 10.0**exponent, rel_tol=1e-9):
        return 10.0**exponent

    # Otherwise the amount contradicts the contract size, as it does for silver
    return nearest_convention(scale)


# Now, derive the price scale of each contract
df["scale"] = df.apply(
    lambda row: price_scale(
        row["main_fraction"],
        row["min_price_increment"],
        row["min_price_increment_amount"],
        row["display_factor"],
        row["unit_of_measure_qty"],
    ),
    axis=1,
)

# Finally, convert one tick and each close price into currency
df["tick_value"] = df["min_price_increment"] * df["unit_of_measure_qty"] * df["scale"]
df["notional"] = df["close"] * df["unit_of_measure_qty"] * df["scale"]

print(
    df[[
        "raw_symbol",
        "unit_of_measure",
        "unit_of_measure_qty",
        "close",
        "tick_value",
        "scale",
        "notional",
    ]],
)

Result

                          raw_symbol unit_of_measure  unit_of_measure_qty        close  tick_value  scale    notional
ts_event
2026-08-19 00:00:00+00:00       6EU6             EUR             125000.0     1.168450       6.250   1.00  146056.250
2026-08-19 00:00:00+00:00       CLV6             BBL               1000.0    84.300000      10.000   1.00   84300.000
2026-08-19 00:00:00+00:00       ESU6            IPNT                 50.0  7740.000000      12.500   1.00  387000.000
2026-08-19 00:00:00+00:00       GCZ6           TRYOZ                100.0  4569.200000      10.000   1.00  456920.000
2026-08-19 00:00:00+00:00       HEV6             LBS              40000.0    81.500000      10.000   0.01   32600.000
2026-08-19 00:00:00+00:00      MZCZ6              BU                500.0   498.000000       2.500   0.01    2490.000
2026-08-19 00:00:00+00:00       SIZ6           TRYOZ               5000.0    67.855000      25.000   1.00  339275.000
2026-08-19 00:00:00+00:00       ZCZ6              BU               5000.0   498.250000      12.500   0.01   24912.500
2026-08-19 00:00:00+00:00       ZLZ6             LBS              60000.0    69.860000       6.000   0.01   41916.000
2026-08-19 00:00:00+00:00       ZNZ6             USD             100000.0   108.578125      15.625   0.01  108578.125