Financial functions

ODDLYIELD

Matches all 6 recorded answers

Recorded: 6 workbook cells. How we measure this · See the Rust code

Local names in 40 languages
LanguageName in Excel
ArabicODDLYIELD
BulgarianODDLYIELD
CzechODDLYIELD
DanishULIGE.SIDSTE.AFKAST
GermanODDLYIELD
GreekODDLYIELD
English (Australia)ODDLYIELD
English (United Kingdom)ODDLYIELD
English (United States)ODDLYIELD
SpanishRENDTO.PER.IRREGULAR.2
EstonianODDLYIELD
FinnishPARITON.VIIM.TUOTTO
FrenchREND.DCOUPON.IRREG
HebrewODDLYIELD
CroatianODDLYIELD
HungarianELTÉRŐ.UHOZAM
IndonesianODDLYIELD
ItalianODDLYIELD
JapaneseODDLYIELD
KoreanODDLYIELD
LithuanianODDLYIELD
LatvianODDLYIELD
NorwegianAVVIKSP.AVKASTNING
DutchAFW.LT.REND
PolishRENT.OST.OKR
Portuguese (Brazil)ODDLYIELD
Portuguese (Portugal)LUCROÚLTINC
RomanianODDLYIELD
RussianДОХОДПОСЛНЕРЕГ
SlovakODDLYIELD
SlovenianODDLYIELD
Serbian (Latin)ODDLYIELD
SwedishUDDASAVKASTNING
ThaiODDLYIELD
TurkishTEKSÖDEME işlevi
UkrainianODDLYIELD
VietnameseODDLYIELD
Chinese (Simplified)ODDLYIELD
Chinese (Hong Kong)ODDLYIELD
Chinese (Traditional)ODDLYIELD

Names from Microsoft's support site.

What it does

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

ODDLYIELD solves annual yield from price for a security with an irregular last coupon. Its dates are settlement, maturity and last_interest. They are followed by coupon rate, price, redemption, frequency and optional basis.

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.

=ODDLYIELD(DATE(2027,8,1),DATE(2027,11,1),DATE(2027,4,1),0.06,101.5,100,2,0) gives a yield near zero. The last coupon spans April to November, seven 30/360 months. Its coupon is 3.5 and accrued interest at August settlement is two. At zero yield the clean price is 100+3.5-2=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. The required date order is last_interest < settlement < maturity. Frequency is one, two or four. Negative coupon rate, invalid selectors and invalid amount/domain cases produce errors. These schedules cannot be reduced to PRICE by changing one date.

How to implement

Build quasi-coupon periods from last_interest, accumulate normalized issue-to-maturity, accrued and remaining fractions, and solve the final simple-discount equation for yield. The current last-yield helper uses a direct algebraic formula rather than the odd-first root solver. The worked zero-yield example isolates the coupon and accrual arithmetic from discount powers. Calendar seams, long/short-period branches and residual numerical differences remain open where the recorded reports say so. The family combines a credited Apache-licensed ExcelFinancialFunctions translation in its odd-first kernel and calendar helpers with project-owned kernels and changes guided by recorded Excel answers.

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.

ODDLYIELD · 4 lines · calc-func/src/catalogue/bonds.rs on GitHub
26 oddlyield_fn "ODDLYIELD" (7, 8) [V "settlement", V "maturity", V "last_interest", V "rate", V "pr", V "redemption", V "frequency", V "basis"] |s, a, sv| {
    let dates = [date_1900(s, a, 0, sv)?, date_1900(s, a, 1, sv)?, date_1900(s, a, 2, sv)?];
    odd_out(s, odd::oddlyield_kernel(dates[0], dates[1], dates[2], num(s, a, 3)?, num(s, a, 4)?, num(s, a, 5)?, num(s, a, 6)?, basis(s, a, 7)?))
}
oddlyield_kernel · 81 lines · calc-func/src/ported/odd_bond_family.rs on GitHub
pub fn oddlyield_kernel(
    settlement: f64,
    maturity: f64,
    last_interest: f64,
    rate: f64,
    pr: f64,
    redemption: f64,
    frequency: f64,
    basis: Option<f64>,
) -> Result<f64, OddBondEvalError> {
    validate_positive_inputs(&[
        settlement,
        maturity,
        last_interest,
        rate,
        pr,
        redemption,
        frequency,
    ])?;
    if rate < 0.0 || pr < 0.0 || redemption <= 0.0 {
        return Err(OddBondEvalError::Domain(WorksheetErrorCode::Num));
    }
    let settlement = parse_date_serial(settlement)?;
    let maturity = parse_date_serial(maturity)?;
    let last_interest = parse_date_serial(last_interest)?;
    let frequency = parse_frequency(frequency)?;
    let basis = parse_basis(basis.unwrap_or(0.0))?;
    if !(last_interest < settlement && settlement < maturity) {
        return Err(OddBondEvalError::Domain(WorksheetErrorCode::Num));
    }
    let months_per_coupon = 12 / frequency;
    let mut nc = 0i64;
    let mut cursor = last_interest;
    while cursor < maturity {
        cursor = add_months_clamped(cursor, months_per_coupon)
            .ok_or(OddBondEvalError::Domain(WorksheetErrorCode::Num))?;
        nc += 1;
        if nc > 64 {
            return Err(OddBondEvalError::Domain(WorksheetErrorCode::Num));
        }
    }
    let mut early_coupon = last_interest;
    let mut dcnl = 0.0;
    let mut anl = 0.0;
    let mut dscnl = 0.0;
    for index in 1..=nc {
        let late_coupon = add_months_clamped(early_coupon, months_per_coupon)
            .ok_or(OddBondEvalError::Domain(WorksheetErrorCode::Num))?;
        let nl = day_count_non_negative_with_us_hack(early_coupon, late_coupon, basis)?;
        if nl <= 0.0 {
            return Err(OddBondEvalError::Domain(WorksheetErrorCode::Num));
        }
        let dci = if index < nc {
            nl
        } else {
            day_count_non_negative_with_us_hack(early_coupon, maturity, basis)?
        };
        let a = if late_coupon < settlement {
            dci
        } else if early_coupon < settlement {
            day_count_non_negative(early_coupon, settlement, basis)?
        } else {
            0.0
        };
        let start_date = settlement.max(early_coupon);
        let end_date = maturity.min(late_coupon);
        let dsc = day_count_non_negative(start_date, end_date, basis)?;
        early_coupon = late_coupon;
        dcnl += dci / nl;
        anl += a / nl;
        dscnl += dsc / nl;
    }
    if dscnl <= 0.0 {
        return Err(OddBondEvalError::Domain(WorksheetErrorCode::Num));
    }
    let x = 100.0 * rate / frequency as f64;
    let term1 = dcnl * x + redemption;
    let term2 = anl * x + pr;
    let term3 = frequency as f64 / dscnl;
    Ok((term1 - term2) / term2 * term3)
}

Kernels shared with other functions

Argument and result plumbing

  • fail catalogue/kit
  • num catalogue/kit

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

Version differences

No same-input comparison between named Excel builds is recorded for this function here. The documented behaviour below is not a measurement of every Excel release.

Alternatives

ODDLPRICE prices the same last-coupon schedule at a supplied yield. ODDFYIELD handles an irregular first coupon; YIELD handles regular coupons.

Named variants

No named variants are recorded yet.

Suggest a correction or contribute an implementation · For agents