'How to obtain different maturities from a yield curve

I have a code for the construction of the yield curve, but I kinda want to extract the yields for every 0.25 months. I don't know, where to change it in the code. If extract the variables y1, y2 and y3 then the rates I get are only for the integer maturities i.e. 1,2,3,etc. on the curve. Where do I need to change the code that I get the rates at 0.25, 0.5, 0.75 etc.

#INPUTS
#ve c t o r with the swap r a t e s (
swaps <- c(0.002, 0.00225, 0.003, 0.004)

#ve c t o r o f cash f low
vector.cf <- c(0.002, 0.00225, 0.003, 0.004)

#ve c t o r o f ma t u r i t i e s f o r observed swaps
maturities <- c(1,2,3,4)

#ve c t o r o f p r i c e s
prices <- c(rep(1, length(swaps)))

#time v e c t o r s needed to c r e a t e the cash f low mat rix
tj <- seq(1:length(swaps))
tj
#ve c t o r ma t u r i t i e s to LLP
t <- seq(1:length(vector.cf))
t

#func t i on that c r e a t e s the cash f l ows o f swaps
fCashFlowMatrix <- function(s=c(), tt, ttj, n) {
  M <- matrix(, length(ttj), length(tt))
  for(i in 1:length(ttj)) {
    M[i,] <- c(rep(s[i], n[i]-1), 1+s[1],
               rep(0, length(M[i,])-n[i]))
  }
  return(M)
}

#cash f low mat r ix
cf <- fCashFlowMatrix(swaps, t, tj, maturities)
tcf <- t(cf)
cf
#l a s t l i q u i d point
LLP <- 20

#func t i on f o r c a l c u l a t i n g the Heart o f Wilson in one point
fHeart.v.u <- function(v, u, a){
  heart=a*min(v,u)-exp(-a*max(v,u))*0.5*
    (exp(a*min(v,u))-exp(-a*min(v,u)))
  return(heart)
}


#Heart o f Wilson f o r u as ve c t o r
fHeart.v <- function(v, u=c(), a){
  heart.v <- NULL
  for(i in 1:length(u)){
    heart.v[i]=fHeart.v.u(v, u[i], a)
    
  }
  return(heart.v)
}

#func t i on f o r the d e r i v a t i v e o f the Heart o f Wilson
fGuv <- function(v, u,a){
  guve <- NULL
  if(v<=u){
    guv=a-a*(exp(-a*u))*(cosh(a*v))
  }
  else guv=a*exp(-a*v)*(sinh(a*u))
  guv
}

#func t i on f o r the d e r i v a t i v e o f the Heart o f Wilson
#with u as ve c t o r
fGuv.v <- function(v, u=c(),a){
  guv.v<- NULL
  for(i in 1:length(u)){
    guv.v[i]=fGuv(v,u[i], a)
    
  }
  return(guv.v)
}

#f u n c ti o n f o r the Wilson f u n ti o n i n one poi n t
fWilson <- function(v, u, ufr, alpha){
  wilson=exp(-ufr*(v+u))*fHeart.v.u(v,u,alpha)
  return(wilson)
}
#f u n c ti o n f o r the Wilson ma t rix
fWilsonMatrix <- function(tt=c(), ufr, alpha){
  W=matrix(length(tt), length(tt), length(tt))
  for(k in 1:length(tt)){
    Wv=c()
    for(i in 1:length(tt)){
      Wv[i] <- fWilson(tt[k], tt[i], ufr, alpha)
    }
    W[k,] <- Wv
  }
  return(W)
}


#calculus

UFR = log(1+0.042)
alpha= 0.123760
wilson <- fWilsonMatrix(t, UFR, alpha)
wilson

#func t i on to c a l c u l a t e the parameter z e ta
zeta.function <- function(X=matrix(), W=matrix(), pr, ufr, u){
  mu <- exp(-ufr*u)
  zeta <- (solve(X%*%W%*%t(X)))%*%(pr-X%*%mu)
  return(zeta)
}

#parameters
zeta <- zeta.function(cf, wilson, prices, UFR, t)


#funt i on to compute the quas i􀀀cons tant k :
kfunction <- function(a, u=c(), ufr, X=matrix(), z){
  mu <- exp(-ufr*u)
  dmu <- diag(mu)
  Q <- dmu%*%t(X)
  k <- (1+a*u%*%Q%*%z)/((sinh(a*u))%*%Q%*%z)
  return(k)
}

#check k
k <- kfunction(alpha, t, UFR, cf, zeta)


#check Qzeta
mu <- exp(-UFR*t)
dmu <- diag(mu)
Q <- dmu%*%t(cf)
Q%*%zeta

#func t i on f o r the conve rgenc e point
cpt.function <- function(llp){
  T <- max(llp+40, 60)
  return(T)
}
T <- cpt.function(LLP)

#func t i on f o r the conve rgenc e pe r i od
cpd.function <- function(llp){
  S <- max(40,60-llp)
  return(S)
}
S <- cpd.function(LLP)
  

#func t i on f o r the upper forward i n t e n s i t y
f.function <- function(w, a, K, v){
  f=(w+(a/1-K*exp(a*v)))
  return(f)
}
#check
g.alpha.1 <- abs(f.function(UFR, alpha, k, T)-UFR)

#func t i on g . alpha
g.alpha.function <- function(a){
  wilson <- fWilsonMatrix(t, UFR, a)
  zeta <- zeta.function(cf, wilson, prices, UFR, t)
  k <- kfunction(a, t, UFR, cf, zeta)
  sg <- a/(abs(1-k*exp(a*T)))
  sg
}
#check
g.alpha.2 <- g.alpha.function(alpha)

#e u r i s t i c s o l u t i o n
g.alpha.function(0.05)
a.lower = 0.05
while (g.alpha.function(a.lower)>=0.0001){
  a.lower=a.lower+0.000001
}

#opt imi z ed alpha
alpha.opt <- a.lower
alpha.opt

#p r i c e func t i on t given time v
fPresentValue <- function(ufr, v,u,q,z,alp) {
  pv <- exp(-ufr*v)*(1+fHeart.v(v,u,alp)%*%q%*%z)
  return(pv)
}

#spot i n t e n s i t y func t i on
fYieldIntensity <- function(ufr, v,u,q,z,alp){
  yi = (-log(fPresentValue(ufr,v,u,q,z,alp)))/v
  return(yi)
}
#y i e l d i n t e n s i t y at time 0
one.vec <- rep(1, length(zeta))
y.zero <- UFR-alpha*one.vec%*%Q%*%zeta+alpha*(exp(-alpha*t)%*%Q%*%zeta)


#y i e l d i n t e n s i t y
x1 <- c(0, seq(from=1, to=30, by=1))
x1
y1 <- c()
y1[1] <- y.zero*100
for(i in seq(from=1, to=30, by=1)) {
  y1[i+1] <- c(fYieldIntensity(UFR, x1[i+1], t,Q, zeta, alpha)*100)
}
y1

#annual i z ed y i e l d r a t e func t i on
fAnnualRate <- function(ufr,v,u,q,z,alp){
  ar = (fPresentValue(ufr, v,u,q,z,alp))^(-1/v)-1
  return(ar)
}

#annual r a t e at time 0
rate.zero <- exp(y.zero)-1

#annual r a t e s
y2 <- c()
y2[1] <- rate.zero*100
for(i in seq(from=1, to=30, by=1)){
  y2[i+1] <- c(fAnnualRate(UFR, x1[i+1],t,Q,zeta, alpha)*100)
}

#forward i n t e n s i t y func t i on
fForwardIntensity <- function(ufr,v,u,q,z,alp){
  fif=ufr-((fGuv.v(v,u,alp)%*%q%*%z)/(1+fHeart.v(v,u,alp)%*%q%*%z))
  return(fif)
}


#forward i n t e n s i t y
y3 <- c()
y3[1]<- y.zero*100
for(i in seq(from=1, to=30, by=0.1)){
  y3[i+1] <- c(fForwardIntensity(UFR, x1[i+1],t,Q,zeta,alpha)*100)
}
#pl o t
plot(x1, y3, type="l", pch=19,
     xlim=c(0,30), ylim=c(-0.22,5), xlab="Maturity",
     ylab="Yields(%)", col="red")
lines(x1, y2, col="green")
lines(x1, y1, col="blue")
legend("bottomright", c("forward intensity", "annual rate",
                        "yield to maturity"), bty = "n", lty =c(1,1,1),
       col=c("red", "green", "blue"))
grid()```


Solution 1:[1]

Not being able to follow the logic of you code up above, but noticing you have the x and y values for the yield curves, a easy solution is to interpolate the desired values by either linear interpolation or a cubic spline approach.
For example the annual rate (green curve)

Using linear interpolation at Maturity=10.5:

approx(x1, y2, xout=10.1)
$x
[1] 10.5

$y
[1] 1.375156

By using a cubic spline:

spline(x1, y2, xout=10.5)
$x
[1] 10.5

$y
[1] 1.37635

Both approaches provide similar values, from the plots, the splines might be slightly more accurate towards the center of the range.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Dave2e