Identifying the Front Month in Futures Data
Kibot ships individual contract files (ESH26, ESM26, ESU26, ESZ26) and a single continuous file per root (ES). A recurring support question is how to know which individual contract is the "active" front month at any given date, and how the continuous file's prices map to the underlying contract on each side of a roll. This page gives the practical answers: how the roll date is computed, which symbol is active on which date, and the join patterns customers use to reconcile or rebuild their own continuous series.
The Definition: What "Front Month" Means in Kibot Files
In Kibot's continuous file, the front-month contract on any given trading day is the contract that the continuous series is currently glued to. That is determined by the calendar-based rollover rule for the root (see Rollover rules for the per-root offset table). The continuous file does not include a column naming the underlying contract, but the underlying contract on any date can be reconstructed deterministically from the rollover offset and the contract expiration calendar.
For example, the ES (E-mini S&P 500) rule is "roll 8 trading days before expiration" against the quarterly Mar/Jun/Sep/Dec cycle. On a given Wednesday in late February, the continuous ES file is showing the March contract (ESH) until 8 trading days before its third-Friday expiration, then switches to the June contract (ESM) for the rest of March and into April, May, and June.
Computing the Active Contract for a Date
The algorithm is deterministic given two inputs: the per-root rollover offset (in trading days) and the contract expiration calendar.
# Pseudocode: which contract is active on a given date?
def active_contract(root, date, expirations, offset_days):
# expirations is a sorted list of (contract_symbol, expiration_date)
# offset_days is the per-root rollover offset (e.g. 8 for ES)
for symbol, exp_date in expirations:
roll_date = exp_date - trading_days(offset_days)
if date < roll_date:
return symbol
return None
The expirations list per root is published in the Futures expirations page with dates calculated through 2030. The per-root offset table is in Rollover rules. With those two inputs and a trading-day calendar (NYSE holidays plus weekends), the active contract can be computed for any historical or forward date.
Joining the Individual and Continuous Files at a Roll
The continuous file's price at the roll date is the new contract's price, not the old contract's. The continuous file is unadjusted: there is no back-fill or ratio-adjustment to smooth the gap. So at a roll date in the continuous file, the customer will see a one-bar price discontinuity equal to the calendar spread between the old and new contracts on that date.
Example: if ES rolls from ESH26 to ESM26 on March 12 2026, the continuous bar for March 11 shows ESH26's settle (say 5210.50) and the continuous bar for March 12 shows ESM26's settle (say 5188.75). The 21.75-point gap is the calendar spread, not a data error.
To rebuild a ratio-adjusted or Panama-style continuous series, the customer keeps the unadjusted continuous file as the price spine and applies their own back-adjustment factor at each roll boundary. The boundaries are the dates where the unadjusted file's bar-to-bar change exceeds the typical daily move for the contract, which corresponds to the dates computed from the offset table.
Verifying the Roll Against Individual Contracts
A useful sanity check: on the roll date, the continuous file's price should match the new contract's individual file price, not the old. This is a one-line check per roll:
# Verify: at the roll date, continuous == new_contract
continuous_on_roll = continuous.loc[roll_date, "close"]
new_contract_on_roll = ESM26.loc[roll_date, "close"]
assert continuous_on_roll == new_contract_on_roll
For every published Kibot continuous series, this check holds on every roll date. Customers who run it across the full archive sometimes catch roll-date drift in their own calendar code (off-by-one on the trading-day count, or wrong holiday list); the deterministic match against Kibot's roll-date table is the canonical reference.
When the Calendar-Based Roll Does Not Match Liquidity
For most products and most cycles, the calendar-based offset places the roll within a day or two of where open interest actually shifts to the back month. For some products (especially less liquid futures or new contract listings), the calendar roll can fire one or two days before or after the open-interest crossover. Kibot uses the calendar rule rather than a volume- or OI-based heuristic for the reasons covered in Rollover rules: predictability and reproducibility over multiple decades.
Customers who need the volume-crossover roll instead can override Kibot's roll dates with their own, joining the individual contract files at whichever date their OI rule produces. The individual contract files are unchanged; only the continuous file embeds the calendar rule.
Other "Active Contract" Questions
A few related questions that surface in support:
- Why does the front month look quiet on the day of the roll? Because by roll date the bulk of liquidity has already moved to the back month. The old front month's last days are thinly traded; the new front month's first day in the continuous series is where the action is.
- Can I get a continuous file for the second-month, third-month, or N-month forward? Kibot's standard continuous file is front-month only. Custom multi-month continuous files (second-month always, third-month always) can be quoted on request. The same offset arithmetic applies, shifted by N expirations.
- How are VIX futures handled, since they expire weekly in the late series? The VIX rule is documented separately in Rollover rules with the VIX-specific calendar.
- Currency continuous (EU, GB, JY): is the front month always the next quarterly? Yes for the majors. The currency offset is published per root in the rollover table; most are 2 to 4 trading days before expiration.
Key Takeaways
- The active contract on any date is computed deterministically from the per-root rollover offset and the contract expiration calendar. Both are published.
- Kibot's continuous file is unadjusted: at the roll date the bar-to-bar price gap is the calendar spread between old and new contracts, not a data error.
- To verify a roll, compare the continuous price on the roll date to the new individual contract's price on the same date; they should match exactly.
- Calendar-based rolls usually land within a day or two of the open-interest crossover. Customers needing the OI-based roll can override Kibot's dates and rejoin the individual contract files themselves.
- Second-month, third-month, and N-month-forward continuous files are not in the standard catalog but can be produced on request from the same individual contract data.
Related
- Rollover rules, the per-root offset table and the rationale for calendar-based versus heuristic rolls.
- Continuous futures, how the continuous series is constructed from individual contracts and what adjustment choices the customer can layer on top.
- Futures expirations, expiration rules by contract group with pre-computed dates through 2030.
- Futures symbols, month codes and the F-Z calendar used to name individual contracts.
- Futures specifications, contract size, tick value, and exchange per root.
- Trading hours, the session window that defines a daily bar for each contract.