I am interested in calculating the effect of the roll return using different roll strategies. In specific I want to mimic a long-only futures investments. I have historical data for several agricultural commodities. In order to compare the returns of the different roll strategies I created ratio back-adjusted time series using the following formula's.
Ratio adjustment = (Price new contract - Price old contract)/(Price old contract) Adjusted prices = (all old futures * ratio adjustment) + Prices new contract
Since I use historical data ranging from the 80's to the end of 2014 there are multiple rolls. For every I make these adjustments (iterative process). So the latest contract is not adjusted while the first contract is adjusted tens of times (depending on the roll strategy). I want to know what the return of the various roll strategies are. Hence, I am not interested in the prices of the futures contracts itself (I realize that these get distorted by the ratio adjustment). Furthermore, since futures are traded on margin I will take a more academic approach and make the assumption that the futures are fully collateralized. Meaning that a 'x' dollar amount is invested in T-bills, where x is equal to the price of the futures contract. Hence I calculate the return of the roll strategies as follows:
Return = (new adjustment price - old adjustment price)/(old adjustment price) - (t-bill interest earned on amount x) * 100
However, I think I am making a mistake since the return on a soybean position is extraordinary. Somewhere in the 600% (when I do not consider the t-bill interest earned) over a time period from 1997 to 2014 when rolling on the last trading day. What am I missing? How should I calculate and compare the performance of the different roll strategies if this approach is wrong?
** EDIT: Added code R ** This is the function which I use to calculate the roll return in R. Every roll date I iterate over this function:
backAdjTSFun <- function(ts, rollRow, pastRollRow, rollFromColumn,df,adjRatio = FALSE,nextRollRow = NULL, lastColumn = NULL) {
#adjust the exisiting data by the ratio
if (is.null(pastRollRow)) {
currentContractPrices <- df[1:rollRow, rollFromColumn]
#because you do not necessarily start at the beginning of the dataset
#there might be some na's from the first row onwards
#hence, delete these first.
currentContractPrices <- na.omit(currentContractPrices)
updatedTS <- as.numeric(currentContractPrices) * as.numeric(adjRatio)
} else {
tsRatioAdj <- as.numeric(ts) * as.numeric(adjRatio)
#You roll at the end of the last trading day to the next contract. Hence, you only need to start counting from the NEXT day. The last trading day is included in the rollFromColumn vector.
dayAfterPastRoll <- pastRollRow + 1
#For the deferred roll the last roll is not made. Due to data constraints.
#Hence you need to make an adjustment and make sure that the data of the second last
#roll is not adjusted.
if(!is.null(lastColumn) && lastColumn == TRUE) {
currentContractPrices <- df[dayAfterPastRoll:rollRow, rollFromColumn]
updatedTS <- c(tsRatioAdj, currentContractPrices)
}
#For the front month roll and last day roll you should add the contract prices of the
#last roll unadjusted.
else {
currentContractPrices <- df[dayAfterPastRoll:rollRow, rollFromColumn] * as.numeric(adjRatio)
#combine the timeseries for the current contract and the already existing adjusted timeseries
updatedTS <- c(tsRatioAdj, currentContractPrices)
#if the column is the last column in the sample then
#select the data in this column and append it to the price vector
#without adjusting it.
nextColumn <- rollFromColumn + 1
if(nextColumn == length(df) && !is.null(nextRollRow)) {
if(!is.null(lastColumn) && lastColumn == TRUE) {
nextColumn <- lastColumn
}
currentContractPrices <- df[(rollRow+1):nextRollRow, nextColumn]
updatedTS <- c(updatedTS, currentContractPrices)
}
}
}
return(updatedTS)
}
ldr <- function (df, settlement = FALSE, ret="roll", startAdj = F) {
error <- NULL
rollReturn <- NULL
retMatrix <- matrix(,nrow=length(df),ncol=13)
colnames(retMatrix) <- c("previousContract", "newContract", "difference", "rollDate","startDate", "endDate", "Mean roll return", "Std.", "Number of rolls", "Min", "25% - 75%", "Median", "Max")
# Ok, there are two possibilities here...
# Possibility number 1: determine the last trading date of a contract.
# The last trading is the settlement date
firstTradingDay <- sapply(df, function (x) min(which(!is.na(x))))
if (settlement == FALSE) {
lastTradingDay <- sapply(df, function (x) max(which(!is.na(x))))
}
else {
lastTradingDay <- settlement
}
n <- 1
z <- 1
pastRollRow <- NULL
for (i in lastTradingDay) {
if (n < length(df)) {
z <- z + 1
rollFrom <- as.numeric(as.character(df[i,n]))
rollTo <- as.numeric(as.character(df[i,n+1]))
#backadj
adjRatio <- rollTo/rollFrom
ts <- backAdjTSFun(ts,i,pastRollRow,n,df,adjRatio,lastTradingDay[z]);
pastRollRow <- i
retMatrix[n,1] <- rollFrom
retMatrix[n,2] <- rollTo
retMatrix[n,3] <- calcReturn(rollFrom,rollTo)
retMatrix[n,4] <- as.character(date[i])
}
n <- n + 1
}
transFormed <- as.numeric(retMatrix[,3])
quantiles <- quantile(transFormed, c(0.25,0.75), na.rm=T)
retMatrix[1,5] <- as.character(date[firstTradingDay[1]])
retMatrix[1,6] <- as.character(date[tail(lastTradingDay,1)])
retMatrix[1,7] <- mean(transFormed, na.rm=T)
retMatrix[1,8] <- sd(transFormed, na.rm=T)
retMatrix[1,9] <- length(na.omit(retMatrix[,3]))
retMatrix[1,10] <- min(transFormed, na.rm=T)
retMatrix[1:2,11] <- quantiles
retMatrix[1,12] <- median(transFormed, na.rm=T)
retMatrix[1,13] <- max(transFormed, na.rm=T)
#Let the dates overlap/correspond with eachother at every entry across strategies --> add NA's before
if (startAdj == TRUE && ret == 'ts' || ret == 'tsReturn') {
ts <- c(rep('NA',firstTradingDay[1]-1),ts)
}
return(returnVal(ret, error, retMatrix, ts))
}
Where df is my dataframe which is Datastream output and data is a vector containing all the dates in the sample.
** EDIT Results **
[1] https://i.stack.imgur.com/FMTlH.jpg "Results"
Where the FMR1 rolls the contract rolls the position on the last day of the month prior to the last settlement day. FMR2 rolls the contract on the last day two months prior to the last settlement day and LDR rolls the contract on the last settlement day of a contract.