Description
MAD.gms: Put/Call efficient frontier model. Consiglio, Nielsen and Zenios. PRACTICAL FINANCIAL OPTIMIZATION: A Library of GAMS Models, Section 5.7 Last modified: Apr 2008.
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
* Last modified: Apr 2008.
$if NOT set out $set out PutCallModel
$include "WorldIndices.inc"
OPTION LIMROW=0,LIMCOL=0,SOLVELINK=2;
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:
- GAMSReader:
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:
- GAMSReader:
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)
Premium(i)
BenchMarkNeutralPrice(i)
Psi(l);
Omega = 0.475;
SOLVE UnConPutCallModel MAXIMIZING z USING LP;
Discount(i) = 0.0;
Premium(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,'Premium') = Premium(i);
liquidity(i,'Discount') = Discount(i);
embeddedCode Connect:
- GAMSReader:
symbols: [ { name: liquidity } ]
- ExcelWriter:
file: %out%.xlsx
symbols: [ { name: liquidity, range: Liquidity!A1 } ]
endEmbeddedCode
DISPLAY Df,Psi,BenchMarkNeutralPrice,Discount,Premium,Price;
* 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:
- GAMSReader:
symbols: [ { name: PutCall }, { name: FrontierPortfolios } ]
- ExcelWriter:
file: %out%.xlsx
symbols:
- { name: PutCall, range: Frontiers!A1 }
- { name: FrontierPortfolios, range: Portfolios!A1 }
endEmbeddedCode