Lesson 1.2.3 · 65 min
Futures: specifications, margin, roll and contango
A future is a standardized commitment to buy or sell an asset on a date at a price set today. Nothing is paid on entry: collateral is deposited and the differences are collected or paid every day. This lesson takes apart a fictitious index contract, FIX, with seven years of settlement prices for all its expiries.
- Module
- 1.2 · Asset classes
- Duration
- 65 min
- Prerequisites
- 1.1.5 · Costs, settlement, leverage and margin, 1.2.1 · Stocks: splits, dividends and corporate actions
- Author
- Jesús Cuesta
- Updated
Level 1 lessons
1.1 · How markets work
1.2 · Asset classes
- 1.2.1 Stocks: splits, dividends and corporate actions
- 1.2.2 ETFs: replication, tracking error, leveraged ETFs and UCITS
- 1.2.3 Futures: specifications, margin, roll and contango
- 1.2.4 Forex: pairs, pips, lots, rollover and CFDs
- 1.2.5 Options: calls, puts, intrinsic value and time value
- 1.2.6 Crypto: spot, perpetuals, funding and custody
- 1.2.7 Fixed income and interest rates; CFDs and leveraged products
1.3 · Market data sources
- 1.3.1 Types of market data: EOD, bars, ticks, order book and reference
- 1.3.2 Free market data sources
- 1.3.3 Retail and prosumer market data APIs
- 1.3.4 Professional market data providers
- 1.3.5 Crypto and on-chain data
- 1.3.6 Brokers as market data sources
- 1.3.7 Market data licensing and terms of use
- 1.3.8 How to choose a market data provider
1.4 · Financial data engineering
- 1.4.1 Downloading over REST and websockets: pagination, rate limits and retries
- 1.4.2 Data cleaning: missing values, bad ticks, gaps and time zones
- 1.4.3 Adjusting for splits and dividends: adjusted and unadjusted prices
- 1.4.4 Universes without survivorship bias: delistings, mergers and symbol changes
- 1.4.5 Building bars: time, tick, volume, dollar and imbalance
- 1.4.6 Continuous futures series: roll rules, difference adjustment and ratio adjustment
- 1.4.7 Storage: CSV, Parquet, partitioning, DuckDB, TimescaleDB and ArcticDB
- 1.4.8 Reproducible pipeline: download, validation, incremental updates and quality tests
1.5 · Fundamental and macro data
1.6 · Financial exploratory analysis
1.7 · Programmed technical analysis
A standardized contract
A future is a contract by which two parties commit to buy and sell an asset (the underlying) on a future date (the expiry) at a price set today. Unlike a private forward contract (forward, lesson 1.2.4), a future is traded on an exchange, with identical terms for everyone, and a central counterparty stands between buyer and seller (lesson 1.1.1). The only thing that is negotiated is the price; everything else is set by the contract specifications.
The course data includes a fictitious future, FIX, on a price index of stocks (without dividends). Its specifications:
import numpy as np
import pandas as pd
esp = pd.read_csv("fix_especificaciones.csv").iloc[0]
print(esp.drop("regla_vencimiento").to_string())
print(esp["regla_vencimiento"])multiplicador 50
tick 0.25
valor_tick 12.5
margen_inicial 16500
margen_mantenimiento 15000
meses H,M,U,Z
tercer viernes del mes del contrato (si no hay sesión, la anterior); liquidación final en efectivo al cierre del índice ese día; último día de negociación = vencimientoEach field answers a question:
| Field | Question | FIX |
|---|---|---|
| Underlying | On what? | FIX price index |
| Multiplier | How much is one point worth? | 50 USD |
| Tick | What is the minimum price change? | 0.25 points |
| Tick value | How much is gained or lost per tick and contract? | 0.25 × 50 = 12.50 USD |
| Months | Which expiries are there? | March, June, September, December (H, M, U, Z) |
| Expiry | Which day? | Third Friday of the month (or the previous session) |
| Final settlement | How is it closed out? | In cash, at the index close that day |
| Margins | What collateral is deposited? | 16,500 USD initial, 15,000 maintenance |
The month codes (H March, M June, U September, Z December) are the convention of US exchanges; the FIXH24 contract
is the March 2024 one. With a price and the specifications, everything else can be calculated:
indice = pd.read_csv("fix_indice_diario.csv", parse_dates=["fecha"],
index_col="fecha")["indice"]
S = indice["2025-06-02"]
nominal = S * esp["multiplicador"]
print(f"Index: {S:.2f} notional of one contract: {nominal:,.0f} USD")
print(f"Initial margin: {esp['margen_inicial']:,} USD"
f" = {esp['margen_inicial'] / nominal:.1%} of notional")
print(f"Leverage: {nominal / esp['margen_inicial']:.1f} to 1")
print(f"1% of the index: {0.01 * nominal:,.0f} USD per contract")Index: 6359.10 notional of one contract: 317,955 USD
Initial margin: 16,500 USD = 5.2% of notional
Leverage: 19.3 to 1
1% of the index: 3,180 USD per contractOne contract controls 317,955 USD of index with 16,500 of collateral: leverage of 19.3 to 1. A 1% move in the index is 3,180 USD, almost a fifth of the margin. To size a futures position you always have to think in notional, never in margin (lesson 0.1.2).
Real contracts follow the same scheme. Some figures from their official specifications:
| Contract | Multiplier | Tick | Expiry and final settlement |
|---|---|---|---|
| E-mini S&P 500 (CME) | 50 USD × index | 0.25 points = 12.50 USD | Cash; special opening quotation of the index on the third Friday of the month |
| IBEX 35 future (MEFF) | 10 EUR × index | Set by circular | Third Friday; average of the index from 16:15 to 16:45, one value per minute |
| Mini IBEX 35 future (MEFF) | 1 EUR × index | 5 points = 5 EUR | Third Friday; same as the IBEX 35 |
FIX mimics the E-mini S&P 500 in multiplier and tick. The difference is in the final settlement: in the E-mini it is not the index close but a special quotation calculated with the opening prices of its stocks on expiry day (rule 35803.A of chapter 358), and trading in the expiring contract ends when the NYSE session starts that day. At MEFF, the daily settlement price of the first expiry is the volume-weighted average of the order book trades between 17:29 and 17:30. Details like these matter when comparing a future with its index on the expiry date.
Many live contracts at once
Every day several expiries of the same future trade. fix_contratos.parquet has one row per session and contract,
with the daily settlement price (the one the clearing house sets at the close to calculate profits and losses), the
volume and the open interest (live contracts, not closed out):
fut = pd.read_parquet("fix_contratos.parquet")
fut["dias"] = (fut["vencimiento"] - fut["fecha"]).dt.days
dia = fut[fut["fecha"] == "2025-06-02"]
dia[["contrato", "vencimiento", "dias", "liquidacion", "volumen",
"interes_abierto"]] contrato vencimiento dias liquidacion volumen interes_abierto
4867 FIXM25 2025-06-20 18 6367.75 315854 786283
4868 FIXU25 2025-09-19 109 6419.00 4406 24548
4869 FIXZ25 2025-12-19 200 6462.50 729 3201On June 2, 2025 there are three live expiries. The June one, 18 days out, concentrates almost everything: 786,283 contracts of open interest versus 24,548 for the September one. It is the front month. The others exist, but hardly anyone trades them until their turn approaches.
The header figure is the “ladder” of 2024 and 2025: each contract trades for about nine months, but it is only the front month during the last three. The thick line marks when each one has the largest open interest. They all expire on a Friday:
venc = fut.groupby("contrato")["vencimiento"].first()
venc = venc[venc.dt.year == 2025]
pd.DataFrame({"vencimiento": venc.dt.date,
"dia": venc.dt.day_name()}) vencimiento dia
contrato
FIXH25 2025-03-21 Friday
FIXM25 2025-06-20 Friday
FIXU25 2025-09-19 Friday
FIXZ25 2025-12-19 FridayMargin and daily settlement
Buying a future does not cost its notional. Buyer and seller deposit collateral, the initial margin, and from then on the clearing house settles every day the difference between today's settlement price and yesterday's (mark to market): the winning side collects and the losing side pays, in cash, before the next session. The example in the MEFF specifications sums it up: buying 30 IBEX 35 futures at 10,000 with a settlement of 10,020 at the end of the session gives (10,020 − 10,000) × 30 × 10 = +6,000 euros that day.
Mermaid source
flowchart LR C[Buyer] --> MC[Member] V[Seller] --> MV[Member] MC -- daily settlement --> K[Clearing house] MV -- daily settlement --> K
If the losses leave the account balance below the maintenance margin, the broker issues a margin call: cash has to be deposited until the account is back at the initial margin. If it is not deposited, the broker closes the position.
Mermaid source
stateDiagram-v2 [*] --> Open Open --> Call: balance below minimum Call --> Open: deposits cash Call --> Closed: does not deposit Open --> Closed: sold or expires Closed --> [*]
With the FIX settlement prices, the margin account of a long in the March 2025 contract can be simulated, opened on December 16, 2024 and held until expiry:
def cuenta_margen(precios, contratos=1, lado=1):
"""Margin account balance with daily settlement.
lado = 1 for a long, -1 for a short. If the balance falls below the
maintenance margin, whatever is needed to return to the initial
margin is deposited.
"""
saldo, filas = float(esp["margen_inicial"]) * contratos, []
anterior = precios.iloc[0]
for fecha, precio in precios.items():
puntos = lado * (precio - anterior)
pyg = puntos * esp["multiplicador"] * contratos
saldo += pyg
aporte = 0.0
if saldo < esp["margen_mantenimiento"] * contratos:
aporte = esp["margen_inicial"] * contratos - saldo
saldo += aporte
filas.append((fecha, precio, pyg, aporte, saldo))
anterior = precio
cols = ["liquidacion", "pyg", "aporte", "saldo"]
tabla = pd.DataFrame(filas, columns=["fecha"] + cols)
return tabla.set_index("fecha")
h25 = fut[fut["contrato"] == "FIXH25"].set_index("fecha")["liquidacion"]
cm = cuenta_margen(h25.loc["2024-12-16":])
cm.loc["2025-02-26":"2025-03-07"] liquidacion pyg aporte saldo
fecha
2025-02-26 5836.25 -1150.0 2500.0 16500.0
2025-02-27 5757.50 -3937.5 3937.5 16500.0
2025-02-28 5753.75 -187.5 0.0 16312.5
2025-03-03 5601.25 -7625.0 7812.5 16500.0
2025-03-04 5618.25 850.0 0.0 17350.0
2025-03-05 5503.50 -5737.5 4887.5 16500.0
2025-03-06 5334.50 -8450.0 8450.0 16500.0
2025-03-07 5234.75 -4987.5 4987.5 16500.0At the end of February 2025 the index starts to fall sharply. Each day of large losses leaves the balance below 15,000 USD and forces a deposit to get back to 16,500: 2,500 USD on February 26, 3,937.50 on the 27th, 7,812.50 on March 3 and, from March 5 to 7, 4,887.50, 8,450 and 4,987.50. Over the six days in the table with a deposit, the account asks for 32,575 USD: almost twice the entire initial margin.
llamadas = cm[cm["aporte"] > 0]
print("Margin calls:", len(llamadas))
print(f"Cash deposited: {llamadas['aporte'].sum():,.2f} USD")
print(f"Position P&L: {cm['pyg'].sum():,.2f} USD")
print(f"Final account balance: {cm['saldo'].iloc[-1]:,.2f} USD")Margin calls: 12
Cash deposited: 64,112.50 USD
Position P&L: -65,332.50 USD
Final account balance: 15,280.00 USDThe position loses 65,332.50 USD: four times the initial margin. The investor has had to deposit 64,112.50 USD in 12 calls, and at expiry has 15,280 left in the account. The numbers add up: 16,500 + 64,112.50 − 65,332.50 = 15,280. The initial margin is not the maximum loss: it is only what the clearing house asks for to cover one or two bad days.
Basis, cost of carry and convergence
Why does a future trade at a price different from spot? Because buying the future and buying the index are not the same. Whoever buys the index pays its full value today (and stops earning interest on that money) and receives the dividends; whoever buys the future pays nothing today and does not receive dividends. For there to be no arbitrage, the future has to compensate for that difference, the cost of carry:
where is the index, the interest rate, the dividend yield of the index and the time to expiry in years. The difference is the basis. On June 2, 2025, with the three-month rate from the course curve and a dividend yield of 1.35%:
curva = pd.read_csv("curva_tipos_diaria.csv", parse_dates=["fecha"],
index_col="fecha")
r = curva.loc["2025-06-02", "3m"] / 100
q = 0.0135
dia = dia.assign(teorico=S * np.exp((r - q) * dia["dias"] / 365))
dia["base"] = dia["liquidacion"] - S
print(f"Index {S}, r = {r:.3%}, q = {q:.2%}")
dia[["contrato", "dias", "liquidacion", "teorico", "base"]].round(2)Index 6359.1, r = 4.354%, q = 1.35%
contrato dias liquidacion teorico base
4867 FIXM25 18 6367.75 6368.53 8.65
4868 FIXU25 109 6419.00 6416.40 59.90
4869 FIXZ25 200 6462.50 6464.64 103.40The three settlement prices are less than three points from their theoretical value: the difference is rounding to the tick and a little noise. The basis grows with maturity: 8.65 points at 18 days, 59.90 at 109 and 103.40 at 200. And since the time to expiry shortens every day, a contract's basis is gradually used up until it disappears:
z25 = fut[fut["contrato"] == "FIXZ25"].set_index("fecha")
base = (z25["liquidacion"] - indice.reindex(z25.index)).rename("base")
pd.concat([z25["dias"], base.round(2)], axis=1).iloc[[0, 50, 100,
150, -2, -1]] dias base
fecha
2025-03-19 275 109.70
2025-05-30 203 103.12
2025-08-12 129 63.00
2025-10-22 58 27.06
2025-12-18 1 0.65
2025-12-19 0 0.00FIXZ25 starts trading in March 2025 with a basis of 109.70 points at 275 days and ends on December 19 with zero basis: its final settlement is the index close. That is why an index future “loses” against the index when the rate exceeds the dividend yield: it is not a poor return, it is the interest the buyer of the future does not pay and that the unspent money does earn.
Contango and backwardation
The term structure is the price of each expiry on the same day. It has two basic shapes:
- Contango: the far expiries trade more expensive than the near ones (and than spot). In an index, when .
- Backwardation: the far expiries trade cheaper. In an index, when .
def curva_futuros(fecha):
d = fut[(fut["fecha"] == fecha) & (fut["dias"] > 0)]
s = indice[fecha]
return d.assign(sobre_contado_pct=100 * (d["liquidacion"] / s - 1))
for fecha in ["2021-06-01", "2025-06-02"]:
print(fecha, f"3m rate: {curva.loc[fecha, '3m']:.2f} %")
print(curva_futuros(fecha)[["contrato", "dias", "liquidacion",
"sobre_contado_pct"]].round(2))2021-06-01 3m rate: 0.16 %
contrato dias liquidacion sobre_contado_pct
1836 FIXM21 17 4040.75 -0.07
1837 FIXU21 108 4022.25 -0.52
1838 FIXZ21 199 4010.75 -0.81
2025-06-02 3m rate: 4.35 %
contrato dias liquidacion sobre_contado_pct
4867 FIXM25 18 6367.75 0.14
4868 FIXU25 109 6419.00 0.94
4869 FIXZ25 200 6462.50 1.63On June 1, 2021, with the three-month rate at 0.16%, below the dividend yield, the curve slopes down: backwardation. On June 2, 2025, with the rate at 4.35%, it slopes up: contango. To measure the periods with all the data, it is enough to compare the two nearest expiries each day and annualize the difference:
vivos = fut[fut["dias"] > 0].sort_values(["fecha", "vencimiento"])
dos = vivos.groupby("fecha").head(2)
par = dos.groupby("fecha").agg(f1=("liquidacion", "first"),
f2=("liquidacion", "last"),
d1=("dias", "first"),
d2=("dias", "last"))
par["carry"] = np.log(par["f2"] / par["f1"]) / ((par["d2"] - par["d1"])
/ 365)
anual = par.groupby(par.index.year)["carry"]
pd.DataFrame({"contango_pct_dias": 100 * anual.apply(lambda x:
(x > 0).mean()),
"carry_medio_pct": 100 * anual.mean()}).round(1) contango_pct_dias carry_medio_pct
fecha
2019 62.7 0.2
2020 0.0 -1.4
2021 0.0 -1.4
2022 62.5 0.7
2023 100.0 3.5
2024 100.0 3.5
2025 100.0 2.7All of 2020 and 2021 in backwardation, with an average carry of −1.4% a year: rates were close to zero and the index dividend weighed more. All of 2023, 2024 and 2025 in contango, with a carry of 2.7 to 3.5 points a year. 2019 and 2022 are transition years, with 63% of sessions in contango.
What changes for an investor? Whoever holds a long futures position and rolls it every quarter sells the expiring contract (close to spot) and buys the next one (more expensive in contango). That “roll cost” is not an extra loss: it is the same cost of carry that the basis gradually uses up, and it is offset by the interest on the cash that has not been invested. Comparing the return of a future with that of the index without adding that interest makes the future look as if it returns less than it does.
The roll: when liquidity moves
A few days before expiry, most positions are moved to the next contract: the front one is closed and the next one is opened, often with a single calendar spread order. Volume and open interest migrate:
roll = fut[fut["contrato"].isin(["FIXM25", "FIXU25"])
& fut["fecha"].between("2025-06-05", "2025-06-23")]
tabla = roll.pivot(index="fecha", columns="contrato",
values="interes_abierto")
cruce = tabla[tabla["FIXU25"] > tabla["FIXM25"]].index[0]
print("The next contract overtakes the front one on", cruce.date())
tablaThe next contract overtakes the front one on 2025-06-13
contrato FIXM25 FIXU25
fecha
2025-06-05 778177.0 34906.0
2025-06-06 764556.0 49050.0
2025-06-09 734660.0 79671.0
2025-06-10 672936.0 141139.0
2025-06-11 563376.0 247645.0
2025-06-12 413715.0 393825.0
2025-06-13 263789.0 540829.0
2025-06-16 153647.0 648266.0
2025-06-17 90019.0 709669.0
2025-06-18 58420.0 741939.0
2025-06-20 44111.0 763316.0
2025-06-23 NaN 805582.0On June 5, FIXM25 has 778,177 open contracts and FIXU25, 34,906. A week later they cross: on June 12 they are almost level (413,715 versus 393,825) and on Friday the 13th the September contract already has more open interest. That same day the volume of FIXU25 shoots up (807,106 contracts): it is the busiest day of the roll. On June 20, expiry day, FIXM25 has 44,111 contracts left, 6% of the peak, which are settled in cash at the index close.
For a trading system, this has two consequences. First, whoever trades the front contract during the roll week does so in a contract that is emptying: spreads widen and the cost rises. Second, to have a long series you have to chain contracts, and the rule for jumping from one to the next (by date, by volume, by open interest) and how the price jump between them is corrected are decisions that change the results of a backtest. That construction is lesson 1.4.6.
What this changes in your data
- The price of a future is a settlement price. The standard daily data point is not the last trade, but the price the clearing house sets. To compare with the index you have to know at what time and how each one is calculated.
- Size is measured in notional. One FIX contract is about 300,000 USD; the margin is collateral, not the risk.
- Cash in reserve is part of the strategy. Margin calls happen on bad days and can add up to several times the initial margin.
- The basis is not return. Future and index differ by the cost of carry; the return of a future is compared with that of the index minus the interest rate, not with the index alone.
- Continuous series are built. There is no ten-year “futures price”: there is a roll rule and an adjustment (lesson 1.4.6).
Exercises
- Repeat the margin account simulation for a short in FIXH25 from December 16, 2024. How many margin calls does it receive and how much cash does the account accumulate by expiry?
Solution
corto = cuenta_margen(h25.loc["2024-12-16":], lado=-1)
print("Margin calls:", (corto["aporte"] > 0).sum())
print(f"Deposited: {corto['aporte'].sum():,.2f} USD")
print(f"P&L: {corto['pyg'].sum():,.2f} USD")
print(f"Final balance: {corto['saldo'].iloc[-1]:,.2f} USD")Margin calls: 5
Deposited: 9,987.50 USD
P&L: 65,332.50 USD
Final balance: 91,820.00 USDThe short gains exactly what the long loses, 65,332.50 USD, and ends with 91,820 USD in the account. But the path is not comfortable: it receives 5 margin calls, for 9,987.50 USD: four in the second half of December 2024 and one on February 19, 2025, days on which the index rises. A future is a zero-sum game between buyer and seller before costs; the clearing house only moves the cash from one to the other every day.
- For each 2024 expiry, find the first day on which the open interest of the next contract exceeds that of the expiring one. How many sessions before expiry does it happen?
Solution
oi = fut.pivot(index="fecha", columns="contrato",
values="interes_abierto")
sesiones = indice.index
pares = [("FIXH24", "FIXM24"), ("FIXM24", "FIXU24"),
("FIXU24", "FIXZ24"), ("FIXZ24", "FIXH25")]
for viejo, nuevo in pares:
v = fut.loc[fut["contrato"] == viejo, "vencimiento"].iloc[0]
x = oi[[viejo, nuevo]].dropna()
x = x[x.index > v - pd.Timedelta(days=30)] # the last month
dia_cruce = x[x[nuevo] > x[viejo]].index[0]
antes = ((sesiones > dia_cruce) & (sesiones <= v)).sum()
print(viejo, "->", nuevo, dia_cruce.date(), f"({antes} sessions)")FIXH24 -> FIXM24 2024-03-11 (4 sessions)
FIXM24 -> FIXU24 2024-06-14 (4 sessions)
FIXU24 -> FIXZ24 2024-09-16 (4 sessions)
FIXZ24 -> FIXH25 2024-12-16 (4 sessions)In the four 2024 rolls the crossover happens four sessions before expiry (counting expiry day itself), in the previous week. A roll rule “by open interest” would switch contracts on those days; a “fixed date” rule, for example eight sessions before, would do so earlier, when the new contract still has less liquidity. The last-month filter is needed: when the new contract starts trading, nine months earlier, both are far expiries and their small open interest can cross by chance.
- A colleague says that ETFs on index futures “lose money at every roll because of contango”. Explain which part of the statement is correct and what is missing.
Solution
It is true that in contango the new contract costs more than the expiring one, and that the price of a long future “falls” toward spot as expiry approaches. What is missing is that this contango is, in a financial future, the cost of carry: the interest rate minus the dividend yield. Whoever buys the future instead of the index does not pay out the notional and earns interest on that cash, which offsets the basis. If the interest on the cash is added (as a well-managed ETF does), the return resembles that of the total return index, minus costs. In commodities, where the term structure reflects storage and expectations, the roll can indeed cost much more than the interest.
Each answer is folded under its question
Self-assessment
The FIX future trades at 6,400 points with a multiplier of 50 USD and a tick of 0.25. How much does one contract gain or lose per tick and what is its notional?
- A0.25 USD per tick; notional of 6,400 USD
- B12.50 USD per tick; notional of 320,000 USD
- C50 USD per tick; notional of 320,000 USD
- D12.50 USD per tick; notional of 16,500 USD
Show answer
Answer B. 12.50 USD per tick; notional of 320,000 USD
Tick value = 0.25 × 50 = 12.50 USD; notional = 6,400 × 50 = 320,000 USD. The 16,500 USD is the initial margin: what is deposited, not what is controlled.
An account has an initial margin of 16,500 USD and a maintenance margin of 15,000. After a daily loss, the balance is 14,200 USD. What happens?
- AMargin call: 2,300 USD has to be deposited to get back to the initial margin
- BNothing: there is still a positive balance
- CMargin call: 800 USD has to be deposited to get back to maintenance
- DThe position is closed automatically
Show answer
Answer A. Margin call: 2,300 USD has to be deposited to get back to the initial margin
When it falls below maintenance, the account has to return to the initial margin: 16,500 − 14,200 = 2,300 USD. If it is not deposited in time, the broker can close the position.
With an interest rate of 4.35% and an index dividend yield of 1.35%, what term structure is expected in the futures on that index?
- ABackwardation: the far expiries cheaper
- BFlat: all expiries at the same price
- CContango: the far expiries more expensive, around 3% a year above spot
- DIt cannot be known without knowing the market's opinion
Show answer
Answer C. Contango: the far expiries more expensive, around 3% a year above spot
By no-arbitrage, F = S·e^((r−q)τ). With r − q = 3%, each expiry trades approximately 3% a year above spot. In a financial future the curve is set by the cost of carry, not by a forecast.
What happens to the basis (future − spot) on the expiry date?
- AIt equals the pending dividend
- BIt equals the initial margin
- CIt depends on that day's volume
- DIt is zero: the final settlement price is set with the index itself
Show answer
Answer D. It is zero: the final settlement price is set with the index itself
In FIX, the final settlement is the index close that day, so the basis vanishes. In real contracts the reference changes (the special opening quotation in the E-mini S&P 500, an average of the IBEX 35 between 16:15 and 16:45 at MEFF), but the idea is the same.
In the June 2025 roll week, the open interest of FIXU25 overtakes that of FIXM25 on June 13. Why does it matter for a trading system?
- AIt does not matter: the two contracts are the same asset
- BBecause the front contract stops trading that day
- CBecause from then on the liquidity is in the next expiry: staying in the front contract makes execution more expensive, and a continuous series has to decide when to switch
- DBecause the margin doubles
Show answer
Answer C. Because from then on the liquidity is in the next expiry: staying in the front contract makes execution more expensive, and a continuous series has to decide when to switch
The front contract keeps trading until expiry (June 20), but with less and less open interest. When and how to move from one contract to the next is the central decision of a continuous series (lesson 1.4.6).
Key points
- The contract sets everything except the price: underlying, multiplier, tick, months, last day and settlement method. In FIX, 50 USD per point and 12.50 USD per tick: a notional of over 300,000 USD with 16,500 of margin.
- Daily settlement turns every move into cash. A long in FIXH25 from mid-December 2024 lost 65,332 USD until expiry and received 12 margin calls: the initial margin is not the maximum loss.
- In a financial future, F = S·e^((r−q)τ): the basis is the cost of carry and it vanishes at expiry.
- Contango (far expiries more expensive) when the rate exceeds the dividend yield; backwardation when it does not. In FIX, backwardation throughout 2020 and 2021, with rates close to zero; contango since 2023.
- In the ~8 sessions before expiry, volume and open interest move to the next contract. Who rolls and when conditions any continuous series.