Listed futures
This page lists what you need to read a listed rate future from its template and value a position in it: which period a contract settles on, when it stops trading, its tick, and how a position is priced. A short-term interest rate future is quoted as a price, 100 minus the rate, and settles on the overnight rate over its reference period.
Quick example
The example reads its quotes from the desk sheets; load them once and it runs as shown. It reads the March 2027 contract on four templates, the June 2027 tick on three dates, and values ten March contracts bought at 95.60.
use chrono::NaiveDate;
use helixio_docs_sheets::{SOFR_CLOSE_DATE, USD_SOFR_LADDER};
use helixrs::FutureTemplate;
use helixrs::{
AnyInstrument, AnyTemplate, CollateralSpec, DayOfWeek, MarketContext, QuoteSheet,
RateFuture, nth_weekday, template,
};
fn date(year: i32, month: u32, day: u32) -> NaiveDate {
NaiveDate::from_ymd_opt(year, month, day).expect("a real calendar date")
}
fn futures(code: &str) -> FutureTemplate {
match template(code).expect("a registered template") {
AnyTemplate::Future(t) => t,
_ => panic!("{code} is not a futures template"),
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let close = date(SOFR_CLOSE_DATE.0, SOFR_CLOSE_DATE.1, SOFR_CLOSE_DATE.2);
// The March 2027 contract on four templates. A quarterly contract's period runs
// from the third Wednesday of March to that of June; a monthly one is March.
println!("{:<20} {:<25} last trading day", "template", "reference period");
let mut periods = Vec::new();
for code in ["USD-SOFR-3M-FUT", "USD-SOFR-1M-FUT", "GBP-SONIA-3M-FUT", "EUR-EURIBOR-3M-FUT"] {
let contract = futures(code);
let (start, end) = contract.reference_period(2027, 3).expect("an IMM month");
let last = contract.last_trading_day(2027, 3).expect("an IMM month").expect("a sourced rule");
periods.push((code, start, end, last));
println!("{code:<20} {start} to {end} {last}");
}
// A CME three-month SOFR contract ticks in half a basis point, and in a quarter
// of one from about four months before its last trading day. The June contract
// references June to September, so it trades until September.
let sr3 = futures("USD-SOFR-3M-FUT");
let june_last = sr3.last_trading_day(2027, 6).expect("an IMM month").expect("a sourced rule");
println!("June 2027 last trading day {june_last}");
let tick = |as_of| sr3.tick_size(2027, 6, as_of).expect("an IMM month").expect("a sourced rule");
for as_of in [date(2026, 10, 1), date(2027, 4, 1), date(2027, 6, 1)] {
println!("June 2027 tick on {as_of} {:.4}", tick(as_of));
}
// Ten March contracts bought at 95.60. The market marked from the ladder quotes
// March at 95.65, so the futures rate is 4.35% and the position has gained five
// basis points on each of ten contracts.
let sheet = QuoteSheet::from_rows(USD_SOFR_LADDER.iter().copied()).expect("a locator");
let usd = CollateralSpec::Currency("USD".parse().expect("a currency"));
let market = MarketContext::as_of(close).with_recipe_quotes(&usd, &sheet).expect("the USD recipe");
let position = AnyInstrument::RateFuture(
RateFuture::for_contract(&sr3, 2027, 3, 10.0, 95.60).expect("an IMM month"),
);
let rate = position.par_rate(&market).expect("a futures rate");
let npv = position.npv(&market).expect("a value");
println!("futures rate {rate:.8}");
println!("npv {npv:.2}");
Ok(())
}import datetime as dt
import helixio as hlx
from desk_sheets import SOFR_CLOSE_DATE, USD_SOFR_LADDER
# The March 2027 contract on four templates. A quarterly contract's period runs
# from the third Wednesday of March to that of June; a monthly one is March.
print(f"{'template':<20} {'reference period':<25} last trading day")
periods = []
for code in ("USD-SOFR-3M-FUT", "USD-SOFR-1M-FUT", "GBP-SONIA-3M-FUT", "EUR-EURIBOR-3M-FUT"):
template = hlx.templates.get(code)
start, end = template.reference_period(2027, 3)
last = template.last_trading_day(2027, 3)
periods.append((code, start, end, last))
print(f"{code:<20} {start} to {end} {last}")
# A CME three-month SOFR contract ticks in half a basis point, and in a quarter
# of one from about four months before its last trading day. The June contract
# references June to September, so it trades until September.
sr3 = hlx.templates.get("USD-SOFR-3M-FUT")
print(f"June 2027 last trading day {sr3.last_trading_day(2027, 6)}")
for as_of in (dt.date(2026, 10, 1), dt.date(2027, 4, 1), dt.date(2027, 6, 1)):
tick = sr3.tick_size(2027, 6, as_of)
print(f"June 2027 tick on {as_of} {tick:.4f}")
# Ten March contracts bought at 95.60. The market marked from the ladder quotes
# March at 95.65, so the futures rate is 4.35% and the position has gained five
# basis points on each of ten contracts.
market = hlx.MarketContext(SOFR_CLOSE_DATE).with_recipe_quotes("USD", USD_SOFR_LADDER)
position = sr3.rate_future_contract(2027, 3, contracts=10.0, traded_price=95.60)
rate = position.par_rate(market)
npv = position.npv(market)
print(f"futures rate {rate:.8f}")
print(f"npv {npv:.2f}")template reference period last trading day
USD-SOFR-3M-FUT 2027-03-17 to 2027-06-16 2027-06-15
USD-SOFR-1M-FUT 2027-03-01 to 2027-04-01 2027-03-31
GBP-SONIA-3M-FUT 2027-03-17 to 2027-06-16 2027-06-15
EUR-EURIBOR-3M-FUT 2027-03-17 to 2027-06-16 2027-03-15
June 2027 last trading day 2027-09-14
June 2027 tick on 2026-10-01 0.0050
June 2027 tick on 2027-04-01 0.0050
June 2027 tick on 2027-06-01 0.0025
futures rate 0.04350000
npv 1250.00
How it's priced
A position of contracts bought at price , with a point worth and the market's futures rate over the reference period, is worth
On a curve marked from the futures themselves, is the contract's own quote, read as , so a position bought below the quoted price has gained. A three-month SOFR point is worth 2,500 dollars. How the exchanges set periods and ticks is covered in how dates and conventions work.
API
| Symbol | Meaning | Rust | Python |
|---|---|---|---|
| reference period | the period a contract settles on | FutureTemplate::reference_period |
Template.reference_period |
| last trading day | the exchange's rule | FutureTemplate::last_trading_day |
Template.last_trading_day |
| tick | the minimum price move on a date | FutureTemplate::tick_size |
Template.tick_size |
| a position | contracts at | RateFuture::for_contract |
Template.rate_future_contract |
| the futures rate | AnyInstrument::par_rate |
Instrument.par_rate |
| Argument | Type | Default | Meaning |
|---|---|---|---|
year, month |
int | required | the delivery month, for every call below |
as_of |
date | required | tick_size only: the day whose tick you want |
contracts |
float | required | rate_future_contract: the number of contracts, ; in Rust, the fourth positional argument of RateFuture::for_contract(&template, year, month, contracts, price) |
traded_price |
float | required | rate_future_contract: the price you traded at, ; in Rust, the fifth positional argument |
short |
bool | False |
rate_future_contract: book the short side |
convexity_adjustment |
float or None |
None |
rate_future_contract: a stated adjustment to the futures rate |
Defaults and limits
- Periods: a three-month contract (CME SOFR, ICE SONIA, Eurex €STR and EURIBOR) covers the IMM quarter from the delivery month's third Wednesday to the third Wednesday three months later. A one-month contract covers the calendar month.
- Last trading day and tick: both come from the exchange's rule, with the template's calendar
standing in for the exchange's. Where the rule isn't sourced, the call returns
Nonein Python. - Ticks narrow near expiry: CME three-month SOFR moves from half a basis point to a quarter of one about four months before its last trading day (from the business day after the Friday before the third Wednesday of the fourth month before the month trading ends). That's why the example's June tick changes between April and June.
- Templates: the futures templates are listed in the template registry.
See also
- Source:
crates/helixrs/src/instruments/rates.rs,crates/helixrs/src/statics/templates/registry.rs - Related pages:
- How dates and conventions work, for why contracts are built this way.
- Rate futures, for the futures rate with its convexity.
- Dates and periods, for IMM dates.
- Curve helpers, for a futures rung.
From the 0.0 line at revision bf7f2e2. Every printed number is that revision's own output.