Description
MeanVar.gms: Mean-Variance model. Consiglio, Nielsen and Zenios. PRACTICAL FINANCIAL OPTIMIZATION: A Library of GAMS Models, Section 3.2 Last modified: Apr 2008.
Category : GAMS FIN library
Mainfile : MeanVar.gms includes : Estimate.gdx
$title Mean-variance model.
* MeanVar.gms: Mean-Variance model.
* Consiglio, Nielsen and Zenios.
* PRACTICAL FINANCIAL OPTIMIZATION: A Library of GAMS Models, Section 3.2
* Last modified: Apr 2008.
SET Assets;
ALIAS(Assets,i,j);
PARAMETERS
RiskFreeRate
ExpectedReturns(i) Expected returns
VarCov(i,j) Variance-Covariance matrix ;
* Read from Estimate.gdx the data needed to run the mean-variance model
$gdxIn Estimate
$load Assets=subset RiskFreeRate=MeanRiskFreeReturn VarCov ExpectedReturns
$gdxIn
* Risk attitude: 0 is risk-neutral, 1 is very risk-averse.;
SCALAR
lambda Risk attitude;
POSITIVE VARIABLES
x(i) Holdings of assets;
VARIABLES
PortVariance Portfolio variance
PortReturn Portfolio return
z Objective function value;
EQUATIONS
ReturnDef Equation defining the portfolio return
VarDef Equation defining the portfolio variance
NormalCon Equation defining the normalization contraint
ObjDef Objective function definition;
ReturnDef .. PortReturn =e= SUM(i, ExpectedReturns(i)*x(i));
VarDef .. PortVariance =e= SUM((i,j), x(i)*VarCov(i,j)*x(j));
NormalCon .. SUM(i, x(i)) =e= 1;
ObjDef .. z =e= (1-lambda) * PortReturn - lambda * PortVariance;
MODEL MeanVar 'PFO Model 3.2.3' /ReturnDef,VarDef,NormalCon,ObjDef/;
* Define a file on the disk and associate it to the file handle FrontierHandle.
* By default, the file will be written in the current directory.
* Define a file on the disk and associate it to the file handle FrontierHandle.
* By default, the file will be written in the current directory.
FILE FrontierHandle /"MeanVarianceFrontier.csv"/;
* Just add some options to appropriately format the output.
* We will write a comma separeted value (CSV) file
* which can be easily read from any spreadsheet (see pag. 137 of the
* GAMS User's Guide).
* Also, enalarge the page width to be sure that the portfolio holdings
* fit in a row.
FrontierHandle.pc = 5;
FrontierHandle.pw = 1048;
* Assign the output stream to the file handle "Frontier"
PUT FrontierHandle;
* Write the heading
PUT "Lambda","z","Variance","ExpReturn";
LOOP (i, PUT i.tl);
PUT /;
FOR (lambda = 0 TO 1 BY 0.1,
SOLVE MeanVar MAXIMIZING z USING nlp;
PUT lambda:6:5, z.l:6:5, PortVariance.l:6:5, PortReturn.l:6:5;
LOOP (i, PUT x.l(i):6:5 );
PUT /;
)
* Close file
PUTCLOSE;
* Output directly to an Excel file through the GDX utility
SET FrontierPoints / PP_0 * PP_10 /
ALIAS (FrontierPoints,p);
PARAMETERS
RiskWeight(p) Investor's risk attitude parameter
MinimumVariance(p) Optimal level of portfolio variance
PortfolioReturn(p) Portfolio return
OptimalAllocation(p,i) Optimal asset allocation
SolverStatus(p,*) Status of the solver
SummaryReport(*,*) Summary report;
* The risk weight, lambda, has to range in the interval [0,1]
RiskWeight(p) = (ORD(p)-1)/(CARD(p)-1);
DISPLAY RiskWeight;
LOOP(p,
lambda = RiskWeight(p);
SOLVE MeanVar MAXIMIZING z USING NLP;
MeanVar.SOLPRINT = 2;
MinimumVariance(p)= PortVariance.l;
PortfolioReturn(p) = PortReturn.l;
OptimalAllocation(p,i) = x.l(i);
SolverStatus(p,'solvestat') = MeanVar.solvestat;
SolverStatus(p,'modelstat') = MeanVar.modelstat;
SolverStatus(p,'objective') = MeanVar.objval
);
* Store results by rows
SummaryReport(i,p) = OptimalAllocation(p,i);
SummaryReport('Variance',p) = MinimumVariance(p);
SummaryReport('Return',p) = PortfolioReturn(p);
SummaryReport('Lambda',p) = RiskWeight(p);
DISPLAY SummaryReport,SolverStatus;
* Write SummaryReport into an Excel file
embeddedCode Connect:
- GAMSReader:
symbols: [ { name: SummaryReport } ]
- ExcelWriter:
file: MeanVarianceFrontier.xlsx
symbols: [ { name: SummaryReport, range: Sheet!A1 } ]
endEmbeddedCode