MATLAB: Do I see a difference in the Zero rates returned by two IRDataCurves – of Type “Zero” and “Forward” created from the same data in Fixed Income Toolbox (R2012a)

irdatacurve.bootstrap

I am doing the following :
(a) Using the Bootstrapping method to create two Interest rate curve models with the same data – the only difference between them being the “Type” parameter. One has the “Type” set to ‘Zero’, and the other to ‘Forward’.
(b) Comparing the values returned by the methods getZeroRates and getForwardRates on each model.
I observe that the Zero rates obtained from the IRCurve of type "Zero" are different from the Zero rates obtained from the IRCurve of type "Forward".
InstrumentTypes = {'Deposit';'Deposit';...
'Futures';'Futures';'Futures';'Futures';'Futures';'Futures';...
'Swap';'Swap';'Swap';'Swap';};
Instruments = [datenum('08/10/2007'),datenum('09/17/2007'),.0532000; ...
datenum('08/10/2007'),datenum('11/17/2007'),.0535866; ...
datenum('08/08/2007'),datenum('19-Dec-2007'),9485; ...
datenum('08/08/2007'),datenum('19-Mar-2008'),9502; ...
datenum('08/08/2007'),datenum('18-Jun-2008'),9509.5; ...
datenum('08/08/2007'),datenum('17-Sep-2008'),9509; ...
datenum('08/08/2007'),datenum('17-Dec-2008'),9505.5; ...
datenum('08/08/2007'),datenum('18-Mar-2009'),9501; ...
datenum('08/08/2007'),datenum('08/08/2014'),.0530; ...
datenum('08/08/2007'),datenum('08/08/2019'),.0551; ...
datenum('08/08/2007'),datenum('08/08/2027'),.0565; ...
datenum('08/08/2007'),datenum('08/08/2037'),.0566];
CurveSettle = datenum('08/10/2007');
maturityDates = Instruments(:,2);
bootModelF = IRDataCurve.bootstrap('Forward', CurveSettle, ...
InstrumentTypes, Instruments,'InterpMethod','pchip');
bootModelZ = IRDataCurve.bootstrap('Zero', CurveSettle, ...
InstrumentTypes, Instruments,'InterpMethod','pchip');
plot(bootModelF.Dates, bootModelF.getZeroRates(bootModelF.Dates))
hold all
plot(bootModelZ.Dates, bootModelZ.getZeroRates(bootModelZ.Dates))
hold off

Best Answer

The nature of the Zero rate interest curve is different from that of the Forward rate interest curve. This is the underlying cause behind the difference that you observe when you compare the Zero rates/Forward rates of the two models. Specifying an interpolation method for a zero curve is not the same as specifying the same method for a forward curve.
The example below ( ‘ZeroVsForward.m’) explains how the two curves are created, how the interpolation method is relevant in this case and how that might lead to the difference in the values that you observe. It uses linear interpolation since it is easier to visualize, but the same message applies to other interpolation methods as well.
In short, assuming that the zero curve is piecewise linear (or piecewise constant, or PCHIP) is very different from assuming that the forward curve is piecewise linear. Both assumptions could be used to bootstrap a set of instruments and both will generate curves that then predict the same prices for those calibrating instruments. Each curve will look different on a point-by-point basis, though.
% ZerovsForward.m
%
% A simple example for explaining differences in IR curves
% Let's consider a simple case: 3 bonds maturing at 1, 2, and 3 years
% (respectively). All are trading at par, and they have increasing coupon
% rates.
Settle = '1/1/2000';
InstrumentTypes = {'Bond';'Bond';'Bond'};
Instruments = [datenum('1/1/2000'),datenum('1/1/2001'),100;...
datenum('1/1/2000'),datenum('1/1/2002'),100;
datenum('1/1/2000'),datenum('1/1/2003'),100];
Coupons = [0.05; 0.08; 0.09];
% Given these coupon rates and that the bonds are trading at per, we
% intuitively expect the zero rates at 1,2, and 3 years to be "close" to
% 5%, 8%, and 9%, respectively.
% For visualization's sake, let' splot our curves at all coupon dates:
plottingDates = [datenum('1/2/2000'),datenum('7/1/2000'),...
datenum('1/1/2001'),datenum('7/1/2001'),...
datenum('1/1/2002'),datenum('7/1/2002'),...
datenum('1/1/2003')];
%%1. Making a zero curve
% First, let's make a zero curve with linear interpolation. (The same
% overall message applies to any interpolation method, but linear is
% easiest to visualize.) The maturity dates for each bond are where we
% expect the zero curve to potentially change its slope, and the mid-year
% coupon dates should have rates that lie on the linear interpolant:
bootModelZ = IRDataCurve.bootstrap('Zero', Settle, ...
InstrumentTypes, Instruments,...
'InstrumentCouponRate', Coupons,...
'InterpMethod','linear');
figure(1)
subplot(2,1,1)
plot(plottingDates, bootModelZ.getZeroRates(plottingDates),'o-')
datetick('x')
ylabel('Zero Rates')
title('An IRDataCurve with linear interpolation on the zero curve')
subplot(2,1,2)
plot(plottingDates, bootModelZ.getForwardRates(plottingDates),'o-')
datetick('x')
ylabel('Forward Rates')
% The key feature here is that while the zero curve is piecewise linear
% between 2000-2001, 2001-2002, and 2002-2003, the equivalent forward curve
% is NOT. When we set the curve type to 'Zero' and the InterpMethod to
% 'linear', we DON'T get linear forward curves.
%%2. Making a forward curve
% Let's repeat the exercise except with a linear-interpolant forward curve:
bootModelF = IRDataCurve.bootstrap('Forward', Settle, ...
InstrumentTypes, Instruments,...
'InstrumentCouponRate', Coupons, 'InterpMethod','linear');
figure(2)
subplot(2,1,1)
plot(plottingDates, bootModelF.getZeroRates(plottingDates),'o-')
datetick('x')
ylabel('Zero Rates')
title('An IRDataCurve with linear interpolation on the forward curve')
subplot(2,1,2)
plot(plottingDates, bootModelF.getForwardRates(plottingDates),'o-')
datetick('x')
ylabel('Forward Rates')
% Now, we see that the forward curve is piecewise linear, which in turn
% forces the zero curve to NOT be piecewise linear. It appears that we
% can't have it both ways.
%%3. Confirming the validity of both curves
% So, which is "right"? Well, both of them are correct given the
% information at hand. Both will correctly re-value our bonds, for
% instance with:
rsZ = toRateSpec(bootModelZ, plottingDates);
priceFromZero = bondbyzero(rsZ, 0.09, '1/1/2000', '1/1/2003')
rsF = toRateSpec(bootModelF, plottingDates);
priceFromForward = bondbyzero(rsF, 0.09, '1/1/2000', '1/1/2003')