immun.gms : Financial Optimization: Risk Management

Description

Several different models have been developed during the seventies
to manage financial risks. Immunization, dedication and combination
models of various flavors are presented. The presentation of the
models follows closely chapter one of the book Financial Optimization.

The models are designed to capture the essential features using a small
data set derived from U.S.Treasury Quotes for 6/23/89 from the Wall Street
Journal.

The family of models presented in this file are

IMMUN1  Dollar Duration Immunization Model
IMMUN2  Gain Oriented Immunization Model
IMMUN3  Dollar Convexity Immunization Model
FACTOR1 Factor Immunization Model
FACTOR2 Factor Immunization Model
DEDIC   Bond Dedication Model
COMB1   Combination Matching Model
COMB2   Horizon Matching Model
COMB3   Factor Horizon Matching Model
SIGMA   Minimum Cashflow Variance Model

All share the same liability and security data. Common formulations
are exploited to better show the relationship between these models


Small Model of Types : QCP lp


Category : GAMS Model library


Main file : immun.gms

$title Financial Optimization: Risk Management (IMMUN,SEQ=110)

$onText
Several different models have been developed during the seventies
to manage financial risks. Immunization, dedication and combination
models of various flavors are presented. The presentation of the
models follows closely chapter one of the book Financial Optimization.

The models are designed to capture the essential features using a small
data set derived from U.S.Treasury Quotes for 6/23/89 from the Wall Street
Journal.

The family of models presented in this file are

IMMUN1  Dollar Duration Immunization Model
IMMUN2  Gain Oriented Immunization Model
IMMUN3  Dollar Convexity Immunization Model
FACTOR1 Factor Immunization Model
FACTOR2 Factor Immunization Model
DEDIC   Bond Dedication Model
COMB1   Combination Matching Model
COMB2   Horizon Matching Model
COMB3   Factor Horizon Matching Model
SIGMA   Minimum Cashflow Variance Model

All share the same liability and security data. Common formulations
are exploited to better show the relationship between these models


Dahl, H, Meeraus, A, and Zenios, S A, Some Financial Optimization
Models: Risk Management. In Zenios, S A, Ed, Financial Optimization.
Cambridge University Press, New York, NY, 1993.

Keywords: linear programming, quadratic constraint programming, finance, risk management,
          financial optimization
$offText

$sTitle Liability Information
Set tl 'liability time' / tl0*tl5 /;

Table liab(tl,*) 'liability data'
         month  day  year  liability  liabrate
   tl0       6   23  1989          0  0.092370
   tl1       9    1  1989      50000  0.092281
   tl2       6   15  1990      42000  0.090367
   tl3      12    1  1990      40000  0.088643
   tl4      12    1  1991      40000  0.085649
   tl5       6    1  1993      45000  0.086548;

Scalar basedate 'earliest liability date';
basedate = smin(tl, jdate(liab(tl,'year'),liab(tl,'month'),liab(tl,'day')));

liab(tl,'days') = jdate(liab(tl,'year'),liab(tl,'month'),liab(tl,'day')) - basedate;
liab(tl,'term') = liab(tl,'days')/365;

Parameter
   rl(tl) 'interest rate of liability'
   pl     'present value of liability '
   kl     'dollar duration of liability'
   ql     'dollar convexity of liability';

rl(tl) =  liab(tl,"liabrate");
pl     =  sum(tl, liab(tl,'liability')*exp(-rl(tl)*liab(tl,'term')));
kl     = -sum(tl, liab(tl,'liability')*exp(-rl(tl)*liab(tl,'term'))*liab(tl,'term'));
ql     =  sum(tl, liab(tl,'liability')*exp(-rl(tl)*liab(tl,'term'))*sqr(liab(tl,'term')));

* note: (1) liability interest rate fitted from cubic spline prototype.
*       (2) continuous compounding used for liabilities.
display pl, kl, ql;

$sTitle Security Information
Set
   i  'securities'  / bond-1*bond-8 /
   ts 'time points' / 89-07, 89-08, 90-02, 90-08, 91-02
                      91-08, 92-02, 92-08, 93-02, 93-08 /;

Table stime(ts,*) 'time information for securities'
           month  day  year
   89-07       7   15  1989
   89-08       8   15  1989
   90-02       2   15  1990
   90-08       8   15  1990
   91-02       2   15  1991
   91-08       8   15  1991
   92-02       2   15  1992
   92-08       8   15  1992
   93-02       2   15  1993
   93-08       8   15  1993;

stime(ts,'days') = jdate(stime(ts,'year'),stime(ts,'month'),stime(ts,'day')) - basedate;
stime(ts,'term') = stime(ts,'days')/365;

Table sdata(*,i) 'security data'
             bond-1    bond-2    bond-3    bond-4
   89-07   103.8125  107.2500
   89-08                         7.4375    3.6250
   90-02                         7.4375    3.6250
   90-08                         7.4375    3.6250
   91-02                         7.4375    3.6250
   91-08                       107.4375    3.6250
   92-02                                   3.6250
   92-08                                 103.6250
   yield     8.35      8.56      8.08      8.29
   price    99.9063  100.2812  113.0625   97.1563
   accr      3.3491    6.3688    5.2597    2.5635

   +         bond-5    bond-6    bond-7    bond-8
   89-08     4.1250    4.3125    4.375     5.9375
   90-02     4.1250    4.3125    4.375     5.9375
   90-08     4.1250    4.3125    4.375     5.9375
   91-02     4.1250    4.3125    4.375     5.9375
   91-08     4.1250    4.3125    4.375     5.9375
   92-02     4.1250    4.3125    4.375     5.9375
   92-08   104.1250    4.3125    4.375     5.9375
   93-02               4.3125    4.375     5.9375
   93-08             104.3125  104.375   105.9375
   yield     8.37      8.35      8.35      8.36
   price    99.6563  100.9375  101.3750  112.0625
   accr      2.9171    3.0497    3.0939    4.1989;

* note: (3) accr is interest accrued in the current coupon period
*           to date.

Parameter
   r(i)     'current yield of security'
   cf(ts,i) 'cash flow of security'
   p(i)     'present value of security (current price)'
   pv(i)    'present value of cashflows of security'
   k(i)     'dollar duration of security'
   q(i)     'dollar convexity of security';

cf(ts,i) =   sdata(ts,i)*10;
r(i)     =   sdata('yield',i)/100;
p(i)     =   (sdata('price',i) + sdata('accr',i)) * 10;
pv(i)    =   sum(ts, cf(ts,i) * (1 + r(i)/2)**(-2*stime(ts,'term') - 1));
k(i)     = - sum(ts, cf(ts,i) * stime(ts,'term') * (1 + r(i)/2)**(-2*stime(ts,'term') - 1));
q(i)     =   sum(ts, cf(ts,i) * (stime(ts,'term') + 1)
           * stime(ts,'term') * (1 + r(i)/2)**(-2*stime(ts,'term') - 2));

* 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, q;

$sTitle Immunization Model Equations
Variable
   omega 'objective value'
   x(i)  'security';

Positive Variable x;

Equations
   objdef1 'objective definition immun1'
   objdef2 'objective definition immun2'
   objdef3 'objective definition immun3'
   pvm     'present value match'
   ddm     'dollar duration match'
   dcm     'dollar convexity constraint';

objdef1.. omega =e= sum(i, k(i)*r(i)*x(i));

objdef2.. omega =e= sum(i, (p(i) - pv(i))*x(i));

objdef3.. omega =e= sum(i, q(i)*x(i));

pvm..     sum(i, p(i)*x(i)) =e= pl;

ddm..     sum(i, k(i)*x(i)) =e= kl;

dcm..     sum(i, q(i)*x(i)) =g= ql;

Model
   immun1 'dollar duration immunization model'
          / objdef1,                   pvm, ddm      /
   immun2 'gain oriented immunization model'
          /          objdef2,          pvm, ddm      /
   immun3 'dollar convexity immunization model'
          /                   objdef3, pvm, ddm, dcm /;

solve immun1 maximizing omega using lp;
solve immun2 minimizing omega using lp;
solve immun3 minimizing omega using lp;

$sTitle Factor loading Model
Set
   tf    'factor dates in years from 6-23-89' / tf0*tf10 /
   j     'factors'                            / shift, tilt, curve /
   ja(j) 'active factors';

* shape risk factors
*   shift   parallel shifts to term structure curve
*   tilt    changes in steepness of term structure curve
*   curve   changes in overall curvature of the term structure curve

Table a(tf,*) 'factor loading array for yearly time intervals'
         term  shift  tilt  curve
   tf0      0     42   -25     -6
   tf1      1     43   -22     -4
   tf2      2     44   -16     -2
   tf3      3     45   -12      0
   tf4      4     46    -6      4
   tf5      5     47     0      8
   tf6      6     47     2      8
   tf7      7     46     4      6
   tf8      8     45     6      4
   tf9      9     44     8      2
   tf10    10     43    10      0;

Parameter
   sfac(ts,j) 'interpolated factor loadings on term of securities'
   lfac(tl,j) 'interpolated factor loadings on term of liabilities'
   f(i,j)     'factor sensitivities of securities'
   fl(j)      'factor sensitivities of liabilities';

loop((ts,tf)$(a(tf,"term") = trunc(stime(ts,"term"))),
   sfac(ts,j) = (a(tf,j) + (a(tf+1,j) - a(tf,j))*(stime(ts,"term") - a(tf,"term")))/100);

loop((tl,tf)$(a(tf,"term") = trunc(liab(tl,"term"))),
   lfac(tl,j) = (a(tf,j) + (a(tf+1,j) - a(tf,j))*(liab(tl,"term") - a(tf,"term")))/100);

f(i,j) = - sum(ts, sfac(ts,j)*cf(ts,i)*stime(ts,"term")*(1+r(i)/2)**(-2*stime(ts,'term')-1));
fl(j)  = - sum(tl, lfac(tl,j)*liab(tl,"liability")*liab(tl,"term")*exp(-rl(tl)*liab(tl,"term")));

Positive Variable dif(j) 'lastic difference in factor match (surplus)';
* note:  nonzero solution values of dif(j) indicate infeasibilities.

Equation
   objdef4  'objective definition'
   fm(j)    'factor match'
   diffm(j) 'difference between factor match when infeasible';

objdef4..   omega =e= sum(i, k(i)*r(i)*x(i)) - sum(ja, dif(ja));

fm(ja)..    sum(i, f(i,ja)*x(i))           =e= fl(ja);

diffm(ja).. sum(i, f(i,ja)*x(i)) - fl(ja)  =e= dif(ja);

ja(j) = yes;

Model
   factor1 'factor immunization model' / objdef1,          pvm, fm       /
   factor2 'factor immunization model' /          objdef4, pvm,    diffm /;

solve factor1 maximizing omega using lp;
solve factor2 maximizing omega using lp;

$sTitle Bond Dedication Model
Parameter
   rr      'reinvestment rate'
   del(tl) 'interval between liability payments'
   d(tl,i) 'reinvested value of bond cashflow between liability dates';

rr      = .05;
del(tl) = liab(tl,"term") - liab(tl-1,"term");
d(tl,i) = sum(ts$(liab(tl-1,"term") < stime(ts,"term")
              and stime(ts,"term") <= liab(tl,"term")),
              cf(ts,i)*(1 + rr)**(liab(tl,"term") - stime(ts,"term")));

Variable
   s(tl) 'cash holdings (surplus) at time tl'
   l(tl) 'funded liability';

Positive Variable s, l;

l.lo(tl) = liab(tl,"liability");

Equation
   objdef5  'objective definition for cost'
   cbal(tl) 'cashflow balance';

objdef5..  omega =e= sum(i, p(i)*x(i)) + s("tl0");

cbal(tl).. sum(i, d(tl,i)*x(i)) + s(tl-1)*(1+rr)**del(tl) =e= l(tl) + s(tl);

Model dedic 'bond dedication model' / objdef5, cbal /;

solve dedic minimizing omega using lp;

$sTitle Combination matching (horizon matching)
l.lo(tl)$(liab(tl,"year") >= 1992) = 0;

Equation hm 'horizon matching';

hm.. kl*(sum(i, p(i)*x(i)) + s("tl0")) =e= pl*sum(i, k(i)*x(i));

Model
   comb1 'combination matching model'    / objdef5, cbal, hm         /
   comb2 'horizon matching model'        / objdef5, cbal,    ddm     /
   comb3 'factor horizon matching model' / objdef5, cbal,        fm  /;

solve comb1 minimizing omega using lp;
solve comb2 minimizing omega using lp;

ja(j) = yes;

solve comb3 minimizing omega using lp;

$onText This is the original model. Below we added another version with better numerical properties.
$sTitle Minimum Cashflow Variance Model
Variable variance 'variance of cashflows';

omega.up = pl;
l.lo(tl) = 0;

Equation objdef6 'cashflow variance';

objdef6..  variance =e= sum(tl, sqr(liab(tl,"liability") - l(tl)));

Model sigma 'minimum cashflow variance model' / objdef6, cbal, objdef2 /;

solve sigma  minimizing variance using qcp;
$offText

$sTitle Minimum Cashflow Std-Dev Model
* improved version added on 2019-01-27, suggested by E. Andersen
Variable stddev 'standard deviation of cashflows';
Variable liabdiff(tl);

Equation objdef6 'cashflow stddev';
Equation def_liabdiff(tl) 'defining liabdiff';

def_liabdiff(tl).. liabdiff(tl) =e= liab(tl,"liability") - l(tl);

objdef6..  sqr(stddev) =g= sum(tl, sqr(liabdiff(tl)));
stddev.lo = 0;

Model sigma 'minimum cashflow stddev model' / objdef6, def_liabdiff, cbal, objdef2 /;

solve sigma minimizing stddev using qcp;