上一篇文章(信用债+python入门碎念和小试牛刀)已经读出了所有的债券样本,并把文件保存在了“wind_code/”,所以本节从读取里面的某一个csv开始:一般公司债未到期2019-08-09.csv,这个现在都还存续着,计算方便。
首先是引用的库开始,以下依次分别:
1. wind的量化接口,
2. pandas(主要使用dataframe的数据结构进行操作),
3. numpy(主要是数学运算),
4. matplotlib(画图)
from WindPy import wimport pandas as pdimport numpy as npimport matplotlib.pyplot as plt
一定要输入这个来启动wind
w.start()
读取上一轮保存好的文件,并把其中的wind_code这一列债券代码读出来,用tolist()转换成list格式
f = open('wind_code/一般公司债未到期2019-08-09.csv', encoding="utf_8_sig")data = pd.read_csv(f, index_col=0)CodeList = data["wind_code"].tolist()print(CodeList) #打印看一下
读取债券要素(截面数据,票息、全称、条款、行业分类...英文写的很清楚)
# 注意长字符串书写规则,一行不要太长bond_property = 'fullname,' \ 'comp_name,' \ 'clause,' \ 'carrydate,' \ 'maturitydate,' \ 'prepaymentdate,' \ 'industry_sw,' \ 'issueamount,' \ 'couponrate'# 要素的参数,比如industryType=1是industry_sw一级行业的意思options = 'industryType=1;serial=1' ws = w.wss(CodeList, bond_property, options) # wind读截面数据的函数wss# 生成一个dataframe方便操作,.T是进行转置data_pd = pd.DataFrame(ws.Data, ws.Fields, ws.Codes).T
提一下ws。wind进行操作的时候返回的是一个特有的wind对象,而并非直接的数据,其中里面主要的成员就是Codes, Data, Fields,ErrorCode,其中数据保存在.Data里面,如果想引用的话,可以直接ws.Codes或者ws.Data,我们仔细看,.Data的数据是一个{list}数据格式,所以只能用list用的方法来进行操作。
为什么喜欢生成Dataframe来用,其实是方便在Pycharm的环境里面观察:
寻找行业:既然是算行业指数,我就要找到其中的一个行业,所以就要根据industry_sw来进行筛选。下面一行可以分步执行:
1. 是获得一个布尔列,看是否满足我的行业条件,
2. 再根据这个是否,来用loc筛选出相应的行
bondlist = data_pd.loc[data_pd["INDUSTRY_SW"] == "SW房地产(信用债)", :]dataID_list = bondlist.index.tolist()
读取时间序列,读取中债估值净价,字段是“net_cnbd”,(全价就是dirty啦)wsd是wind读取时间序列的接口。
col_name = "net_cnbd"TimeStart = "2017-1-1"TimeEnd = "2019-08-23"options = 'credibility=1'price_net = w.wsd(dataID_list, col_name, TimeStart, TimeEnd, options)timeSeries = pd.DataFrame(price_net.Data, price_net.Codes, price_net.Times).T
timeSeries:
计算指数:获取时间序列,把数据转换成array矩阵,设定指数的初始值
timeIndex = timeSeries.index.values.tolist()PriceArray = timeSeries.valuesindex_ini = 100
PriceArray:注意与timeSeries的区别
指数计算:从上到下做时间的循环,对每一行所有的债券净价进行平均(也就是等权重方法),
债券指数(T) = 债券指数(T-1)*债券平均价格(T)/债券平均价格(T-1)
# python内的矩阵都是从0开始索引for idx in range(0, PriceArray.shape[0]): # 一定要用nanmean 不能用 mean 可以百度NA是什么 ibondPrice = np.nanmean(PriceArray[idx, :]) # 循环开始的时候进行初始化,是不进行计算的 if idx == 0: indexSeries = [] bondPrice = [] indexSeries.append(index_ini) bondPrice.append(ibondPrice) else: bondPrice.append(ibondPrice) dayYearnRate = bondPrice[idx]/bondPrice[idx-1] IndexSlice = indexSeries[idx-1]*dayYearnRate indexSeries.append(IndexSlice)
备注:其实可以直接进行矩阵错位相减,一个循环都不用写,如果数据量比较大,速度差异会非常明显,因为矩阵运算是单独优化的啊,肯定比写循环快。
画图和存储
plt.plot(indexSeries)plt.show() # 画图dataSave = pd.DataFrame(indexSeries, timeIndex)dataSave.to_csv('房地产信用债指数201701-201908.csv') # 存成CSV
结果1:
结果2:
其实可以看一下2018年下半年开始房地产指数在往上走,一方面是某些房企信用风险缓解了,另外确实是无风险利率表现的也比较好,看近期的指数波动不大,但是利率下的其实比较多,主要还是房地产债自身的问题,至于为什么没有跌很多,因为我选的是所有的交易所房企啊,自然AAA的多一些。其实还要
可能被你发现了,是不是需要把品种1和品种二进行剔除呢?
不过这个是净价指数不能作为回测和相对价值比较的,因为相当于没有票息了,最终还是要看全价/财富指数才可以,后面就需要把付息/行权加进来。下次在处理一些“dirty”的工作,还有会代码的功能多了,还需要写一写函数
感谢大家支持,如果觉得哪里表述的不清楚,或者语法错误不能运行,还希望多多反馈!
完整代码:
from WindPy import wimport pandas as pdimport numpy as npimport matplotlib.pyplot as pltw.start()f = open('wind_code/一般公司债未到期2019-08-09.csv', encoding="utf_8_sig")data = pd.read_csv(f, index_col=0)CodeList = data["wind_code"].tolist()print(CodeList)bond_property = 'fullname,' \ 'comp_name,' \ 'clause,' \ 'carrydate,' \ 'maturitydate,' \ 'prepaymentdate,' \ 'industry_sw,' \ 'issueamount,' \ 'couponrate'options = 'industryType=1;serial=1'ws = w.wss(CodeList, bond_property, options)data_pd = pd.DataFrame(ws.Data, ws.Fields, ws.Codes).Tbondlist = data_pd.loc[data_pd["INDUSTRY_SW"] == "SW房地产(信用债)", :]dataID_list = bondlist.index.tolist()col_name = "net_cnbd"TimeStart = "2017-1-1"TimeEnd = "2019-08-23"options = 'credibility=1'price_net = w.wsd(dataID_list, col_name, TimeStart, TimeEnd, options)timeSeries = pd.DataFrame(price_net.Data, price_net.Codes, price_net.Times).TtimeIndex = timeSeries.index.values.tolist()PriceArray = timeSeries.valuesindex_ini = 100# python内的矩阵都是从0开始索引,而matlab里面都是从1开始索引for idx in range(0, PriceArray.shape[0]): ibondPrice = np.nanmean(PriceArray[idx, :]) # 循环开始的时候进行初始化,是不进行计算的 if idx == 0: indexSeries = [] bondPrice = [] indexSeries.append(index_ini) bondPrice.append(ibondPrice) else: bondPrice.append(ibondPrice) dayYearnRate = bondPrice[idx]/bondPrice[idx-1] IndexSlice = indexSeries[idx-1]*dayYearnRate indexSeries.append(IndexSlice)plt.plot(indexSeries)plt.show()dataSave = pd.DataFrame(indexSeries, timeIndex)dataSave.to_csv('房地产信用债指数201701-201908.csv')
完整代码