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);