1

私は仕事でいくつかのコードをより速く実行することを任されており、並列計算で障害に遭遇しました。並行して実行したいオリジナルの for ループがあります。for ループを使用せずにコードを再現し、代わりに lapply() を使用するのが最も簡単に思えますが、これはループと同じくらい長く実行されます。parLapply() を使用してコードを書き直すと、lapply() と元の for ループの結果とは異なる結果になりますが、はるかに迅速な結果が得られます。どちらも同等です。このプログラムの目的は、各国の各満期レベルでのキャッシュ スプレッド (スプレッド カーブ) を計算することです。

「bonddata.csv」リンク: http://www.mediafire.com/download/hfcdbryhedpso77/bonddata.csv 「weocountries.csv」リンク: http://www.mediafire.com/download/7x15csw7lwwataj/weocountries.csv

必要なデータとライブラリの読み込み:

library(reshape2)
library(ggplot2)
library(Rblpapi)
library(xts)
library(YieldCurve)
library(parallel)
library(snow)
library(countrycode)
library(gridExtra)
library(compare)

#Read in the data
countries<-read.csv("weocountries.csv",stringsAsFactors=FALSE,na.strings="")
bonddata <- read.csv("bonddata.csv")
bonddata$iso <- as.character(bonddata$iso)
bonddata$maturity <- as.Date(as.character(bonddata$maturity))
rownames(bonddata) <- as.character(bonddata$X)
bonddata$X <- NULL
bonddata <- na.omit(bonddata)

キャッシュ スプレッドを計算する関数の作成:

calcspreadcurve<-function(data,maturities){
  numbonds<-nrow(data)
  if(numbonds<=3){
    ForceIntercept<-.5*min(data$spread)
    mod<-lm(I(data$spread-ForceIntercept)~0+log(100*data$averagelife))
    fits<-mod$coefficients*log(100*maturities)+ForceIntercept
    return(fits)
  }
  else {
    mod<-try(Nelson.Siegel(data$spread,12*data$averagelife),TRUE)
    if(is.numeric(mod)){
      fits<-as.vector(NSrates(xts(mod,Sys.Date()),12*maturities))
    } else {
      ForceIntercept<-.8*mean(data$spread)
      mod<-lm(I(data$spread-ForceIntercept)~0+log(100*data$averagelife))
      fits<-mod$coefficients*log(100*maturities)+ForceIntercept
    }       

    if(min(fits)<0){
      ForceIntercept<-.8*mean(data$spread)
      mod<-lm(I(data$spread-ForceIntercept)~0+log(100*data$averagelife))
      fits<-mod$coefficients*log(100*maturities)+ForceIntercept
    } 

    if(mean(fits)>2*mean(data$spread)){
      ForceIntercept<-.8*mean(data$spread)
      mod<-lm(I(data$spread-ForceIntercept)~0+log(100*data$averagelife))
      fits<-mod$coefficients*log(100*maturities)+ForceIntercept
    }

    return(fits)
  }
}

# Calculate standardized USD spread curves for all countries
bondcountries<-unique(bonddata$iso)
maturities<-c(1,2,5,10,20,30,50,100)

元のコード:

#Original for loop
cashspreads<-NULL
for(i in 1:length(bondcountries)){
  curve<-calcspreadcurve(bonddata[bonddata$iso==bondcountries[i],],maturities)
  cashspreads<-rbind(cashspreads,curve)
}
rownames(cashspreads)<-sapply(bondcountries,function(x) countries$ISO3[which(countries$ISO2==x)])
colnames(cashspreads)<-c("1Y","2Y","5Y","10Y","20Y","30Y","50Y","100Y")

lapply() コード:

#What loop is doing (lapply)
cashspreads2 <- t(as.data.frame(lapply(split(bonddata,bonddata$iso),function(data,m=maturities){
  numbonds<-nrow(data)
  if(numbonds<=3){
    ForceIntercept<-.5*min(data$spread)
    mod<-lm(I(data$spread-ForceIntercept)~0+log(100*data$averagelife))
    fits<-mod$coefficients*log(100*m)+ForceIntercept
    return(fits)
  }
  else {
    mod<-try(Nelson.Siegel(data$spread,12*data$averagelife),TRUE)
    if(is.numeric(mod)){
      fits<-as.vector(NSrates(xts(mod,Sys.Date()),12*m))
    } else {
      ForceIntercept<-.8*mean(data$spread)
      mod<-lm(I(data$spread-ForceIntercept)~0+log(100*data$averagelife))
      fits<-mod$coefficients*log(100*m)+ForceIntercept
    }       
    if(min(fits)<0){
      ForceIntercept<-.8*mean(data$spread)
      mod<-lm(I(data$spread-ForceIntercept)~0+log(100*data$averagelife))
      fits<-mod$coefficients*log(100*m)+ForceIntercept
    } 
    if(mean(fits)>2*mean(data$spread)){
      ForceIntercept<-.8*mean(data$spread)
      mod<-lm(I(data$spread-ForceIntercept)~0+log(100*data$averagelife))
      fits<-mod$coefficients*log(100*m)+ForceIntercept
    }
    return(fits)
  }
})))
rownames(cashspreads2)<-countrycode(rownames(cashspreads2),"iso2c","iso3c")
colnames(cashspreads2) <- c("1Y","2Y","5Y","10Y","20Y","30Y","50Y","100Y")

parLapply() コード:

#Run in parallel (parLapply)
cl <- makeCluster(type="SOCK",detectCores()-1)
cashspreads3 <- t(as.data.frame(parLapply(cl,split(bonddata,bonddata$iso),function(data,m=c(1,2,5,10,20,30,50,100)){
  numbonds<-nrow(data)
  if(numbonds<=3){
    ForceIntercept<-.5*min(data$spread)
    mod<-lm(I(data$spread-ForceIntercept)~0+log(100*data$averagelife))
    fits<-mod$coefficients*log(100*m)+ForceIntercept
    return(fits)
  }
  else {
    mod<-try(Nelson.Siegel(data$spread,12*data$averagelife),TRUE)
    if(is.numeric(mod)){
      fits<-as.vector(NSrates(xts(mod,Sys.Date()),12*m))
    } else {
      ForceIntercept<-.8*mean(data$spread)
      mod<-lm(I(data$spread-ForceIntercept)~0+log(100*data$averagelife))
      fits<-mod$coefficients*log(100*m)+ForceIntercept
    }       
    if(min(fits)<0){
      ForceIntercept<-.8*mean(data$spread)
      mod<-lm(I(data$spread-ForceIntercept)~0+log(100*data$averagelife))
      fits<-mod$coefficients*log(100*m)+ForceIntercept
    } 
    if(mean(fits)>2*mean(data$spread)){
      ForceIntercept<-.8*mean(data$spread)
      mod<-lm(I(data$spread-ForceIntercept)~0+log(100*data$averagelife))
      fits<-mod$coefficients*log(100*m)+ForceIntercept
    }
    return(fits)
  }
})))
stopCluster(cl)
rownames(cashspreads3)<-countrycode(rownames(cashspreads3),"iso2c","iso3c")
colnames(cashspreads3) <- c("1Y","2Y","5Y","10Y","20Y","30Y","50Y","100Y")

データフレームの比較:

compare(cashspreads[order(rownames(cashspreads)),],cashspreads2[order(rownames(cashspreads2)),])
compare(cashspreads[order(rownames(cashspreads)),],cashspreads3[order(rownames(cashspreads3)),])

コードが適切に実行された場合、結果のデータフレーム "cashspreads" および "cashspreads2" は、データフレーム "cashspreads3" と比較できません。

これが同じデータフレームを生成しない理由について何か考えはありますか?

4

0 に答える 0