结合时间序列对象和列表:套餐“termstrc”(Combining time-series obj

2019-07-04 01:47发布

将R包“termstrc”,专为术语-结构估计,是一个非常有用的工具,但它需要的数据以特别别扭格式进行设置:列表中的列表。

:什么是准备和形状数据的最佳方式,无论是外部的R或内部R,以创建运行功能“dyncouponbonds”所需的重复子列表格式?

所述“dyncouponbonds”命令需要在重复的子列表,由此键和那些键的时不变特征的列表(我们称之为“bondlist”)要被设置的数据,附加有那些键的一些时间t特征(价格和应计利息)和复制时间t + 1到T.

下面是一个周期列表格式的例子。 该“dyncouponbonds”命令需要这种格式被复制,雨伞列表中,对于所有的T周期。 ISIN,MATURITYDATE,ISSUEDATE,COUPONRATE将是每个周期是相同的。 PRICE,应付,现金流,今天将是各个时期不同。

R> str(govbonds$GERMANY)

List of 8
$ ISIN : chr [1:52] "DE0001141414" "DE0001137131" "DE0001141422" ...
$ MATURITYDATE:Class 'Date' num [1:52] 13924 13952 13980 14043 ...
$ ISSUEDATE :Class 'Date' num [1:52] 11913 13215 12153 13298 ...
$ COUPONRATE : num [1:52] 0.0425 0.03 0.03 0.0325 ...
$ PRICE : num [1:52] 100 99.9 99.8 99.8 ...
$ ACCRUED : num [1:52] 4.09 2.66 2.43 2.07 ...
$ CASHFLOWS :List of 3
..$ ISIN: chr [1:384] "DE0001141414" "DE0001137131" "DE0001141422" ...
..$ CF : num [1:384] 104 103 103 103 ...
..$ DATE:Class 'Date' num [1:384] 13924 13952 13980 14043 ...
$ TODAY :Class 'Date' num 13908

Answer 1:

这是一个相当先进的数据处理问题。 R有许多强大的数据处理工具,你就不会需要移动与R客场准备(当然相当钝)dyncouponbonds对象。 事实上,你确实不应该,因为从另一种语言采取的结构,然后变成dyncouponbonds将只是更多的工作。

我会确保的第一件事情是,你是非常熟悉的lapply功能。 你将要作出大量地使用它。 你会用它来创建couponbonds对象的列表,这是实际dyncouponbonds是。 创建couponbonds对象但主要是因为其希望与债券的ISIN,并与现金流的日期相关联的每个现金流的现金流子表的有点艰难。 为此,您将使用lapply和一些相当先进的下标。 该子集功能也能派上用场。

这个问题也很大程度上取决于在那里你会得到从数据,并得到它的彭博是不平凡的,主要是因为你需要使用BDS功能和“DES_CASH_FLOW”字段分别结合在回去的历史得到它的现金流。 我说,历史的,因为如果你使用dyncouponbonds我假设你会想要做历史收益率曲线分析。 你需要重写BDS功能的“SETTLE_DT”领域,你会收到使用BDP功能和领域“FIRST_SETTLE_DT”债券的价值,让你得到所有从债券的生活开始的现金流(否则它只会从今天返回,这是对历史的分析没有好)。 但是,我离题。 如果你不使用彭博我不知道在那里你会从中获取这些数据。

那么你就需要以获取静态数据,每张债券,即到期时,ISIN和票面利率和发行日期。 你还需要历史的价格和应计利息的数据。 同样地,如果使用彭博,你将使用BDP功能与这个领域,你会在代码中看到,下面,和历史数据功能BDH我已经包装成bbdh。 再次,你是彭博用户假设,这里是代码:

bbGetCountry <- function(cCode, up = FALSE) {
# this function is going to get all the data out of bloomberg that we need for a
# country, and update it if ncessary
    if (up == TRUE) startDate <- as.Date("2012-01-01") else startDate <- histStartDate 
    # first get all the curve members for history
    wdays <- wdaylist(startDate, Sys.Date()) # create the list of working days from startdate
    actives <- lapply(wdays, function(x) { 
        bds(conn, BBcurveIDs[cCode], "CURVE_MEMBERS", override_fields = "CURVE_DATE",
        override_values = format(x, "%Y%m%d"))
    })
    names(actives) <- wdays
    uniqueActives <- unique(unlist(actives)) # there will be puhlenty duplicates. Get rid of them
    # now get the unchanging bond data
    staticData <- bdp(conn, uniqueActives, bbStaticDataFields)
    # now get the cash flowdata
    cfData <- lapply(uniqueActives, function(x) {
        bds(conn, x, "DES_CASH_FLOW_ADJ", override_fields = "SETTLE_DT", 
            override_values = format(as.Date(staticData[x, "FIRST_SETTLE_DT"]), "%Y%m%d"))
    })
    names(cfData) <- uniqueActives
    # now for historic data
    historicData <- lapply(bbHistoricDataFields, function(x) bbdh(uniqueActives, flds = x, startDate = startDate))
    names(historicData) <- bbHistoricDataFields   # put the names in otherwise we get a numbered list
    allDates <- as.Date(index(historicData$LAST_PRICE)) # all the dates we will find settlement dates for for all bonds. No posix
    save(actives, file = paste("data/", cCode, "actives.dat", sep = ""))      #save all the files now
    save(staticData, file = paste("data/", cCode, "staticData.dat", sep = ""))
    save(cfData, file = paste("data/", cCode, "cfData.dat", sep = ""))
    save(historicData, file = paste("data/", cCode, "historicData.dat", sep = ""))
    #save(settleDates, file = paste("data/", cCode, "settleDates.dat", sep = ""))
    assign(paste(cCode, "data", sep = ""), list(actives = actives, staticData = staticData, cfData = cfData,    #
        historicData = historicData), pos = 1)

}

我在上面使用bbdh功能是围绕Rbbg库的BDH功能的包装,看起来像这样:

bbdh <- function(secs, years = 1, flds = "last_price", startDate = NULL) {
        #this function gets secs over years from bloomberg daily data
            if(is.null(startDate)) startDate <- Sys.Date() - years * 365.25
            if(class(startDate) == "Date") stardDate <- format(startDate, "%Y%m%d") #convert date classes to bb string
            if(nchar(startDate) > 8) startDate <- format(as.Date(startDate), "%Y%m%d") # if we've been passed wrong format character string 
            rawd <- bdh(conn, secs, flds, startDate, always.display.tickers = TRUE, include.non.trading.days = TRUE,
                option_names = c("nonTradingDayFillOption", "nonTradingDayFillMethod"),
                option_values = c("NON_TRADING_WEEKDAYS", "PREVIOUS_VALUE"))
            rawd <- dcast(rawd, date ~ ticker) #put into columns
            colnames(rawd) <- sub(" .*", "", colnames(rawd)) #remove the govt, currncy bits from bb tickers
            return(xts(rawd[, -1], order.by = as.POSIXct(rawd[, 1])))
        }

国家代码来自其关联彭博收益率曲线描述的两个字母名称的结构:

BBcurveIDs  <- list(PO = "YCGT0084 Index", #Portugal
                    DE = "YCGT0016 Index", 
                    FR = "YCGT0014 Index", 
                    SP = "YCGT0061 Index",
                    IT = "YCGT0040 Index",
                    AU = "YCGT0001 Index", #Australia
                    AS = "YCGT0063 Index", #Austria
                    JP = "YCGT0018 Index",
                    GB = "YCGT0022 Index",
                    HK = "YCGT0095 Index",
                    CA = "YCGT0007 Index",
                    CH = "YCGT0082 Index",
                    NO = "YCGT0078 Index",
                    SE = "YCGT0021 Index",
                    IR = "YCGT0062 Index",
                    BE = "YCGT0006 Index",
                    NE = "YCGT0020 index", 
                    ZA = "YCGT0090 Index",
                    PL = "YCGT0177 Index", #Poland
                    MX = "YCGT0251 Index")

所以bbGetCountry将创建4层不同的数据结构,称为活性,staticData,dynamicData和historicData,所有从以下彭博字段:

bbStaticDataFields <- c("ID_ISIN",
                      "ISSUER", 
                      "COUPON",
                      "CPN_FREQ",
                      "MATURITY",
                      "CALC_TYP_DES",                    # pricing calculation type 
                      "INFLATION_LINKED_INDICATOR",     # N or Y, in R returned as TRUE or FALSE
                      "ISSUE_DT",
                      "FIRST_SETTLE_DT",
                      "PX_METHOD",                      # PRC or YLD 
                      "PX_DIRTY_CLEAN",                 # market convention dirty or clean
                      "DAYS_TO_SETTLE",
                      "CALLABLE",
                      "MARKET_SECTOR_DES",
                      "INDUSTRY_SECTOR",
                      "INDUSTRY_GROUP",
                      "INDUSTRY_SUBGROUP")

bbDynamicDataFields <- c("IS_STILL_CALLABLE",
                        "RTG_MOODY",
                        "RTG_MOODY_WATCH",
                        "RTG_SP",
                        "RTG_SP_WATCH",
                        "RTG_FITCH",
                        "RTG_FITCH_WATCH")

bbHistoricDataFields <- c("PX_BID",
                          "PX_ASK",
                          #"PX_CLEAN_BID",
                          #"PX_CLEAN_ASK",
                          "PX_DIRTY_BID",
                          "PX_DIRTY_ASK",
                          #"ASSET_SWAP_SPD_BID",
                          #"ASSET_SWAP_SPD_ASK",
                          "LAST_PRICE",
                          #"SETTLE_DT",
                          "YLD_YTM_MID")

现在,您可以创建couponbond对象,使用所有这些数据结构:

createCouponBonds <- function(cCode, dateString) {
    cdata <- get(paste(cCode, "data", sep = "")) # get the data set
    today <- as.Date(dateString)
    settleDate <- today
    daycount <- 0
    while(daycount < 3) {
        settleDate <- settleDate + 1
        if (!(weekdays(settleDate) %in% c("Saturday", "Sunday"))) daycount <- daycount + 1
    }
    goodbonds <- subset(cdata$staticData, COUPON != 0 & INFLATION_LINKED_INDICATOR == FALSE) # clean out zeros and tbills
    goodbonds <- goodbonds[rownames(goodbonds) %in% cdata$actives[[dateString]][, 1], ]
    stripnames <- sapply(strsplit(rownames(goodbonds), " "), function(x) x[1])
    pxbid <- cdata$historicData$PX_BID[today, stripnames]
    pxask <- cdata$historicData$PX_ASK[today, stripnames]
    pxdbid <- cdata$historicData$PX_DIRTY_BID[today, stripnames]
    pxdask <- cdata$historicData$PX_DIRTY_ASK[today, stripnames]
    price <- as.numeric((pxbid + pxask) / 2)
    accrued <- as.numeric(pxdbid - pxbid)
    cashflows <- lapply(rownames(goodbonds), function(x) {
        goodflows <- cdata$cfData[[x]][as.Date(cdata$cfData[[x]][, "Date"]) >= today, ]
        #gfstipnames <- sapply(strsplit(rownames(goodflows), " "), function(x) x[1]) dunno if I need this
        isin <- rep(cdata$staticData[x, "ID_ISIN"], nrow(goodflows))
        cf <- apply(goodflows[, 2:3], 1, sum) / 10000
        dt <- as.Date(goodflows[, 1])
        return(list(isin = isin, cf = cf, dt = dt))
    })
    isinvec <- unlist(lapply(cashflows, function(x) x$isin))
    cfvec <- as.numeric(unlist(lapply(cashflows, function(x) x$cf)))
    datevec <- unlist(lapply(cashflows, function(x) x$dt))
    govbonds <- list(ISIN = goodbonds$ID_ISIN, 
                     MATURITYDATE = as.Date(goodbonds$MATURITY),
                     ISSUEDATE = as.Date(goodbonds$FIRST_SETTLE_DT),
                     COUPONRATE = as.numeric(goodbonds$COUPON) / 100,
                     PRICE = price,
                     ACCRUED = accrued,
                     CASHFLOWS = list(ISIN = isinvec, CF = cfvec, DATE = as.Date(datevec)),
                     TODAY = settleDate)
    govbonds <- list(govbonds)
    names(govbonds) <- cCode
    class(govbonds) <- "couponbonds"
    return(govbonds)
}

仔细看的现金流< - lapply ......功能,因为这是在这里您可以创建子列表,是回答你的问题的核心,当然,这是如何完成在很大程度上取决于你如何有决定建立中间数据结构,我已经给你仅仅是一种可能性。 我意识到,我的答案是复杂的,但问题是非常复杂的。 所有你需要的代码是不是在这个答案要么,几个辅助功能缺失,但我很高兴,如果你与我联系,为他们提供。 当然的核心功能骨架都在这里,实际上,很多问题越来越摆在首位的数据,并适当地将其结构。 您正确地推测一些数据是静态的每个键,它的一些是动态的,有的却是历史。 因此,中间DATAS结构的尺寸是不同的片couponbonds对象的不同。 你如何代表是你的,虽然我已经使用了每个单独的列表/数据帧,通过债券的ID必要挂在那里。

上面的函数将日期字符串,因此您可以为每一个历史数据点的做到这一点,利用上述lapply,哎“急”,dyncouponds:

spl <<- lapply(dodates, function(x) createCouponBonds("SP", x))
    names(spl) <<- lapply(spl, function(x) x$SP$TODAY)
    class(spl) <- "dyncouponbonds"

你去那里。 你自找的....

如果你不使用彭博资讯,您输入的数据结构会有很大的不同,但是,正如我所说的起步,获得超熟悉lapply和sapply。 显然,还有很多其他的方法解决此问题可以解决,但彭博上述作品。 如果你了解这个代码,你肯定会知道你在做什么其他数据源。

最后请注意, Rbbg从findata.org包用于连接彭博。



Answer 2:

我的2美分,我一直在试图获得新的这项工作Rblpapi 。 我仍然有一些问题createCouponBonds一部分,但我认为其他功能正常返回。 不能解决整个问题,但至少部分修复。 BBcurveIDs, bbStaticDataFields, bbDynamicDataFields, bbHistoricDataFields是与上述相同。

bbGetCountry <- function(cCode, up = FALSE) {
  if (up == TRUE) startDate <- as.Date("2016-01-01") else startDate <- histStartDate 
  cal <- Calendar(weekdays=c("saturday", "sunday"))
  wdays <- as.list(bizseq(startDate, Sys.Date(), cal))
  actives <- lapply(wdays, function(x) { 
    bds(BBcurveIDs[cCode][[1]], "CURVE_MEMBERS", override = c(CURVE_DATE=format(x, "%Y%m%d")))
  })
  names(actives) <- wdays
  uniqueActives <- unique(unlist(actives))
  staticData <- bdp(uniqueActives, bbStaticDataFields)
  cfData <- lapply(uniqueActives, function(x) {
    bds(x, "DES_CASH_FLOW_ADJ", override = c(SETTLE_DT = format(as.Date(staticData[x, "FIRST_SETTLE_DT"]), "%Y%m%d")))
  })
  names(cfData) <- uniqueActives

  historicData <- lapply(bbHistoricDataFields, function(x) bbdh(uniqueActives, flds = x, startDate = startDate))
  names(historicData) <- bbHistoricDataFields
  allDates <- as.Date(index(historicData$LAST_PRICE))

  save(actives, file = paste("data_", cCode, "actives.dat", sep = ""))
  save(staticData, file = paste("data_", cCode, "staticData.dat", sep = ""))
  save(cfData, file = paste("data_", cCode, "cfData.dat", sep = ""))
  save(historicData, file = paste("data_", cCode, "historicData.dat", sep = ""))
  #save(settleDates, file = paste("data_", cCode, "settleDates.dat", sep = ""))
  assign(paste(cCode, "data", sep = ""), list(actives = actives, staticData = staticData, cfData = cfData,    #
                                              historicData = historicData), pos = 1)

}

而bbdh功能:

bbdh <- function(secs, years = 1, flds = "last_price", startDate = NULL) {
  if(is.null(startDate)) startDate <- Sys.Date() - years * 365.25
  if(class(startDate) == "Date") stardDate <- format(startDate, "%Y%m%d")
  if(nchar(startDate) > 8) startDate <- format(as.Date(startDate), "%Y%m%d")
  rawd <- bdh(secs, flds, 
              startDate, 
              include.non.trading.days = FALSE,
              options = structure(c("PREVIOUS_VALUE", "NON_TRADING_WEEKDAYS"),
                                  names = c("nonTradingDayFillMethod","nonTradingDayFillOption")))
  rawd <- ldply(rawd, data.frame)
  colnames(rawd) <- c("sec", "date", "fld")
  rawd <- dcast(rawd, date ~ sec, value.var="fld")
  colnames(rawd) <- gsub(" Corp", "", colnames(rawd))
  return(xts(rawd[,-1], order.by=rawd[,1]))
}


文章来源: Combining time-series objects and lists: Package “termstrc”