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.
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
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.
InfoA
scaleof 0.01 reads as cents whenunit_of_measureis 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.
InfoA
scalereached 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