The price of a bond is the present value of all its future expected cash flows. These cash flows consist of periodic coupon payments and the final return of the face value (par value) at maturity. Because money received today is worth more than the same amount in the future, we "discount" these future payments using a rate called the Yield to Maturity (YTM).
The Bond Pricing Formula
Our calculator uses the standard formula for valuing fixed-rate bonds:
C: Coupon payment per period (Face Value × Coupon Rate / Frequency)
r: Yield to maturity per period (YTM / Frequency)
n: Total number of periods (Years × Frequency)
F: Face Value of the bond
Premium vs. Discount Bonds
The relationship between the Coupon Rate and the Yield to Maturity determines the market price:
Discount Bond: If YTM > Coupon Rate, the bond sells for less than its face value.
Premium Bond: If YTM < Coupon Rate, the bond sells for more than its face value.
Par Bond: If YTM = Coupon Rate, the bond price equals its face value.
Real-World Example
Suppose you have a bond with a $1,000 Face Value, a 5% Coupon Rate, and 10 years until it matures. If the current market interest rate (YTM) for similar risk bonds is 4%, and it pays semi-annually:
Coupon payment (C) = ($1,000 * 0.05) / 2 = $25
Periodic rate (r) = 0.04 / 2 = 0.02 (2%)
Total periods (n) = 10 * 2 = 20
Using the formula, the market price would be approximately $1,081.76. Since the coupon (5%) is higher than the market yield (4%), the bond trades at a Premium.
function calculateBondPrice() {
var faceValue = parseFloat(document.getElementById('faceValue').value);
var annualCouponRate = parseFloat(document.getElementById('couponRate').value) / 100;
var annualYTM = parseFloat(document.getElementById('ytm').value) / 100;
var years = parseFloat(document.getElementById('years').value);
var frequency = parseInt(document.getElementById('frequency').value);
if (isNaN(faceValue) || isNaN(annualCouponRate) || isNaN(annualYTM) || isNaN(years)) {
alert("Please enter valid numeric values in all fields.");
return;
}
var r = annualYTM / frequency;
var n = years * frequency;
var c = (faceValue * annualCouponRate) / frequency;
var bondPrice = 0;
// Handle zero YTM case to avoid division by zero
if (r === 0) {
bondPrice = (c * n) + faceValue;
} else {
// Present Value of Annuity (Coupons)
var pvCoupons = c * (1 – Math.pow(1 + r, -n)) / r;
// Present Value of Face Value
var pvFaceValue = faceValue / Math.pow(1 + r, n);
bondPrice = pvCoupons + pvFaceValue;
}
// Display Results
var resultBox = document.getElementById('result-box');
var priceDisplay = document.getElementById('bondPriceResult');
var statusDisplay = document.getElementById('bondStatus');
resultBox.style.display = 'block';
priceDisplay.innerHTML = '$' + bondPrice.toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2});
if (bondPrice > faceValue + 0.01) {
statusDisplay.innerHTML = "Trading at a PREMIUM";
statusDisplay.style.color = "#2f855a";
} else if (bondPrice < faceValue – 0.01) {
statusDisplay.innerHTML = "Trading at a DISCOUNT";
statusDisplay.style.color = "#c53030";
} else {
statusDisplay.innerHTML = "Trading at PAR";
statusDisplay.style.color = "#2b6cb0";
}
// Scroll to results on mobile
resultBox.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
}