Esc

    The API is under testing and may change before release.

    Fee

    This page lists what you need to book and value a standalone fee: its one call, the sign of its amount, how it's valued, and what happens once its date has passed. A fee is one known amount paid or received on a date, such as an arrangement fee on a loan, an upfront on a swap or a break cost.

    Quick example

    The example reads its quotes from the desk sheets; load them once and it runs as shown.

    This books an arrangement fee of 250,000 EUR next March, from the side that pays it and the side that receives it. It checks the value against the discount factor by hand, reads the fee's one row in the cashflow table, and values a fee whose date has already passed. The market is the EUR close built on quote sheets and recipes.

    Rust
    use chrono::NaiveDate;
    use helixio_docs_sheets::{EUR_CLOSE, SOFR_CLOSE_DATE};
    use helixrs::{AnyInstrument, CollateralSpec, Currency, Fee, MarketContext, 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 fee(currency: Currency, payment: NaiveDate, amount: f64) -> AnyInstrument {
        AnyInstrument::Fee(Box::new(Fee::new(currency, payment, amount)))
    }
    
    fn main() -> Outcome<()> {
        let eur: Currency = "EUR".parse()?;
        let market = MarketContext::as_of(date(SOFR_CLOSE_DATE)).with_recipe_quotes(
            &CollateralSpec::Currency(eur),
            &QuoteSheet::from_rows(EUR_CLOSE.iter().copied())?,
        )?;
        let payment = date((2027, 3, 15));
    
        // An arrangement fee of 250,000 EUR paid next March, and the same fee received.
        let paid = fee(eur, payment, -250_000.0);
        let received = fee(eur, payment, 250_000.0);
        println!("paid      {:.2}", paid.npv(&market)?);
        println!("received  {:.2}", received.npv(&market)?);
    
        // By hand: the amount times the discount factor to the payment date, and one
        // row in the cashflow table whose pv is that value.
        let (curve, _) = market
            .curve(&"discount(EUR)".parse()?)
            .expect("the EUR discount curve");
        let df = curve.view::<f64>().discount(payment)?;
        let by_hand = -250_000.0 * df;
        let rows = paid.cashflow_records(&market)?;
        let kind = rows["kind"].text().expect("text");
        let side = rows["direction"].text().expect("text");
        let pv = rows["pv"].numbers().expect("numbers");
        println!("discount factor  {df:.10}");
        println!("by hand          {by_hand:.2}");
        println!("row              {} {} {:.2}", kind[0], side[0], pv[0]);
    
        // A fee paid before the valuation date has already left: it is worth nothing,
        // and its table is empty.
        let settled = fee(eur, date((2026, 9, 15)), -250_000.0);
        println!("settled   {:.2}", settled.npv(&market)?);
        println!("rows      {}", settled.cashflow_records(&market)?.len());
    
        Ok(())
    }
    Python
    import datetime as dt
    
    import helixio as hlx
    from desk_sheets import EUR_CLOSE, SOFR_CLOSE_DATE
    
    market = hlx.MarketContext(SOFR_CLOSE_DATE).with_recipe_quotes("EUR", EUR_CLOSE)
    PAYMENT = dt.date(2027, 3, 15)
    
    # An arrangement fee of 250,000 EUR paid next March, and the same fee received.
    paid = hlx.products.fee("EUR", PAYMENT, amount=-250_000.0)
    received = hlx.products.fee("EUR", PAYMENT, amount=250_000.0)
    print(f"paid      {paid.npv(market):.2f}")
    print(f"received  {received.npv(market):.2f}")
    
    # By hand: the amount times the discount factor to the payment date, and one
    # row in the cashflow table whose pv is that value.
    df = market.discount_factor("EUR", PAYMENT)
    by_hand = -250_000.0 * df
    rows = paid.cashflow_records(market).to_dict()
    print(f"discount factor  {df:.10f}")
    print(f"by hand          {by_hand:.2f}")
    print(f"row              {rows['kind'][0]} {rows['direction'][0]} {rows['pv'][0]:.2f}")
    
    # A fee paid before the valuation date has already left: it is worth nothing,
    # and its table is empty.
    settled = hlx.products.fee("EUR", dt.date(2026, 9, 15), amount=-250_000.0)
    print(f"settled   {settled.npv(market):.2f}")
    print(f"rows      {len(settled.cashflow_records(market).to_dict()['kind'])}")
    paid      -247797.19
    received  247797.19
    discount factor  0.9911887520
    by hand          -247797.19
    row              Fee Pay -247797.19
    settled   0.00
    rows      0

    The payer and the receiver hold the same value with opposite signs, and the one row in the table carries exactly the fee's value.

    How it's priced

    A fee of amount AA paid on tpt_p is worth the amount discounted from its payment date, and nothing once that date has passed:

    V=A P(tp).V = A\,P(t_p).

    AA is positive when received and negative when paid. Why a fee is booked beside its trade rather than folded into a price is covered in how financing works.

    API

    Argument Type Default Meaning
    currency str required the fee's currency; it discounts on that currency's cash collateral curve
    payment_date date required the day the amount changes hands
    amount float required, keyword only the amount: positive received, negative paid

    The Python call is products.fee(currency, payment_date, amount=). In Rust it's AnyInstrument::Fee(Box::new(Fee::new(currency, payment_date, amount))).

    Symbol Meaning Rust Python
    AA the amount, signed by side Fee::new(.., amount) products.fee(.., amount=)
    P(tp)P(t_p) the discount factor to the payment date curve.view::<f64>().discount(t_p) MarketContext.discount_factor
    VV its value AnyInstrument::npv Instrument.npv
    the row its one cashflow AnyInstrument::cashflow_records Instrument.cashflow_records

    Defaults and limits

    • What the market needs: the discount curve of the fee's currency, and nothing else. A fee has no rate, index or schedule.
    • Sign: the sign of amount is the side. There's no side argument.
    • After its date: a fee whose payment date is before the valuation date is worth 0.0, and its cashflow table has no rows.
    • Its row: the cashflow table holds one row of kind Fee, whose pv is the fee's value.

    See also

    • Source: crates/helixrs/src/instruments/fee.rs
    • Related pages:
      • How financing works, the ideas behind the financing products.
      • Loan, for the trade an arrangement fee usually sits beside.
      • Cashflow records, for the table its one row joins.

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