Description
CreditImmunization.gms: Factor Immunization model for corporate bonds. Consiglio, Nielsen and Zenios. PRACTICAL FINANCIAL OPTIMIZATION: A Library of GAMS Models, Section 4.6 Last modified: Apr 2008.
Category : GAMS FIN library
Mainfile : CreditImmunization.gms includes : BondAndLiabilityData.inc CreditYieldRates.inc FactorLoadings.inc TimeDefinitionSets.inc
$title Factor Immunization model for corporate bonds
* CreditImmunization.gms: Factor Immunization model for corporate bonds.
* Consiglio, Nielsen and Zenios.
* PRACTICAL FINANCIAL OPTIMIZATION: A Library of GAMS Models, Section 4.6
* Last modified: Apr 2008.
SETS
i Maximum number of securities /Bond-1 * Bond-13/
j Factors risk types /shift, tilt, curve/
class Rating classes /AAA, B3/
ja(j) Active factors;
SCALAR
BaseDate Earliest liability date;
$include "TimeDefinitionSets.inc"
$include "CreditYieldRates.inc"
* Continous yields
yield(ty,class,'yield')= log( 1 + ( yield(ty,class,'interest') /100 ) ) * 100;
DISPLAY yield;
$include "BondAndLiabilityData.inc"
PARAMETERS
rl(tl,class) Interest rate of liability
pl(class) Present value of liability
r(ts,class) Current yield of bonds
cf(ts,i,class) Cash flow of bonds
p(i,class) Present value of bonds (current price)
pv(i,class) Present value of cashflows of bonds
k(i,class) Dollar duration of bonds;
BaseDate = SMIN(tl, jdate(LiabData(tl,'year'),LiabData(tl,'month'),LiabData(tl,'day')));
DISPLAY BaseDate;
* Convert time points from days to year units.
LiabData(tl,'days') = jdate(LiabData(tl,'year'),LiabData(tl,'month'),LiabData(tl,'day')) - BaseDate;
LiabData(tl,'term') = LiabData(tl,'days')/365;
stime(ts,'days') = jdate(stime(ts,'year'),stime(ts,'month'),
stime(ts,'day'))- BaseDate;
stime(ts,'term') = stime(ts,'days') / 365;
* Compute term structure data for liabilities and bonds on their dates,
* using interpolation:
LOOP( (tl,ty,class)$(yield(ty,class,"term") eq trunc(LiabData(tl,"term"))),
rl(tl,class) = ( yield(ty,class,"yield" ) +
( yield(ty+1,class,"yield") - yield(ty,class,"yield") ) /
( yield(ty+1,class,"term") - yield(ty,class,"term") ) * ( LiabData(tl,"term") - yield(ty,class,"term") ) ) / 100
);
LOOP( (ts,ty,class)$(yield(ty,class,"term") eq trunc(stime(ts,"term"))),
r(ts,class) = ( yield(ty,class,"interest" ) +
( yield(ty+1,class,"interest" ) - yield(ty,class,"interest") ) /
( yield(ty+1,class,"term") - yield(ty,class,"term") ) * ( stime(ts,"term") - yield(ty,class,"term") ) ) / 100
);
DISPLAY rl,r,yield,LiabData;
pl(class) = SUM( tl, LiabData(tl,'liability') * exp(-rl(tl,class)*LiabData(tl,'term')) );
cf(ts,i,class) = BondData(ts,i,class);
p(i,class) = BondData('price',i,class) + BondData('accr',i,class) ;
pv(i,class) = SUM( ts, cf(ts,i,class) * ( 1 + r(ts,class)/2 )**( -2*stime(ts,'term') ) );
k(i,class) = -SUM( ts, cf(ts,i,class) * stime(ts,'term') * ( 1 + r(ts,class)/2 )**(-2*stime(ts,'term') - 1) );
* note: (4) dollar amounts scaled by 10 to indicate par value.
* (5) current price used to indicate present value.
* (6) dollar duration and dollar convexity uses semiannual compounding.
DISPLAY k;
$include "FactorLoadings.inc"
PARAMETERS
sfac(ts,class,j) Interpolated factor loadings on term of securities
lfac(tl,class,j) Interpolated factor loadings on term of liabilities
f(i,j,class) Factor sensitivities of securities
fl(j,class) Factor sensitivities of liabilities ;
SCALAR
lambda Penalty on squared deviations from given factor liability;
LOOP( (ts,tf,class)$( a(tf,class,"term") eq trunc(stime(ts,"term"))),
sfac(ts,class,j) = ( a(tf,class,j) + ( a(tf+1,class,j) - a(tf,class,j) ) /
( a(tf+1,class,"term") - a(tf,class,"term") ) * (stime(ts,"term")-a(tf,class,"term") ) ) / 100
);
LOOP( (tl,tf,class)$(a(tf,class,"term") eq trunc(LiabData(tl,"term"))),
lfac(tl,class,j) = ( a(tf,class,j) + ( a(tf+1,class,j) - a(tf,class,j) ) /
( a(tf+1,class,"term") - a(tf,class,"term") ) * ( LiabData(tl,"term") - a(tf,class,"term") ) ) / 100
);
f(i,j,class) = - SUM( ts, sfac(ts,class,j) * cf(ts,i,class) * stime(ts,"term") *
( 1 + r(ts,class)/2 )**( -2*stime(ts,'term')-1 ) );
fl(j,"AAA") = - SUM( tl, lfac(tl,"AAA",j) * LiabData(tl,"liability") * LiabData(tl,"term") * exp(-rl(tl,"AAA")*LiabData(tl,"term")) );
fl(j,"B3") = - SUM( tl, lfac(tl,"B3",j) * LiabData(tl,"liability")/100 * LiabData(tl,"term") * exp(-rl(tl,"B3")*LiabData(tl,"term")) );
POSITIVE VARIABLE
x(i,class) Holdings of bonds (amount of face value);
POSITIVE VARIABLE
long(i,class) Holdings of bonds (amount of face value)
short(i,class) Holdings of bonds (amount of face value);
VARIABLES
z Objective function value
Deviations(j,class) Deviations from the correspondent liability factor level;
EQUATIONS
PresentValueMatchOne Equation matching the present value of asset and liability
PresentValueMatchTwo Equation matching the present value of asset and liability
DurationMatchOne(j,class) Equation matching the factor duration of asset and liability for each credit class
DurationMatchTwo(j,class) Equation matching the factor duration of asset and liability for each credit class
DeviationsEq(j,class) Equation defining the deviation from the correspondent liability factor
xDef(i,class) Equation defining the asset allocations as the sum of long and short positions
xShort Equation limiting the amount of bonds shorted
ObjDefOne Objective function definition (only AAA bonds)
ObjDefTwo Objective function definition (both credit classes)
ObjDefThree Objective function definition (minimizing also the sum of the squared deviations);
ObjDefOne .. z =E= SUM(i, k(i,"AAA")* ( BondData('yield',i,"AAA") / 100 ) * x(i,"AAA") );
ObjDefTwo .. z =E= SUM((i,class), k(i,class) * ( BondData('yield',i,class) / 100 ) * x(i,class) );
ObjDefThree .. z =E= (SUM(i, k(i,"AAA")* ( BondData('yield',i,"AAA") / 100 ) * x(i,"AAA") ) +
lambda * SUM((ja,class), SQR(Deviations(ja,class))))/1000000;
PresentValueMatchOne .. SUM(i, pv(i,"AAA")*x(i,"AAA")) =E= pl("AAA");
DurationMatchOne(ja,"AAA") .. SUM(i, f(i,ja,"AAA")*x(i,"AAA")) =E= fl(ja,"AAA");
PresentValueMatchTwo .. SUM((i,class), pv(i,class)*x(i,class)) =E= pl("AAA");
DurationMatchTwo(ja,class) .. SUM(i, f(i,ja,class)*x(i,class)) =E= fl(ja,"AAA");
DeviationsEq(ja,class) .. Deviations(ja,class) =E= SUM(i, f(i,ja,class)*x(i,class))- fl(ja,"AAA");
xDef(i,class).. x(i,class) =E= long(i,class) - short(i,class);
xShort .. SUM((i,class), short(i,class)) =L= 5000.0;
MODEL FactorCreditOne 'PFO Model 4.5.1' /ObjDefOne, PresentValueMatchOne, DurationMatchOne/;
MODEL FactorCreditTwo /ObjDefTwo, PresentValueMatchTwo, DurationMatchTwo/;
MODEL FactorCreditThree /ObjDefTwo, PresentValueMatchTwo, DurationMatchTwo, xDef, xShort/;
MODEL FactorCreditFour /ObjDefThree, PresentValueMatchTwo, DeviationsEq/;
ja( "shift" ) = YES;
ja( "tilt" ) = YES;
ja( "curve" ) = YES;
OPTION LIMROW = 100, LIMCOL = 100;
PARAMETER SummaryReport;
SOLVE FactorCreditOne MINIMIZING z USING LP;
SummaryReport(class,i,'one') = x.l(i,class);
SummaryReport('model','status','one') = FactorCreditOne.MODELSTAT;
SOLVE FactorCreditTwo MINIMIZING z USING LP;
SummaryReport(class,i,'two') = x.l(i,class);
SummaryReport('model','status','two') = FactorCreditTwo.MODELSTAT;
DISPLAY i,pv,pl,f,fl,x.L;
x.LO(i,class) = -INF;
SOLVE FactorCreditThree MINIMIZING z USING LP;
SummaryReport(class,i,'three') = x.l(i,class);
SummaryReport('model','status','three') = FactorCreditThree.MODELSTAT;
DISPLAY ja,class,x.L;
x.LO(i,class) = 0.0;
lambda = 2;
SOLVE FactorCreditFour MINIMIZING z USING NLP;
SummaryReport(class,i,'four') = x.l(i,class);
SummaryReport('model','status','four') = FactorCreditFour.MODELSTAT;
DISPLAY x.L,Deviations.L,fl;
DISPLAY SummaryReport;
embeddedCode Connect:
- GAMSReader:
symbols: [ { name: SummaryReport } ]
- ExcelWriter:
file: CreditSummary.xlsx
symbols: [ { name: SummaryReport, range: Sheet!A1 } ]
endEmbeddedCode