CITE THIS NOTEBOOK: Modern Portfolio Theory by Jonathan Kinlay. Wolfram Community FEB 20 2023.
Extract from the upcoming book “Equity Analytics” by Jonathan Kinlay where complete materials will be available.
In 1952, Harry Markowitz introduced the concept of Modern Portfolio Theory through his doctoral thesis, commonly referred to as the Markowitz model. This theory is based on the idea that investors aim to maximize a portfolio' s expected return while considering a certain level of risk. Efficient portfolios, which meet this criterion, are those where achieving a higher expected return necessitates taking on more risk. As a result, investors must strike a balance between risk and expected return. The relationship between risk and expected return for efficient portfolios is illustrated by the efficient frontier, a graph that displays this trade - off. All efficient portfolios, represented as points on the efficient frontier, are diversified to minimize risk. In this chapter we review some of the core concepts of MTP and illustrate how to approach the portfolio optimization problem in the Wolfram Language.

Portfolio Construction

We begin our exploration of the topic of modern portfolio theory by defining a universe of stocks comprising a random sample of 25 of the constituents of the S&P 500 index as a selected point in time:
In[]:=
startDate=DateObject[{2018,1,3}]
Out[]=
Wed 3 Jan 2018
In[]:=
portfolioStocks=RandomSampleSelectEntity["Equities",#]&/@EntityMemberList
SP500
EQUITIES
,startDate,EntityQ,25//Sort;​​nstocks=Length@portfolioStocks​​portfolioStocks//Short
Out[]=
25
Out[]//Short=

AAP
,
ALGN
,
AMT
,
BBY
,
BMY
,
CME
,
CRM
,
DISCA
,
DVN
,
EMR
,
GE
,
HOG
,
ICE
,
IDXX
,
LKQ
,
LYB
,
MAS
,
PEP
,
REG
,
RHI
,
RJF
,
SIG
,
TAP
,
TPR
,
UA

The RandomWeighting function is used to generate 10,000 different sets of weights that are applied to the stocks in the investment universe to create 10,000 different portfolios. All of the portfolio weights must lie in the range {0, 1}, i.e. we do not allow short sales and the sum of the weights must equal 1.0 (no leverage). We examine the annual return and volatility of these portfolios over the preceding 5 years.
In[]:=
wgts=RandomWeighting[10000,nstocks,1.0];
In[]:=
weights=Table[
ω
i
,{i,nstocks}];
In[]:=
tsPortfolioReturns=PortfolioReturns[portfolioStocks,{2013,1,3},{2017,12,29}];
In[]:=
AbsoluteTiming[portfolioRiskReturn=ParallelTable[PortfolioRiskReturn[tsPortfolioReturns,weights/.weights->wgt],{wgt,wgts},Method->"CoarsestGrained"];]
Out[]=
{101.076,Null}
The result is an array of annual return and volatilities for each of the 10,000 portfolios:
In[]:=
portfolioRiskReturn[[1;;5,1;;2]]
Out[]=
{{0.127391,0.139031},{0.155703,0.138864},{0.130991,0.140689},{0.122654,0.133249},{0.121784,0.134468}}

Minimum Variance Portfolio

We will shortly plot these results on a chart, but first we will use the FindMinimum function to identify the return and volatility of the portfolio having the minimum variance, amongst all the possible variations of allocation weightings.
In[]:=
{portfolioAverageReturns,portfolioVolatility}=Take[PortfolioRiskReturn[tsPortfolioReturns,weights],2];
In[]:=
portfolioConstraints=Total[weights]==1&&And@@(0<=#<=1&/@weights);(*Setconstraintsonweightstothattheumoftheweights=1andallweightslieintherange{0,1}*)
In[]:=
minVarPortfolio={portfolioVolatility,portfolioAverageReturns}/.FindMinimum[{portfolioVolatility,portfolioConstraints},weights][[2]]
Out[]=
{0.104783,0.0998676}
For completeness, we also find the volatility and return of the S&P 500 index over the same period
In[]:=
tsSP500Returns=EntityDailyReturns
SP500
EQUITIES
,{2013,1,3},{2017,12,29};
In[]:=
SP500RiskReturn=PortfolioRiskReturn[tsSP500Returns][[{2,1}]]
Out[]=
{0.118687,0.120999}

The Efficient Frontier

The efficient frontier comprises portfolios which, for a given level of risk, have the highest expected return and, conversely, for a given rate of return have the lowest volatility. We can identify portfolios lying on the frontier using the FindMinimum function to identify the allocation weights for portfolios that have the lowest volatility for a specified rate of return (in the range of 1% to 32%).
In[]:=
effFrontier=ParallelTable[{FindMinimum[{portfolioVolatility,portfolioConstraints&&portfolioAverageReturns==i},weights][[1]],i},{i,0.01,0.32,.02},Method->"CoarsestGrained"]//Quiet;
We will also compute the allocation weights for several portfolios on the frontier:
In[]:=
effFrontierWgts=ParallelTable[FindMinimum[{portfolioVolatility,Total[weights]==1&&portfolioAverageReturns==i&&And@@(0<=#<=1&/@weights)},weights][[2]],{i,0.15,0.30,.05},Method->"CoarsestGrained"]//Quiet;
Finally, we are ready to combine all of the above information in a single plot that shows the efficient frontier, global minimum variance portfolio and other portfolios on the frontier and the collection of portfolios we created using random sets of allocation weights:

Composition of Portfolios on the Efficient Frontier

It is striking that none of the randomly generated portfolios lie close to the efficient frontier. That’s because the frontier portfolios typically have allocation weights that are “extreme”, with very large weights for some stocks and very small allocations to others. For example:
In[]:=
portfolio1=AssociationThread[portfolioStocks->Values@effFrontierWgts[[1]]]
Out[]=

AAP
0.00215412,
ALGN
0.0279105,
AMT
0.0707088,
BBY
0.0205041,
BMY
0.0375922,
CME
0.175761,
CRM
7.38827×
-6
10
,
DISCA
8.84198×
-6
10
,
DVN
6.58751×
-6
10
,
EMR
0.0102983,
GE
0.0000425169,
HOG
0.0000209618,
ICE
0.026013,
IDXX
0.0633854,
LKQ
0.0000269247,
LYB
0.00567528,
MAS
7.66668×
-6
10
,
PEP
0.405446,
REG
0.0580264,
RHI
3.98111×
-6
10
,
RJF
7.00697×
-6
10
,
SIG
0.00325516,
TAP
0.0131276,
TPR
0.00288251,
UA
0.077128
In[]:=
PieChart3D[portfolio1,ChartLegends->Placed[Automatic,Right],SectorOrigin->{Automatic,1}]
Out[]=
AAP
ALGN
AMT
BBY
BMY
CME
CRM
DISCA
DVN
EMR
GE
HOG
ICE
IDXX
LKQ
LYB
MAS
PEP
REG
RHI
RJF
SIG
TAP
TPR
UA

Performance of Portfolios on the Efficient Frontier

Because the allocation weights have been optimized so that efficient portfolios provide the maximum expected returns for a given level of risk, the equity curve of compounded returns is relatively smooth and monotonic and the portfolios easily outperform the S&P500 index over the formation period from 2013-2017:
In[]:=
tsPortReturns=PortfolioReturns[tsPortfolioReturns,Values@effFrontierWgts]
Out[]=
TimeSeries
Time:
03 Jan 2013GMT-5
to
29 Dec 2017GMT-5
Data points: 1258

In[]:=
DateListPlot[{CompoundReturn[tsPortReturns],CompoundReturn[tsSP500Returns]},Filling->Axis,PlotLabels->Join[Table[StringJoin["Portfolio ",ToString[i]],{i,4}],{" SP500"}],ImageSize->Large,PlotRange->All]
Out[]=
When we evaluate portfolio performance after the formation period, however, the story is very different. Although efficient portfolios outperform the S&P500 over the period from 2018-2022, there are times when they under-perform the index and the equity curve suffers from several large periodic declines lasting for several days, or weeks. This is the result of the extreme allocation profile of the portfolios, which entails making several large bets on stocks such as PEP and CME, which performed well during the formation period, but did much less well in the subsequent period from 2018. This variability in performance is a typical characteristic of portfolios constructed by mean-variance optimization.
​
For this reason equity portfolio managers will typically impose additional constraints on the allocation weights, to avoid over- or under-weighting specific stocks or industry sectors, with the aim of constructing portfolios that perform more robustly out of sample.
In[]:=
tsSP500Returns=EntityDailyReturns
SP500
EQUITIES
,{2018,1,3},{2022,12,30}
Out[]=
TimeSeries
Time:
03 Jan 2018GMT-5
to
30 Dec 2022GMT-5
Data points: 1258

In[]:=
tsPortfolioReturns=PortfolioReturns[portfolioStocks,{2018,1,3},{2022,12,30}];
In[]:=
tsPortReturns=PortfolioReturns[tsPortfolioReturns,Values@effFrontierWgts]
Out[]=
TimeSeries
Time:
03 Jan 2018GMT-5
to
30 Dec 2022GMT-5
Data points: 1258


Dynamics of the Efficient Frontier

One of the major challenges in portfolio construction is that the temporal variability in asset returns and covariances induces substantial change in the shape of the efficient frontier. This means that the composition of a portfolio with a specific risk-return profile is liable to alter significantly over time. Furthermore, the volatility of an optimal portfolio with a specific rate of expected returns will likewise be subject to substantial variation. To illustrate this effect, we estimate the efficient frontier for our universe of 25 stocks for six years, using daily returns data for the prior five years in each case.
​
Depending on the year in question, we observe that an optimal portfolio with an expected return of, say, 12% per year, might have an estimated annual volatility of as low as 7% (in 2015) to as high as 12% (in 2019).

Notes

◼
  • More on Modern Portfolio Theory