SAS Products
SAS Risk Dimensions - Using Cash Flow Legs
Overview
Set Up Your Environment
Define Your Portfolio
Register Market Data
Define Valuation Methods
Specify the Analysis and Create the Project
Run the Project
Example Code (ZIP file)
Overview
In SAS Risk Dimensions you can define cash flow legs to track separate parts of a cash flow. For example, when you value an interest rate swap, you might want to track the floating rate payment
and the fixed rate payment separately. To do this, you define one leg for the floating rate amount and another leg for the fixed rate amount.
In the following example, you value a fixed-rate mortgage and observe the monthly payments in a cash flow structure. You separate the amount paid toward interest and the amount paid toward principal.
You define three cash flow legs, one for the principal payment, a second for the interest payment, and a third to track the remaining balance.
Set Up Your Environment
First, set up the library for your analysis.
libname RDExamp "C:\users\sasdemo\RD_Examples";
%let test_env = cashflowlegs;
In this code, you use the SAS Macro Language Facility to create the macro variable Test_Env. You assign the value
cashflowlegs to that variable.
Using macro variables in this way enables you to change the physical location of the target library and the environment name in just two lines of code. The macro does not directly affect calculations.
You can assign the library to any path as long as you have Write access to the referenced directory.
Next, create a new SAS Risk Dimensions environment assigned the name CashFlowLegs in the RDExamp library.
proc risk;
env new=RDExamp.&test_env;
env save;
run;
Define Your Portfolio
Next, describe the assets in your portfolio. The following code creates a data set called InstData that stores information about the instruments
in your portfolio.
You create a single instrument that is a fixed rate mortgage. The instrument variables are as follows:
- InstType
- InstID
- StartDate
- EndDate
- MortgageAmt
- FixedRate
- PaymentDayofMonth
- DiscountCurve
- Currency
- Holding
data RDExamp.instdata;
length Insttype Instid $32.;
informat StartDate EndDate date9.;
format StartDate EndDate date9.;
length MortgageAmt FixedRate PaymentDayofMonth 8. DiscountCurve $32. Currency $3
infile datalines delimiter = '|';
input Insttype $ Instid $ StartDate$ EndDate $ MortgageAmt FixedRate PaymentDayofMonth
DiscountCurve $ Currency $ holding;
datalines;
FixedRateMortgage |instid1 |01JUN2013|01JUN2043|300000| 0.05 |15 |USTREASURY |USD |1
;
Now declare the instrument variables and register the instrument data in the environment.
proc risk;
env open = RDExamp.&test_env;
declare instvars=(
StartDate date var label='Start date of mortgage loan',
EndDate date var label='End date of mortgage loan',
MortgageAmt num var label = 'Amount borrowed',
FixedRate num var label = 'Fixed interest rate paid',
PaymentDayofMonth num var label = 'Day of month payment paid',
DiscountCurve char 32 var label = 'Reference to discount curve'
);
instdata Mortgage file = RDExamp.instdata format = simple;
env save;
run;
Register Market Data
Next, provide current risk factor values. Declare the risk factors and register the market data in the environment. The risk factors in this example are US Treasury rates of different maturities.
After you declare each of the factors individually, declare a risk factor array to create a risk factor curve. The REFMAP option assigns the reference value "USTreasury" to this curve.
For more information about risk factor references, see the SAS Risk Dimensions and SAS High-Performance Risk: Procedures Guide.
data RDExamp.currentmkt;
informat Date date9.;
format date date9.;
length USTREAS_1M USTREAS_3M USTREAS_6M USTREAS_1Y USTREAS_2Y USTREAS_3Y
USTREAS_5Y USTREAS_7Y USTREAS_10Y USTREAS_20Y USTREAS_30Y 8;
infile datalines delimiter = ' ';
input Date USTREAS_1M USTREAS_3M USTREAS_6M USTREAS_1Y USTREAS_2Y
USTREAS_3Y USTREAS_5Y USTREAS_7Y USTREAS_10Y USTREAS_20Y USTREAS_30Y;
datalines;
31MAY2013 0.03 0.04 0.07 0.14 0.30 0.52 1.05 1.55 2.16 2.95 3.30
;
proc risk;
environment open = RDExamp.&test_env;
declare riskfactors= (
USTREAS_1M num IR currency = USD maturity = 1Month group = "US Treasury Rates",
USTREAS_3M num IR currency = USD maturity = 3Month group = "US Treasury Rates",
USTREAS_6M num IR currency = USD maturity = 6Month group = "US Treasury Rates",
USTREAS_1Y num IR currency = USD maturity = 1Year group = "US Treasury Rates",
USTREAS_2Y num IR currency = USD maturity = 2Year group = "US Treasury Rates",
USTREAS_3Y num IR currency = USD maturity = 3Year group = "US Treasury Rates",
USTREAS_5Y num IR currency = USD maturity = 5Year group = "US Treasury Rates",
USTREAS_7Y num IR currency = USD maturity = 7Year group = "US Treasury Rates",
USTREAS_10Y num IR currency = USD maturity = 10Year group = "US Treasury Rates",
USTREAS_20Y num IR currency = USD maturity = 20Year group = "US Treasury Rates",
USTREAS_30Y num IR currency = USD maturity = 30Year group = "US Treasury Rates"
);
array USTreasury IR
elements = (
USTREAS_1M
USTREAS_3M
USTREAS_6M
USTREAS_1Y
USTREAS_2Y
USTREAS_3Y
USTREAS_5Y
USTREAS_7Y
USTREAS_10Y
USTREAS_20Y
USTREAS_30Y
)
currency = USD label = "US Treasury Rates Curve" Group = "US Treasury Rates"
refmap=( DiscountCurve_Ref = "USTreasury" )
;
environment save;
run;
proc risk;
env open=RDExamp.&test_env;
marketdata CurrentMarket file=RDExamp.currentmkt type=current;
env save;
run;
Define Valuation Methods and Instrument Types
Next, create a pricing method using the COMPILE procedure to value the portfolio. You create two functions for use in the pricing method. The function GetRate uses linear interpolation
on the provided interest rate curve to derive the correct interest rate. The function FindClosest is used by GetRate to search the interest rate curve for the closest value.
proc compile env=RDExamp.&test_env outlib=RDExamp.&test_env package = Interpolation_Functions;
label = "Discount curve interpolation";
function FindClosest(value,FindArray[*]);
UpperCap = dim(FindArray)+1;
UpBound = UpperCap;
LowBound = 1;
do while( UpBound-LowBound > 0 );
MidPoint = floor((UpBound+LowBound)/2);
if FindArray[MidPoint] < value then LowBound = MidPoint + 1;
else if MidPoint eq 1 then return(1);
else if FindArray[MidPoint-1] ge value then UpBound = MidPoint;
else return(MidPoint);
end;
return(UpperCap);
endsub;
function GetRate(maturity, IntRateCurve[*],MaturityCurve[*]);
CurveDim = dim(IntRateCurve);
index = FindClosest( maturity, MaturityCurve );
if index eq 1 then
InterestRate = IntRateCurve[1];
else if index > CurveDim then
InterestRate = IntRateCurve[CurveDim];
else
InterestRate = IntRateCurve[index-1] + ( ( IntRateCurve[index] - IntRateCurve[index-1] ) *
( maturity - MaturityCurve[index-1] ) / ( MaturityCurve[index] - MaturityCurve[index-1] ) );
return ( InterestRate );
endsub;
run;
The following pricing method computes the value of the mortgage and assigns the values of the cash flow legs to the cash flow structure. The embedded comments describe the steps followed to complete these tasks.
proc compile env=RDExamp.&test_env outlib=RDExamp.&test_env;
method FixedRateMortgage desc= "Fixed Rate Mortage" kind= price;
array TimePeriod[360] /nosym;
/*Determine number of payments to be made. There will be a cash flow for each payment*/
totalpayments = intck("MONTH", StartDate, EndDate);
payments = intck("MONTH", _date_, EndDate);
_cashflow_.Num = payments;
_cashflow_.BALANCE.Num = payments;
_cashflow_.PRINCIPAL.Num = payments;
_cashflow_.INTEREST.Num = payments;
/*Determine the payment dates. The maturity dates of the cash flows are the payment dates*/
do i = 1 to payments;
PaymentDay = intnx( "MONTH", EndDate, i-payments, "BEG") + PaymentDayofMonth;
PaymentDay = min( PaymentDay, intnx( "MONTH", EndDate, i-payments, "END") );
PaymentDay = intnx("WEEKDAY", PaymentDay, 0);
_cashflow_.matdate[i] = PaymentDay;
_cashflow_.BALANCE.matdate[i] = PaymentDay;
_cashflow_.PRINCIPAL.matdate[i] = PaymentDay;
_cashflow_.INTEREST.matdate[i] = PaymentDay;
/*Calculate amount of time for discounting payment (to determine current value of mortgage)*/
TimePeriod[i] = (PaymentDay - _date_)/365;
end;
/*Determine fixed payment amount*/
MonthlyPayment = pmt((FixedRate/12),totalpayments, MortgageAmt);
/*Loop over the payments to fill amounts and compute mortgage value*/
PresentVal = 0;
Beginning_Balance = MortgageAmt;
do i = 1 to payments;
/*Total payment is the monthly payment*/
PaymentAmount = MonthlyPayment;
/*Determine amount of payment that is interest*/
InterestAmount = Beginning_Balance *(FixedRate)/12 ;
/*Determine the amount that is principal*/
PrincipalAmount = PaymentAmount - InterestAmount;
/*Update principal balance*/
Beginning_Balance = Beginning_Balance - PrincipalAmount;
/*Fill cash flow instrument*/
_cashflow_.matamt[i] = PaymentAmount;
_cashflow_.BALANCE.matamt[i] = Beginning_Balance;
_cashflow_.PRINCIPAL.matamt[i] = PrincipalAmount;
_cashflow_.INTEREST.matamt[i] = InterestAmount;
/*Discount cash flow and add to present value of previous cash flows*/
discount_rate = GetRate( TimePeriod[i], DiscountCurve_Ref.DiscountCurve, DiscountCurve_Ref.DiscountCurve.mat);
discount_factor = exp( -1 *TimePeriod[i]*discount_rate);
PresentVal = PresentVal + discount_factor*PaymentAmount;
end;
_value_ = PresentVal;
endmethod;
run;
After declaring the method, use the INSTRUMENT statement to register the instrument type in the environment.
proc risk;
environment open = RDExamp.&test_env;
instrument FixedRateMortgage methods = (Price FixedRateMortgage)
variables = (
StartDate
EndDate
MortgageAmt
FixedRate
PaymentDayofMonth
DiscountCurve
Currency
holding
);
env save;
run;
Specify Analyses and Create the Project
Next, set up a project to perform the cash flow analysis.
The following code creates a portfolio file from the instrument data set and identifies the cross-classifications for portfolio aggregation. Then it defines a time grid for cash flow bucketing.
Configure a traditional cash flow analysis with the BUCKETTYPE option, which is set to produce cash flow buckets and cumulative cash flow buckets.
Next, define the project itself. Specify the three cash flow legs in the CFBUCKETLIST option. Each leg is assigned the time gird, CashFlowGrid.
proc risk;
environment open = RDExamp.&test_env;
sources InstDataSource (Mortgage);
read sources=InstDataSource out=Portfolio;
crossclass InstIDCC (InstID);
timegrid CashFlowGrid(
1 MONTH,
2 MONTH,
3 MONTH,
4 MONTH,
5 MONTH,
6 MONTH,
1 YEAR,
5 YEAR,
10 YEAR,
15 YEAR,
20 YEAR,
25 YEAR,
30 YEAR
);
cashflow CashFlow_Analysis analysis=Traditional buckettype=all duration=none;
project CashFlow_Project
data = (CurrentMarket)
analysis = (CashFlow_Analysis)
portfolio = Portfolio
crossclass = InstIDCC
rundate = "03JUN2013"d
CFBUCKETLIST = (BALANCE(CashFlowGrid(REL)),
PRINCIPAL(CashFlowGrid(REL)),
INTEREST(CashFlowGrid(REL)))
CFDIST = BACKWARD
CFMAXSIZE = 360;
environment save;
run;
Run the Project
Run the project, putting output files in the CashFlow_Project directory. Use the RUNPROJECT statement options to specify the cash flow output data set.
proc risk;
env open=RDExamp.&test_env;
run;
proc risk;
env open=RDExamp.&test_env;
runproject CashFlow_Project
out= CashFlow_Project
options=(outall);
env save;
run;
Back to Examples index page