国债收益率曲线构建方法是有很多的,这里我们使用三次 Hermite 插值模型,这个是中债登上使用的方法,实现的工具是matbal上的pchip函数。相关的数学原理我没有专门学过,一知半解的,网络上有很多介绍的也有相关的书。
根据中国人民银行的工作论文《国债收益率曲线构建方法:国际实践与启示》,这里给出了很多方法,国际上怎么构建的,大家可以去这个链接看看2016年第11号 国债收益率曲线构建方法:国际实践与启示 (pbc.gov.cn)
数据是在CSMAR下载的,matbal我刚开始使用,所以我还是用的python做了一个简单的数据处理,就是把这些债券整理成一个个季度的,然后算每一个季度的利率期限结构
2016第一季度的结果和代码
addpath(genpath('C:\Users\Administrator\Desktop\hermitezi插值'))
cd 'C:\Users\Administrator\Desktop\hermitezi插值'
% 指定 Excel 文件名和工作表名
filename = Hermite插值.xlsx';
sheet1 = 1;
sheet2 = 2;
% 读取 Excel 文件数据
data1 = xlsread(filename, sheet1,'A1:P17');
data2 = xlsread(filename, sheet2,'A1:P6');
% 提取每一列数据为向量
x1 = data1(:, 1);
y1 = data1(:, 2);
x2 = data2(:, 1);
y2 = data2(:, 2);
new_x1 = 0:0.01:50;
% 分段三次Hermite插值
p1 = pchip(x1,y1,new_x1);
% 三次样条插值
p2 = spline(x1,y1,new_x1);
figure(1);
plot(x1,y1,'o',new_x1,p1,'r-',new_x1,p2,'g-');
legend('样本点','三次Hermite插值','三次样条插值','Location','NorthWest')
new_x2 = 0:0.01:5;
% 分段三次Hermite插值
p12 = pchip(x2,y2,new_x2);
% 三次样条插值
p22 = spline(x2,y2,new_x2);
plot(x2,y2,'o',new_x2,p12,'r-',new_x2,p22,'g-');
legend('样本点','三次Hermite插值','三次样条插值','Location','NorthWest')
然后通过循环的方式,将每一个季度的曲线构造出来,这样就得得到了一个时间序列的曲线,然后就可以在季度上的曲线,选择不同期限相应的利率计算利差,等等。
% 获取前三列数据
column1 = data(:, 1);
column2 = data(:, 2);
column3 = data(:, 3);
% 通过第三列数据分类
unique_values = unique(column3); % 获取第三列中的唯一值
num_categories = numel(unique_values); % 分类的数量
% 创建一个存储分类数据的单元格数组
category_data = cell(num_categories, 3); % 第一列存储第一列数据,第二列存储第二列数据,第三列存储标志
for i = 1:num_categories
category = unique_values(i);
indices = (column3 == category); % 根据第三列的值获取索引
% 存储分类数据
category_data{i, 1} = column1(indices);
category_data{i, 2} = column2(indices);
category_data{i, 3} = category;
end
% 分段三次Hermite插值
new_x = 0:0.1:max(column1); % 新的 x 值,取决于分类后数据的第一列的最大值向上取整到 0,步长为 0.1
interpolated_data = []; % 存储插值后的数据
for i = 1:num_categories
x = category_data{i, 1}; % 第一列数据
y = category_data{i, 2}; % 第二列数据
flags = category_data{i, 3}; % 标志
% 分段三次Hermite插值
p = pchip(x, y, new_x);
% 保存插值后的数据和标志
interpolated_data = [interpolated_data; new_x', p', repmat(flags, numel(new_x), 1)];
end
% 打印插值后的数据
disp(interpolated_data);