Skip to content
All library documents

Calculating Macaulay and Modified Bond Duration in Python

Article Quant Q&A · Author: Shashank

Summary

The document collects approaches for computing Macaulay and modified duration from a bond’s cash flows. One method discounts each payment using its period-specific rate, weights the payment time by its present value, and divides by the bond price; modified duration is then obtained by adjusting Macaulay duration for yield and payment frequency. Other replies give explicit formulas for regular coupon bonds, including a special case when coupon rate and yield match, and a continuous-compounding example that calculates present value and duration from dated payments.

The examples illustrate that duration can be calculated from cash flows or through a closed-form expression, and that irregular payment dates may require a more flexible cash-flow representation. The examples are not a unified library or a full treatment of conventions: compounding, yield units, payment timing, and day-count assumptions must match the bond being valued. One reply points to a commercial analytics product, which is a recommendation rather than evidence about calculation accuracy.

Key ideas

  • Macaulay duration weights each cash-flow time by its discounted value relative to bond price.
  • Modified duration adjusts Macaulay duration for yield and the coupon payment convention.
  • Explicit formulas can simplify calculations for regular coupon bonds and include a special case when coupon rate equals yield.
  • Irregular payment dates require cash-flow timing details that simple regular-period formulas may not represent.
  • Compounding and rate conventions must be consistent with the bond valuation setup.

Tags

Full text
# Modified or Macauley Duration in python


# Modified or Macauley Duration in python












are there any existing python modules that can calculate Modified and/or Macauley Duration of a bond.

## Answer by mbudda (score 2)

https://quant.stackexchange.com/a/21611

I calculate duration in Python using numpy, it's nice and simple:

```
def durations(cfs, rates, price, ytm, no_coupons, payments_per_year=2):
    import numpy as np 
    mac_dur = np.sum([cfs[i]*((i+1)/payments_per_year)/np.power(1+rates[i],i+1) for i in range(len(cfs))])/price
    mod_dur = mac_dur/(1+ytm/no_coupons)
    return mac_dur, mod_dur
```

## Answer by kevin_theinfinityfund (score 2)

https://quant.stackexchange.com/a/50074

Example: Consider a 7% bond with 3 years to maturity. Assume bond is selling at 8% yield.

Most concise function for explicit formulas:

```
def durations_explicit(c, y, m, n):
    macaulay_duration = ((1+y) / (m*y)) - ( (1 + y + n*(c-y)) / ((m*c* ((1+y)**n - 1)) + m*y) )
    modified_duration = macaulay_duration / (1 + y)
return macaulay_duration, modified_duration

durations_explicit(c=.035, y=.04, m=2, n=6)
(2.75371702450442, 2.6478048312542497)
```

For a more complete answer with docstrings and accounting for the case when coupon rate per period equals yield per period

```
def durations_explicit(c, y, m, n):
    """Parameters:
        c = coupon rate per period
        y = yield per period
        m = periods per year
        n = periods remaining"""
    if c==y: # Shorter explicit formula if coupon rate per period = yield per period
        macaulay_duration = ((1+y)/(m*y))*(1 - (1 / (1+y)**n))
        modified_duration = macaulay_duration / (1 + y)
        print(f"Macaulay Duration: {macaulay_duration}")
        print(f"Modified Duration: {modified_duration}")
        return macaulay_duration, modified_duration
    else:
        macaulay_duration = ((1+y) / (m*y)) - ( (1 + y + n*(c-y)) / ((m*c* ((1+y)**n - 1)) + m*y) )
        modified_duration = macaulay_duration / (1 + y)
        print(f"Macaulay Duration: {macaulay_duration}")
        print(f"Modified Duration: {modified_duration}")
        return macaulay_duration, modified_duration

durations_explicit(c=.035, y=.04, m=2, n=6)
Macaulay Duration: 2.75371702450442
Modified Duration: 2.6478048312542497
(2.75371702450442, 2.6478048312542497)
```

## Answer by Phil H (score 1)

https://quant.stackexchange.com/a/15607

Go talk to Fincad. Here is their page on integrating with scripting languages:

http://www.fincad.com/news-events/assets/pdfs/mar07/using-fincad-developer-scripting-languages.pdf

Their analytics libraries include bond analytics, and they have a spreadsheet product so you can test methods and results before implementing them.

Disclaimer: I work for a company who is a customer of Fincad's analytics.

## Answer by Tural Valiyev (score 1)

https://quant.stackexchange.com/a/43275

```
You can use my script:def Duration (timetomaturity,nominalvalue,yieldrate,couponrate):    import math as m    yld=yieldrate/100    cpnr=couponrate/100    t=list(range(1,timetomaturity+1))    cfi=nominalvalue*cpnr    cfN=nominalvalue*cpnr+nominalvalue    cfl=[cfi]*(len(t)-1)+[cfN]    B=0 # B is the bond's present value    for k in range(0,timetomaturity):        B=B+cfl[k]*(m.exp(-yld*t[k]))    D=0 # D is the duration    for i in range(0,timetomaturity):        D+=(t[i]*cfl[i]*m.exp(-yld*t[i]))/B    return round(D,2),round(B,2)#Duration(5,100,1,1)#By Tural Valiyev
```

## Answer by Pythonista anonymous (score 0)

https://quant.stackexchange.com/a/61028

You can look at the answer I gave here: https://quant.stackexchange.com/a/61025/40827 which is based on potentially irregular cashflows. Ie you pass the exact dates or periods and amounts, you don't specify, say, a bond paying 5% every semester for the next 3 years.

Shown in full with attribution under the source's licence. Licence: CC BY-SA 4.0 (Stack Exchange)

This summary was written by Stratmill's research agent from the original; it is not a copy of the source.