Esc

    The API is under testing and may change before release.

    Reading a curve

    This page lists the three readings a discount curve answers, a discount factor, a zero rate and a forward rate, and the setting that decides what day count the rates are formed on.

    Quick example

    This reads a curve marked from the SOFR close: factors and zero rates at three dates, a forward, and the same factors under an ACT/360 rate day count, which scales every rate by 360/365. The example reads its quotes from the desk sheets; load them once and it runs as shown.

    Rust
    use chrono::NaiveDate;
    use helixio_docs_sheets::{SOFR_CLOSE_DATE, USD_SOFR_CLOSE};
    use helixrs::{
        CollateralSpec, Curve, DayCountFraction, MarketContext, PiecewiseDiscount, QuoteSheet,
        YieldCurve,
    };
    
    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")
    }
    
    fn main() -> Outcome<()> {
        let close = date(SOFR_CLOSE_DATE);
        let sheet = QuoteSheet::from_rows(USD_SOFR_CLOSE.iter().copied())?;
        let market = MarketContext::as_of(close)
            .with_recipe_quotes(&CollateralSpec::Currency("USD".parse()?), &sheet)?;
        let dates = [date((2027, 10, 1)), date((2031, 10, 1)), date((2036, 10, 1))];
    
        // The SOFR curve, read at one, five and ten years.
        let (curve, _) = market.curve(&"discount(USD)".parse()?).expect("the USD curve");
        let view = curve.view::<f64>();
        println!("rate day count  {}", view.rate_day_count().code());
        let mut factors = Vec::new();
        for d in dates {
            let factor = view.discount(d)?;
            println!("{d}  discount {factor:.10}  zero {:.8}", view.zero_rate(d)?);
            factors.push(factor);
        }
    
        // The forward between five and ten years: what the curve implies a rate over
        // that window is, seen from today.
        let forward = view.forward_rate(dates[1], dates[2])?;
        println!("5Y-10Y forward  {forward:.8}");
    
        // The same factors, told to form rates on ACT/360: every factor is unchanged,
        // and every zero rate is scaled by 360/365.
        let pillars: Vec<(NaiveDate, f64)> = dates.iter().copied().zip(factors.iter().copied()).collect();
        let act360 = Curve::Piecewise(
            PiecewiseDiscount::from_discount_factors(close, &pillars)?
                .with_rate_day_count(DayCountFraction::Act360),
        );
        let act360 = act360.view::<f64>();
        println!("rate day count  {}", act360.rate_day_count().code());
        let ratio = act360.zero_rate(dates[1])? / view.zero_rate(dates[1])?;
        println!("zero rate ratio {ratio:.10}");
    
        Ok(())
    }
    Python
    import datetime as dt
    
    import helixio as hlx
    from desk_sheets import SOFR_CLOSE_DATE, USD_SOFR_CLOSE
    
    market = hlx.MarketContext(SOFR_CLOSE_DATE).with_recipe_quotes("USD", USD_SOFR_CLOSE)
    DATES = [dt.date(2027, 10, 1), dt.date(2031, 10, 1), dt.date(2036, 10, 1)]
    
    # The SOFR curve, read at one, five and ten years.
    curve = market.curve("discount(USD)")
    print(f"rate day count  {curve.rate_day_count()}")
    factors = [curve.discount(d) for d in DATES]
    for d, factor in zip(DATES, factors):
        print(f"{d}  discount {factor:.10f}  zero {curve.zero_rate(d):.8f}")
    
    # The forward between five and ten years: what the curve implies a rate over
    # that window is, seen from today.
    forward = curve.forward_rate(DATES[1], DATES[2])
    print(f"5Y-10Y forward  {forward:.8f}")
    
    # The same factors, told to form rates on ACT/360: every factor is unchanged,
    # and every zero rate is scaled by 360/365.
    act360 = hlx.curves.DiscountCurve(
        SOFR_CLOSE_DATE, list(zip(DATES, factors)), rate_day_count="ACT/360"
    )
    print(f"rate day count  {act360.rate_day_count()}")
    ratio = act360.zero_rate(DATES[1]) / curve.zero_rate(DATES[1])
    print(f"zero rate ratio {ratio:.10f}")
    rate day count  ACT/365.FIXED
    2027-10-01  discount 0.9574394995  zero 0.04349275
    2031-10-01  discount 0.7916588736  zero 0.04669935
    2036-10-01  discount 0.6184302261  zero 0.04801762
    5Y-10Y forward  0.04933518
    rate day count  ACT/360
    zero rate ratio 0.9863013699

    How it's priced

    With τ\tau the year fraction on the curve's rate day count, the continuously compounded zero rate to tt and the forward between t1t_1 and t2t_2 are

    z(t)=−ln⁡D(t)τ(t0,t),f(t1,t2)=ln⁡D(t1)−ln⁡D(t2)τ(t1,t2).z(t) = -\frac{\ln D(t)}{\tau(t_0, t)}, \qquad f(t_1, t_2) = \frac{\ln D(t_1) - \ln D(t_2)}{\tau(t_1, t_2)}.

    Changing the rate day count from ACT/365 to ACT/360 changes no factor and scales every rate by 360/365360/365. The rates rebuilt by hand from the factors are on how curves work.

    API

    Symbol Meaning Rust Python
    D(t)D(t) the factor YieldCurve::discount curves.DiscountCurve.discount
    z(t)z(t) the zero rate YieldCurve::zero_rate curves.DiscountCurve.zero_rate
    f(t1,t2)f(t_1, t_2) the forward YieldCurve::forward_rate curves.DiscountCurve.forward_rate
    τ\tau's day count the rate day count YieldCurve::rate_day_count; set with PiecewiseDiscount::with_rate_day_count curves.DiscountCurve.rate_day_count; set with rate_day_count=
    Argument Type Default Meaning
    at date required the date, for discount(at) and zero_rate(at)
    start, end date required the window, for forward_rate(start, end)
    rate_day_count str or DayCountFraction "ACT/365.FIXED" set when the curve is built, see discount curves

    Defaults and limits

    !!! warning "A curve's zero rate is not an index fixing" The zero rate is continuously compounded on the curve's rate day count. The rate an index fixes at is simple, on the index's own day count, over its own period; read that with Index.forecast, as indices shows.

    • Before the reference date discount raises ValueError.
    • A factor is strictly between zero and one for a positive rate, and falls with time.

    See also

    • Source: crates/helixrs/src/curves/discount.rs
    • Related pages:
      • Discount curves, for building a curve.
      • Day counts, for the year fractions.
      • Indices, for the rate an index fixes at.

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