[ { "name": "Microsoft's YIELD example: 5.75% to 2016 at 95.04287 on 30/360 is 6.5%", "args": [ "2008-02-15", "2016-11-15", 575, "95.04287", 2, "30-360" ], "expect": { "yieldBasisPoints": 650, "yieldToMaturity": "0.065000007", "currentYieldBasisPoints": 605, "accruedInterest": "1.437500", "dirtyPrice": "96.480370", "previousCoupon": "2007-11-15", "nextCoupon": "2008-05-15", "couponsRemaining": 18 } }, { "name": "the same bond on actual/actual: 92 of 182 days accrued", "args": [ "2008-02-15", "2016-11-15", 575, "95.04287", 2, "act-act" ], "expect": { "yieldBasisPoints": 650, "yieldToMaturity": "0.065001821", "currentYieldBasisPoints": 605, "accruedInterest": "1.453297", "dirtyPrice": "96.496167", "previousCoupon": "2007-11-15", "nextCoupon": "2008-05-15", "couponsRemaining": 18 } }, { "name": "a gilt-style 4.25% semi-annual on actual/actual", "args": [ "2025-09-23", "2027-12-07", 425, "101.5", 2, "act-act" ], "expect": { "yieldBasisPoints": 353, "yieldToMaturity": "0.035347152", "currentYieldBasisPoints": 419, "accruedInterest": "1.254098", "dirtyPrice": "102.754098", "previousCoupon": "2025-06-07", "nextCoupon": "2025-12-07", "couponsRemaining": 5 } }, { "name": "settling on a coupon date accrues nothing", "args": [ "2025-12-07", "2027-12-07", 425, "101.5", 2, "act-act" ], "expect": { "yieldBasisPoints": 347, "yieldToMaturity": "0.034672155", "currentYieldBasisPoints": 419, "accruedInterest": "0.000000", "dirtyPrice": "101.500000", "previousCoupon": "2025-12-07", "nextCoupon": "2026-06-07", "couponsRemaining": 4 } }, { "name": "at par on a coupon date the yield is the coupon, exactly", "args": [ "2026-06-15", "2036-06-15", 450, "100", 2, "30-360" ], "expect": { "yieldBasisPoints": 450, "yieldToMaturity": "0.045000000", "currentYieldBasisPoints": 450, "accruedInterest": "0.000000", "dirtyPrice": "100.000000", "previousCoupon": "2026-06-15", "nextCoupon": "2026-12-15", "couponsRemaining": 20 } }, { "name": "inside the last period: Excel's simple-yield formula", "args": [ "2027-09-01", "2027-12-07", 425, "99.8", 2, "act-act" ], "expect": { "yieldBasisPoints": 496, "yieldToMaturity": "0.049649871", "currentYieldBasisPoints": 426, "accruedInterest": "0.998634", "dirtyPrice": "100.798634", "previousCoupon": "2027-06-07", "nextCoupon": "2027-12-07", "couponsRemaining": 1 } }, { "name": "inside the last period on 30/360", "args": [ "2027-09-01", "2027-12-07", 425, "99.8", 2, "30-360" ], "expect": { "yieldBasisPoints": 496, "yieldToMaturity": "0.049607276", "currentYieldBasisPoints": 426, "accruedInterest": "0.991667", "dirtyPrice": "100.791667", "previousCoupon": "2027-06-07", "nextCoupon": "2027-12-07", "couponsRemaining": 1 } }, { "name": "annual coupons", "args": [ "2026-03-10", "2031-06-15", 300, "97.25", 1, "30-360" ], "expect": { "yieldBasisPoints": 358, "yieldToMaturity": "0.035802953", "currentYieldBasisPoints": 308, "accruedInterest": "2.208333", "dirtyPrice": "99.458333", "previousCoupon": "2025-06-15", "nextCoupon": "2026-06-15", "couponsRemaining": 6 } }, { "name": "quarterly coupons", "args": [ "2026-01-20", "2029-04-15", 500, "102.125", 4, "act-act" ], "expect": { "yieldBasisPoints": 429, "yieldToMaturity": "0.042930500", "currentYieldBasisPoints": 490, "accruedInterest": "0.069444", "dirtyPrice": "102.194444", "previousCoupon": "2026-01-15", "nextCoupon": "2026-04-15", "couponsRemaining": 13 } }, { "name": "a month-end maturity keeps coupons on month ends: 31 December, not 30th", "args": [ "2026-01-15", "2030-06-30", 400, "98", 2, "act-act" ], "expect": { "yieldBasisPoints": 450, "yieldToMaturity": "0.044996644", "currentYieldBasisPoints": 408, "accruedInterest": "0.165746", "dirtyPrice": "98.165746", "previousCoupon": "2025-12-31", "nextCoupon": "2026-06-30", "couponsRemaining": 9 } }, { "name": "a zero-coupon bond: (100/90)^(1/5) - 1", "args": [ "2026-01-01", "2031-01-01", 0, "90", 1, "act-act" ], "expect": { "yieldBasisPoints": 213, "yieldToMaturity": "0.021295688", "currentYieldBasisPoints": 0, "accruedInterest": "0.000000", "dirtyPrice": "90.000000", "previousCoupon": "2026-01-01", "nextCoupon": "2027-01-01", "couponsRemaining": 5 } }, { "name": "a price above every future payment is a negative yield", "args": [ "2026-01-01", "2028-01-01", 0, "105", 1, "act-act" ], "expect": { "yieldBasisPoints": -241, "yieldToMaturity": "-0.024099927", "currentYieldBasisPoints": 0, "accruedInterest": "0.000000", "dirtyPrice": "105.000000", "previousCoupon": "2026-01-01", "nextCoupon": "2027-01-01", "couponsRemaining": 2 } }, { "name": "a distressed price", "args": [ "2026-02-01", "2036-02-01", 500, "50", 2, "30-360" ], "expect": { "yieldBasisPoints": 1470, "yieldToMaturity": "0.146961743", "currentYieldBasisPoints": 1000, "accruedInterest": "0.000000", "dirtyPrice": "50.000000", "previousCoupon": "2026-02-01", "nextCoupon": "2026-08-01", "couponsRemaining": 20 } }, { "name": "settlement on maturity", "args": [ "2026-01-01", "2026-01-01", 500, "100", 2, "30-360" ], "expectError": "settlement must be before maturity" }, { "name": "a frequency Excel does not accept", "args": [ "2026-01-01", "2030-01-01", 500, "100", 3, "30-360" ], "expectError": "frequency must be 1, 2 or 4" }, { "name": "a negative coupon", "args": [ "2026-01-01", "2030-01-01", -1, "100", 2, "30-360" ], "expectError": "couponBasisPoints must be a whole number from 0 to 100000" }, { "name": "a fractional coupon in basis points", "args": [ "2026-01-01", "2030-01-01", 412.5, "100", 2, "30-360" ], "expectError": "couponBasisPoints must be a whole number from 0 to 100000" }, { "name": "a price that is not a decimal", "args": [ "2026-01-01", "2030-01-01", 500, "par", 2, "30-360" ], "expectError": "cleanPrice must be a positive decimal with at most 6 places" }, { "name": "a price with seven decimal places", "args": [ "2026-01-01", "2030-01-01", 500, "99.1234567", 2, "30-360" ], "expectError": "cleanPrice must be a positive decimal with at most 6 places" }, { "name": "a price of zero", "args": [ "2026-01-01", "2030-01-01", 500, "0.000", 2, "30-360" ], "expectError": "cleanPrice must be greater than zero" }, { "name": "an unsupported day count", "args": [ "2026-01-01", "2030-01-01", 500, "100", 2, "act-360" ], "expectError": "basis must be 30-360 or act-act" }, { "name": "an impossible date", "args": [ "2026-02-30", "2030-01-01", 500, "100", 2, "30-360" ], "expectError": "is not a real calendar date" }, { "name": "a price no yield above -50% a period explains", "args": [ "2026-01-01", "2028-01-01", 0, "1000", 1, "act-act" ], "expectError": "the price implies a yield below -50% a coupon period" }, { "name": "more than 100 years to maturity", "args": [ "2000-01-01", "2101-01-01", 500, "100", 1, "act-act" ], "expectError": "maturity must be within 100 years of settlement" }, { "name": "30/360 bond basis can count past a month-end coupon", "args": [ "2025-08-30", "2030-08-31", 500, "100", 2, "30-360" ], "expectError": "by the 30/360 count settlement is not before the next coupon date" }, {"name": "a price with a trailing newline", "args": ["2026-01-01", "2030-01-01", 500, "100\n", 2, "30-360"], "expectError": "cleanPrice must be a positive decimal with at most 6 places"}, {"name": "a decimal price with a trailing newline", "args": ["2026-01-01", "2030-01-01", 500, "99.5\n", 2, "30-360"], "expectError": "cleanPrice must be a positive decimal with at most 6 places"} ]