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.
Financial functions
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
| Language | Name in Excel |
|---|---|
| Arabic | العائد |
| Bulgarian | ДОБИВ |
| Czech | YIELD |
| Danish | AFKAST |
| German | RENDITE |
| Greek | ΑΠΟΔΟΣΗ |
| English (Australia) | YIELD |
| English (United Kingdom) | YIELD |
| English (United States) | YIELD |
| Spanish | RENDTO |
| Estonian | YIELD |
| Finnish | TUOTTO |
| French | RENDEMENT.TITRE |
| Hebrew | YIELD |
| Croatian | YIELD |
| Hungarian | HOZAM |
| Indonesian | HASIL |
| Italian | REND |
| Japanese | YIELD |
| Korean | YIELD |
| Lithuanian | YIELD |
| Latvian | ATDEVE |
| Norwegian | AVKAST |
| Dutch | OPBRENGST |
| Polish | PLON |
| Portuguese (Brazil) | RENDIMENTO |
| Portuguese (Portugal) | LUCRO |
| Romanian | PRODUCȚIE |
| Russian | ДОХОД |
| Slovak | VÝNOS |
| Slovenian | YIELD |
| Serbian (Latin) | YIELD |
| Swedish | AVKASTNING |
| Thai | YIELD |
| Turkish | ÖDEME |
| Ukrainian | ПРИБУТОК |
| Vietnamese | HOA LỢI |
| Chinese (Simplified) | YIELD |
| Chinese (Hong Kong) | YIELD |
| Chinese (Traditional) | YIELD |
Names from Microsoft's support site.
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.
=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.
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.
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.
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.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.
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 GitHub2 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 GitHubfn 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 GitHubfn 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 GitHubpub 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)
})
}
basis catalogue/bondsyield_date catalogue/bondsbond_out catalogue/bondsrequired_number catalogue/financialrequired_num catalogue/financialdate_1900 catalogue/financialdays_from_civil localecivil_from_days localeexcel_serial_from_ymd localeymd_from_excel_serial localemax_serial ported/bond_core_familyderr ported/bond_core_familydyear ported/bond_core_familydim ported/bond_core_familyact ported/bond_core_familybasis ported/bond_core_familyfreq ported/bond_core_familydser ported/bond_core_familypos ported/bond_core_familyrate ported/bond_core_familyaddm ported/bond_core_familyd360us ported/bond_core_familyd360eu ported/bond_core_familydc ported/bond_core_familydd ported/bond_core_familyctx ported/bond_core_familyperiod ported/bond_core_familyexcel_bond_pow ported/bond_core_familypcomp_disc ported/bond_core_familymap_bond_core_error_to_ws ported/bond_core_familydays_in_month ported/day_count_commonus_30_360 ported/day_count_commonbinary_with ported/excel_numericexcel_pow_chain ported/excel_numericexcel_x87_mul ported/excel_numericmul ported/excel_numeric/x87pow2_positive ported/excel_numeric/x87_chainspow2 ported/excel_numeric/x87_chainsexp_ext ported/excel_numeric/x87_chainsexp_with ported/excel_numeric/x87_chainsexcel_exp ported/excel_numeric/x87_chainslog_with ported/excel_numeric/x87_chainsexcel_log ported/excel_numeric/x87_chainschecked_date_serial catalogue/kitfail catalogue/kitgiven catalogue/kitnum catalogue/kitnum_without_logical catalogue/kitreject_logical catalogue/kitNo implementation has been published with a Handbook test suite for this function.
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 build | Platform and CPU | Captured inputs |
|---|---|---|
| 20228 | Windows, 64-bit, CPU not recorded | 504 |
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.
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.
PRICE performs the inverse calculation; ODDFPRICE and ODDLPRICE handle irregular coupons.
No named variants are recorded yet.
Suggest a correction or contribute an implementation · For agents