After tax bond yield to maturity

168 Views Asked by At

I am trying to solve the following problem, but it is proving tougher than I originally thought and there are surprisingly few resources available online. I have essentially given up looking for an exact solution and will settle for a rough approximation.

Assume that an investor buys a bond that settles on April 19 2023 and matures on March 1st 2026. It pays a $0.25\%$ coupon semiannually and was purchased for $\$90.99$ per $\$100$ face value. Further, assume that interest income is taxed at $50\%$ and capital gains at $25\%$. I am looking to find the net after-tax yield to maturity of this bond.

My thinking is as follows:

  1. Find the after-tax coupon: $(1-0.5)0.25=0.125$
  2. Find the after-tax capital gain: $(1-0.25)(100-90.99)=6.7575$
  3. Now we use the bisection algorithm (python code below) to find a yield to maturity for a bond with $0.125\$$ coupons and a market price equal to $100-6.7575$. The idea is to proxy the after-tax cash flows of the target bond with a whole new bond with the above adjusted parameters.

Do any of you have experience with this problem? Can you offer me any feedback? Tell me why my idea is a worse approximation than I think it is? Or better yet, point me in the direction of a known method? Thank you very much.

def bisect(low_brac, high_brac, func, tolerance=0.0001):

    if func(high_brac) * func(low_brac) > 0:
        raise ValueError("initial bracket does not contain root")

    while abs(high_brac - low_brac) > tolerance:
        x_mid = (low_brac + high_brac) / 2

        if func(x_mid) * func(low_brac) > 0:
            low_brac = x_mid
        else:
            high_brac = x_mid

    return (high_brac + low_brac) / 2

from price_formulas import price

mktprice = 0.9324
coupon = 0.0025*(1-0.50)
freq = 2
settle_date = 20230419
mat_date = 20260301

def obj_func(x):

    return price(settle_date, mat_date, coupon, x, freq) - mktprice


print(bisect(0.001, 0.10, obj_func))

Code outputs YTM of $0.0259$ or $2.59\%$