Coding towards CFA (4) – Interest Rate Swap Pricing and Valuation

Coding towards CFA (4) – Interest Rate Swap Pricing and Valuation

In this blog series, I will aim to code the formulas and model algorithms covered in the CFA Level 2 program using Python and DolphinDB. Each topic will begin with a brief explanation of the formulas or algorithms, followed by their implementations in Python and DolphinDB.

An Interest Rate Swap (IRS) is a financial derivative agreement in which two parties exchange interest rate payments. For the plain vanilla IRS, one party pays a fixed rate, while the other pays a floating rate, both based on a notional amount. These swaps are commonly used to hedge against interest rate risk or to speculate on the future movement of interest rates. This blog post will focus on the pricing and valuation of interest rate swap contracts.

Interest Rate Swap Pricing

The pricing of an interest rate swap contract is the process of determining the fair value of the swap at the contract’s initiation. In essence, it involves calculating the fixed rate that makes the present value of the fixed leg payments equal to the present value of the floating leg payments:

PV(fixed leg payments) = PV(floating leg payments)

The calculation of the fixed rate of an IRS contract is simple. We can effectively consider an IRS contract as a portfolio consisting of a floating-rate bond and a fixed-rate bond. For the fixed-rate payer of the contract, he or she effectively holds a long position in a floating-rate bond and a short position in a fixed-rate bond. Since the present value of the floating-rate bond is considered ‘at par’ at initiation (because the floating rate is tied to market rates, which are assumed to make the floating leg worth exactly its notional amount at initiation), the present value of the fixed-rate bond is effectively the par rate of this fixed-rate bond.

To simplify the calculation, let’s assume the par value is 1 for the floating-rate bond at initiation, which makes the present value of the fixed-rate bond cash flows equal to 1. This leads to the equation below, where df(i) is the discount factor that can be derived from the market spot curve or the swap curve.

From the equation, we can calculate the coupon value C, which is equal to the par rate, considering that we have set the par value to 1.

Finally, we also need to annualise the rate and obtain the final formula for pricing a plain vanilla IRS contract:

Here is the Python implementation of the formula.

Since discount factors are commonly needed in various scenarios, I have created a generic function to derive them, which can be reused in future posts in this series.

Interest Rate Swap Valuation

Interest Rate Swap valuation refers to the process of determining the fair value of an interest rate swap contract at any point after initiation and before expiration. The fair value of an IRS contract is considered the present value of the remaining future cash flows from both the fixed leg and the floating leg.

We already know the fixed rate of the fixed leg payment, r_fix_0, which is the rate locked in at the initiation. Since interest rates and the term structure have changed since initiation, the floating rates have been reset to reflect the current market rates. From the current market rates, we can calculate the new fixed rate (using the same pricing approach described above) that reflects the current market condition. The value of the swap is then the present value of the difference between the future payments at the old locked-in fixed rate and the new fixed rate based on current market rates.

Here is the Python implementation.

Full Code – Python

import numpy as np
from scipy.optimize import fsolve

def calculate_discount_factors(days_to_maturity, spot_rates):

    return np.array([1/(1+r*(d/360)) 
                for r, d in zip(spot_rates, days_to_maturity)])


def calculate_fixed_rate(days_to_maturity, spot_rates, payments_per_year):
    discount_factors = calculate_discount_factors(days_to_maturity, spot_rates)

    df_n = discount_factors[-1]
    sum_df = np.sum(discount_factors)
    
    fixed_rate = (1-df_n)/sum_df*payments_per_year

    return fixed_rate

days_to_maturity = [90, 180, 270, 360]
spot_rates = [0.025, 0.026, 0.027, 0.028]
payments_per_year = 1
fixed_rate = calculate_fixed_rate(days_to_maturity, spot_rates, payments_per_year)
print("The fixed rate is "+str(fixed_rate))


def calculate_irs_value(notional_amount, discount_factors, r_fix_0, r_fix_t, party="receive-fixed"):
    
    sum_df = np.sum(discount_factors)

    irs_value = notional_amount*(r_fix_0-r_fix_t)* sum_df

    irs_value = -irs_value if party == "pay-fixed" else irs_value

    return irs_value

notional_amount = 100000000
discount_factors = [0.990099, 0.977876, 0.965136, 0.951529, 0.937467]
r_fix_0=0.02
r_fix_t=0.013
party="receive-fixed"
irs_value = calculate_irs_value(notional_amount, discount_factors, r_fix_0, r_fix_t, party)
print("The value of IRS is "+str(irs_value))

Full Code – DolphinDB


def calculate_discount_factors(days_to_maturity, rates){

    return each(def(d, r): 1/(1+r*(d/360)), 
                rates, days_to_maturity)

}

def calculate_fixed_rate(days_to_maturity, spot_rates, payments_per_year){
    discount_factors = calculate_discount_factors(days_to_maturity, spot_rates)

    df_n = last(discount_factors)
    sum_df = sum(discount_factors)
    
    fixed_rate = (1-df_n)/sum_df*payments_per_year

    return fixed_rate
}

days_to_maturity = [90, 180, 270, 360]
spot_rates = [0.025, 0.026, 0.027, 0.028]
payments_per_year = 1
fixed_rate = calculate_fixed_rate(days_to_maturity, spot_rates, payments_per_year)
print("The fixed rate is "+fixed_rate)


def calculate_irs_value(notional_amount, discount_factors, r_fix_0, r_fix_t, party="receive-fixed"){
    
    sum_df = sum(discount_factors)

    irs_value = notional_amount*(r_fix_0-r_fix_t)* sum_df

    if (party == "pay-fixed" ){
        irs_value = -irs_value
    }

    return irs_value
}

notional_amount = 100000000
discount_factors = [0.990099, 0.977876, 0.965136, 0.951529, 0.937467]
r_fix_0=0.02
r_fix_t=0.013
party="receive-fixed"
irs_value = calculate_irs_value(notional_amount, discount_factors, r_fix_0, r_fix_t, party)
print("The value of IRS is "+irs_value)

Leave a comment