Code covered by the BSD License  

Highlights from
Financial Seminar Demos

from Financial Seminar Demos by Michael Weidman
Demos commonly used at The MathWorks financial modeling seminars.

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

Contact us at files@mathworks.com