Esc

    The API is under testing and may change before release.

    Meeting schedules

    This page lists what you need to read a central bank's meeting schedule, see which windows it lets you quote, and pin a decision the library doesn't ship. A meeting schedule lists a bank's decision days and the day each takes effect, which is where the front end of a curve steps.

    Quick example

    The example reads its quotes from the desk sheets; load them once and it runs as shown. It reads the three shipped schedules, marks a curve from a quote on a 2026 decision, and shows a quote on the last shipped decision being refused. Pinning a later decision so that quote marks a curve is the how-to Pin a meeting schedule.

    Rust
    use chrono::{Datelike, NaiveDate};
    use helixio_docs_sheets::SOFR_CLOSE_DATE;
    use helixrs::{
        BusinessDayConvention, CentralBank, CollateralSpec, MarketContext, MeetingSchedule, QuoteSheet,
        calendar,
    };
    
    fn date(year: i32, month: u32, day: u32) -> NaiveDate {
        NaiveDate::from_ymd_opt(year, month, day).expect("a real calendar date")
    }
    
    fn main() -> Result<(), Box<dyn std::error::Error>> {
        let close = date(SOFR_CLOSE_DATE.0, SOFR_CLOSE_DATE.1, SOFR_CLOSE_DATE.2);
    
        // The library ships two years of decisions for three banks, 2026 and 2027. Each
        // decision's effective date follows from its bank's rule.
        let mut seeded = Vec::new();
        for bank in [CentralBank::Fed, CentralBank::Ecb, CentralBank::Boe] {
            let schedule = MeetingSchedule::seeded(bank.clone()).expect("a seeded bank");
            let (decisions, effective) = (schedule.decisions(), schedule.effective_dates());
            println!(
                "{}  {} decisions, {} to {}, last effective {}",
                bank.code(),
                decisions.len(),
                decisions[0],
                decisions[decisions.len() - 1],
                effective[effective.len() - 1]
            );
            seeded.push((bank, schedule));
        }
    
        // A meeting swap covers the window from one decision's effective date to the
        // next's. December 2026's window closes on the first 2027 decision, so a quote
        // on it marks a curve; the last seeded decision opens no window, since no later
        // decision closes it.
        let fed = MeetingSchedule::seeded(CentralBank::Fed).expect("a seeded bank");
        let horizon = date(2027, 3, 31);
        let knots: Vec<NaiveDate> = fed.between(close, horizon).iter().map(|k| k.date).collect();
        println!(
            "Fed effective dates after the close  {}",
            knots.iter().map(NaiveDate::to_string).collect::<Vec<_>>().join(", ")
        );
        let usd = CollateralSpec::Currency("USD".parse().expect("a currency"));
        let december = QuoteSheet::from_rows([
            ("USD-SOFR-MeetingOIS", "2026-12-09", 0.0380),
            ("USD-SOFR-OIS", "2Y", 0.0459),
            ("USD-SOFR-OIS", "5Y", 0.0471),
        ])
        .expect("a well-formed sheet");
        let marked = MarketContext::as_of(close).with_recipe_quotes(&usd, &december).expect("a closed window");
        let (december_curve, _) = marked.curve(&"discount(USD)".parse().expect("a key")).expect("the USD curve");
        let december_pillars = december_curve.parameter_count();
        println!("a quote on the 9 December 2026 decision marks a curve with {december_pillars} pillars");
        let last = fed.decisions()[fed.decisions().len() - 1];
        let spelled = last.to_string();
        let sheet = QuoteSheet::from_rows([
            ("USD-SOFR-MeetingOIS", spelled.as_str(), 0.0360),
            ("USD-SOFR-OIS", "2Y", 0.0459),
            ("USD-SOFR-OIS", "5Y", 0.0471),
        ])
        .expect("a well-formed sheet");
        let refused = MarketContext::as_of(close)
            .with_recipe_quotes(&usd, &sheet)
            .expect_err("a window with no closing decision must be refused");
        println!("a quote on the last seeded decision, {last}, is refused");
    
        Ok(())
    }
    Python
    import datetime as dt
    
    import helixio as hlx
    from desk_sheets import SOFR_CLOSE_DATE
    
    dates = hlx.dates
    
    # The library ships two years of decisions for three banks, 2026 and 2027. Each
    # decision's effective date follows from its bank's rule.
    seeded = {}
    for bank in ("FED", "ECB", "BOE"):
        schedule = dates.MeetingSchedule.seeded(bank)
        decisions, effective = schedule.decisions(), schedule.effective_dates()
        seeded[bank] = (decisions, effective)
        print(f"{bank}  {len(decisions)} decisions, {decisions[0]} to {decisions[-1]}, last effective {effective[-1]}")
    
    # A meeting swap covers the window from one decision's effective date to the
    # next's. December 2026's window closes on the first 2027 decision, so a quote
    # on it marks a curve; the last seeded decision opens no window, since no later
    # decision closes it.
    fed = dates.MeetingSchedule.seeded("FED")
    knots = dates.meeting_dates("FED", SOFR_CLOSE_DATE, dt.date(2027, 3, 31))
    print(f"Fed effective dates after the close  {', '.join(d.isoformat() for d in knots)}")
    december = {"USD-SOFR-MeetingOIS": {"2026-12-09": 0.0380}, "USD-SOFR-OIS": {"2Y": 0.0459, "5Y": 0.0471}}
    marked = hlx.MarketContext(SOFR_CLOSE_DATE).with_recipe_quotes("USD", december)
    december_pillars = marked.curve("discount(USD)").parameter_count()
    print(f"a quote on the 9 December 2026 decision marks a curve with {december_pillars} pillars")
    last = fed.decisions()[-1]
    sheet = {"USD-SOFR-MeetingOIS": {last.isoformat(): 0.0360}, "USD-SOFR-OIS": {"2Y": 0.0459, "5Y": 0.0471}}
    try:
        hlx.MarketContext(SOFR_CLOSE_DATE).with_recipe_quotes("USD", sheet)
        refused = None
    except ValueError as error:
        refused = str(error)
    print(f"a quote on the last seeded decision, {last}, is {'refused' if refused else 'accepted'}")
    FED  16 decisions, 2026-01-28 to 2027-12-08, last effective 2027-12-09
    ECB  16 decisions, 2026-01-29 to 2027-12-16, last effective 2027-12-22
    BOE  16 decisions, 2026-02-05 to 2027-12-16, last effective 2027-12-16
    Fed effective dates after the close  2026-10-29, 2026-12-10, 2027-01-28, 2027-03-18
    a quote on the 9 December 2026 decision marks a curve with 3 pillars
    a quote on the last seeded decision, 2027-12-08, is refused

    How it's priced

    With decision days d1<d2<⋯<dnd_1 < d_2 < \dots < d_n and the bank's rule EE, the effective dates are ek=E(dk)e_k = E(d_k), and the meeting windows are

    Wk=ek, ek+1),k=1,…,n−1.W_k = e_k,\ e_{k+1}), \qquad k = 1, \dots, n - 1.

    A meeting quote on decision dkd_k is the average overnight rate over WkW_k, so it needs ek+1e_{k+1}. A step curve puts a pillar at each ek+1e_{k+1}, and its forward is flat across each window. Why markets quote meeting by meeting is covered in [how dates and conventions work.

    API

    Symbol Meaning Rust Python
    {dk}\{d_k\} a bank's decisions MeetingSchedule::seeded, MeetingSchedule::new dates.MeetingSchedule.seeded, dates.MeetingSchedule
    ek=E(dk)e_k = E(d_k) the effective dates MeetingSchedule::effective_dates MeetingSchedule.effective_dates
    {ek}\{e_k\} in a range the knots a curve pillars on MeetingSchedule::between dates.meeting_dates
    a pinned schedule the schedule a market resolves against MarketContext::with_meetings MarketContext.with_meetings
    Argument Type Default Meaning
    bank str required "FED", "ECB" or "BOE", for seeded, MeetingSchedule and meeting_dates; Rust takes a CentralBank
    decisions list of dates required MeetingSchedule(bank, decisions): the decision days, from which the effective dates follow
    start, end date required meeting_dates: the range, inclusive
    schedule MeetingSchedule or None None meeting_dates: read from this schedule instead of the shipped one
    schedule MeetingSchedule required MarketContext.with_meetings: the schedule the market uses

    Defaults and limits

    • Shipped schedules: the library ships two years of decisions for the Fed, the ECB and the Bank of England, 2026 and 2027. The Fed's 2027 dates are its published calendar, each tentative until the meeting before it confirms it.
    • Effective dates: the Fed's take effect the next business day, the ECB's the following Wednesday, the Bank of England's on the decision day itself.
    • The last window needs a later decision: a quote on the last shipped decision is refused, naming the decision, because no later decision closes its window. Pin a schedule with a later decision to quote it; see Pin a meeting schedule.
    • A pinned schedule moves no value: two markets that differ only in their pinned schedule still compare equal.

    !!! warning "A pinned decision is your assumption" A decision you add after the shipped ones is a desk's assumption, not a published date. Replace it with the bank's schedule when it's published.

    See also

    • Source: crates/helixrs/src/statics/meetings.rs
    • Related pages:
      • How dates and conventions work, for why the front end is quoted meeting by meeting.
      • Pin a meeting schedule, the task step by step.
      • Curve helpers, for meeting and turn rungs.
      • Step curves, for the curve a schedule knots.

    From the 0.0 line at revision bf7f2e2. Every printed number is that revision's own output.