-
Notifications
You must be signed in to change notification settings - Fork 52
Description
Hi all,
This post pertains to QuantLib version 1.16 and RQuantLib version 0.4.12 (ran in RStudio 1.1.419 with R 64bit 4.0.2)
Looking at the Bermudan.R file, I can see that the variable increment = min(matYears/6,1.0) (and matYears=as.numeric(params$maturity-params$tradeDate)/365). What is the goal of the increment formulae? If increment is less than 0.50 then there will always be en error in the for-loop in line 70 in Bermudan.R due to expiryIDX=findInterval(i*increment,swaptionMaturities) = 0 at i = 2 thus vol[i]=volMatrix[0, tenorIDX+1]. I assume we are dividing by 6 in increment as we assume that swaptions are to be exercised semiannually - but doesn't this defeat the purpose of defining dt in params?
To give some example data - everything is the same as the built-in Bermudan example except params and EvaluationDate:
params <- list(tradeDate=as.Date('2019-12-16'),
settleDate=as.Date('2019-12-16'),
startDate=as.Date('2019-12-18'),
maturity=as.Date('2022-12-12'),
dt=.25,
payFixed=TRUE,
european=FALSE,
strike=0.02589379,
method="HWTree",
interpWhat="discount",
interpHow="linear")
setEvaluationDate(as.Date('2020-04-30'))
# Market data used to construct the term structure of interest rates
tsQuotes <- list(d1w =0.05,
# d1m =0.0372,
# fut1=96.2875,
# fut2=96.7875,
# fut3=96.9875,
# fut4=96.6875,
# fut5=96.4875,
# fut6=96.3875,
# fut7=96.2875,
# fut8=96.0875,
s3y =0.05,
s5y =0.05,
s10y =0.05,
s15y =0.05)
times=seq(0,14.75,.25)
swcurve=DiscountCurve(params,tsQuotes,times)
# Use this to compare with the Bermudan swaption example from QuantLib
#tsQuotes <- list(flat=0.04875825)
# Swaption volatility matrix with corresponding maturities and tenors
swaptionMaturities <- c(1,2,3,4,5)
swapTenors <- c(1,2,3,4,5)
volMatrix <- matrix(
c(0.1490, 0.1340, 0.1228, 0.1189, 0.1148,
0.1290, 0.1201, 0.1146, 0.1108, 0.1040,
0.1149, 0.1112, 0.1070, 0.1010, 0.0957,
0.1047, 0.1021, 0.0980, 0.0951, 0.1270,
0.1000, 0.0950, 0.0900, 0.1230, 0.1160),
ncol=5, byrow=TRUE)
# volMatrix <- matrix(
# c(rep(.20,25)),
# ncol=5, byrow=TRUE)
# Price the Bermudan swaption
pricing <- BermudanSwaption(params, ts=.05,
swaptionMaturities, swapTenors, volMatrix)
summary(pricing)
This throws an error: Error in vol[i] <- volMatrix[expiryIDX, tenorIDX + 1] : replacement has length zero which is caused by the for loop in Bermudan.R from line 61:
for(i in 2:numObs){
expiryIDX=findInterval(i*increment,swaptionMaturities)
tenorIDX=findInterval(matYears-(i-1)*increment,swapTenors)
if(tenorIDX >0 & expiryIDX>0){
vol[i]=volMatrix[expiryIDX,tenorIDX]
expiry[i]=swaptionMaturities[expiryIDX]
tenor[i]=swapTenors[tenorIDX]
} else {
vol[i]=volMatrix[expiryIDX,tenorIDX+1]
expiry[i]=swaptionMaturities[expiryIDX]
tenor[i]=swapTenors[tenorIDX+1]
}
}
The else condition is triggered with the provided dates in params because expiryIDX = 0 due to increment being equal to about 0.498 at i = 2. In my example, the swaption tenor is just below 3 years with a quarterly exercise possibility. Of course, everything works if the swaption tenor is above 3 years (i.e. matYear > 3) as increment >= 0.50 thus expiryIDX=findInterval(i*increment,swaptionMaturities) >= 1 thus in line 70 vol[i]=volMatrix[expiryIDX,tenorIDX+1] we have expiryIDX > 0 (no error).
I realise these are just checks to confirm whether the params list has been properly filled, as nothing calculated in Bermudan.R is passed onto the C++ code, but I do not feel as the example-data I provided is unreasonable.