4

項構造推定用に設計された R パッケージ「termstrc」は非常に便利なツールですが、データを特に扱いにくい形式 (リスト内のリスト) で設定する必要があります。

質問: 関数「dyncouponbonds」を実行するために必要な繰り返しサブリスト形式を作成するために、R の外部または R の内部でデータを準備および整形する最良の方法は何ですか?

「dyncouponbonds」コマンドでは、繰り返しサブリストにデータを設定する必要があります。これにより、債券のリストとそれらの債券の時不変機能 (これを「bondlist」と呼びます) に、それらの債券の時間 t 機能 (価格と価格) が追加されます。経過利息)、時間 t+1 から T まで複製されます。

以下は、1 期間のリスト形式の例です。「dyncouponbonds」コマンドでは、すべての T 期間について、この形式をアンブレラ リスト内で複製する必要があります。ISIN、MATURITYDATE、ISSUEDATE、COUPONRATE は各期間で同一です。PRICE、ACCRUED、CASHFLOWS、および TODAY は、期間ごとに異なります。

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
4

2 に答える 2

4

これはかなり高度なデータ操作に関する質問です。R には多くの強力なデータ操作ツールがあり、(確かにかなり鈍い) dyncouponbonds オブジェクトを準備するために R から離れる必要はありません。実際、別の言語から構造を取得してから dyncouponbonds に変換することは、単により多くの作業になるため、実際にはすべきではありません。

最初に確認することは、あなたが lapply 関数に精通していることです。存分に活用していただきます。これを使用して、実際の dyncouponbonds である、couponbonds オブジェクトのリストを作成します。しかし、クーポン債オブジェクトの作成は、主に債券の ISIN とキャッシュフローの日付に関連付けられた各キャッシュフローを必要とする CASHFLOWS サブリストのため、少し難しくなります。これには、lapply とかなり高度な添え字を使用します。サブセット機能も便利です。

この質問は、どこからデータを取得するかにも大きく依存します。Bloomberg からデータを取得することは、主に BDS 関数と各債券の「DES_CASH_FLOW」フィールドを使用して履歴をさかのぼる必要があるため、自明ではありません。そのキャッシュフローを取得します。私が履歴と言うのは、dyncouponbonds を使用している場合は、過去の利回り曲線分析を行いたいと思うからです。BDS 関数の「SETTLE_DT」フィールドを、BDP 関数とフィールド「FIRST_SETTLE_DT」を使用して債券に対して受け取った値にオーバーライドする必要があります。そうしないと、今日からしか返されず、履歴分析には適していません)。しかし、私は脱線します。ブルームバーグを使用していない場合は、どこにいるかわかりません」

次に、各債券の静的データ、つまり満期、ISIN、クーポン レート、発行日を取得する必要があります。また、過去の価格と経過利息のデータが必要になります。ブルームバーグを使用する場合も、BDP 関数を使用して、以下のコードに表示されるフィールドと、bbdh としてラップした履歴データ関数 BDH を使用します。あなたがブルームバーグのユーザーであると仮定すると、コードは次のとおりです。

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

国コードは、2 文字の名前をブルームバーグの利回り曲線の説明に関連付ける構造に由来します。

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 は、すべて次のブルームバーグ フィールドから、actives、staticData、dynamicData、historyData と呼ばれる 4 つの異なるデータ構造を作成します。

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

これで、これらすべてのデータ構造を使用して、クーポンボンド オブジェクトを作成する準備が整いました。

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

cacheflows <- lapply... 関数をよく見てください。これは、サブリストを作成する場所であり、質問への回答の中心となるためです。中間データ構造を構築することに決めました。私は 1 つの可能性だけを示しました。私の答えは複雑ですが、問題は非常に複雑です。必要なすべてのコードがこの回答にも含まれているわけではありません。いくつかのヘルパー関数が欠落していますが、ご連絡いただければ喜んで提供させていただきます。確かに、コア関数の骨組みはすべてここにあります。実際、問題の多くは、最初にデータを取得し、適切に構造化することです。データの一部は各結合について静的であり、一部は動的であり、一部は履歴であると正しく推測できます。そのため、中間データ構造の次元は、クーポンボンド オブジェクトのさまざまな部分で異なります。それをどのように表現するかはあなた次第ですが、必要に応じてボンド ID を介してリンクされた、それぞれに個別のリスト/データ フレームを使用しました。

上記の関数は日付文字列を取得するため、上記のラップリーを使用して履歴データ ポイントごとに実行できます。

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

ほらね。あなたはそれを求めた....

ブルームバーグを使用していない場合、入力データ構造は大きく異なりますが、最初に述べたように、lapply と sapply に精通してください。もちろん、この問題を解決する方法は他にもたくさんありますが、ブルームバーグでは上記の方法が有効です。このコードを理解すれば、他のデータ ソースに対して何を行っているかがわかります。

最後に、ブルームバーグとのインターフェイスには findata.org のRBBGパッケージが使用されていることに注意してください。

于 2013-02-13T20:44:21.030 に答える