#' @title Compute the mean-variance efficient frontier (on returns) by quadratic programming.
#'
#' @description Compute the mean-variance efficient frontier (on returns) by quadratic programming, as described in
#' A. Meucci "Risk and Asset Allocation", Springer, 2005
#'
#' @param NumPortf [scalar] number of portfolio in the efficient frontier
#' @param Covariance [matrix] (N x N) covariance matrix
#' @param ExpectedValues [vector] (N x 1) expected returns
#' @param Constraints [struct] set of constraints. Default: weights sum to one, and no-short positions
#'
#' @return ExpectedValue [vector] (NumPortf x 1) expected values of the portfolios
#' @return Volatility [vector] (NumPortf x 1) standard deviations of the portfolios
#' @return Composition [matrix] (NumPortf x N) optimal portfolios
#'
#' @references
#' A. Meucci - "Exercises in Advanced Risk and Portfolio Management" \url{http://symmys.com/node/170}.
#'
#' See Meucci's script for "EfficientFrontierReturns.m".
#'
#' @author Xavier Valls \email{flamejat@@gmail.com}
#' @export
EfficientFrontierReturns = function(NumPortf, Covariance, ExpectedValues, Constraints = NULL)
{
NumAssets = ncol(Covariance);
##################################################################################################################
# determine return of minimum-risk portfolio
FirstDegree = matrix( 0, NumAssets, 1);
SecondDegree = Covariance;
if( !length(Constraints) )
{
Aeq = matrix( 1, 1, NumAssets);
beq = 1;
A = -diag( 1, NumAssets); # no-short constraint
b = matrix( 0, NumAssets, 1); # no-short constraint
}else
{
Aeq = Constraints$Aeq;
beq = Constraints$beq;
A = Constraints$Aleq; # no-short constraint
b = Constraints$bleq; # no-short constraint
}
x0 = 1 / NumAssets * matrix( 1, NumAssets, 1);
Amat = rbind( Aeq, A);
bvec = rbind( beq, b);
###### MinVol_Weights = quadprog( SecondDegree, -FirstDegree, A, b, Aeq, beq, [], [], x0, options );
MinVol_Weights = matrix( solve.QP( Dmat = SecondDegree, dvec = -FirstDegree, Amat = -t(Amat), bvec = -bvec, meq = length( beq ) )$solution );
MinVol_Return = t( MinVol_Weights ) %*% ExpectedValues;
##################################################################################################################
### Determine return of maximum-return portfolio
MaxRet_Return = max(ExpectedValues);
MaxRet_Index = which( ExpectedValues == max(ExpectedValues) );
##################################################################################################################
### Slice efficient frontier in NumPortf equally thick horizontal sectors in the upper branch only
Step = (MaxRet_Return - MinVol_Return) / (NumPortf - 1);
TargetReturns = seq( MinVol_Return, MaxRet_Return, Step );
##################################################################################################################
### Compute the NumPortf compositions and risk-return coordinates of the optimal allocations relative to each slice
# initialization
Composition = matrix( NaN, NumPortf, NumAssets);
Volatility = matrix( NaN, NumPortf, 1);
ExpectedValue = matrix( NaN, NumPortf, 1);
# start with min vol portfolio
Composition[ 1, ] = t(MinVol_Weights);
Volatility[ 1 ] = sqrt(t(MinVol_Weights) %*% Covariance %*% MinVol_Weights);
ExpectedValue[ 1 ] = t(MinVol_Weights) %*% ExpectedValues;
for( i in 2 : (NumPortf - 1) )
{
# determine least risky portfolio for given expected return
AEq = rbind( matrix( 1, 1, NumAssets), t(ExpectedValues) );
bEq = rbind( 1, TargetReturns[ i ]);
Amat = rbind( AEq, A);
bvec = rbind( bEq, b)
Weights = t( solve.QP( Dmat = SecondDegree, dvec = -FirstDegree, Amat = -t(Amat), bvec = -bvec, meq = length( bEq ) )$solution );
#Weights = t(quadprog(SecondDegree, FirstDegree, A, b, AEq, bEq, [], [], x0, options));
Composition[ i, ] = Weights;
Volatility[ i ] = sqrt( Weights %*% Covariance %*% t(Weights));
ExpectedValue[ i ] = Weights %*% ExpectedValues;
}
# add max ret portfolio
Weights = matrix( 0, 1, NumAssets);
Weights[ MaxRet_Index ] = 1;
Composition[ nrow(Composition), ] = Weights;
Volatility[ length(Volatility) ] = sqrt(Weights %*% Covariance %*% t(Weights));
ExpectedValue[ length(ExpectedValue) ] = Weights %*% ExpectedValues;
return( list( ExpectedValue = ExpectedValue, Volatility = Volatility, Composition = Composition ) );
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.