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