Pallara and Renne (2023) and Renne and Pallara (2023) investigate the pricing the sovereign credit risk in the context of shadow-intensity frameworks. In that type of framework, the prices of defaultable bonds are given by conditional expectations of the form: \[\begin{equation} \mathbb{E}_t(\exp[\color{blue}{-z_{t+1}-\dots-z_{t+h}}-\max(0,\lambda_{t+1})-\dots -\max(0,\lambda_{t+h})]),\tag{1.1} \end{equation}\] where \(z_t\) (risk-free short-term rate) and \(\lambda_t\) (shadow default intensity) are affine functions of the state vector \(x_t\). In addition, \(x_t\) follows a Gaussian vector auto-regressive (VAR) model. That is, we have: \[\begin{eqnarray*} z_t &=& \dot{a}'x_t + \dot{b}\\ \lambda_t &=& a'x_t + b, \end{eqnarray*}\] and \[\begin{equation} x_t = \mu + \Phi x_{t-1}+ \Sigma\varepsilon_t,\tag{1.2} \end{equation}\] with \(\varepsilon_t \sim \mathcal{N}(0,Id)\) (where \(Id\) denotes the identity matrix).
Equation (1.1) gives the risk-neutral price of a bond of maturity \(h\), issued by an entity whose default intensity is \(\underline{\lambda}_t = \max(0,\lambda_t)\). (That is, the conditional default probability of the issuer, on date \(t\), is \(1-\exp(-\underline{\lambda}_t)\).)
Absent the blue terms, the conditional expectations appearing in (1.1) would be of the same type as the ones considered in the shadow-rate literature (see Black (1995)). In that case, one could for instance use the approaches proposed by Priebsch (2013) or Wu and Xia (2016) to calculate approximations for these conditional expectations. Pallara and Renne (2023) and Renne and Pallara (2023) extend the approach of Wu and Xia (2016) to compute approximate values to (1.1). Th present page uses the latter approach, employing codes contained in package TSModels
to implement this approach.
To start with, load package TSModels
. This library is available on GitHub and can be accessed using the following lines of code:
install.packages("devtools")
library(devtools)
install_github("jrenne/TSModels")
Consider a two-factor model, that is \(x_t = [x_{1,t},x_{2,t}]'\). Assume that \(z_t\) (that can be interpreted as the risk-free short term rate) depends on \(x_{1,t}\) only, and that \(\lambda_t\) (the shadow default intensity) depends on \(x_{2,t}\).
We consider the following VAR dynamics for \(x_t\): \[ x_t = \left[\begin{array}{cc}0.9 & 0 \\ 0 & 0.9\end{array}\right] x_{t-1} + \left[\begin{array}{cc}1 & 0.1 \\ 0 & 1\end{array}\right]\varepsilon_t, \] which determines \(\mu\), \(\Phi\), and \(\Sigma\) of (1.2).
Further, we want \(z_t\) (respectively \(\lambda_t\)) to be of mean 2% (respectively 0) and of standard deviation \(1\%\) (resp. 2/%).
Let us code these specifications:
Phi_x <- .9 * diag(2) # set Phi
Sigma_x <- diag(2) # set Sigma
Sigma_x[1,2] <- .1
Mu_x <- matrix(0,2,1) # set mu
stdv.z <- .01 # set the unconditional std dev of z
stdv.lambda <- .02 # set the unconditional std dev of lambda
# Compute the unconditional variance of x_t:
uncond.Variance.X <- matrix(solve(diag(2*2) - Phi_x %x% Phi_x) %*%
c(Sigma_x %*% t(Sigma_x)),2,2)
# Deduce a and a.dot:
a.dot <- matrix(c(stdv.z/sqrt(uncond.Variance.X[1,1]),0))
a <- matrix(c(0,stdv.lambda/sqrt(uncond.Variance.X[2,2])))
# Set the unconditional means of and lambda:
b.dot <- .02
b <- .0
Let us have a look at simulated paths for \(z_t\) and \(\lambda_t\):
library(TSModels)
nb.periods <- 200
X <- simul.X(Phi_x,Mu_x,Sigma_x,nb.periods)
z <- b.dot + a.dot[1] * X[1,1,]
lambda <- b + a[2] * X[2,1,]
Let us now evaluate the conditional expectations of (1.1), for \(h=\{1,\dots,10\}\). For that, we make use of function compute.condit.Exp
of package TSModels
.
H <- 10
res <- compute.condit.Exp(a,b,a.dot,b.dot,
Phi_x,Mu_x,Sigma_x,
X=cbind(X[1,1,],X[2,1,]),
max.h = H)
t.min.lambda <- which(lambda==min(lambda))
t.max.lambda <- which(lambda==max(lambda))
rbind(res$E.n[t.max.lambda,], #approximate values of the conditional expect. for date t
-log(res$E.n[t.max.lambda,])/(1:H))
## [,1] [,2] [,3] [,4] [,5] [,6]
## [1,] 0.93776082 0.88336292 0.83545648 0.79295285 0.75496469 0.72077426
## [2,] 0.06426035 0.06200958 0.05992567 0.05799788 0.05621686 0.05457155
## [,7] [,8] [,9] [,10]
## [1,] 0.6897996 0.66156599 0.63568382 0.61183102
## [2,] 0.0530506 0.05164319 0.05033933 0.04912991
The last two lines respectively give, for the date featuring the highest \(\lambda_t\), the term structures of the bond prices and of associated yields-to-maturity.
Let us now compute credit-risk-free bond prices. This is obtained by taking \(a=0\) and \(b=0\) (so that \(\lambda_t=0\)):
res0 <- compute.condit.Exp(a*0.00001,b*0.00001,a.dot,b.dot,
Phi_x,Mu_x,Sigma_x,
X=cbind(X[1,1,],X[2,1,]),
max.h = H)
y <- - log(res$E.n) / t(matrix(1:H,H,nb.periods))
y_RF <- - log(res0$E.n) / t(matrix(1:H,H,nb.periods))
spreads <- y - y_RF
Let us plot the term strcutures of yields and spreads for the date on which we observe the highest \(\lambda_t\):
plot(y[t.max.lambda,],type="l",ylim=c(0,max(y)),xlab="maturity",ylab="yields",
main="Term structures of bond yields (risk-free and defaultable bonds)",lwd=2)
lines(y_RF[t.max.lambda,],col="red",lwd=2)
lines(y_RF[t.min.lambda,],col="red",lwd=2,lty=2)
lines(y[t.min.lambda,],lwd=2,lty=2)
In this section, we calculate the conditional expectation given in (1.1) using Monte-Carlo simulations, for different maturities \(h\). We will then compare these prices with the ones resulting from function compute.condit.Exp
.
We consider the date on which \(\lambda_t\) is the highest.
nb.replics <- 10000 # Number of simulated trajectories
t <- t.max.lambda # date on which cond. expect. are computed
Xt <- matrix(X[,1,t],ncol=1) # state vector on that date
# Simulate trajectories starting from Xt:
X <- simul.X(Phi_x,Mu_x,Sigma_x,nb.periods=H,X0 = Xt,nb.replics = nb.replics)
# Compute prices for each trajectory:
aux1 <- apply(X,c(2,3),function(x){exp(- b.dot - t(x)%*%a.dot -
pmax(0,b + t(x)%*%a))})
aux2 <- apply(aux1,1,cumprod)
# Compute averages of prices across simulated trajectories:
simul.prices <- apply(aux2,1,mean)
# Compare with output of compute.condit.Exp:
plot(res$E.n[t,],lwd=2,main="Approximate formula versus Monte-Carlo approach")
lines(simul.prices)
legend("topright",c("Approximate formula","Monte-Carlo"),lty=c(NaN,1),pch=c(1,NaN),lwd=c(2,1))