TBILLEQ(settlement, maturity, discount) returns the bond-equivalent yield of a Treasury bill:
the yield that lets a bill quoted at a bank-discount rate be compared with a coupon bond.
A bill's price per 100 follows from its discount rate d and the actual day count DSM:
price = 100 × (1 − d × DSM/360)
Write p = price/100. What happens next depends on how long the bill runs, and Microsoft's page
describes only one of the two cases.
Microsoft's page
What Excel does
DSM up to 182
(365 × rate) / (360 − rate × DSM)
The same formula
DSM above 182
The same formula
The quadratic below
DSM as a count
"computed according to the 360 days per year basis"
Actual days
For the bill of 182 days or fewer, the two forms below are the same number:
with t = DSM/365, as recorded in the notes below. Microsoft's page does not mention 182 days or
this expression. Both accounts are shown here because they differ, and on the note's own row the
difference is large: 203 days at a discount of about 21.2%, where the documented formula gives
0.244038 and Excel gives 0.241103.
Where the quadratic comes from
A coupon bond pays every half year, so a bill longer than about half a year has to be compared with
a bond that has already paid once. The standard construction lets the first half year earn y/2,
with the interest reinvested, and the rest of the span earn simple interest at y:
p × (1 + y/2) × (1 + y × (t − 1/2)) = 1
Expanding gives a quadratic in y, and its positive root is the expression above. That is algebra
from the construction; Microsoft does not state it.
The table shows how the two compare at a 5% discount. These are formula values, not Excel readings.
DSM
Documented formula
Quadratic
Excel's branch
91
0.051343
not applied
documented
182
0.052009
0.052013
documented
183
0.052017
0.052013
quadratic
270
0.052670
0.052228
quadratic
364
0.053394
0.052701
quadratic
The 366-day bill
The note writes t = DSM/365, and that holds with one exception. All 33 numeric rows with
DSM = 366 (for example 13 July 2047 to 13 July 2048, a span that crosses a 29 February) fit
t = 1, that is 366/366, and do not fit 366/365. The 95 rows of shorter long bills across a 29
February keep 365. The one reading at this length, from serial 0 to serial 366, agrees.
The documented DSM wording
Microsoft says DSM is computed on a 360-day-year basis. Its own example does not bear that out:
31 March 2008 to 1 June 2008 at 9.14% gives 0.0941515 with 62 actual days, matching the 9.42%
Microsoft shows, whereas a 30/360 count of 61 gives 0.0941272, or 9.41%. The note's row is 203
actual days where 30/360 would give 200. The 360 in the formula is the year length of the discount
quotation; the day count is actual.
Arguments
Argument
Meaning
Default
settlement
The bill's settlement date, the date after issue when it trades to the buyer. Required.
—
maturity
The date the bill expires. Required.
—
discount
The bill's discount rate, as a decimal fraction. Required.
—
There is no basis. The day count is always actual, and the conventions in the formulas are fixed.
Dates are documented as truncated to integers, and 205 of the 2,400 rows behind the notes carry a
fractional date that fits this.
discount is the bank-discount quotation, not a price and not a yield. The function that takes a
price is TBILLYIELD.
Date arguments do not follow the ordinary to-number rules. Logicals are refused with #VALUE!
in all three slots, including FALSE. An empty cell as settlement reads as serial 0 and gives a
normal answer, as the notes below record: TBILLEQ(B1,5,0.1) is 36.5/359.5. A direct 0 gives
the same answer. See Coercion and lifting for the shared
model these depart from.
Try it
Quirks
Result and edge cases
Returns Number, an annualized yield as a decimal fraction.
Figures in this section and the next are from the 2,400 rows behind the notes below (Excel 16.0
build 20430, Windows 64-bit, AMD Ryzen 7 4800H) unless marked as a reading. Readings are from Excel
16.0.20527.20088 on Windows, with bitness and CPU not recorded in the reading file.
The branch point is exact in the rows. The 992 numeric rows with DSM ≤ 182 fit the documented
formula, including 48 at 182. The 712 numeric rows above it fit the quadratic, including 91 at 183.
No row above 182 fits the documented formula.
A non-positive price is refused. Where d × DSM/360 ≥ 1 the bill would have no positive price,
and all 25 such rows inside the one-year limit return #NUM!.
The one-year limit is a calendar rule. The bound is the same month and day a year on, not a
count of days. A 366-day bill across a 29 February is allowed. From 28 February of the year before
a leap year, maturity on 29 February a year later is #NUM! (2 rows), although that is the last
day of the month. From 29 February, the 28 February a year later is allowed, and 2 March is #NUM!.
Serial 0 works as a settlement date. Readings give numbers for maturities of serial 1, 5, 365
and 366, and #NUM! for serial 367.
The order of arguments decides which error appears. Readings show the first failing argument
wins: TBILLEQ(#REF!,TRUE,0.1) is #REF! and TBILLEQ(TRUE,#REF!,0.1) is #VALUE!.
Errors
Error
Condition
Source
#VALUE!
settlement or maturity is not a valid date
Documented; see below
#NUM!
discount ≤ 0
Documented; 60 rows inside the limit
#NUM!
Maturity more than one year after settlement
Documented; 541 rows with no other fault
#NUM!
settlement > maturity
Documented; reading at serial 1 and 0
#NUM!
settlement = maturity
Not documented; one reading
#NUM!
d × DSM/360 ≥ 1
Not documented; 25 rows
#NUM!
A negative or past-year-9999 serial
Differs from documentation; readings
#VALUE!
A logical in any slot
Not documented; readings
Three of these depart from Microsoft's page, and both accounts are shown:
Microsoft's TBILLEQ page says settlement > maturity, where its TBILLYIELD page says
settlement ≥ maturity. The formula has a value at DSM = 0, so the difference is not vacuous. A
reading of TBILLEQ(0,0,0.1) returns #NUM!. That is the only equal-dates reading.
Microsoft says an invalid date is #VALUE!. Readings of settlement −1, −0.5 and 2958466 (the
first serial past 31 December 9999) all return #NUM!, so an out-of-range number is not treated
that way. The #VALUE! measured for a date argument is the logical one.
Microsoft does not mention a price that reaches zero.
For bills longer than 182 days TBILLEQ is a quadratic, not the documented formula
When DSM is above 182, TBILLEQ does not use the documented formula. It uses the bond-equivalent quadratic (-t + sqrt(t^2 - (2t-1)(1 - 1/p))) / (t - 1/2), with t = DSM/365 and p = price/100. At DSM 366, a bill across a 29 February, t is 1 and not 366/365. The square root is taken in extended precision and stored, RN53(RN64(sqrt)); the rest is binary64. For the row below, DSM 203, the documented formula gives 0.244038 and Excel 0.241103. Excel's bits are 22 units below the correctly rounded quadratic because of that staging.
Formula
Excel
Mathematical value
TBILLEQ(40633.25, 40836.25, 0.21193100748125787) Excel 16.0 build 20430, Windows 64-bit, AMD Ryzen 7 4800HInputs and reference value
Number supplied through a cell.
settlement: 40633.25 0x40e3d72800000000
maturity: 40836.25 0x40e3f08800000000
discount: 0.21193100748125787 0x3fcb208e2511f676
mpmath at 800 bits: the exact quadratic at the binary64 inputs, correctly rounded.
0.24110326418450792 0x3fcedc78c550cec1
0.24110326418450853 0x3fcedc78c550ced7
TBILLEQ(53886, 54252, 0.4522540814812992) Excel 16.0 build 20430, Windows 64-bit, AMD Ryzen 7 4800HInputs and reference value
An empty cell as a first date is serial 0, but a logical in that cell is #VALUE!
A reference to an empty cell as the first date of these functions reads as serial 0 and gives a normal answer: NETWORKDAYS(B1,5) is 4 and WORKDAY(B1,2) is 3. YEARFRAC(B1,5,0) is 5/360. TRUE in the same cell gives #VALUE!, as a direct TRUE does, so a blank is not treated as the logical FALSE either.
Formula
Excel
Mathematical value
=NETWORKDAYS(B1,5) Excel 16.0.20527.20088 Current Channel, Windows 64-bit (NT 10.0.26200), x86-64, AMD Ryzen 7 4800H, en-ZAInputs and reference value
Number supplied through a cell.
B1: (empty cell)
4 0x4010000000000000
—
=NETWORKDAYS(B1,5) Excel 16.0.20527.20088 Current Channel, Windows 64-bit (NT 10.0.26200), x86-64, AMD Ryzen 7 4800H, en-ZAInputs and reference value
Number supplied through a cell.
B1: TRUE
#VALUE!
—
=WORKDAY(B1,2) Excel 16.0.20527.20088 Current Channel, Windows 64-bit (NT 10.0.26200), x86-64, AMD Ryzen 7 4800H, en-ZAInputs and reference value
Number supplied through a cell.
B1: (empty cell)
3 0x4008000000000000
—
=WORKDAY(B1,2) Excel 16.0.20527.20088 Current Channel, Windows 64-bit (NT 10.0.26200), x86-64, AMD Ryzen 7 4800H, en-ZAInputs and reference value
Number supplied through a cell.
B1: TRUE
#VALUE!
—
=NETWORKDAYS.INTL(B1,5,1) Excel 16.0.20527.20088 Current Channel, Windows 64-bit (NT 10.0.26200), x86-64, AMD Ryzen 7 4800H, en-ZAInputs and reference value
Number supplied through a cell.
B1: (empty cell)
4 0x4010000000000000
—
=WORKDAY.INTL(B1,2,1) Excel 16.0.20527.20088 Current Channel, Windows 64-bit (NT 10.0.26200), x86-64, AMD Ryzen 7 4800H, en-ZAInputs and reference value
Number supplied through a cell.
B1: (empty cell)
3 0x4008000000000000
—
=YEARFRAC(B1,5,0) Excel 16.0.20527.20088 Current Channel, Windows 64-bit (NT 10.0.26200), x86-64, AMD Ryzen 7 4800H, en-ZAInputs and reference value
Number supplied through a cell.
B1: (empty cell)
0.013888888888888888 0x3f8c71c71c71c71c
—
=TBILLEQ(B1,5,0.1) Excel 16.0.20527.20088 Current Channel, Windows 64-bit (NT 10.0.26200), x86-64, AMD Ryzen 7 4800H, en-ZAInputs and reference value
The first branch is plain. One multiplication, one subtraction and one division. It has a pole
at d × DSM = 360, which is where the price reaches zero, and Excel refuses from there on.
The second branch has a cancellation site. The numerator is −t plus a square root that is close
to t, and it is small when the yield is small or t is close to 1/2. The denominator t − 1/2 is
smallest at DSM = 183, where it is 1/730. The expression cannot be evaluated at t = 1/2, and
the integer day count keeps it away, because DSM = 182.5 does not exist.
The exact arithmetic. The note records how the square root is staged, and why Excel's answer on
its row sits 22 units below the correctly rounded value of the quadratic. Reproducing Excel means
following that staging, not computing the quadratic more accurately. The note's count applies to
the same 2,400 rows, and one row separates the staged result from the plain one, so this is a small
effect measured on few rows.
Discriminant. The value under the square root was positive on all 712 long-bill rows that
reached it, so no row shows what a negative value would do. For 0 < p < 1 and t > 1/2 the term
−(2t − 1)(1 − 1/p) is positive, so it does not arise on admissible inputs.
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.
/// TBILLEQ for bills of more than 182 days: Excel switches to the bond-equivalent yield of a/// bill longer than one coupon period, the root of a quadratic in the price. With/// t = dsm / year and p = price / 100:////// TBILLEQ = (-t + sqrt(t*t - (2t - 1) * (1 - 1/p))) / (t - 0.5)////// `year` is 365, except that a 366-day bill (possible only across a Feb 29) uses 366, so t = 1./// The shared staged SQRT resolves the recorded cancellation discrepancy in/// the long-bill numerator; all 2,400 TBILLEQ bank outcomes agree at R23.fntbilleq_long_bill(dsm: f64, discount: f64) -> Result<f64, DiscountBillYearfracEvalError> {
let num = || DiscountBillYearfracEvalError::Domain(WorksheetErrorCode::Num);
let price = 100.0 - discount * 100.0 * dsm / 360.0;
if price <= 0.0 {
returnErr(num());
}
let year = if dsm == 366.0 { 366.0 } else { 365.0 };
let t = dsm / year;
let term = 1.0 - 1.0 / (price / 100.0);
let disc = t * t - (2.0 * t - 1.0) * term;
if disc < 0.0 {
returnErr(num());
}
Ok((-t + crate::ported::excel_numeric::excel_sqrt_staged(disc)) / (t - 0.5))
}
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 build
Platform and CPU
Captured inputs
20430
Windows, 64-bit, AMD Ryzen 7 4800H with Radeon Graphics
2,400
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.
TBILLEQ(40633.25, 40836.25, 0.21193100748125787) returned 0.24110326418450792 (0x3fcedc78c550cec1). TBILLEQ(53886, 54252, 0.4522540814812992) returned 0.7211303677406913 (0x3fe7137ffe3328bc). Inputs were supplied through cells using Value2. These are controls from this environment, not a same-input comparison with another build.
Windows 64-bit (NT 10.0.26200), x86-64, AMD Ryzen 7 4800H, en-ZA
=TBILLEQ(B1,5,0.1) returned 0.10152990264255911 (0x3fb9fddd1b6a757f). Inputs were supplied through cells using Value2. These are controls from this environment, not a same-input comparison with another build.
Windows, 64-bit, AMD Ryzen 7 4800H with Radeon Graphics
2,400 captured inputs are indexed for this environment. Capture dates: 2026-09-24 to 2026-09-25. This is a reading count, not a comparison with another build.
Alternatives
Relationships
TBILLYIELD — the yield of the same bill from its price, on a 360-day
year and with no long-bill branch. Up to 182 days, on the same bill,
TBILLEQ = TBILLYIELD × 365/360. Above that the relation fails.
TBILLPRICE — the price from the discount, which is the first step of this function.
DISC — the general discount quotation with a basis. The T-bill functions fix
the convention and add the one-year limit.
INTRATE — the simple rate on the investment. For bills up to 182 days,
TBILLEQ is INTRATE on an actual/365 footing.
YIELD — the coupon-bond yield that a bond-equivalent yield is built to be compared with.