MATLAB Examples

CFEVALDEMO2

Function cfeval calculates cash flows of fixed-income portfolios and structured products, given a quasi-symbolic, Matlab-syntax, typically recursive description of principal and coupon dynamics. Combined, these descriptions are passed to cfsim in cell arrays of strings, whose rows correspond to securities, and columns to periods.

Contents

Examples below replicate exhibits in Fixed Income Analysis for the Chartered Financial Analyst Program, 2nd ed., edited by Frank Fabozzi.

help cfeval
  CFEVAL    Evaluate portfolio cash flows given their symbolic definitions
  INPUTS  : N*T cell arrays of strings, where cell (i,t) contains definition
            of .. on security i in period t:
              pofun - principal outstanding
              cpfun - coupon payment
              psfun - scheduled principal repayment
              ppfun - unscheduled principal repayment
            par   - parameter structure, available  to calculations  defined 
                    in pofun, cpfun, psfun, ppfun 
  OUTPUTS : N*T arrays, where element (i,t) contains value of .. on security
            i in period t:
              cfval - total cash flow (sum of cfval, psval and ppval)
              poval - principal outstanding
              cpval - coupon payment
              psval - scheduled principal repayment
              ppval - unscheduled principal repayment
  NOTES   : Cells of input arrays are evaluated sequentially, iterating over 
            * periods: t = 1,..,T 
            * securities: i = 1,..,N
            * input arrays: pofun, cpfun, psfun, ppfun
            Computing xval(i,t) - note that xfun arrays definitions must use
            indexes i and t - one can reference already-evaluated quantities 
  EXAMPLE : See CFEVALDEMO
  AUTHOR  : Dimitri Shvorob, dimitri.shvorob@vanderbilt.edu, 9/25/07

Example 1. Residential mortgage

a) set up security definitions

y = 30; T = 12*y;
par.S = 1e5;                      % loaned amount
par.m = T;                        % mortgage term
par.r = 0.08125;                  % mortgage rate
[pofun,cpfun,psfun,ppfun] = deal(cell(1,T));
  • Principal outstanding: initially 100,000, reduced by principal repayments
pofun{1}   = 'par.S'; [pofun{2:T}] = deal('poval(i,t-1) - psval(i,t-1)');
  • Interest: 8.125%, paid out monthly
[cpfun{:}] = deal('poval(i,t)*par.r/12');
  • Principal repayment: scheduled only, no prepayment. Function mgpmt computes (constant) amount of monthly payment on a level-payment, fixed-rate, fully amortized mortgage.
[psfun{:}] = deal('poval(i,1)*mgpmt(par.r,par.m) - cpval(i,t)');
[ppfun{:}] = deal('0');

b) calculate total payment, interest and principal-repayment series

[cfval,poval,cpval,psval] = cfeval(pofun,cpfun,psfun,ppfun,par);  %#ok

c) plot interest and principal-repayment series

figure
colormap autumn
area([cpval' psval'])
title('Interest and principal repayment as parts of mortgage payment')
xlabel('Month'), ylabel('$')
legend('Interest','Principal repaid')
set(gcf,'Color','w')

d) recalculate cfval using mbscfamounts of Fixed-Income Toolbox

  • cfeval calculation
cfval(1)                                                   %#ok
ans =

        742.50

  • mbscfamounts calculation
t0 = today; t1 = addtodate(t0,T/12,'year');
[cf,d,t,f] = mbscfamounts(t0,t1,t0,par.r,par.r,0,0);       %#ok
par.S*cf(2)                                                %#ok
ans =

        742.50

Example 2. Mortgage passthrough

  • backed by loans of the type described in Example 1
  • WAM = 357 months
  • 100 PSA prepayment a) set up security definitions
y = 30; T = 12*y;
par.S = 4e8;                      % passthrough notional amount
par.m = T;                        % mortgage term
par.r = 0.08125;                  % mortgage rate
par.c = 0.075;                    % coupon rate
par.psa = 100;                    % prepayment scenario
[pofun,cpfun,psfun,ppfun] = deal(cell(1,T));
  • Principal: 400,000,000 in period 4 - note that loans are seasoned by 3 months - reduced by principal repayments. We are interested in cash flows in periods 4-360.
[pofun{:}]   = deal('poval(i,t-1) - psval(i,t-1) - ppval(i,t-1)');
[pofun{1:4}] = deal('par.S');
  • Coupon payment: 7.5%, paid monthly
[cpfun{:}] = deal('poval(i,t)*par.c/12');
  • Principal repayment: scheduled, plus prepayment 100 PSA

(PSA-benchmarked single month mortality rates are computed with function smmpsa )

[psfun{:}] = deal('poval(i,t)*(mgpmt(par.r,par.m + 1 - t) - par.r/12)');
[ppfun{:}] = deal('poval(i,t)*smmpsa(t,par.psa)');

b) calculate total cash flow

[cfval,poval,cpval,psval,ppval] = cfeval(pofun,cpfun,psfun,ppfun,par);  %#ok
cfval100 = cfval(4:end);
prval100 = psval(4:end) + ppval(4:end);

c) examine the effect of a change in prepayment behavior

par.psa  = 165;
[cfval,poval,cpval,psval,ppval] = cfeval(pofun,cpfun,psfun,ppfun,par);  %#ok
cfval165 = cfval(4:end);
prval165 = psval(4:end) + ppval(4:end);
  • plot cash flow dynamics
figure
colormap autumn
t = 1:357;
plot(t,cfval100,'y--', ...
     t,cfval165,'r--')
axis([4 360 0 6e6])
legend('PSA 100', 'PSA 165')
xlabel('Month'), ylabel('$')
title('Passthrough cash flows under alternative prepayment scenarios')
set(gcf,'Color','w')
  • compute average lives
al100 = sum(t.*prval100)/(12*par.S)                        %#ok
al165 = sum(t.*prval165)/(12*par.S)                        %#ok
al100 =

         11.66


al165 =

          8.77

Example 3. Collateralized mortgage obligation

  • backed by loans of the type described in Example 5
  • WAM = 357 months
  • 165 PSA prepayment
  • 4 sequential pay tranches

a) set up security definitions

y = 30; T = 12*y;
par.S = [194.5 36 96.5 73]*1e6;   % tranche par amounts
par.m = T;                        % mortgage term
par.r = 0.08125;                  % mortgage rate
par.c = 0.075;                    % coupon rate
par.psa = 165;                    % prepayment scenario
[pofun,cpfun,psfun,ppfun] = deal(cell(5,T));

First row of input and output arrays will refer to the entire portfolio, i.e. sum of all tranches

  • Principal: 400,000,000, split between four tranches, in period 4 - note that loans are seasoned by 3 months - reduced by principal repayments. We are interested in cash flows in periods 4-360.
[pofun{:,1:4}]     = deal('sum(par.S)');
[pofun{1,5:end}]   = deal('sum(poval(2:5,t-1) - psval(2:5,t-1) - ppval(2:5,t-1))');
[pofun{2:5,4}]     = deal('par.S(i-1)');
[pofun{2:5,5:end}] = deal('poval(i,t-1) - psval(i,t-1) - ppval(i,t-1)');
  • Interest payment: 7.5% for each tranche, paid monthly
[cpfun{:}] = deal('poval(i,t)*par.c/12');
  • Principal repayment: scheduled, plus prepayment 165 PSA

(PSA-benchmarked single month mortality rates are computed with function smmpsa )

[psfun{1,:}]   = deal('(poval(1,t)*(mgpmt(par.r,par.m + 1 - t) - par.r/12))');
[psfun{2:5,:}] = deal('min(poval(i,t), psval(1,t)- sum(psval(2:(i-1),t)) )');
[ppfun{1,:}]   = deal('smmpsa(t,par.psa)*(poval(1,t) - psval(1,t))');
[ppfun{2:5,:}] = deal('min(poval(i,t) - psval(i,t), ppval(1,t)- sum(ppval(2:(i-1),t)) )');

b) calculate total cash flow and principal repayment

[cfval,poval,cpval,psval,ppval] = cfeval(pofun,cpfun,psfun,ppfun,par);  %#ok
name = {'Cash flow (interest and principal)', ...
        'Principal outstanding', ...
        'Scheduled principal repayment', ...
        'Unscheduled principal repayment (prepayment)'};
data  = {cfval,poval,psval,ppval};
for i = 1:4
    figure
    colormap autumn
    x = data{i};
    bar(x(2:5,4:end)','stacked');
    title(name{i})
    set(gcf,'Color','w')
end
close all