| zbtprice(Bonds, Prices, Settle, OutputCompoundingZERO, OutputBasisZERO, ...
|
function [varargout] = zbtprice(Bonds, Prices, Settle, OutputCompoundingZERO, OutputBasisZERO, ...
OutputCompoundingFWD, OutputBasisFWD, OutputBasisDISC, PlotOptions)
%ZBTPRICE An updated Zero Curve Bootstrapping from Coupon Bond Data Given Price.
%
% [ZeroRates, CurveDates, ForwardRates, DiscountRates] = ...
% zbtyield(Bonds, Yields, Settle, OutputCompoundingZERO, OutputBasisZERO, ...
% OutputCompoundingFWD, OutputBasisFWD, OutputBasisDISC, PlotOptions)
%
%Summary: This function derives a zero curve given basic parameters and
% price values for a source portfolio of coupon bonds using the
% "bootstrap" methodology. The zero curve is defined as the
% collective yields to maturity on a portfolio of theoretical
% zero coupon bonds which are in turn derived from the source
% portfolio. The bootstrapping method used by this function does
% NOT require alignment among the cash flow dates of the bonds
% contained in the source portfolio. Instead it uses theoretical
% par bond arbitrage and yield interpolation to derive all zero
% rates.
%
% Inputs: Bonds - the portfolio of coupon bonds from which the zero curve
% will be derived; specifically, an NxM matrix of bond
% parameters where each row of the matrix corresponds to an
% individual bond and each column corresponds to a particular
% parameter; the required columns (parameters) for this matrix
% are:
% Maturity - (Column 1) the maturity for each bond in the portfolio
% in serial date number form
% CouponRate - (Column 2) the coupon rate for each bond in the
% portfolio in decimal form
% Optional columns (parameters) are:
% Face - (Column 3) face value of each bond in the portfolio; default
% is $100
% Period - (Column 4) the number of coupon payments per year in
% integer form; possible values are 0, 1, 2 (default), 3, 4, 6
% and 12
% Basis - (Column 5) values specifying the basis for each bond in the
% portfolio; possible values are:
% 1) Basis = 0 - actual/actual(default)
% 2) Basis = 1 - 30/360 (SIA compliant)
% 3) Basis = 2 - actual/360
% 4) Basis = 3 - actual/365
% 5) (NEW) Basis = 4 - 30/360 (PSA compliant)
% 6) (NEW) Basis = 5 - 30/360 (ISDA compliant)
% 7) (NEW) Basis = 6 - 30/360 (European)
% 8) (NEW) Basis = 7 - act/365 (Japanese)
% EndMonthRule - (Column 6) value specifying whether or no the "end
% of month rule" is in effect for each bond contained in the
% portfolio possible values are:
% 1) EndMonthRule = 1 (default) - rule is in effect for the bond
% (meaning that a security which pays coupon interest on the
% last day of the month will always make payment on the
% last day of the month)
% 2) EndMonthRule = 0 - rule is NOT in effect for the bond
%
% Prices - Nx1 column vector containing price values for each bond
% contained in the portfolio represented by the Bonds matrix
%
% Settle - scalar value representing time zero in derivation of the
% zero curve; normally this is also the settlement date for
% the bonds contained in the portfolio from which the zero
% curve will be derived
%
% OutputCompoundingZERO - scalar value representing the period by which
% the output zero rates will be compounded; the default value
% is semi-annual (i.e. "2") compounding. Possible values are
% 1,2,3,4,6,12,365,-1.
%
% OutputBasisZERO - scalar value representing the basis used to convert
% length of time between Settlement date and
% Maturity dates into years in determining the output
% zero rates possible values include:
% 1) Basis = 0 - actual/actual(default)
% 2) Basis = 1 - 30/360 (SIA compliant)
% 3) Basis = 2 - actual/360
% 4) Basis = 3 - actual/365
% 5) (NEW) Basis = 4 - 30/360 (PSA compliant)
% 6) (NEW) Basis = 5 - 30/360 (ISDA compliant)
% 7) (NEW) Basis = 6 - 30/360 (European)
% 8) (NEW) Basis = 7 - act/365 (Japanese)
%
% (NEW)OutputCompoundingFORWARD - scalar value representing the period
% by which the output forward rates will be compounded; the default
% value is semi-annual (i.e. "2") compounding. Possible values are
% 1,2,3,4,6,12,365,-1.
%
% (NEW) OutputBasisFORWARD - analogous to / please see OutputBasisZERO
% (NEW) OutputBasisDISCOUNT -analogous to / please see OutputBasisZERO
%
% (OBSOLETE) MaxIterations - scalar value for the maximum number of iterations
% to be used in deriving yield to maturity value for each bond
% contained in the Bonds matrix; default value is 50 - to be eliminated soon.
%
% (NEW) PlotOptions (optional) - a scalar value of 0 (off, default) or 1 (on).
% This will plot the ZERO, FORWARD, and DISCOUNT curves against the
% length of time from settle to Maturity given OUTPUTBASISZERO,
% OUTPUTBASISFORWARD and OUTPUTBASISDISCOUNT, respectively.
% The length of time in year is computed the same way as using
% YEARFRAC, i.e: number_of_years = yearfrac(Settle, Maturity, Basis).
% PlotOptions will plot the requested Output ONLY (it is assumed
% that only the requested output is of interest. It will let user know
% if default value of OUTPUTBASIS (0s) were used through the x-label.
%
%Outputs: ZeroRates - Nx1 vector containing the values for the implied zero
% rates for each point along the investment horizon defined
% by a maturity date
% CurveDates - Nx1 vector containing the maturity date for each
% zero rate along the investment horizon (from time T = Settle
% to time T = maturity of the longest dated bond in the source
% portfolio)
% (NEW) ForwardRates - Nx1 vector of Forward rates. This rate is the future spot rate
% between CurveDates.
% (NEW) DiscountRates -Nx1 vector of Discount rates. This rate is the discount rate
% of cash flow at corresponding CurveDates, with reference to
% settlement date at Settle.
%
% Notes: 1) In cases where the source portfolio of bonds contains more
% than one bond with the same maturity date, the mean zero rate
% is calculated for that maturity date.
% 2) Ensuring that the source portfolio contains a sufficient number
% of bonds and that those bonds are evenly distributed with
% respect to maturity date will significantly enhance the
% performance of this function.
%
%See also: ZBTYIELD, TERMFIT, ZERO2FWD, FWD2ZERO, ZERO2DISC, DISC2ZERO,
% ZERO2PYLD, PYLD2ZERO
%Reference(s): 1) Fabozzi, Frank J. "The Structure of Interest Rates."
% Chapter 6 in Fabozzi, Frank J. and T. Dessa Fabozzi. The
% Handbook of Fixed Income Securities, Fourth Edition. New
% York: Irwin Professional Publishing. 1995.
% 2) McEnally, Richard W. and James V. Jordan. "The Term
% Structure of Interest Rates." Chapter 37 in Fabozzi,
% Frank J. ibid.
% 3) Das, Satyajit. "Calculating Zero Coupon Rates." Appendix
% to Chapter 6. pp. 219 - 225. in Das, Satyajit. Swap and
% Derivative Financing. New York: Irwin Professional
% Publishing. 1994.
% Author(s): J. Akao and C. Bassignani, 11-12-97, Bob Winata 30-01-2002
% Copyright (c) 1995-2002 The MathWorks, Inc. All Rights Reserved.
% $Revision: 2.1 $ $Date: 2002/01/30 19:53:23 $
%---------------------------------------------------------------------
% ************* GET/PARSE INPUT(S) **************
%---------------------------------------------------------------------
%Check to ensure that the minimum number of arguments has been passed in
if (nargin < 3)
error('You must enter the Bonds matrix, a Prices vector and a settlement date');
end
[NumBonds, NumCols] = size(Bonds);
if (NumCols < 2)
error(['The Bonds matrix must contain at least columns for the maturity' ...
' date and coupon rate'])
elseif (NumCols > 6)
error('The Bonds matrix may only contain 6 columns')
end
% Set default columns: Face 100, Period 2, Basis 0, EOMRule 1.
Col = ones(NumBonds,1);
DefaultCols = [100*Col, 2*Col, 0*Col, 1*Col];
Bonds = [Bonds, DefaultCols(:, (NumCols-1):4)];
% Parse out bond parameters
Maturity = Bonds(:,1);
CpnRate = Bonds(:,2);
Face = Bonds(:,3);
Period = Bonds(:,4);
Basis = Bonds(:,5);
EOMRule = Bonds(:,6);
% Prices
Prices = Prices(:);
if length(Prices)~=NumBonds
error(sprintf('The number of Prices, %d, does not match the number of bonds %d',...
length(Prices), NumBonds))
end
% Parse Settlement
Settle = finargdate(Settle);
if any(Settle ~= Settle(1))
error('All Bonds must Settle on the same day.');
else
Settle = Settle(1);
end
% Set OutputCompounding, OutputBasis, and PlotOptions default
if nargin<4 | isempty(OutputCompoundingZERO)
OutputCompoundingZERO = 2;
end
if nargin<5 | isempty(OutputBasisZERO)
OutputBasisZERO = 0;
end
if nargin<6 | isempty(OutputCompoundingFWD)
OutputCompoundingFWD = 2;
end
if nargin<7 | isempty(OutputBasisFWD)
OutputBasisFWD = 0;
end
if nargin<8 | isempty(OutputBasisDISC)
OutputBasisDISC = 0;
end
if nargin<9| isempty(PlotOptions)
PlotOptions = 1;
end
if nargin>9
error ('Too many input arguments, please type "help zbtprice" for usage')
end
%----------------------------------------------------------------------
% Generate outputs - the Zero Rates
%----------------------------------------------------------------------
% Create the cash flow amounts, dates, and time factors
[CFAmounts, CFDates, CFTimesSemi] = cfamounts(CpnRate, Settle, Maturity, ...
Period, Basis, EOMRule, [], [], [], [], Face);
% Bootstrap a zero curve with semi-annual compounding
[ZeroRatesSemi, EndTimesSemi, CurveDates] = zerobootcf(Prices, ...
CFAmounts, CFDates, CFTimesSemi);
% Transform to a different OutputCompounding if requested
if OutputCompoundingZERO~=2
if OutputCompoundingZERO == -1
ZeroRates = 2*log(1 + ZeroRatesSemi/2);
else
% This is where OutputCompoundingFORWARD could replace Output Compounding the old code
ZeroRates = OutputCompoundingZERO * ((1 + ZeroRatesSemi/2).^(2/OutputCompoundingZERO) - 1);
end
else
% return semi-annual rates
ZeroRates = ZeroRatesSemi;
EndTimes = EndTimesSemi;
end
varargout{1} = ZeroRates;
varargout{2} = CurveDates;
if nargout > 2
%%%%%%%%%%%%%%%%%%%%%% ADAPTED ZERO2FWD %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Convert input rates to discounts
%Get values for T in terms of fractional years from the settlement date
%Past Implementation: InYearMats = yearfrac(Settle, CurveDates, InputBasis); -> Made OBSOLETE.
%%%Note: 1. max(CFTimesSemi,[],2) will get the Time Factors on semiannual basis.
%%% 2. Input Compounding = Output Compounding from zero rates. // This only matters "internally"
[EndDates, I, InstOrder] = unique(Maturity);
InYearMats = 0.5*max(CFTimesSemi,[],2); %Get "number of years" based on CFTimesSemi
InYearMats = sort(InYearMats(I)); %Get the ordered "unique (based on I)" Maturity years
%Set continuous output compounding flag
InContCompFlag = 0;
InputCompoundingFWD = OutputCompoundingZERO;
%check for Continuous compounding
% Get discount factors between time zero and CurveDates
if InputCompoundingFWD == -1
DiscountFromSettle = exp( - ZeroRates .* InYearMats );
else
DiscountFromSettle = ( 1 + ZeroRates/InputCompoundingFWD ).^(-InYearMats*InputCompoundingFWD);
end
% Compute Forward Discounts
FwdDiscounts = [ DiscountFromSettle(1) ; DiscountFromSettle(2:end)./DiscountFromSettle(1:end-1) ];
% Convert Fwd Discounts to Forward Rates
%OutYearMats = yearfrac(Settle, CurveDates, InputBasis);
FwdYearMats = [InYearMats(1); diff(InYearMats)];
if OutputCompoundingFWD == -1
ForwardRates = -log(FwdDiscounts)./FwdYearMats;
else
% This is where OutputCompoundingFORWARD could replace Output Compounding the old code
ForwardRates = OutputCompoundingFWD * ( FwdDiscounts.^(-1./(FwdYearMats*OutputCompoundingFWD)) - 1 );
end
varargout{3} = ForwardRates;
end
if nargout < 4
%do nothing
elseif nargout == 4
%%%%%%%%%%%%%%%%%%%%%% ADAPTED ZERO2DISC %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
varargout{4} = DiscountFromSettle;
end
if nargout == 1 | nargout == 2
nargout_temp = 1;
else
nargout_temp = nargout - 1;
end
if PlotOptions == 0
break
else
% should be just 1 (one) , but just to safeguard anybody typing other PlotOptions
% Create Plots of Zero, Forward, and Discount rates depending on what's available
scrsz = get(0,'ScreenSize');
figure('Position',[scrsz(3)/2.5 1 scrsz(3)/2 scrsz(4)/2])
if OutputBasisZERO == 0
isdefaultZERO = ' (default)';
else
isdefaultZERO = '';
end
if OutputBasisFWD == 0
isdefaultFWD = ' (default)';
else
isdefaultFWD = '';
end
if OutputBasisDISC == 0
isdefaultDISC = ' (default)';
else
isdefaultDISC = '';
end
Typerate = {'Zero (Spot)', 'Forward', 'Discount'};
OutputBasisPlot = [OutputBasisZERO, OutputBasisFWD, OutputBasisDISC];
isdefaulttype = {isdefaultZERO; isdefaultFWD; isdefaultDISC};
OCidx = [ 1 , 2 , 3 , 4 , 6 , 12 , 365 , -1];
OC = {'Yearly', 'Semi-annually' '4-monthly', 'Quarterly', 'Bimonthly', 'Monthly', 'Daily', 'Continuously'};
whichOC=[find(OutputCompoundingZERO==OCidx), find(OutputCompoundingFWD==OCidx), find(OutputCompoundingZERO==OCidx)] ;
style = ['b';'r';'k'];
for idx = 1:nargout_temp
subplot(nargout_temp,1,idx);
numyear = yearfrac(Settle, CurveDates, OutputBasisPlot(idx));
if idx == 1
idx2 = idx;
else
idx2 = idx + 1;
end
plot(numyear, varargout{idx2}, style(idx));
ylabel([Typerate{idx}, ' Rates']);
xlabel(['Number of years from Settlement Date using Basis = ', num2str(OutputBasisPlot(idx)), isdefaulttype{idx}]);
legend(['Rate shown is compounded: ', OC{whichOC(idx)}],0);
grid on;
end
end
|
|