Skip to content

Instantly share code, notes, and snippets.

@albert-yu
Last active May 8, 2020 17:48
Show Gist options
  • Save albert-yu/b9b909bb32f7ff2c9851b2f0e8edaac5 to your computer and use it in GitHub Desktop.
Save albert-yu/b9b909bb32f7ff2c9851b2f0e8edaac5 to your computer and use it in GitHub Desktop.
Some potentially useful functions for bond math
def _solver_try(y, face_val, num_periods, coupon_payment):
result = 0
for t in range(1, num_periods + 1):
result += coupon_payment / (1 + y) ** t
if t == num_periods:
result += face_val / (1 + y) ** t
return result
def solver(price, face_val, num_periods, coupon_payment):
"""
Computes the yield-to-maturity, just like Excel's solver
Parameters
----------
price : double
present value or price
face_val : double
bond's face value
num_periods : int
number of periods this bond pays
coupon_payment : double
coupon payment per period, if any
"""
start = 0.05 # start at 5%
tol = 1e-10
last_result = 0
to_try = start
step_size = 0.025
iters = 0
while iters < 1000:
res = _solver_try(to_try, face_val, num_periods, coupon_payment)
if abs(res - price) < tol:
print("converged")
break
if res < price:
# we've been increasing: need to decrease
if step_size > 0:
step_size = step_size / 2
step_size = -step_size
else:
# we've been decreasing, need to increase
# y now
if step_size < 0:
step_size = step_size / 2
step_size = -step_size
to_try += step_size
iters += 1
if iters == 1000:
print("failed to converge")
return to_try
def bond_dur(ytm, price, face_val, num_periods, coupon_payment=0):
"""
Computes bond duration
Parameters
----------
ytm : double
yield to maturity
price : double
the price the bond is trading at
face_val : double
face value
num_periods: int
the number of periods
coupon_payment : double
coupon payment per period
"""
result = 0
for t in range(1, num_periods + 1):
pv = 0
if t == num_periods:
pv = (coupon_payment + face_val) / (1 + ytm) ** t
else:
pv = coupon_payment / (1 + ytm) ** t
s = pv * t
result += s
return result / price
def main():
num_periods = 5
coupon = 80
face = 1000
price = 1090
ytm = solver(price, face, num_periods, coupon)
print(ytm)
# 0.058709
print(bond_dur(ytm, price, face, num_periods, coupon))
# 4.34 (in years)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment