Financial functions

YIELD

Known larger differences on 561 of 625 recorded answers

Of 625 recorded answers (533 in the answer bank and 92 workbook cells), 561 do not match: 455 differ by more than 16 ULP, 100 differ by at most 16 ULP, 6 differ in kind or value. How we measure this · See the Rust code

Local names in 40 languages
LanguageName in Excel
Arabicالعائد
BulgarianДОБИВ
CzechYIELD
DanishAFKAST
GermanRENDITE
GreekΑΠΟΔΟΣΗ
English (Australia)YIELD
English (United Kingdom)YIELD
English (United States)YIELD
SpanishRENDTO
EstonianYIELD
FinnishTUOTTO
FrenchRENDEMENT.TITRE
HebrewYIELD
CroatianYIELD
HungarianHOZAM
IndonesianHASIL
ItalianREND
JapaneseYIELD
KoreanYIELD
LithuanianYIELD
LatvianATDEVE
NorwegianAVKAST
DutchOPBRENGST
PolishPLON
Portuguese (Brazil)RENDIMENTO
Portuguese (Portugal)LUCRO
RomanianPRODUCȚIE
RussianДОХОД
SlovakVÝNOS
SlovenianYIELD
Serbian (Latin)YIELD
SwedishAVKASTNING
ThaiYIELD
TurkishÖDEME
UkrainianПРИБУТОК
VietnameseHOA LỢI
Chinese (Simplified)YIELD
Chinese (Hong Kong)YIELD
Chinese (Traditional)YIELD

Names from Microsoft's support site.

What it does

YIELD(settlement, maturity, rate, pr, redemption, frequency, [basis])

YIELD(settlement,maturity,rate,pr,redemption,frequency,[basis]) solves an annual yield from a coupon security’s clean price per 100 face value. Rate is the annual coupon rate; frequency is one, two or four payments per year.

Try it

Input cells (optional)

Example: {"B2": 3, "B3": 4}. A1 holds the formula. Other cells need values before a formula can read them.

Enter a formula, then calculate.

Runs locally in your browser with OneCalc. Its answer may differ from Excel. Use English function names and commas between arguments.

=YIELD(DATE(2027,1,1),DATE(2028,1,1),0.06,100,100,2,0) is about 0.06. This on-coupon par bond takes the current exact par shortcut, rather than needing a generic numerical inversion.

=YIELD(DATE(2027,4,1),DATE(2027,7,1),0.06,100,100,2,0) is about 0.0591133005. The final coupon is three and accrued interest is 1.5, so the clean price of 100 corresponds to an invested dirty amount of 101.5.

Quirks

Basis defaults to zero: 0 US 30/360, 1 actual/actual, 2 actual/360, 3 actual/365, 4 European 30/360. Dates and selectors are truncated under their documented rules. Use DATE values rather than locale-dependent date text. Settlement must precede maturity; negative coupon rate, invalid frequency/basis or nonpositive redemption gives #NUM!. Price must be positive. The one-coupon and multiple-coupon branches use different formulas.

How to implement

After validating dates, positive price/redemption, nonnegative coupon rate and the frequency/basis, build the coupon schedule and remaining count N. The current code uses three distinct routes, all with ordinary binary64 arithmetic.

  1. For an on-coupon settlement with N>1 and both price and redemption exactly 100, return the coupon rate when its coupon amount is finite. This par shortcut has its own retained controls; it is not evidence of the general solver’s accuracy.
  2. For N=1, calculate coupon C=100*rate/frequency, coupon denominator E, accrued span A and the direct settlement-to-next-coupon span S using the current day-count helpers. Return (((redemption+C)/(price+C*A/E))-1)*frequency*E/S, preserving the source’s left-to-right multiplication and division. This one-coupon YIELD span differs from PRICE’s use of derived E-A where the calendar rules distinguish them.
  3. For N>1, solve the internal clean-price callback for the supplied target price. Its schedule quantities use the derived settlement complement, but its current discount leaf is the runtime crt_pow, whereas the public PRICE route uses its newer integer and x87-chain helper. Calling public PRICE unconditionally would also reject the negative trial yields that this solver needs to probe.

The current general solver starts at lo=-frequency+1e-10; an unevaluable lower endpoint is treated as infinite price. Start hi at one and double it, up to eighty times, until its internal price is no greater than target. Reject an unreachable target or propagate an unhandled evaluation error.

Bisect with ordinary arithmetic midpoint (lo+hi)/2 for up to 2,200 iterations. Return an exact-price midpoint immediately. Otherwise move lo upward when its price is above target and hi downward when below. Stop when the midpoint can no longer lie strictly between the stored bounds, then choose the endpoint with smaller absolute price residual; a tie chooses hi. This is an arithmetic-midpoint search, distinct from the encoding-midpoint distribution inverses.

For the one-coupon example, C=3, A=90, E=180 and S=90. The first ratio is 103/101.5; subtracting one and multiplying by 2*180/90=4 gives about 0.0591133005.

Microsoft documents a one-coupon formula and a hundred-iteration Newton method for longer bonds. The current candidate instead uses the bisection route above. Its internal price callback, root selection, return rounding and remaining report differences are not fully identified. The pinned source’s explicit split between PRICE and YIELD is a limit to retain, rather than an algebraic identity to remove.

Rust code

Show the CalcFunc source of this function

Quoted from the public repository DnaCalc/DnaCalc, crates calc-func and calc-fml, at commit 9e1884369a67. Comments are the source's own. A kernel shared with other functions appears once, on its module page.

YIELD · 9 lines · calc-func/src/catalogue/bonds.rs on GitHub
2 yield_fn "YIELD" (6, 7) [V "settlement", V "maturity", V "rate", V "pr", V "redemption", V "frequency", V "basis"] |s, a, sv| {
    let settlement = yield_date(s, a, 0, sv)?;
    let maturity = yield_date(s, a, 1, sv)?;
    let (rate, price, redemption) = (required_num(s, a, 2)?, required_num(s, a, 3)?, required_num(s, a, 4)?);
    // Fn8 adjacent-error controls read basis before frequency in YIELD.
    let basis = if given(a, 6) { num_without_logical(s, a, 6)? } else { 0.0 };
    let frequency = required_num(s, a, 5)?;
    bond_out(s, bond::yield_kernel(settlement, maturity, rate, price, redemption, frequency, Some(basis)))
}
pcomp · 13 lines · calc-func/src/ported/bond_core_family.rs on GitHub
fn pcomp(
    rate: f64,
    yld: f64,
    red: f64,
    c: Ctx,
    p: Period,
) -> Result<(f64, f64, f64, f64, f64), BondCoreEvalError> {
    // `binexp = false` keeps the legacy `powf` discount path. Callers that need Excel's
    // C-runtime integer-`pow` staging (PRICE) pass `true`; YIELD's solver and DURATION keep
    // `false` until their own identifications land (the forward fix is coupled to the YIELD
    // schedule — see the workset notes).
    pcomp_disc(rate, yld, red, c, p, false)
}
solve · 48 lines · calc-func/src/ported/bond_core_family.rs on GitHub
fn solve(
    target: f64,
    f: i64,
    fun: impl Fn(f64) -> Result<f64, BondCoreEvalError>,
) -> Result<f64, BondCoreEvalError> {
    let low = -(f as f64) + 1e-10;
    // Price → +∞ as yield → -frequency, but the price kernel can overflow/reject
    // that near-degenerate endpoint. Treat an un-evaluable low-yield endpoint as
    // an effectively infinite price so the "is the target achievable" guard does
    // not spuriously fail a well-posed bond (BUG-FUNC-031). The bisection below
    // moves off `low` on its first step, so it never re-probes the endpoint.
    let lowp = fun(low).unwrap_or(f64::INFINITY);
    if target > lowp {
        return Err(derr(WorksheetErrorCode::Num));
    }
    let mut hi = 1.0;
    let mut hip = fun(hi)?;
    let mut g = 0;
    while hip > target && g < 80 {
        hi *= 2.0;
        hip = fun(hi)?;
        g += 1;
    }
    if hip > target {
        return Err(derr(WorksheetErrorCode::Num));
    }
    // Bisection to adjacent binary64 bounds (full convergence, dc-ifc: Excel's YIELD converges
    // past the former 1e-15 price tolerance), then the bound with the smaller residual.
    let mut lo = low;
    let mut hh = hi;
    for _ in 0..2200 {
        let mid = (lo + hh) / 2.0;
        if mid <= lo || mid >= hh {
            break;
        }
        let mp = fun(mid)?;
        if mp == target {
            return Ok(mid);
        }
        if mp > target { lo = mid } else { hh = mid }
    }
    let (lo_res, hi_res) = (fun(lo).map(|v| (v - target).abs()), fun(hh).map(|v| (v - target).abs()));
    Ok(match (lo_res, hi_res) {
        (Ok(a), Ok(b)) if a < b => lo,
        (Ok(_), Err(_)) => lo,
        _ => hh,
    })
}
yield_kernel · 40 lines · calc-func/src/ported/bond_core_family.rs on GitHub
pub fn yield_kernel(
    settlement: f64,
    maturity: f64,
    rate_: f64,
    price: f64,
    red: f64,
    frequency: f64,
    basis_: Option<f64>,
) -> Result<f64, BondCoreEvalError> {
    let c = ctx(settlement, maturity, frequency, basis_)?;
    let p = period(c)?;
    let rate_ = rate(rate_)?;
    let price = pos(price)?;
    let red = pos(red)?;
    // On a coupon date, a multi-period bond priced and redeemed at its 100 face value
    // has yield equal to its coupon rate. At y=rate, the geometric coupon
    // sum 100*c*sum((1+c)^-k) plus redemption 100*(1+c)^-n is 100.
    // Return that exact algebraic root before the iterative price inversion.
    // Preserve the existing coupon-overflow route. The build 20228 bank has
    // both short and long par observations; wider Excel coverage stays open.
    if p.n > 1 && c.settlement == p.prev && price == 100.0 && red == 100.0
        && (100.0 * rate_ / c.frequency as f64).is_finite()
    {
        return Ok(rate_);
    }
    if p.n == 1 {
        let coup = 100.0 * rate_ / c.frequency as f64;
        let e = dc(p.prev, p.next, c.basis, c.frequency)?;
        let a = dd(p.prev, c.settlement, c.basis)?;
        let dsc = dd(c.settlement, p.next, c.basis)?;
        return Ok((((red + coup) / (price + coup * a / e)) - 1.0) * c.frequency as f64 * e / dsc);
    }
    // Solve over candidate yields with `pcomp` directly. `price_kernel` rejects
    // `yld < 0` via `rate(yld)`, but the root-finder must probe negative candidate
    // yields (its bracket runs down to `-frequency`); `pcomp`'s own guards
    // (`yld <= -frequency`, `base <= 0`) keep the domain correct (BUG-FUNC-031).
    solve(price, c.frequency, |cand| {
        Ok(pcomp(rate_, cand, red, c, p)?.0)
    })
}

Kernels shared with other functions

Argument and result plumbing

No implementation has been published with a Handbook test suite for this function.

Version differences

The recorded environments below distinguish a reading from a same-input comparison. Counts describe captured inputs in each environment; overlapping captures and comparisons are not totals of unique worksheet calls.

Excel 16.0 buildPlatform and CPUCaptured inputs
20228Windows, 64-bit, CPU not recorded504

The record contains no same-input comparison between these environments. Reading different inputs on different builds does not establish either a version change or cross-build agreement.

Recorded environments and comparison details.

Excel 16.0 build 20228

Windows, 64-bit, CPU not recorded

504 captured inputs are indexed for this environment. Capture dates: 2026-08-09 to 2026-08-09. This is a reading count, not a comparison with another build.

Alternatives

PRICE performs the inverse calculation; ODDFPRICE and ODDLPRICE handle irregular coupons.

Named variants

No named variants are recorded yet.

Suggest a correction or contribute an implementation · For agents