function [Price, DirtyPrice, CFlowAmounts, CFlowDates] = ...
    fixedbyzero(RateSpec, CouponRate, Settle, Maturity, varargin)
%FIXEDBYZERO Price of a fixed rate note by a set of zero curves.
%
%   Price = fixedbyzero(RateSpec, CouponRate, Settle, Maturity)
%
%   Price = fixedbyzero(RateSpec, CouponRate, Settle, Maturity, ...
%                                 Reset, Basis,  Principal, EndMonthRule)
% 
%   Price = fixedbyzero(RateSpec, CouponRate, Settle, Maturity, ...
%                                 'Param1','Value1',...)
%
%   [Price, DirtyPrice, CFBondDate, AllDates]  = fixedbyzero(RateSpec, 
%                   CouponRate, Settle,Maturity,'Param1','Value1',...)
%
%   Required inputs:
%     All inputs are either scalars or NINST by 1 vectors unless otherwise
%     specified. Dates can be serial date numbers or date strings.
%     Optional arguments can be passed as empty matrices [].
%
%     RateSpec      - The annualized zero rate term structure.
%     CouponRate    - NINSTx1 decimal annual rate or NINSTx1 cell array
%                     where each element is a NumDates x 2 cell array where the
%                     first column is dates and the second column is associated
%                     rates.  The date indicates the last day that the coupon
%                     rate is valid.
%     Settle        - NINSTx1 Settlement date.
%     Maturity      - NINSTx1 Maturity date.
%
%   Optional Inputs:
%     Reset        - NINSTx1 of frequency of payments per year. Default is 1.
%     Basis        - NINSTx1 Day-count basis. Default is 0 (actual/actual).
%
%     Principal    - NINSTx1 of notional principal amounts or NINSTx1 cell array
%                    where each element is a NumDates x 2 cell array where the 
%                    first column is dates and the second column is associated 
%                    principal amount.  The date indicates the last day that the  
%                    principal value is valid. Default is 100.
%
%     EndMonthRule - NINSTx1 End-of-month rule. Default is 1 (in effect).
%
%   AdjustCashFlowsBasis - NINSTx1 vector of logicals. Adjusts cash flows according 
%                          to the accrual amount. Default is false.
%
%   Holidays - NHOLIDAYSx1 vector of MATLAB date numbers. Holidays to be used in 
%              computing business days. Default is to use the holidays in 
%              holidays.m.
%
%   BusinessDayConvention - NINSTx1 cell array of business day convention 
%                           to be used in computing payment dates - possible 
%                           values are actual (default), follow, modifiedfollow, 
%                           previous, modifiedprevious.
%
%     Note that optional inputs can be specified as parameter value pairs.  
%     If AdjustCashFlowsBasis, Holidays or BusinessDayConvention are specified, 
%     optional inputs must be specified as parameter value pairs. Otherwise, 
%     optional inputs may be specified by order according to the help.
%
%   Outputs:
%     Price        - NINST by NUMCURVES matrix of fixed rate note prices.
%                    Each column arises from one of the zero curves.
%
%     DirtyPrice    - NINST by NUMCURVES matrix of dirty bond price (clean + 
%                    accrued interest). Each column arises from one of the 
%                    zero curves.
%     
%     CFlowAmounts - NINST by NUMCFS matrix of cash flows for each bond
%   
%     CFlowDates   - NINST by NUMCFS matrix of payment dates for each bond
%
%   See also BONDBYZERO, CFBYZERO, FLOATBYZERO, SWAPBYZERO.
%

%   Copyright 1995-2012 The MathWorks, Inc.

% --------------------------------------------------------
% Checking the input arguments
% --------------------------------------------------------
if nargin > 2
    Settle = convertStringsToChars(Settle);
end

if nargin > 3
    Maturity = convertStringsToChars(Maturity);
end

if nargin > 4
    [varargin{:}] = convertStringsToChars(varargin{:});
end

if (nargin < 4)
    error(message('finance:fixedbyzero:missingInputs'));
end

% Check first input argument to be term structure
if (nargin<1) || ~isafin(RateSpec,'RateSpec')
    error(message('finance:fixedbyzero:invalidTermStruct'));
end

StartDate = NaN;

% Check to see whether we have the case of ordered inputs or PV pairs
if ~isempty(varargin) && ischar(varargin{1})
        
    p = inputParser;
    p.addParamValue('principaltype', {'sinking'},...
            @(x) all(ismember(x,{'sinking','bullet'})));
    p.addParamValue('adjustcashflowsbasis', false, @islogical);
    p.addParamValue('holidays', []);
    p.addParamValue('businessdayconvention', {'actual'},...
        @(x) all(ismember(x,{'actual', 'follow', 'previous', ...
        'modifiedfollow', 'modifiedprevious'})));   
    p.addParamValue('reset', []);
    p.addParamValue('basis', []);
    p.addParamValue('principal', []);
    p.addParamValue('endmonthrule', []);
    p.addParamValue('startdate', NaN);
        
    try
        p.parse(varargin{:});
    catch ME
        newMsg = message('finance:fixedbyzero:optionalInputError');
        newME = MException(newMsg.Identifier, getString(newMsg));
        newME = addCause(newME, ME);
        throw(newME)
    end
        
    AdjustCashFlowsBasis = p.Results.adjustcashflowsbasis;
    Holidays =  p.Results.holidays;
    BusinessDayConvention = p.Results.businessdayconvention;
    PrincipalType = p.Results.principaltype;      
    StartDate = p.Results.startdate;
        
    [CouponRate, Settle, Maturity, Reset, Basis, Principal, EOM] = ...
        instargfixed(CouponRate, Settle, Maturity, p.Results.reset,...
        p.Results.basis, p.Results.principal, p.Results.endmonthrule);
else
    AdjustCashFlowsBasis = false;
    Holidays = [];
    BusinessDayConvention = 'actual';
    PrincipalType = 'sinking';
    [CouponRate, Settle, Maturity, Reset, Basis, Principal, EOM] = ...
        instargfixed(CouponRate, Settle, Maturity, varargin{:});
end

[Price, DirtyPrice, CFlowAmounts, CFlowDates] = ...
    bondbyzero(RateSpec, CouponRate, Settle, Maturity, ...
    'Period', Reset, 'Basis', Basis, 'EndMonthRule', EOM, 'Face', Principal,...
    'PrincipalType', PrincipalType, 'AdjustCashFlowsBasis', AdjustCashFlowsBasis,...
    'Holidays', Holidays, 'BusinessDayConvention', BusinessDayConvention, ...
    'StartDate', StartDate);