Equity & Fixed Income
Chapter: 2.1 Equity & Fixed Income Level: 3 — Production (from-scratch derivations, code-from-memory, explain-out-loud) Time limit: 45 minutes Total marks: 60
Instructions: Show all working. Derive formulas from first principles where asked. For coding questions, write clean pseudocode or Python from memory. Round money to 2 decimals, yields to 4 decimals unless stated.
Question 1 — Bond pricing from first principles (12 marks)
A corporate bond has face value , an annual coupon rate of paid annually, and years to maturity. The market discount rate (yield) is .
(a) Derive the general present-value formula for a coupon bond price in terms of coupon , face value , yield , and years . Explain each term. (4)
(b) Compute the price of this bond. Show every discounted cash flow. (5)
(c) State whether the bond trades at a premium or discount and explain why in terms of coupon rate vs yield. (3)
Question 2 — Yield-to-maturity and the inverse relationship (10 marks)
(a) Define yield-to-maturity (YTM) in one precise sentence, and explain why YTM is the internal rate of return of the bond. (3)
(b) Using the bond from Q1, the yield falls from to . Recompute the price. (4)
(c) Explain the inverse price–yield relationship you just observed, and state whether the price–yield curve is linear or convex. (3)
Question 3 — Zero-coupon bonds (10 marks)
(a) Derive the price formula for a zero-coupon bond from the coupon-bond formula by setting . (3)
(b) A zero-coupon bond with face value matures in years and is priced at \680$. Derive its YTM from scratch. (4)
(c) Explain why zero-coupon bonds have the highest interest-rate sensitivity of any bond of the same maturity. (3)
Question 4 — Duration and rate sensitivity (12 marks)
(a) Write the Macaulay duration formula from memory and explain what it measures. (3)
(b) For a 2-year annual bond, , coupon , yield (so it trades at par), compute the Macaulay duration. Show the weighted-time table. (6)
(c) Convert to modified duration and estimate the % price change for a bp yield move. (3)
Question 5 — Code from memory: bond pricer (8 marks)
Write a Python function bond_price(face, coupon_rate, ytm, years, freq=1) that returns the price of a coupon bond. It must:
- handle arbitrary payment frequency,
- sum discounted coupons plus discounted face value,
- be correct for the zero-coupon case.
Then state one line calling it for the Q1 bond. (8)
Question 6 — Explain out loud (8 marks)
Answer in 2–4 sentences each:
(a) A yield curve is inverted. Explain what this means and what it often signals. (2)
(b) Explain the difference between a debenture and a secured bond, and where a convertible bond sits. (3)
(c) A bond is downgraded from AAA to BBB. Explain what happens to its price and yield, and why. (3)
Answer keyMark scheme & solutions
Question 1 (12)
(a) Bond price = PV of all future cash flows discounted at yield :
- Each coupon paid at time discounted by (money later is worth less). (2)
- Final term is redemption of face value at maturity . (1)
- Sum = fair present value / market price. (1)
(b) , , .
- :
- :
- :
- Face:
(5) (1 per CF, 1 for total)
(c) Trades at a discount (). Because coupon rate () < yield (): the bond pays less than the market demands, so its price must fall below par to compensate the buyer. (3)
Question 2 (10)
(a) YTM is the single discount rate that equates the present value of all a bond's future cash flows to its current market price. It is the IRR because it is exactly the rate that makes NPV(price − PV of cashflows) = 0 — the return earned if held to maturity with coupons reinvested at . (3)
(b) :
(4)
(c) As yield fell from to , price rose from to — inverse relationship: lower discount rate → higher PV of fixed cash flows. The curve is convex (curved, not linear): price rises more for a yield drop than it falls for an equal yield rise. (3)
Question 3 (10)
(a) Set in : all coupon terms vanish, leaving
(3)
(b)
(≈8.02%) (4)
(c) A zero has a single cash flow at maturity, so its full value depends on with the longest possible exponent — no intermediate coupons return capital early. Its duration equals its maturity (the maximum), giving the greatest price sensitivity to yield changes. (3)
Question 4 (12)
(a) It is the PV-weighted average time to receive the bond's cash flows (in years). (3)
(b) Coupon , , par price .
| 1 | 60 | 56.6038 | 56.6038 |
| 2 | 1060 | 943.3962 | 1886.7925 |
| Σ=1000.00 | Σ=1943.3963 |
years (6)
(c) . . (3)
Question 5 (8)
def bond_price(face, coupon_rate, ytm, years, freq=1):
n = years * freq # total periods
c = face * coupon_rate / freq # coupon per period
r = ytm / freq # periodic yield
price = 0.0
for t in range(1, n + 1):
price += c / (1 + r) ** t # discounted coupon
price += face / (1 + r) ** n # discounted face value
return price
# zero-coupon: coupon_rate=0 -> loop adds 0, returns face/(1+r)**n ✓
# Q1 call:
bond_price(1000, 0.08, 0.10, 3) # -> 950.26Marks: loop/discounting (3), face value term (2), freq handling (2), correct Q1 call (1). (8)
Question 6 (8)
(a) An inverted yield curve means short-term yields exceed long-term yields. It often signals expected economic slowdown or recession, as markets anticipate future rate cuts. (2)
(b) A debenture is an unsecured bond backed only by the issuer's creditworthiness (no specific collateral); a secured bond is backed by pledged assets and ranks higher in default. A convertible bond is typically a debenture that also carries an option to convert into equity shares. (3)
(c) After a downgrade AAA→BBB, perceived default risk rises, so investors demand a higher yield; since yield and price move inversely, the bond's price falls and its yield rises. (3)
[
{"claim":"Q1 bond price at 10% yield is 950.26","code":"C=80; F=1000; y=Rational(1,10); P=sum(C/(1+y)**t for t in range(1,4))+F/(1+y)**3; result = round(float(P),2)==950.26"},
{"claim":"Q2 bond price at 6% yield is 1053.46","code":"C=80; F=1000; y=Rational(6,100); P=sum(C/(1+y)**t for t in range(1,4))+F/(1+y)**3; result = round(float(P),2)==1053.46"},
{"claim":"Q3 zero-coupon YTM approx 0.0802","code":"y=(1000/680)**(Rational(1,5))-1; result = round(float(y),4)==0.0802"},
{"claim":"Q4 Macaulay duration is 1.9434 years","code":"y=Rational(6,100); pv1=60/(1+y); pv2=1060/(1+y)**2; P=pv1+pv2; D=(1*pv1+2*pv2)/P; result = round(float(D),4)==1.9434"},
{"claim":"Q4 percent price change for +50bp is about -0.92%","code":"y=Rational(6,100); pv1=60/(1+y); pv2=1060/(1+y)**2; P=pv1+pv2; Dmac=(1*pv1+2*pv2)/P; Dmod=Dmac/(1+y); chg=-Dmod*Rational(5,1000); result = round(float(chg)*100,2)==-0.92"}
]