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

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. |

Cap |
Weight cap in 0..1 range; maximum weight of a single asset at the minimum variance point, or 0 for no weight cap. |

Caps |
A var[N] array containing individual weight caps in 0..1 range, or 0 for no weight cap. |

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. |

- For getting the minimum variance point, call
**markowitzReturn**with**Variance**at**0**. For maximum Sharpe ratio, call**markowitzReturn**with the**Variance**returned by**markowitz()**. For the maximum return point at the right side of the diagram, call**markowitzReturn**with**Variance**at**1**. For the maximum and minimum variances, call**markowitzVariance**with a return value above resp. below the maximum and minimum portfolio return. - Markowitz weights can be used alternatively to OptimalF factors for allocating capital to a portfolio system. Unlike
**OptimalF**, they require only a relatively short time horizon and thus can be adapted during live trading. For a long-term ETF rotation strategy, use the last year price returns of the ETFs (see example) and recalculate their markowitz weights every 4 weeks. - For calculating the returns of portfolio components with currently zero weight in real time, use phantom trades.
- In some cases it makes sense to limit the asset weights with the
**Cap**or**Caps**parameter (f.i.**0.33**for 33% maximum weight) for getting a higher portfolio diversification. This can produce better out-of-sample results. - MVO fails when there is no point on the efficient frontier that represents the portfolio, for instance when all means are negative. This can lead to weights of zero or - when a weight cap is used - to a total weight less than 1.
- Applications of the
**markowitz**function are described in the blog post Get Rich Slowly.

#define N 10// 10 assets#define DAYS 252// 1 yearvars 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 10 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 matrixfor(i=0; i<N; i++) for(j=0; j<N; j++) Covariances[i][j] = Covariance(Returns[i],Returns[j],DAYS);// calculate efficient frontiervar OptimalV = markowitz(Covariances,Means,N); printf("\nBest daily return %.3f %% at variance %.4f", 100*markowitzReturn(0,OptimalV),OptimalV);// plot the frontierfor(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(""); } }