收益

比較不同滾動策略的回報

  • January 14, 2015

我有興趣使用不同的滾動策略計算滾動返回的效果。具體來說,我想模仿只做多的期貨投資。我有幾種農產品的歷史數據。為了比較不同滾動策略的回報,我使用以下公式創建了比率反向調整的時間序列。

比率調整=(新合約價格-舊合約價格)/(舊合約價格)調整後價格=(所有舊期貨*比率調整)+新合約價格

由於我使用從 80 年代到 2014 年底的歷史數據,因此有多個卷。對於每次我進行這些調整(迭代過程)。所以最新的合約沒有調整,而第一個合約調整了幾十次(取決於滾動策略)。我想知道各種滾動策略的回報是什麼。因此,我對期貨合約本身的價格不感興趣(我意識到這些價格會被比率調整扭曲)。此外,由於期貨是以保證金交易的,我將採取更學術的方法,並假設期貨是完全抵押的。這意味著將“x”美元金額投資於國庫券,其中 x 等於期貨合約的價格。因此,我計算滾動策略的回報如下:

回報=(新調整價格-舊調整價格)/(舊調整價格)-(金額x賺取的國庫券利息)*100

然而,我認為我犯了一個錯誤,因為大豆頭寸的回報是非凡的。在 1997 年至 2014 年的最後一個交易日滾動時,在 600% 的某個地方(當我不考慮所賺取的國庫券利息時)。我錯過了什麼?如果這種方法是錯誤的,我應該如何計算和比較不同滾動策略的性能?

** 編輯:添加程式碼 R ** 這是我用來計算 R 中的滾動回報的函式。我迭代此函式的每個滾動日期:

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))  
}

其中 df 是我的數據框,它是 Datastream 輸出,而 data 是包含樣本中所有日期的向量。

** 編輯結果 **

$$ 1 $$ http://imgur.com/NWXv6FL “結果” 如果 FMR1 展期,合約會在最後一個結算日之前的一個月的最後一天展期。FMR2 在最後結算日前兩個月的最後一天滾動合約,LDR 在合約的最後結算日滾動合約。

好。我執行的一種天真的快速調整方法顯示,在不包括任何利息的情況下,同期增長了約 230%,因此這個結果本身不一定不合理。調整後的回報有時會在很大程度上取決於您的滾動規則,尤其是當您深入了解歷史時。

也許快速瀏覽一下您的價格/退貨。一些合約(11 月的大豆合約加上其他合約?)交易非常稀少,應該被排除在滾動系列之外。滾動日期的糟糕價格可能會搞砸一個系列。

引用自:https://quant.stackexchange.com/questions/16175