Guides · bonds
To price a fixed-rate bond over REST, POST its coupon, dates, day count and a yield (or zero curve) to https://quantbox.dev/v1/bonds/price. One call returns the clean price, dirty price, accrued interest, YTM, modified duration, convexity and basis-point value — all per 100 of face value, with the conventions restated in the response.
A 5% annual bond issued 2024-07-01, maturing 2029-07-01, settling 2026-10-15, priced at a flat 4% yield:
curl -s https://quantbox.dev/v1/bonds/price \
-H "X-API-Key: $KEY" -H "Content-Type: application/json" \
-d '{"coupon_rate": 0.05,
"issue_date": "2024-07-01",
"maturity_date": "2029-07-01",
"settlement_date": "2026-10-15",
"frequency": "annual",
"day_count": "act/act",
"yield_rate": 0.04}'
Runs on the free tier — 500 calls/month, no credit card. Get a key.
{
"clean_price": 102.4892,
"dirty_price": 103.9413,
"accrued": 1.4521,
"ytm": 0.04,
"modified_duration": 2.4748,
"convexity": 8.7012,
"bpv": -0.0257,
"conventions": {
"prices": "per 100 of face value (market quote convention)",
"settlement": "as provided (settlementDays=0, no implicit T+2)",
"ytm": "compounded annual, act/act",
"zero_curve": "zero rates continuously compounded, act/365",
"calendar": "TARGET, unadjusted schedule"
}
}
import requests
KEY = "YOUR_API_KEY" # free key from https://quantbox.dev
r = requests.post("https://quantbox.dev/v1/bonds/price",
headers={"X-API-Key": KEY},
json={"coupon_rate": 0.05,
"issue_date": "2024-07-01",
"maturity_date": "2029-07-01",
"settlement_date": "2026-10-15",
"frequency": "annual",
"day_count": "act/act",
"yield_rate": 0.04})
bond = r.json()
print(bond["clean_price"], bond["dirty_price"], bond["bpv"])
# 102.4892 103.9413 -0.0257
Pricing a fixed-rate bond means discounting its remaining cash flows — here the 5.00 coupons of July 2027, 2028 and 2029 plus the 100 principal at maturity — at the yield you supply, compounded at the coupon frequency. The API generates the coupon schedule backwards from maturity, applies the day count you name, and splits the present value into the three numbers markets actually use: the clean price (what is quoted), the accrued interest (coupon earned since the last payment), and the dirty price (what the buyer pays: clean + accrued).
The schedule and day-count bookkeeping is where spreadsheet bond math quietly goes wrong — which is why the request states every convention explicitly and the response repeats them back.
| Field | Value | Meaning |
|---|---|---|
| clean_price | 102.4892 | Present value of remaining cash flows minus accrued interest — the number markets quote, per 100 face. |
| dirty_price | 103.9413 | What the buyer actually pays at settlement: clean + accrued. See clean vs dirty, explained with code. |
| accrued | 1.4521 | Coupon earned since the last payment (2026-07-01): 106 of 365 days into the period under act/act, so 5.00 × 106/365 = 1.4521. |
| ytm | 0.04 | Echoes the flat yield here (compounded annual, act/act). When you price off a zero_curve instead, the equivalent YTM is backed out for you. |
| modified_duration | 2.4748 | First-order rate sensitivity: ΔP ≈ −D·P·Δy. |
| convexity | 8.7012 | Second-order correction — add ½·C·P·Δy² for larger yield moves. |
| bpv | -0.0257 | Exact price change for +1 bp of yield, per 100 face — repriced, not approximated. Also called DV01; see the DV01/BPV guide. |
Sanity check the trio: modified duration × dirty price / 10,000 = 2.4748 × 103.9413 / 10,000 ≈ 0.0257 — the BPV, with the sign telling you the direction.
| Convention | Value |
|---|---|
| prices | per 100 of face value (market quote convention) |
| settlement | as provided (settlementDays=0, no implicit T+2) |
| ytm | compounded annual, act/act |
| zero_curve | zero rates continuously compounded, act/365 |
| calendar | TARGET, unadjusted schedule |
Two of these bite in practice. Settlement is taken literally — no implicit T+2, you pass the date the trade actually settles, which makes results reproducible instead of "correct on the day you ran it". And the YTM convention follows your request: it is compounded at the frequency you set and measured with your day_count, so an annual 4% and a semiannual 4% are different yields.
Replace yield_rate with a zero_curve (pillars in years + continuously-compounded zero rates) and the bond is discounted off the curve instead; you provide exactly one of the two. Need the curve itself from market quotes? That is POST /v1/curves/bootstrap. For the risk side of this same response — duration, convexity, BPV in depth — see bond duration, convexity and BPV over HTTP.
Price your own bond. Key in seconds, 500 free calls a month, full request schema in the docs.
Get a free API keyNo credit card · schemas and error codes in /docs
Related: Clean vs dirty bond price and accrued interest · DV01 / BPV of a bond via API · Bond duration, convexity and BPV over HTTP