我国债券历史成交日度数据(20190121-20190628)
问题背景:
从2014年出现第一只公募债券违约,到现在2021年,高收益债市场经历了明显的扩容。2014年以后,零星出现一些弱资质企业和中小企业集合债违约,当时违约主要集中在抗风险能力比较差的企业。2017-2018年,出现一波民营产业类企业违约潮,并伴随股权质押爆仓,民间借贷也出现了风险。2018年之后,市场中出现了一批所谓的“假国企”违约,比如华阳经贸、中城建、北大方正等等,市场赋予这类企业一定信仰,但企业内部的公司治理和商业经营层面存在问题。再后来,2020年底弱资质大型国企违约,2021年又蔓延到了恒大这种超大型房地产企业,到后来多个大型房企进入违约潮,高收益债市场迅速扩容。
在高收益债市场迅速扩容,标的不断增加的契机下,高收益债也出现了较好的投资机会,如何对高收益债市场成交数据进行日度、周度或月度的监控,深挖投资机会,也显得尤其重要。
数据描述:
债券简称(name),成交价格(price),年化到期收益率%(yield),估值(val),估值和收益率的偏离%(diff),成交量(volume),交易日期(trddate),代码(code),发行人(issuer),中介成交收益(brokeryield),中介成交日期(brokerdate)。
注:代码以SH和SZ结尾的,成交量单位是“万”, 以IB结尾的,成交量单位是“亿”。
数据集分享链接:https://pan.baidu.com/s/1-NcO5s9yhs9pjdQaUr1mPA,提取码qf55。
---
title: "Mid-term Review"
author: "leon"
date: "2022-10-28"
output: html_document
---
path = "C:/Users/胡图图/Desktop/为了宝子/统计学/ibex_example/IBEX_example/"
filenames = list.files(path, pattern="*.csv", full.names=FALSE) # These functions produce a character vector of the names of files or directories in the named directory.
n = length(filenames)
tmp = read.csv(header = T, paste0(path,filenames[1]), fileEncoding="GBK")
num_feature = rep(0, n)
for(i in 1:n){
tmp = read.csv(header = T, paste0(path,filenames[i]), fileEncoding="GBK")
# print(colnames(tmp))
num_feature[i] = length(colnames(tmp))
} #如果不是UTF-8的格式,可以用write.csv来重新读写
table(num_feature)
which(num_feature==11)
colnames(tmp)
colnames(read.csv(header = T, paste0(path,filenames[35]), fileEncoding="GBK"))
data0 = NULL
for(i in 1:n){
tmp = read.csv(header = T, paste0(path, filenames[i]), fileEncoding = "GBK")
date0 = substring(filenames[i], 5, 12) #注意到各个数据表中的trddate有的带有具体时间有的不带,又注意到各个数据表的命名规律,因此为了统一,可以用substring函数取出数据表的名字的第5~12位,并以之代替表中的日期
data0 = rbind(data0, data.frame(name = tmp$name, price = tmp$price,
yield = tmp$yield, val = tmp$val,
diff = tmp$diff, volume = tmp$volume,
trddate = date0, code = tmp$code))
print(i)
# 方便了解电脑进行到了第几步
}
class(data0); dim(data0)
利用substring函数替换trddate中不规则的日期,利用rbind函数提取、合并想要的数据并得到需要的数据框后的部分结果如下所示:
name | price | yield | val | diff | volume | trddate | code |
国开1704 | 101.20850 | 2.865500 | 2.8170 | 4.850000e+00 | 3305.8735 | 20190121 | 108602.SZ |
国开1804 | 100.50000 | 2.120800 | 2.4416 | -3.208000e+01 | 83.616 | 20190121 | 108603.SZ |
农发1801 | 100.30000 | 2.390100 | 2.5990 | -2.089000e+01 | 22.8684 | 20190121 | 108901.SZ |
14长证债 | 100.78140 | 3.846600 | 3.2556 | 5.910000e+01 | 7.0547 | 20190121 | 112232.SZ |
15西部02 | 101.00000 | 3.948600 | 3.5168 | 4.318000e+01 | 10.1 | 20190121 | 112283.SZ |
11陕气债 | 101.30000 | 3.407900 | 3.2540 | 1.539000e+01 | 30.39 | 20190121 | 112034.SZ |
##数据特征概览
#缺失值
sum(is.na(data0))
sum(apply(is.na(data0), 1, sum)!=0) #有多少行是缺失的?;apply函数中的"1"指对行运用,"!="是不等
data1 = data0[which(apply(is.na(data0), 1, sum)==0),] #","在右边,则把每一行取出来;“=”是赋值,"=="是相等
#异常值
attach(data1)
hist(price); length(price[which(price>120)]); min(price)
hist(val); min(val); sum(val>100); quantile(val,0.99); hist(val[which(val>100)])
hist(price)的结果如图所示:
hist(val)的结果如图所示:
由于数据过于集中,因此在利用quantile函数查看val列所对应的数据的分位数后,尝试hist(val[which(val>100)]),结果如图所示:
volume0 = as.numeric(volume)
which(is.na(volume0))
data1$volume[which(is.na(volume0))]
ind = which(is.na(volume0))
data2 = data1[,-6]
data2$volume = volume0
data2 = data2[-ind,]
detach(data1)
为了处理缺失的数据,此处简单粗暴地删掉了所有缺失数据的行。
##进一步区分市场
market = NA
for(i in 1:nrow(data2)){
nc = nchar(data2$code[i])
market[i] = substring(data2$code[i], nc-1, nc)
}
table(market)
data2$market = market
#单位转换(SH/SZ万,IB亿)
data3 = data2
data3$volume[data2$market=="IB"] = data2$volume[data2$market=="IB"]*10000
#比较市场间差异
layout(matrix(c(1,2,3), nrow=1, ncol=3, byrow=TRUE), heights=1)
hist(data3$volume[data2$market=="IB"], main = "Histogram_1", xlab= "IB volume")
hist(data3$volume[data2$market=="SH"], main = "Histogram_2", xlab= "SH volume")
hist(data3$volume[data2$market=="SZ"], main = "Histogram_3", xlab= "SZ volume")
效果图如下:
由于数据右偏极其明显,考虑采用对数变换:
quantile(data3$volume[data2$market=="IB"])
quantile(data3$volume[data2$market=="SH"])
quantile(data3$volume[data2$market=="SZ"])
hist(log(data3$volume[data2$market=="IB"]), main = "Logtransformed_1", xlab= "IB volume")
hist(log(data3$volume[data2$market=="SH"]), main = "Logtransformed_2", xlab= "SH volume")
hist(log(data3$volume[data2$market=="SZ"]), main = "Logtransformed_3", xlab= "SZ volume") #高度右偏的变量可以用log变换
效果图如下:
除了用条形图,还可以用箱线图来实现数据可视化:
layout(matrix(c(1,2), nrow=1, ncol=2, byrow=TRUE), heights=1)
boxplot(data3$volume~data3$market)
boxplot(log(data3$volume)~data3$market)
效果图如下:
可以认为SH market 和SZ market的均值相当吗?
t.test((data3$volume[data2$market=="SH"]),
(data3$volume[data2$market=="SZ"]))
t.test(log(data3$volume[data2$market=="SH"]),
log(data3$volume[data2$market=="SZ"]))
寻找新兴高收益主体:
#对于每日的成交数据,及时发现新出现的高收益债券
date4 = unique(data3$trddate)
max(date4)
data_current = data3[data3$trddate!="20190628",]
data_new = data3[data3$trddate=="20190628",]
#定义高收益
high_yield = 50
high_yield_bond = unique(data_current$name[data_current$yield > high_yield]) #由于关心的是某一个债券到底是不是高收益,所以外套一个unique函数:unique returns a vector, data frame or array like x but with duplicate elements/rows removed.
new_high_yield_bond = unique(data_new$name[data_new$yield > high_yield])
#找到新的高收益主体
setdiff(new_high_yield_bond, high_yield_bond)
new_b = "13永利债"
for(i in 1:length(high_yield_bond)){
if(high_yield_bound[i]==new_b){
print(i)
}
} #循环函数for嵌套条件函数if,检验13永利债是否真的为“新的”高收益主体
最后的循环函数没有输出结果,或输出结果为NULL,证明“13永利债”就是我们要找的新兴高收益主体。
就这样通过一顿“猛如虎”的操作,我们复习了《统计学——基于R(第4版)》的第1章~第6章。