PutCall : Put/Call efficient frontier model.

Description

```MAD.gms: Put/Call efficient frontier model.
Consiglio, Nielsen and Zenios.
PRACTICAL FINANCIAL OPTIMIZATION: A Library of GAMS Models, Section 5.7
```

Category : GAMS FIN library

Mainfile : PutCall.gms   includes :  Corporate.inc  WorldIndices.inc  Index.inc

``````\$title Put/Call efficient frontier model

* MAD.gms: Put/Call efficient frontier model.
* Consiglio, Nielsen and Zenios.
* PRACTICAL FINANCIAL OPTIMIZATION: A Library of GAMS Models, Section 5.7

\$if NOT set out \$set out PutCallModel

\$include "WorldIndices.inc"

SCALARS
Budget       Nominal investment budget
Omega        Bound on the expected shortfalls;

Budget = 100.0;

PARAMETERS
pr(l)       Scenario probability
P(i,l)      Final values
EP(i)       Expected final values;

pr(l) = 1.0 / CARD(l);

P(i,l) = 1 + AssetReturns ( i, l );

EP(i) = SUM(l, pr(l) * P(i,l));

PARAMETER
TargetIndex(l)   Target index returns;

* To test the model with a market index, uncomment the following line two lines.
* Note that, this index is consistent only when using WorldIndexes.inc.

\$include "Index.inc"

TargetIndex(l) = Index(l);

* Primal of the UnConstrained Put/Call model

PARAMETERS
LowerBounds(i)
UpperBounds(i);

POSITIVE VARIABLES
yPos(l)     Positive deviations
yNeg(l)     Negative deviations;

VARIABLES
x(i)            Holdings of assets in monetary units (not proportions)
z               Objective function value;

EQUATIONS
BudgetCon         Equation defining the budget contraint
ObjDef            Objective function definition for MAD
TargetDevDef(l)   Equations defining the positive and negative deviations
PutCon            Constraint to bound the expected value of the negative deviations ;

BudgetCon ..        SUM(i, x(i)) =E= Budget;

PutCon ..           SUM(l, pr(l) * yNeg(l) ) =L= Omega;

TargetDevDef(l)..   SUM(i, ( P(i,l) - TargetIndex(l) ) * x(i) ) =E= yPos(l) -  yNeg(l);

ObjDef    ..        z =E= SUM(l, pr(l) * yPos(l));

MODEL UnConPutCallModel 'Model PFO 5.7.1' / PutCon, TargetDevDef, ObjDef /;

* Set the average level of downside (risk) allowed

Omega = 0.1;

SOLVE UnConPutCallModel MAXIMIZING z USING LP;

* Dual of the UnConstrained Put/Call model

POSITIVE VARIABLES
Pi(l)
PiOmega;

EQUATIONS
DualObjDef
DualTrackingDef(i)
MeasureDef(l);

DualObjDef ..           z =E= Omega * PiOmega;

DualTrackingDef(i)..    SUM(l, (P(i,l) - TargetIndex(l)) * Pi(l)) =E= 0.0;

MeasureDef(l)..         pr(l) * PiOmega - Pi(l) =G= 0;

Pi.LO(l) = pr(l);

MODEL UnConDualPutCallModel 'Model PFO 5.7.2' / DualObjDef, DualTrackingDef, MeasureDef /;

SOLVE UnConDualPutCallModel MINIMIZING z USING LP;

* Display PiOmega.l and Pi.l and check that they are, respectively, equal
* to TargetDevDef.m and PutCon.m
* GAMS provides the dual prices directly, so it is not
* really necessary to build explicitly the dual model.

PARAMETER PrimalDual(l,*) Compare primal and dual soultions;

PrimalDual(l,'pi.l')           = - pi.l(l);
PrimalDual(l,'TargetDevDef.m') = TargetDevDef.m(l);
PrimalDual(l,'Difference') =     TargetDevDef.m(l)+pi.l(l);

DISPLAY z.l,PiOmega.l,PutCon.m,PrimalDual;

* We propose an alternative way to build a frontier using
* the loop statement. Such a structure is suitable for the
* GDX utility (for details, see gdxutility.pdf included in the doc folder )

OPTION SOLPRINT = OFF;

SET
FrontierPoints /P_1 * P_50/;

* Number of points in the frontier

ALIAS ( FrontierPoints, j );

PARAMETER
FrontierPortfolios(j,i) Frontier portfolios
CallValues(j,*)         Call values
DualPrices(j,*)         Dual prices
PutCall(j,*)            Put and Call values
OmegaLevels(j)          Risk levels (Omega);

FILE temp file handle / temp.txt /;

* We assign to each point a risk level Omega

OmegaLevels('P_1') = 0.01;

LOOP (j\$(ORD(j) > 1),

OmegaLevels(j) = OmegaLevels(j-1) + (0.01)\$(ORD(j) <= 10) + (0.025)\$(ORD(j) > 10)
);

Dualprices(j,'Omega') = OmegaLevels(j);

CallValues(j,'Omega') = OmegaLevels(j);

* Set some liquidity constraints

x.LO(i) = -100.0;
x.UP(i) =  100.0;

LOOP (j,

Omega = OmegaLevels(j);

SOLVE UnConPutCallModel MAXIMIZING z USING LP;

FrontierPortfolios(j,i) = x.L(i);

CallValues(j,'Mild Constraint') = z.L;

Dualprices(j,'Mild Constraint') = PutCon.M

);

embeddedCode Connect:
symbols: [ { name: FrontierPortfolios } ]
- ExcelWriter:
file: %out%.xlsx
symbols: [ { name: FrontierPortfolios, range: MildPortfolios!A1 } ]
endEmbeddedCode

* Set tight liquidity constraints

x.LO(i) = -20.0;
x.UP(i) =  20.0;

LOOP (j,

Omega = OmegaLevels(j);

SOLVE UnConPutCallModel MAXIMIZING z USING LP;

FrontierPortfolios(j,i) = x.L(i);

CallValues(j,'Tight Constraint') = z.L;

Dualprices(j,'Tight Constraint') = PutCon.M

);

embeddedCode Connect:
symbols: [ { name: DualPrices }, { name: CallValues }, { name: FrontierPortfolios } ]
- ExcelWriter:
file: %out%.xlsx
symbols:
- { name: DualPrices, range: DualPrices!A1 }
- { name: CallValues, range: CallValues!A1 }
- { name: FrontierPortfolios, range: TightPortfolios!A1 }
endEmbeddedCode

* Determine the liquidity and discount premium
* for one put/call efficient portfolio.

SCALAR
Df;

PARAMETER
Price(i)
Discount(i)
BenchMarkNeutralPrice(i)
Psi(l);

Omega = 0.475;

SOLVE UnConPutCallModel MAXIMIZING z USING LP;

Discount(i) = 0.0;

Df = SUM(l, -TargetDevDef.M(l) );

Psi(l) = -TargetDevDef.M(l) / Df;

BenchMarkNeutralPrice(i) = SUM(l, Psi(l) * P(i,l)) / SUM(l, Psi(l) * TargetIndex(l));

Discount(i)\$(x.M(i) > 0) =  x.M(i) / SUM(l, (-TargetDevDef.M(l)) * TargetIndex(l));

Premium(i)\$(x.M(i) < 0) =  (-x.M(i)) / SUM(l, (-TargetDevDef.M(l)) * TargetIndex(l));

Price(i) = BenchMarkNeutralPrice(i) +  Premium(i)  -  Discount(i);

PARAMETER liquidity(i,*) Liquidity report;

liquidity(i,'Discount') = Discount(i);

embeddedCode Connect:
symbols: [ { name: liquidity } ]
- ExcelWriter:
file: %out%.xlsx
symbols: [ { name: liquidity, range: Liquidity!A1 } ]
endEmbeddedCode

* Put/call model with balance constraint

MODEL PutCallModel 'Model PFO 5.7.3' / BudgetCon, PutCon, TargetDevDef, ObjDef /;

LOOP (j,
Omega = OmegaLevels(j);
SOLVE PutCallModel MAXIMIZING z USING LP;
FrontierPortfolios(j,i) = x.L(i);
putcall(j,'Put side') = PutCon.L;
putcall(j,'Call side')= z.L );

embeddedCode Connect:
symbols: [ { name: PutCall }, { name: FrontierPortfolios } ]
- ExcelWriter:
file: %out%.xlsx
symbols:
- { name: PutCall, range: Frontiers!A1 }
- { name: FrontierPortfolios, range: Portfolios!A1 }
endEmbeddedCode
``````
GAMS Development Corp.
GAMS Software GmbH

General Information and Sales
U.S. (+1) 202 342-0180
Europe: (+49) 221 949-9170
GAMS is a registered trademark of GAMS Software GmbH in the European Union