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.

bondprice2spread(varargin)
function varargout = bondprice2spread(varargin)
% BONDPRICE2SPREAD: Static Spread to a reference spot curve.
% 
% staticspread = bondprice2spread(ZeroMatrix, Price, CouponRate, Settle, Maturity)
% staticspread = bondprice2spread(ZeroMatrix, Price, CouponRate, Settle, Maturity, ...
%       Period, Basis, EndMonthRule, IssueDate, FirstCouponDate, LastCouponDate, ...
%           StartDate, Face, Interpolation)
%
% Required Inputs:
%   ZeroMatrix      - A matrix of THREE columns, the first is serial date,  
%                     the second contains Spot Rates with maturities corresponding 
%                     to the dates in the first column, in decimal (e.g. 0.075),
%                     and the third column  is the Compounding of the rates given
%                     in the first column
%                     (This is the agency spot-rate ON the settlement date.)
%   Price           - Clean Price for every $100 face of bond issue.
%                     Example: 115.25
%   CouponRate      - Coupon rate in decimal form
%   Settle          - (Scalar) Settlement date
%   Maturity        - Maturity date
%
% Optional Inputs:
%   Period          - Coupons payments per year; default is 2
%   Basis           - Day-count basis; default is 0 (actual/actual) 
%   EndMonthRule    - End-of-month rule; default is 1 (in effect)
%   IssueDate       - Bond issue date
%   FirstCouponDate - Irregular or normal first coupon date
%   LastCouponDate  - Irregular or normal last coupon date
%   StartDate       - Forward starting date of payments (Input ignored in 2.0)
%   Face            - Face value of the bond; default is 100
%   Interpolation   - (Scalar) Interpolation method,
%                     to compute for the corresponding spot rates for the 
%                     bond's cash flow. Default is (1), linear.
%                     Avalilable methods are (0) nearest, (1) linear, and 
%
% Output: 
%   staticspread    - Static spread in basis points. (bp).

%
% Author: Bob Winata. 04/16/2002
% Copyright: The Mathworks, Inc.


if nargin <5
    error('Need at least ZeroMatrix, Price, CouponRate, Settle, Maturity')
else
    % Required parameters
    ZeroRates = varargin{1};
    
    CurveDates = ZeroRates(:,1);
    SpotRates  = ZeroRates(:,2);
    RateCompounding = ZeroRates(:,3);
    
    % Make sure align these arrays into Column
    CurveDates = CurveDates(:);
    SpotRates = SpotRates(:);
    RateCompounding = RateCompounding(:);
    Price = varargin{2};
end

[CouponRate, Settle, Maturity, Period, Basis, EndMonthRule, IssueDate, FirstCouponDate,...
      LastCouponDate, StartDate, Face] = instargbond(varargin{3:end});

if nargin < 14 | isempty(varargin{14})
    Interpolation = 1;
else
    Interpolation = varargin{14};
end

[CFlowAmounts, CFlowDates, TFactors] = cfamounts(CouponRate, ...
    Settle, Maturity, Period, Basis, EndMonthRule, IssueDate, ...
        FirstCouponDate, LastCouponDate, StartDate, Face);

% Check Settle-Maturity vs Spot Dates consistency
% The case with "outdated" Spot Curve
if any(Settle > min(CurveDates))
    error('Settle is less than the earliest point in the Spot curve. The Spot Curve is outdated.')
end

% The case with insufficient "length" of spot rates
if any(Maturity > max(CurveDates))
    error('Maturity must be both within CurveDates to discount Maturity cashflow, thus Maturity <= max(CurveDates)')
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% If the zero rates are not semiannually compounded    %
% then it is first changed to that compounding scheme  %
% THEN interpolated, to preserve "linearity"           %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%convert the spotrates into a semiannual compounding:

for i = 1:length(SpotRates)
    if RateCompounding(i)~=2
        
        if RateCompounding(i) == -1
            SpotRates(i) = 2*(exp(SpotRates(i)/2) - 1);
        else
            % This is where OutputCompoundingFORWARD could replace Output Compounding the old code
            SpotRates(i) = 2 * ((1 + SpotRates(i)/RateCompounding(i)).^(RateCompounding(i)/2) - 1);
        end
        
    else
        % do nothing. Rate is on semiannual compounding already.
    end
end

% Flat until the first CurveDates.
% See, for example, below:
%
%                                      *
%                       *
%               *
%           *
% ********

CurveDates(2:end+1) = CurveDates;
CurveDates(1) = Settle(1);

SpotRates(2:end+1) = SpotRates;
SpotRates(1) = SpotRates(2);

% interpolate for the spot rates on Cashflow dates
% INTERP1 handles matrix as long as it is Column oriented
% thus one must transpose mbsdates, which is Row oriented.
% to interpolate properly for each bond

switch Interpolation
case 0
    spotrates = interp1(CurveDates, SpotRates, CFlowDates', 'nearest');
case 1
    spotrates = interp1(CurveDates, SpotRates, CFlowDates', 'linear');
case 2
    spotrates = interp1(CurveDates, SpotRates, CFlowDates', 'cubic');
end

% Transpose spotrates once done interpolating
spotrates = spotrates';

% Subtract price so OAS will make this NPV = 0
CFlowAmounts(:,1) = CFlowAmounts(:,1) - Price;
NumCF = size(CFlowAmounts, 2);

% Guessed to be close to the "monthly" coupon
x0 = CouponRate/2;

options1 = optimset('Display','off');
X = fsolve(@bondintfun, x0, options1, CFlowAmounts, TFactors, NumCF, spotrates);

varargout{1} = 10000*X;


function y = bondintfun(x,CF,TF,b, spotrates)

Disc = 1./(1+spotrates/2+x(:, ones(b,1)));
dcf = CF .* (Disc.^TF);
dcf(isnan(dcf))= 0;
y = sum(dcf,2);

Contact us at files@mathworks.com