Mean/Variance Optimization

markowitz (var* Covariances, var* Means, int N, var Cap) : var

markowitz (var* Covariances, var* Means, int N, var* Caps) : var

Performs a mean / variance optimization (MVO) using the algorithm from the 1959 publication Portfolio Selection: Efficient Diversification of Investments by Harry M. Markowitz; also referred to as modern portfolio theory (MPT). The fucntion calculates the optimal distribution of capital among a portfolio of assets or algorithms for achieving a given total return or variance. The algorithm starts with assigning all capital to the component with the highest return. It then adds or removes more components step by step, calculating the optimal return/variance combination on any step.
 
The efficient frontier is a line consisting of corner points in a return over variance plot. At any corner point the portfolio composition changes by adding or removing one or several components. Between the corner points the included components don’t change, only their capital allocation changes linearly. Connecting all corner points with lines establishes the efficient frontier with the maximum return for any given variance (see image).
 

Efficient Frontier
Efficient frontier of an ETF portfolio, x axis = variance, y axis = annual return in %

Parameters:

Covariances A var[N*N] array containing the covariance matrix of the component returns.
Means A var[N] array containing the mean of the component returns.
N Number of components, at least 3.
Cap Weight cap in 0..1 range; soft weight limit of a single asset at the minimum variance point, or 0 for no weight cap.
Caps A var[N] array containing individual weight limits in 0..1 range, or 0 for no weight cap.

Returns

Variance at the efficient frontier point with the best Sharpe Ratio (i.e. return divided by standard deviation), or 0 if the efficient frontier could not be calculated. The efficient frontier line segments are internally stored for subsequent markowitzReturn or markowitzVariance calls.

 

markowitzReturn (var* Weights, var Variance) : var

Calculates the return and the optimal capital allocation weights for a given variance at a previously calculated efficient frontier. The markowitz() function must be called before for calculating the frontier.

markowitzVariance (var* Weights, var Return) : var

Calculates the variance and the optimal capital allocation for a given return at a previously calculated efficient frontier. The markowitz() function must be called before for calculating the frontier.

Parameters:

Weights A var[N] array to be filled with the capital allocation weights of the N portfolio components. The sum of the weights is 1. Pass 0 when no weights are needed.
Variance The desired variance. When below the lowest variance, the return and weights at the left end of the efficient frontier are returned.
Return The desired return. When below the lowest return of the efficient frontier, the variance and weights at the left end of the efficient frontier are returned.

Returns

The optimal portfolio return at the given variance, or vice versa..

Modifies

Weights - set to the capital allocation weights.
 

Remarks:

Example:

#define N    10  // 10 assets
#define DAYS 252 // 1 year
 
vars Returns[N];
var  Means[N];
var  Covariances[N][N];
 
function run()
{
  BarPeriod = 1440;
  StartDate = 20150101;
  LookBack = DAYS;
  
  string Name;
  int n = 0;
  while(Name = loop(.../*list of some assets*/ ... )) 
  {
    asset(Name);    
    Returns[n] = series((price(0)-price(1))/price(1));
    Means[n] = SMA(Returns[n],DAYS);
    n++;
  }
  
  int i,j;
  if(!is(LOOKBACK))
  {
// generate covariance matrix
    for(i=0; i<N; i++)
      for(j=0; j<N; j++)
        Covariances[i][j] = Covariance(Returns[i],Returns[j],DAYS);

// calculate efficient frontier
    var OptimalV = markowitz(Covariances,Means,N);
    printf("\nBest daily return %.3f %% at variance %.4f",
      100*markowitzReturn(0,OptimalV),OptimalV);

// plot the frontier
    for(i=1; i<70; i++) {
      var VStep = i*OptimalV*0.03;
      var Return = markowitzReturn(0,VStep);
      plotBar("Frontier",i,VStep,Return,LINE|LBL2,BLACK);
    }
    plotGraph("Max Sharpe",1./0.03,markowitzReturn(0,OptimalV),SQUARE,RED);
    PlotScale = 6;
    PlotHeight1 = 300;    
    quit("");
  }
}

See also:

OptimalF, Covariance, distribute, knapsack

► latest version online