# Comparing Bond Duration Functions in C, Python, and Haskell

By
Published on

Lately I’ve been studying for a Working Capital Management exam coming up on Wednesday, April 25th. As you can probably guess, the subject matter can be dry at times so I’ve tried to come up with something productive to do during study breaks. Since it’s been a few weeks since I’ve coded something I decided to see how implementing a bond duration calculation would compare between C, Python, and Haskell.

For those who don’t know, C is one of the older, more traditional statically typed imperative programming languages that has widely influenced most newer languages like Java and Python. Python is a newer language that mixes imperative and functional constructs and uses dynamic typing. Finally, Haskell is a statically typed functional language.

In terms of the calculation being implemented, bond duration is a weighted average time until repayment as well as a measure of how sensitive a bond’s price is to changes in interest rates. The calculation takes a coupon rate (the percentage of face value paid out on an annual basis), the current interest rate (typically this would be the prevailing rate on a one year American treasury bill), and a time to maturity (how many years until the bond matures). Coupon rates and interest rates are negatively related to duration while time to maturity is positively related. You can check out the Wikipedia article linked above to see the formula for bond duration.

Here is my C implementation for bond duration:

This is one possible C implementation. I tried to implement it in such a way that it would perform faster than the Python or Haskell implementation by taking advantage of C’s imperative nature. For example, it will only run through the loop once and it only uses as much memory as it needs to. There is a small repetition in calculating the payment present values for principal repayment, the only difference being that the principal repayment adds 1 to the coupon rate. Granted that this could have been handled inside the loop but as it’s different logic and it always affects only the last payment term, I think it makes more sense to place it after the loop and have a tiny DRY violation.

Now, here is my Python implementation:

Now, I could have coded this almost identically to the C version but that would’ve been boring and pointless. Instead I chose to take advantage of Python’s functional language constructs, specifically list generators, map, and reduce to illustrate a different coding style. As opposed to trying to do the calculations in one go, this approach builds lists of payments, discounts, and weighting co-efficients and then “zips” them together (think of it like a zipper joining two teeth together) using map before summing up the weighted present values and bond payment present values using reduce.

Finally, here is my Haskell implementation:

```import System.Environment
import Text.Printf
-- Calculates bond duration given a coupon rate, interest rate, and time to
-- maturity
--
-- Args:
--   c - coupon rate (>= 0), e.g., 0.04
--   k - interest rate (>= 0), e.g., 0.08
--   t - time to maturity (> 0), e.g., 5
duration :: Double -> Double -> Int -> Double
duration c k t = (sum weighted_pvs) / (sum payments_pvs)
where weighted_pvs  = zipWith (*) (map fromIntegral [1..t]) payments_pvs
payments_pvs  = zipWith (/) payments discounts
payments = replicate (t-1) c ++ [1 + c]
discounts = [ (1 + k) ^ i | i <- [1..t]]
main = do
(c:k:t:_) <- getArgs
printf "%.2f\n" \$ duration (read c :: Double) (read k :: Double)