楚新元 | All in R

Welcome to R Square

用 R 获取中国国债到期收益率曲线数据

楚新元 / 2021-08-18


这里直接给出代码如下,读者自行体验。

get_cnbond_yield = function(from, to) {
  
  # 规范化日期格式
  from = lubridate::ymd(from)
  to = lubridate::ymd(to)
  
  # 参数检查,参数输入错误后给出必要的提示
  test_internet = curl::has_internet()
  if (!test_internet) {
    stop('没有发现网络链接...')
  }
  
  if (is.na(from) | is.na(to)) {
    stop('输入的起止日期参数必须是包含年月日的字符。')
  }
  
  if (to < from) {
    stop('发现期初日期 > 期末日期,你把两者弄混了吗?')
  }
  
  if (to > Sys.Date()) {
    stop('输入的期末日期不能大于当前日期。')
  }
  
  if (from < "2006-03-01") {
    stop('数据库不包含2006年3月1日之前的数据。')
  }
  
  # 生成起止时间段完整的日期向量
  dates = seq.Date(from = from, to = to, by = "day")
  
  # 生成每一天的数据下载地址
  url = paste0(
    "http://yield.chinabond.com.cn/cbweb-mn/yc/downBzqxDetail?ycDefIds=2c9081e50a2f9606010a3068cae70001&&zblx=txy&&workTime=",
    dates,
    "&&dxbj=0&&qxlx=0,&&yqqxN=N&&yqqxK=K&&wrjxCBFlag=0&&locale=zh_CN"
  )
  
  # 批量下载数据到data文件夹下
  if (!dir.exists("data")) dir.create("data")
  purrr::pwalk(
    list(
      url = url, 
      mode = "wb", 
      quiet = TRUE,
      destfile = paste0("./data/", dates, ".xlsx")
    ),
    download.file
  )
  
  # 批量读取非空.xlsx文件后合并成一个数据框
  data_list = fs::dir_ls(path = "./data", glob = "*.xlsx")
  data_list = data_list[file.info(data_list)$size > 3235]
  names(data_list) = data_list
  df = purrr::map_dfr(
    data_list, 
    readxl::read_xlsx, 
    .id = "Date"
  )
  fs::dir_delete("data")  # 删除data文件夹
  
  # 必要的数据清洗加工
  df[, 2] = NULL
  colnames(df)[2:3] = c("Term", "Rate")
  df$Rate = as.numeric(df$Rate)
  df$Date = gsub("./data/", "", df$Date)
  df$Date = gsub(".xlsx", "", df$Date)
  df$Term[df$Term == 0] = "1D"
  df$Term[df$Term == 0.08] = "1M"
  df$Term[df$Term == 0.17] = "2M"
  df$Term[df$Term == 0.25] = "3M"
  df$Term[df$Term == 0.5] = "6M"
  df$Term[df$Term == 0.75] = "9M"
  df$Term[df$Term ==1] = "1Y"
  df$Term[df$Term ==2] = "2Y"
  df$Term[df$Term ==3] = "3Y"
  df$Term[df$Term ==5] = "5Y"
  df$Term[df$Term ==7] = "7Y"
  df$Term[df$Term ==10] = "10Y"
  df$Term[df$Term ==15] = "15Y"
  df$Term[df$Term ==20] = "20Y"
  df$Term[df$Term ==30] = "30Y"
  df$Term[df$Term ==40] = "40Y"
  df$Term[df$Term ==50] = "50Y"
  result = tidyr::pivot_wider(
    data = df, 
    names_from = Term, 
    values_from = Rate
  )
  
  # 导出数据到Excel文件中
  writexl::write_xlsx(result, "result.xlsx")

}