BondIndex : Tracking international bond index - The BSI Model.

Description

BondIndexGDX.gms: Tracking international bond index - GDX input.
Consiglio, Nielsen and Zenios.
PRACTICAL FINANCIAL OPTIMIZATION: A Library of GAMS Models, Section 8.2
Last modified: Apr 2008.


Category : GAMS FIN library


Mainfile : BondIndex.gms   includes :  BondIndexData.gdx

$title  Tracking international bond index - GDX input

* BondIndexGDX.gms: Tracking international bond index - GDX input.
* Consiglio, Nielsen and Zenios.
* PRACTICAL FINANCIAL OPTIMIZATION: A Library of GAMS Models, Section 8.2
* Last modified: Apr 2008.

$eolCom #


SETS
         Currencies   Currencies set
         Bonds        Bonds set
         Scenarios    Scenarios set

ALIAS(Currencies,j);
ALIAS(Bonds,i);
ALIAS(Scenarios,l,SS);

SET
         JxI(j,i) Bonds by Currencies;

PARAMETERS
         ExchangeRates0(j)         Exchange rate (USD against XXX)  at settlement
         ExchangeRates1(j,l)       Exchange rate scenarios ( USD against XXX ) at the end of the first stage
         Price0(i)                 Prices today (in unit of face value)
         Price1(i,l)               Prices at the end of the first stage (in unit of face value)
         InitialHoldings(i)        Initial bond holdings
         Accruals0(i)              Bonds initial accruals
         Accruals1(i,l)            Accruals for the first stage (in unit of face value)
         Outstanding(i,l)          Outstanding face for the first stage
         ReinvestmentRate(l)       Reinvestment rate scenarios ( plus one ) for USD
         IndexReturns(l)           Return of the Salomon index under each scenario
         pr(l)                     Scenario probability;



$gdxIn BondIndexData                                                     # open GDX container
$load Bonds Currencies Scenarios JxI ExchangeRates0 ExchangeRates1       # extract data
$load Price0 Price1 InitialHoldings  Accruals0 Accruals1                 # extract data
$load Outstanding ReinvestmentRate IndexReturns pr                       # extract data
$gdxIn                                                                   # close GDX container

SCALARS TrnCstB          Buying transaction costs   /0.0025/
        TrnCstS          Selling transaction costs  /0.0015/
        CashInfusion     Available budget infused /100000/
        EpsTolerance     Tolerance    /0.10/
        UpprBnd          Maximum holding percentage for each bond  /0.1/
        CHFtrade         Maximum trading value allowed for Swiss bonds (in CHF) /15000000/
        HoldVal          Value of the initial holdings
        InitAccrCash     Accrued cash originated by the initial holdings
        InitVal          Initial portfolio value;

* Calculate initial portfolio value

HoldVal      = SUM(JxI(j,i), ExchangeRates0(j)*InitialHoldings(i)*Price0(i));
InitAccrCash = SUM(JxI(j,i), ExchangeRates0(j)*InitialHoldings(i)*Accruals0(i));
InitVal      = CashInfusion + InitAccrCash + HoldVal;


POSITIVE VARIABLES
        X0(*)         Face value bought today.
        Y0(*)         Face value sold today.
        Z0(*)         Face value hold today for the next period.
        Cash          Amount of cash resulting from trading (sell and buy) today.
        FinalCash(l)  Amount of cash resulting from portfolio liquidation;

FREE VARIABLES
        z        Objective function value;

* Set the upper bound on the holdings

loop(JxI(j,i), Z0.UP(i) = InitVal/ExchangeRates0(j)/Price0(i)*UpprBnd );

* Set the limit on trading (sell or buy)
* CHF bonds for liquidity reasons

X0.UP(i)$JxI('CHF',i) = CHFtrade / Price0(i);
Y0.UP(i)$JxI('CHF',i) = CHFtrade / Price0(i);

EQUATIONS

   ObjDef            Objective function definition (Expected return)
   CashInventoryCon  Cash balance equation today.
   FinalCashCon(l)   Cash balance equations at the end of first stage.
   InventoryCon(i)   Constraints defining the asset inventory balance
   MADCon(l)         MAD constraints;


ObjDef ..     z =E= 1000*SUM(l, pr(l)*(FinalCash(l)/InitVal - 1 ) );

CashInventoryCon ..   CashInfusion
                    + SUM(JxI(j,i), ExchangeRates0(j)*Y0(i)*Price0(i)*(1-TrnCstS) )
                  =E= SUM(JxI(j,i), ExchangeRates0(j)*X0(i)*Price0(i)*(1+TrnCstB) )
                    + Cash;

FinalCashCon(l) ..  SUM(JxI(j,i), ExchangeRates1(j,l)*Accruals1(i,l)*Z0(i) )
                  + ReinvestmentRate(l)*Cash
                  + SUM(JxI(j,i), ExchangeRates1(j,l)*Z0(i)*Outstanding(i,l)*Price1(i,l)*(1-TrnCstS) )
                =E= FinalCash(l);

InventoryCon(i) .. InitialHoldings(i) + X0(i) =E= Y0(i) + Z0(i);


MADCon(l) ..  ( FinalCash(l)/InitVal  - 1 ) - IndexReturns(l) =G= - EpsTolerance;


MODEL BondIndex 'PSO 7.4.4' / All /;


OPTION LIMROW=0,LIMCOL=0,SOLPRINT=off; # 'Turn off row and colum listing'

* Find a feasible EpsTolerance

SCALAR low    Lower bisection value
       high   Upper bisection value;

high = -INF;  low = 0; EpsTolerance = .01;

REPEAT
   SOLVE BondIndex USING LP MAXIMIZING z;
   IF(BondIndex.MODELSTAT <= 2,
      high := EpsTolerance
   ELSE
      EpsTolerance = 2*EpsTolerance)
UNTIL high > 0;

* Find a small feasible EpsTolerance via bisection

REPEAT
   EpsTolerance = (low+high)/2;
   SOLVE BondIndex USING LP MAXIMIZING z;
   IF(BondIndex.MODELSTAT <=2,
      High = EpsTolerance
   ELSE
      low  = EpsTolerance );
UNTIL (high-low) < 0.005 AND BondIndex.MODELSTAT <= 2;

PARAMETER
CurrentValue(i) Holdings in USD;

CurrentValue(i) = SUM(JxI(j,i), ExchangeRates0(j))*Price0(i)*Z0.L(i);

SET ColHeaders Column headers / 'Face Value','USD Value','Percent'/

PARAMETER SummaryReport(*,ColHeaders);

SummaryReport(i,'Face Value') = Z0.l(i);

SummaryReport(i,'USD Value')  = currentValue(i);

SummaryReport(i,'Percent')    = currentValue(i)/InitVal*100;

SummaryReport('Total',ColHeaders)    = SUM(i, SummaryReport(i,ColHeaders));

DISPLAY SummaryReport,EpsTolerance,z.l,InitVal;

FILE ResultHandle /"BondIndex.csv"/;

ResultHandle.pc = 5; ResultHandle.pw = 1048;

PUT ResultHandle "Objective Function", z.L:12:8 /;

PUT "Final Epsilon", EpsTolerance:12:8/;

PUT "Initial Portfolio Value in USD",InitVal:0:0/;

PUT /;
PUT "Bond number","CUSIP code","Holdings in unit of face value","Holdings in USD","Percentage of the portfolio value";
LOOP(i$Z0.L(i),

      PUT / i.TL:0:0,i.TE(i):0:0,Z0.L(i)::3;

      PUT currentValue(i)::2,((currentValue(i)/InitVal)*100)::2

);

PUTCLOSE / "Cash in US dollar",Cash.L::2,((Cash.L/InitVal)*100)::3;