The dated market
If you value anything over more than one day (P&L, risk over time, a book revalued every close), this page explains how one market holds several dates: a snapshot of curves per date it was marked on, one shared history of fixings, and the reference data that never changes from day to day.
Why a market keeps every close
A desk revalues its book every day. Each close brings a new sheet, and each day brings new fixing prints for the trades that reset on it. Keeping each close as its own snapshot means yesterday's valuation can be repeated exactly while today's is made, which is what explaining a day's P&L needs.
What does not change from day to day lives once, outside the snapshots: the recipes that say how a sheet builds curves, central bank meeting schedules, counterparties, and the data source.
How a date is read
Write for the market, for the date it is at, and for its snapshots. A valuation reads the snapshot at the date asked:
where is the fixing history as known on . Moving the market to another date selects another snapshot and leaves every other snapshot as it was; dropping a date removes its snapshot and changes no other.
Every print in the history carries the date it became known and whether it was pinned by hand or fetched. A valuation at reads only prints known by , and a pinned print is read over any fetched version of the same print. Pinning the prints again on a later date keeps what earlier dates knew: a print pinned again with the same value adds no version, a new print is known from the date it is pinned, and a changed value is a restatement known from that date, kept beside the old one. So for an earlier is the same after a later pin as it was before.
From formula to API
| Symbol | Meaning | Rust | Python |
|---|---|---|---|
| the date the market is at | MarketContext::reference_date |
MarketContext.as_of |
|
| the snapshot at | MarketContext::on(t) |
MarketContext.on(t) |
|
| the dates with a snapshot | MarketContext::dates |
MarketContext.dates |
|
| drop | remove one snapshot | MarketContext::without(t) |
MarketContext.without(t) |
| the fixing history, by version | MarketContext::fixing_history then versions |
MarketContext.fixing_history |
|
| pin into | pin prints, keeping what earlier dates knew | MarketContext::with_fixings |
MarketContext.with_fixings |
Two closes on one market
This program marks two closes on one market, pins a new print on the second day, and reads the fixing history. The September prints keep the close as the date they became known, so a swap that accrued over them values on the close exactly as it did before the second pin. Marking a close, moving on, valuing and dropping a date is the how-to Mark a daily close. The program reads its quotes from the desk sheets.
use chrono::NaiveDate;
use helixio_docs_sheets::{SOFR_CLOSE_DATE, Sheet, USD_SOFR_CLOSE, USD_SOFR_PRINTS};
use helixrs::{
CollateralSpec, FixingKey, FixingStore, MarketContext, QuoteSheet, Termination,
template,
};
type Outcome<T> = Result<T, Box<dyn std::error::Error>>;
fn date((year, month, day): (i32, u32, u32)) -> NaiveDate {
NaiveDate::from_ymd_opt(year, month, day).expect("a real calendar date")
}
/// A sheet with every quote moved by `shift`.
fn sheet(rows: Sheet, shift: f64) -> Outcome<QuoteSheet> {
let shifted = rows.iter().map(|&(template, locator, quote)| (template, locator, quote + shift));
Ok(QuoteSheet::from_rows(shifted)?)
}
/// The shared September prints, and any published since.
fn prints(since: &[(&str, (i32, u32, u32), f64)]) -> Outcome<FixingStore> {
let observations: Vec<(FixingKey, NaiveDate, f64)> = USD_SOFR_PRINTS
.iter()
.chain(since)
.map(|(index, day, value)| (FixingKey::Typed((*index).to_owned()), date(*day), *value))
.collect();
Ok(FixingStore::from_observations_checked(&observations)?)
}
fn joined(dates: &[NaiveDate]) -> String {
dates.iter().map(NaiveDate::to_string).collect::<Vec<_>>().join(", ")
}
fn main() -> Outcome<()> {
let close = date(SOFR_CLOSE_DATE);
let next_day = date((2026, 10, 2));
let usd = CollateralSpec::Currency("USD".parse()?);
// Mark the close, then move to the next day and mark it on a sheet one basis
// point higher. The first day's snapshot is kept.
let market = MarketContext::as_of(close)
.with_fixings(prints(&[])?)
.with_recipe_quotes(&usd, &sheet(USD_SOFR_CLOSE, 0.0)?)?
.on(next_day)
.with_recipe_quotes(&usd, &sheet(USD_SOFR_CLOSE, 0.0001)?)?;
println!("dates {}", joined(&market.dates()));
println!("as of {}", market.reference_date());
// On the second day the 1 October print is published, and the market pins
// the full set again. Prints live in one history across the dates, each
// stamped with the date it became known: the September prints keep the close,
// an unchanged print adds no version, and the new print is known from the
// second day.
let pinned = market.clone().with_fixings(prints(&[("USD-SOFR", SOFR_CLOSE_DATE, 0.0391)])?);
let versions = pinned.fixing_history().versions();
for (index, day, known, pinned, value) in &versions {
let source = if *pinned { "pinned" } else { "fetched" };
println!("{index} {day} known {known} {source} {value:.4}");
}
// So the close still knows the September prints: a trade that accrued over
// them values on the first day exactly as it did before the second pin.
let seasoned = template("USD-SOFR-OIS")?
.swap(date((2026, 9, 24)))?
.with_maturity("5Y".parse::<Termination>()?)?
.with_notional(10_000_000.0)
.with_fixed_rate(0.0466)
.build()?;
let accrued = seasoned.npv(&pinned.clone().on(close))?;
let before = MarketContext::as_of(close)
.with_fixings(prints(&[])?)
.with_recipe_quotes(&usd, &sheet(USD_SOFR_CLOSE, 0.0)?)?;
println!("seasoned npv on {close} {accrued:.2}");
println!("before the second pin {:.2}", seasoned.npv(&before)?);
Ok(())
}import datetime as dt
import helixio as hlx
from desk_sheets import SOFR_CLOSE_DATE, USD_SOFR_CLOSE, USD_SOFR_PRINTS
NEXT_DAY = dt.date(2026, 10, 2)
# Mark the close, then move to the next day and mark it on a sheet one basis
# point higher. The first day's snapshot is kept.
monday = USD_SOFR_CLOSE
tuesday = {t: {k: v + 0.0001 for k, v in q.items()} for t, q in USD_SOFR_CLOSE.items()}
market = (
hlx.MarketContext(SOFR_CLOSE_DATE)
.with_fixings(USD_SOFR_PRINTS)
.with_recipe_quotes("USD", monday)
.on(NEXT_DAY)
.with_recipe_quotes("USD", tuesday)
)
print(f"dates {', '.join(d.isoformat() for d in market.dates())}")
print(f"as of {market.as_of()}")
# On the second day the 1 October print is published, and the market pins the
# full set again. Prints live in one history across the dates, each stamped
# with the date it became known: the September prints keep the close, an
# unchanged print adds no version, and the new print is known from the second
# day.
pinned = market.with_fixings([*USD_SOFR_PRINTS, ("USD-SOFR", SOFR_CLOSE_DATE, 0.0391)])
history = pinned.fixing_history().to_dict()
for index, day, known, source, value in zip(
history["index"], history["date"], history["known_on"], history["source"], history["value"]
):
print(f"{index} {day} known {known} {source} {value:.4f}")
# So the close still knows the September prints: a trade that accrued over them
# values on the first day exactly as it did before the second pin.
seasoned = (
hlx.templates.get("USD-SOFR-OIS")
.swap(dt.date(2026, 9, 24))
.with_maturity("5Y")
.with_notional(10_000_000.0)
.with_fixed_rate(0.0466)
.build()
)
accrued = seasoned.npv(pinned.on(SOFR_CLOSE_DATE))
before = hlx.MarketContext(SOFR_CLOSE_DATE).with_fixings(USD_SOFR_PRINTS).with_recipe_quotes("USD", monday)
print(f"seasoned npv on {SOFR_CLOSE_DATE} {accrued:.2f}")
print(f"before the second pin {seasoned.npv(before):.2f}")dates 2026-10-01, 2026-10-02
as of 2026-10-02
USD-SOFR 2026-09-28 known 2026-10-01 pinned 0.0390
USD-SOFR 2026-09-29 known 2026-10-01 pinned 0.0388
USD-SOFR 2026-09-30 known 2026-10-01 pinned 0.0390
USD-SOFR 2026-10-01 known 2026-10-02 pinned 0.0391
seasoned npv on 2026-10-01 -20632.04
before the second pin -20632.04
See also
- Source:
crates/helixrs/src/market/store.rs,crates/helixrs/src/marketdata/fixings.rs - Related pages:
- Books carry their market, for a book valued on each date.
- Data sources, for prints learnt by fetching.
- Mark a daily close, the task step by step.
From the 0.0 line at revision bf7f2e2. Every printed number is that revision's own output.