L’ottimizzazione di portafoglio con il modello media-varianza di Markowitz in R

Print Friendly

Il modello media-varianza di Markowitz (MV), presentato nel suo celebre articolo del 19521, sebbene abbia ha trovato ampissimo spazio nella ricerca in campo accademico non ha conosciuto una diffusione altrettanto profonda e ampia nel campo pratico visto dalla prospettiva delle imprese di investimento.

Una possibile ragione di tale scarsa diffusione nella pratica degli investimenti è una differenza sostanziale nella prospettiva di riferimento a cui è abituato chi si occupa professionalmente — e non solo — di investimenti rispetto al rigore matematico/statistico richiesto dall’approccio previsto dal modello MV.

Nonostante una scarsa applicazione del modello MV nella pratica — almeno iniziale — al riscontro che ha avuto nella ricerca in campo accademico ha iniziato successivamente a trovare sempre più spazio, seppur relativamente modesto ancora, con l’affermarsi e il diffodersi dei computer. La sua applicazione ora è un irrinunciabile punto di riferimento almeno per qualunque applicazione pratica di corsi universitari, e non solo, che utilizzano applicativi come R con cui sono stati realizzati i calcoli di questo lavoro2.

Il presupposto di un modello di ottimizzazione — come quello trattato qui — è di realizzare un portafoglio di investimento diversificando tra attività finanziarie con l’obiettivo di massimizzare il rendimento atteso tenendo conto dell’esposizione al rischio che è necessario sopportare per poterlo conseguire.

Esistono diversi approcci alla gestione di portafoglio in relazione alle scelte di diversificazione operate dagli addetti ai lavori e tra questi i più diffusi metodi operativi applicati sono di natura empirica (o euristica). La ragione della maggiore applicazione di metodi alternativi risiede nel fatto che il modus operandi di una impresa di investimento che si avvale di gestori e analisti non può presuppore il rigore necessario da un modello di natura quantitativa come quello MV.

Troppo spesso l’analisi di questo modello viene colpevolmente sviluppata ignorando il fatto che i parametri di input siano stimatori di parametri ignoti. (Ugo Pomante)

Soprattutto il modello di ottimizzazione MV presuppone la stima di parametri — rendimenti attesi, volatilità e correlazioni — non conosciuti ex-ante troppo spesso l’analisi di questo modello viene colpevolmente sviluppata ignorando il fatto che i parametri di input siano stimatori di parametri ignoti3: le verifiche out-of-sample effettuate tramite dei backtest su insiemi di dati diversi da quelli utilizzati per l’ottimizzazione, chiaramente, mostrano che il modello MV soffre di problemi che non possono essere risolti solamente tramite un approccio metodico e sofisticato.

I dati di input

I dati di input utilizzati in questa applicazione sono le serie storiche mensili (fonte Yahoo!) dal 1 gennaio 2007 al 1 maggio 20174 dei seguenti ETF:

tickers <- c("SPY", "IEF", "XLF", "IWM", "VWO", "GLD")
  1. SPY, SPDR S&P 500 ETF;
  2. IEF, iShares 7-10 Year Treasury Bond ETF;
  3. XLF, Financial Select Sector SPDR Fund;
  4. IWM, iShares Russell 2000 ETF;
  5. VWO, Vanguard FTSE Emerging Markets ETF;
  6. GLD, SPDRÂ Gold Shares.
library(fPortfolio)
library(readr)
ret <-  read_csv("ETFs.csv")
lppAssets <- ts(ret[ , tickers], 
                start = c(2007, 1), 
                end = c(2017, 5), 
                frequency = 12, 
                names = tickers
                )
lppAssets <- as.timeSeries(lppAssets)
lppData <- portfolioData(data = lppAssets)

Alcune statistiche di sintesi riguardanti i sei ETF: i rendimenti medi e le volatilità mensili (in percentuale) e la matrice varianza-covarianza (alcuni dati sono riportati in notazione scientifica).

library(knitr)
library(tibble)
mv <- tibble(Asset = lppData@data$names, 
             R = lppData@statistics$mean * 100,
             S = sqrt(diag(lppData@statistics$Cov)) * 100)
# mv
kable(mv, 
      caption = "I rendimenti medi (R) e le volatilità mensili (S) in percentuale", 
      format.args = list(decimal.mark =",", digits = 2))
I rendimenti medi (R) e le volatilità mensili (S) in percentuale
Asset R S
SPY 0,49 4,3
IEF 0,24 1,9
XLF 0,14 8,4
IWM 0,59 5,6
VWO 0,26 6,8
GLD 0,66 5,5

La stima della matrice varianza-covarianza (MCV) è uno dei passaggi fondamentali per l’applicazione del modello MV che normalmente fa affidamento alle serie storiche dei rendimenti periodali — di seguito la matrice MCV.

kable(data.frame(round(lppData@statistics$Cov, digits = 5)),
      row.names = TRUE, 
      caption = "La matrice varianza/covarianza", 
      format.args = list(decimal.mark =",", 
                         digits = 4, nsmall = 4, 
                         scientific=FALSE
                         )
      )
La matrice varianza/covarianza
SPY IEF XLF IWM VWO GLD
SPY 0,00188 -0,00025 0,00257 0,00220 0,00233 0,00011
IEF -0,00025 0,00036 -0,00040 -0,00040 -0,00027 0,00036
XLF 0,00257 -0,00040 0,00712 0,00309 0,00318 -0,00020
IWM 0,00220 -0,00040 0,00309 0,00314 0,00274 0,00006
VWO 0,00233 -0,00027 0,00318 0,00274 0,00457 0,00103
GLD 0,00011 0,00036 -0,00020 0,00006 0,00103 0,00302

La matrice di correlazione può essere rappresenta graficamente tramite una heatmap (v. figura di seguito). Le aree rosse rappresentano coppie di ETF significativamente correlati tra di loro, mentre le aree verde chiaro rappresentano le coppie meno (o anche negativamente) correlate.

assetsCorImagePlot(lppAssets)

La matrice di correlazione

La matrice di correlazione

L’ottimizzazione media-varianza a la Markowitz

Nell’ambito del modello MV uno degli output più ricercati è il portafoglio tangente la frontiera efficiente (TP, di seguito e in tabella), ossia il portafoglio con il maggior indice di Sharpe. Questo portafoglio si colloca sulla capital market line (CML), la linea tangente che rappresenta i portafogli efficienti ricavabili dall’abbinamento del portafoglio tangente (detto anche portafoglio di mercato perché è dato dalla composizione di mercato realizzata dalle capitalizzazioni con cui gli investitori detengono il portafoglio collettivamente) e dell’attività priva di rischio.

tg <- tangencyPortfolio(lppData)
kable(as_tibble(tg@portfolio@portfolio$weights * 100), 
      format.args = list(decimal.mark = ",", digits = 3), 
      caption = "I pesi del portafoglio di tangenza (in perc.)", 
      col.names = "Peso")
I pesi del portafoglio di tangenza (in perc.)
Peso
SPY 8,98
IEF 66,72
XLF 0,00
IWM 16,32
VWO 0,00
GLD 7,98

Il portafoglio TP ha un rendimento pari a 0,355 e una volatilità pari a 1,64 espresse in percentuale sempre mensile. È inoltre possibile riportare le composizioni di alcuni dei portafogli derivanti dall’applicazione — sotto vincolo di posizioni lunghe — del modello di ottimizzazione MV nella tabella seguente.

mveSpec = portfolioSpec()
setNFrontierPoints(mveSpec) <- 25
frontier <- portfolioFrontier(data = lppData, 
                              constraints = "LongOnly", 
                              spec = mveSpec)
mvcv <- round(frontier@portfolio@portfolio$weights[c(1,5,10,15,20), ] * 100, digits = 2)
kable(mvcv, format.args = list(decimal.mark=",", digits = 2, nsmall = 2,
                         scientific = FALSE), 
      caption = "Alcuni portafogli generati dal modello MV")
Alcuni portafogli generati dal modello MV
SPY IEF XLF IWM VWO GLD
0,00 0,00 100,00 0,00 0,00 0,00
0,00 83,90 16,10 0,00 0,00 0,00
10,08 71,71 0,00 13,85 0,00 4,36
4,37 45,98 0,00 26,59 0,00 23,06
0,00 19,87 0,00 38,34 0,00 41,79

In figura sono riportati due grafici che contengono dettagli diversi riguardanti la frontiera efficiente.

frontierPlot(frontier, risk = 'Sigma', auto = F)
tangencyLines(frontier, col = 'orange')
monteCarloPoints(frontier, col = 'green', 
                 mcSteps = 250, cex = 1.0)
singleAssetPoints(frontier, col = "blue", 
                  cex = 1.0, pch = 20, 
                  auto = F,lwd = 2)
grid()
tailoredFrontierPlot(frontier, risk = "Sigma")
grid()

La frontiera efficienteLa frontiera efficiente

La frontiera efficiente

La frontiera efficiente assieme ad alcune metriche di rischio alternative VaR e CVaR.

frontierPlot(frontier, risk = 'Sigma', auto = F, xlim=c(-0.05, 0.15))
grid()
frontierPlot(frontier, risk = 'VaR', auto = F, xlim=c(-0.05, 0.15))
grid()
frontierPlot(frontier, risk = 'CVaR', auto = F, xlim=c(-0.05, 0.15))
grid()

La frontiera efficiente con VaR e CVaRLa frontiera efficiente con VaR e CVaRLa frontiera efficiente con VaR e CVaR

La frontiera efficiente con VaR e CVaR

Le composizioni di portafoglio possono essere descritte in termini di contributo al rischio del portafoglio, ricordando che il rischio di un portafoglio è influenzato dalle correlazioni esistenti tra le attività finanziarie (v. figura grafico sulla sinistra) e in termini di pesi percentuali assegnati alle singole asset class (v. figura grafico sulla destra).

covRiskBudgetsPlot(frontier)
weightsPlot(frontier)

Le composizioni di portafoglioLe composizioni di portafoglio

Le composizioni di portafoglio

Il backtest

Un backtest è una simulazione, fatta con in retrospettiva, finalizzata a ricostruire con i dati storici le transazioni di portafoglio che sarebbero state effettuate in base a regole predefinite da una determinata strategia.

La strategia che vogliamo testare è quella del portafoglio tangente (tangency portfolio) individuata applicando il modello MV e per fare questo identifichiamo come benchmark rispetto al quale effettuare un confronto l’indice S&P 500 rappresentato dall’ETF SPY.

form <- SPY ~ SPY + IWM + VWO + GLD + XLF
defaultBacktest <- portfolioBacktest()
constr <- 'LongOnly'
defaultPortfolios <- portfolioBacktesting(data = lppData, 
                                          formula = form, 
                                          backtest = defaultBacktest, 
                                          spec = mveSpec, 
                                          constraints = constr, 
                                          trace = F)

setSmootherInitialWeights(defaultPortfolios$backtest) <- rep(1/5, 5)
setSmootherLambda(defaultPortfolios$backtest) <- "12m"
defSmooth <- portfolioSmoothing(defaultPortfolios)
#> [1] "smooth ..."
#> [1] "aggregate ..."
#> [1] "offset ..."

Rappresentiamo i risultati del backtest nel grafico che segue in figura .

backtestPlot(defSmooth)

Il backtest

Il backtest


  1. Markowitz, Harry, 1952, Portfolio Selection, Journal of Finance, 7.

  2. Con il supporto del pacchetto fPortfolio del Core Team di Rmetrics, Diethelm Wuertz https://www.rmetrics.org.

  3. Pomante, Ugo, 2008, Asset allocation razionale, Bancaria Editrice.

  4. Scaricabili da http://bit.ly/2qrgKl0.

Share Button
Posted in Economics, R-stats
Tags: , ,

Leave a Reply

Your email address will not be published. Required fields are marked *

*

+ 76 = 83

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Tweets