Agenda

Introduction to continuous-time single-factor interest rate models.

Introduction to continuous-time single-factor interest rate models.

The Seminal Academic Paper

What do the actual interest rate paths look like?

Snippets from Yahoo Finance

# Install and load required packages
# install.packages("quantmod")
library(quantmod)
## Loading required package: xts
## Warning: package 'xts' was built under R version 4.0.2
## Loading required package: zoo
## 
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
## Loading required package: TTR
## Warning: package 'TTR' was built under R version 4.0.2
## Registered S3 method overwritten by 'quantmod':
##   method            from
##   as.zoo.data.frame zoo
library(ggplot2)

# Set the start and end dates for the data
start_date <- as.Date("2012-01-01")
end_date <- as.Date("2022-01-01")

# Set the ticker symbol for the Treasury rates
ticker1 <- "^IRX"
ticker2 <- "^FVX"
ticker3 <- "^TNX"
ticker4 <- "^TYX"

# Fetch the data from Yahoo Finance
getSymbols(Symbols = ticker1, src = "yahoo", from = start_date, to = end_date)
## Warning: ^IRX contains missing values. Some functions will not work if objects
## contain missing values in the middle of the series. Consider using na.omit(),
## na.approx(), na.fill(), etc to remove or replace them.
## [1] "IRX"
getSymbols(Symbols = ticker2, src = "yahoo", from = start_date, to = end_date)
## Warning: ^FVX contains missing values. Some functions will not work if objects
## contain missing values in the middle of the series. Consider using na.omit(),
## na.approx(), na.fill(), etc to remove or replace them.
## [1] "FVX"
getSymbols(Symbols = ticker3, src = "yahoo", from = start_date, to = end_date)
## Warning: ^TNX contains missing values. Some functions will not work if objects
## contain missing values in the middle of the series. Consider using na.omit(),
## na.approx(), na.fill(), etc to remove or replace them.
## [1] "TNX"
getSymbols(Symbols = ticker4, src = "yahoo", from = start_date, to = end_date)
## Warning: ^TYX contains missing values. Some functions will not work if objects
## contain missing values in the middle of the series. Consider using na.omit(),
## na.approx(), na.fill(), etc to remove or replace them.
## [1] "TYX"
# Extract the adjusted closing prices
dat1 <- IRX[,6]
dat2 <- FVX[,6]
dat3 <- TNX[,6]
dat4 <- TYX[,6]

par(mfrow = c(2,2))
plot(dat1, main = "13-week Rates")
plot(dat2, main = "5-Year Rates")
plot(dat3, main = "10-Year Rates")
plot(dat4, main = "30-Year Rates")

A Quick Introduction to Brownian Motion

A Quick Introduction to Brownian Motion

Equation/Definition:

Properties of Brownian Motion:

Brownian Motion: A Sample R Code

# Load required libraries
library(ggplot2)

# Function to simulate a Brownian motion path
brownian_motion_path <- function(steps) {
  dt <- 1  # Time increment
  
  # Generate random increments
  dW <- rnorm(steps, mean = 0, sd = sqrt(dt))
  
  # Calculate the cumulative sum to obtain the path
  path <- cumsum(dW)
  
  return(path)
}

# Function to simulate Brownian motion with drift
brownian_motion_with_drift <- function(steps, drift) {
  dt <- 1  # Time increment
  
  # Generate random increments
  dW <- rnorm(steps, mean = 0, sd = sqrt(dt))
  
  # Calculate the drift component
  drift_component <- drift * seq(1, steps)
  
  # Calculate the cumulative sum to obtain the path with drift
  path <- cumsum(dW + drift_component)
  
  return(path)
}

# Set Seed
set.seed(100)

# Set number of steps and drift
steps <- 200
drift <- 0.005

# Simulate a Brownian motion path
path <- brownian_motion_path(steps)

# Simulate Brownian motion with drift
path_with_drift <- brownian_motion_with_drift(steps, drift)

# Create time vector
time <- 1:steps

# Plot the simulated paths
plot_data <- data.frame(Time = time, Path = path, PathWithDrift = path_with_drift)
ggplot(plot_data) +
  geom_line(aes(x = Time, y = Path, color = "Brownian Motion"), linetype = "solid", size = 1) +
  geom_line(aes(x = Time, y = PathWithDrift, color = "Brownian Motion with Drift"), linetype = "solid", size = 1) +
  xlab("Time") +
  ylab("Value") +
  ggtitle("Simulated Brownian Motion Path\nwith and without Drift") +
  scale_color_manual(values = c("Brownian Motion" = "blue", "Brownian Motion with Drift" = "red")) +
  theme_bw() +
  labs(color = "Path Type")
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.

## Warning: Please use `linewidth` instead.

The Basic Structure of the Interest Rate Model: Stochastic Differential Equation (SDE)

The Basic Structure of the Interest Rate Model: Ho-Lee Model

The Basic Structure of the Interest Rate Model: Rendleman-Bartter Model

A Better Model for Interest Rate Dynamics: Vasicek Model

Vasicek Model - The Equation

Vasicek Model - R Codes

# Clear Working Environment 
rm(list = ls())

# Load required libraries
library(ggplot2)

# Function for Vasicek interest rate Monte Carlo simulation
vasicek_simulation <- function(theta, alpha, sigma, steps) {
  dt <- 1  # Time increment
  
  r <- numeric(steps)  # Vector to store simulated interest rates
  r[1] <- theta  # Initial interest rate
  
  for (i in 2:steps) {
    # Generate random shock term
    dW <- rnorm(1, mean = 0, sd = sqrt(dt))
    
    # Calculate next interest rate using Vasicek model equation
    r[i] <- r[i - 1] + alpha * (theta - r[i - 1]) * dt + sigma * dW
  }
  
  return(r)
}

# Set model parameters
theta <- 0.04  # Long-term mean or equilibrium interest rate
alpha <- 0.05  # Speed of mean reversion
sigma <- 0.01  # Volatility

# Set number of simulation steps
steps <- 1000

# Perform Vasicek Monte Carlo simulation
simulated_rates <- vasicek_simulation(theta, alpha, sigma, steps)

# Create time vector
time <- 1:steps

# Plot simulated interest rates
plot_data <- data.frame(Time = time, Rate = simulated_rates)
ggplot(plot_data, aes(x = Time, y = Rate)) +
  geom_line(color = ifelse(simulated_rates < 0, "red", "blue")) +
  geom_hline(yintercept = 0, linetype = "dashed") +
  geom_hline(yintercept = 0.05, linetype = "dashed") +
  xlab("Time") +
  ylab("Interest Rate") +
  ggtitle("Vasicek Interest Rate Monte Carlo Simulation") +
  theme_bw()

A Better Model for Interest Rate Dynamics: CIR Model

CIR Model

CIR Model - R Codes

# Load required libraries
library(ggplot2)

# Function for CIR interest rate Monte Carlo simulation with standard normal shocks
cir_simulation <- function(theta, alpha, sigma, steps) {
  dt <- 1  # Time increment
  
  r <- numeric(steps)  # Vector to store simulated interest rates
  r[1] <- theta  # Initial interest rate
  
  for (i in 2:steps) {
    # Generate standard normal shock term
    dW <- rnorm(1, mean = 0, sd = 1)
    
    # Calculate next interest rate using CIR model equation
    gamma <- sqrt(alpha^2 + 2 * sigma^2)
    psi <- (gamma + alpha) * dt
    
    z <- dW^2
    r[i] <- r[i - 1] + (alpha * (theta - r[i - 1]) * dt) + (sigma * sqrt(r[i - 1]) * sqrt(dt) * sqrt(z) / sqrt(psi))
  }
  
  return(r)
}

# Set model parameters
theta <- 0.01  # Long-term mean or equilibrium interest rate
alpha <- 0.05  # Speed of mean reversion
sigma <- 0.1  # Volatility

# Set number of simulation steps
steps <- 1000

# Perform CIR Monte Carlo simulation with standard normal shocks
simulated_rates <- cir_simulation(theta, alpha, sigma, steps)

# Create time vector
time <- 1:steps

# Plot simulated interest rates
plot_data <- data.frame(Time = time, Rate = simulated_rates)
ggplot(plot_data, aes(x = Time, y = Rate)) +
  geom_line() +
  xlab("Time") +
  ylab("Interest Rate") +
  ggtitle("CIR Interest Rate Monte Carlo Simulation")

Some Important Single Factor Models

Vetzal, K. R. (1994). A survey of stochastic continuous time models of the term structure of interest rates. Insurance: Mathematics and Economics, 14(2), 139-161.

What about the Multifactor Models

Vetzal, K. R. (1994). A survey of stochastic continuous time models of the term structure of interest rates. Insurance: Mathematics and Economics, 14(2), 139-161.

Summary

Next Class