8 Portfolioptimierung

Wir betrachten im Folgenden, wie mittels R die quadratische (Mean-Variance) und die lineare (Mean-Expected-Shortfall) Optimierung durchgeführt werden kann. In beiden Fällen wird ein entsprechender Algorithmus zur Lösung derartiger Probleme verwendet. Wichitg ist es bei der Implementierung darauf zu achten, wie das Optimierungsproblem übergeben werden muss, so dass es vom Algorithmus gelöst werden kann. Für beide Fälle beziehen wir als Beispiel Daten das Dax. In der Realität ist es jedoch nicht sinnvoll lediglich in einem Markt zu investieren, da auf internationaler und vor allem interkontinentaler Ebene hohes Diversifikationspotential besteht.

##          date 1COV.DE ADS.DE ALV.DE BAS.DE BAYN.DE BEI.DE BMW.DE CON.DE DAI.DE
## 1: 2010-02-01      NA 37.065  80.49 41.730 48.8210 42.275 31.065 41.320 33.570
## 2: 2010-02-02      NA 36.975  81.19 42.000 49.2048 41.965 31.175 41.280 33.765
## 3: 2010-02-03      NA 36.280  80.41 42.130 48.4126 42.220 31.225 41.100 34.340
## 4: 2010-02-04      NA 35.560  79.29 40.255 47.5810 41.795 30.335 39.030 33.100
## 5: 2010-02-05      NA 35.175  77.61 39.430 46.0753 41.275 29.920 37.765 32.320
## 6: 2010-02-08      NA 35.005  78.11 40.020 46.7986 41.910 29.610 36.400 33.310
##    DB1.DE  DBK.DE DPW.DE DTE.DE EOAN.DE FME.DE  FRE.DE HEI.DE HEN3.DE IFX.DE
## 1: 47.965 35.4626 12.810  9.410 24.3161 36.685 14.7067 43.375   36.26  4.208
## 2: 48.950 36.2355 13.145  9.440 24.5744 37.130 14.6700 44.530   36.12  4.343
## 3: 47.240 35.5869 12.925  9.342 24.2844 36.990 14.6767 44.170   35.83  4.220
## 4: 47.095 34.0839 12.415  9.240 23.7905 36.225 14.5717 42.600   35.21  4.110
## 5: 45.860 33.5440 12.140  9.211 23.2014 36.115 14.3833 41.420   35.29  3.959
## 6: 46.105 33.4780 12.210  9.372 23.5186 36.380 14.7050 41.935   35.81  3.958
##    LHA.DE LIN.DE MRK.DE MUV2.DE  RWE.DE SAP.DE  SIE.DE TKA.DE VNA.DE VOW3.DE
## 1: 11.770  80.18 32.065  109.35 64.7643 33.585 63.0354 23.365     NA 60.2575
## 2: 11.980  80.65 32.160  108.75 65.5318 33.795 64.0529 23.785     NA 60.6750
## 3: 11.745  80.89 32.060  107.95 64.5750 34.050 63.4424 23.550     NA 61.1323
## 4: 11.330  79.56 31.755  106.90 63.2195 33.795 61.0973 22.350     NA 60.2377
## 5: 11.045  79.26 31.275  106.25 62.4421 33.385 59.7601 22.035     NA 58.8858
## 6: 11.080  79.74 31.570  107.55 63.3690 32.560 60.6225 22.280     NA 58.2993
##    WDI.DE
## 1:  9.208
## 2:  9.570
## 3:  9.173
## 4:  9.048
## 5:  8.820
## 6:  8.756
##          date ADS.DE ALV.DE BAS.DE BAYN.DE BEI.DE BMW.DE CON.DE DAI.DE DB1.DE
## 1: 2010-02-01 37.065  80.49 41.730 48.8210 42.275 31.065 41.320 33.570 47.965
## 2: 2010-02-02 36.975  81.19 42.000 49.2048 41.965 31.175 41.280 33.765 48.950
## 3: 2010-02-03 36.280  80.41 42.130 48.4126 42.220 31.225 41.100 34.340 47.240
## 4: 2010-02-04 35.560  79.29 40.255 47.5810 41.795 30.335 39.030 33.100 47.095
## 5: 2010-02-05 35.175  77.61 39.430 46.0753 41.275 29.920 37.765 32.320 45.860
## 6: 2010-02-08 35.005  78.11 40.020 46.7986 41.910 29.610 36.400 33.310 46.105
##     DBK.DE DPW.DE DTE.DE EOAN.DE FME.DE  FRE.DE HEI.DE HEN3.DE IFX.DE LHA.DE
## 1: 35.4626 12.810  9.410 24.3161 36.685 14.7067 43.375   36.26  4.208 11.770
## 2: 36.2355 13.145  9.440 24.5744 37.130 14.6700 44.530   36.12  4.343 11.980
## 3: 35.5869 12.925  9.342 24.2844 36.990 14.6767 44.170   35.83  4.220 11.745
## 4: 34.0839 12.415  9.240 23.7905 36.225 14.5717 42.600   35.21  4.110 11.330
## 5: 33.5440 12.140  9.211 23.2014 36.115 14.3833 41.420   35.29  3.959 11.045
## 6: 33.4780 12.210  9.372 23.5186 36.380 14.7050 41.935   35.81  3.958 11.080
##    LIN.DE MRK.DE MUV2.DE  RWE.DE SAP.DE  SIE.DE TKA.DE VOW3.DE WDI.DE
## 1:  80.18 32.065  109.35 64.7643 33.585 63.0354 23.365 60.2575  9.208
## 2:  80.65 32.160  108.75 65.5318 33.795 64.0529 23.785 60.6750  9.570
## 3:  80.89 32.060  107.95 64.5750 34.050 63.4424 23.550 61.1323  9.173
## 4:  79.56 31.755  106.90 63.2195 33.795 61.0973 22.350 60.2377  9.048
## 5:  79.26 31.275  106.25 62.4421 33.385 59.7601 22.035 58.8858  8.820
## 6:  79.74 31.570  107.55 63.3690 32.560 60.6225 22.280 58.2993  8.756

8.1 Quadratische Optimierung

Als Inputdaten bei der Optimierung schätzen wir die Erwartungswerte der Renditen und die Kovarianzmatrix über ihre empirichen Schätzer.

Die Optimierung wird mittels der solve.QP Funktion durchgeführt. In dieser wird neben der Kovarianzmatrix als Zielfunktion eine Matrix und ein Vektor mit Nebenbedingungen angegeben, wobei der meq-Parameter der Funktion angibt, wie viele der ersten Nebenbedingungen Gleicheitsbedingungen sind. Bei den übrigen Nebenbedingungen geht die Funktion von Ungleichungen mit \(\geq\) Relation aus. Möchten wir beispielsweise lediglich volle Investition und einen Mindesrendite als Nebenbedingung, so lautet die Matrix und der Vektor.

## $solution
##  [1] -0.005890768 -0.159815940 -0.040064640 -0.055556610  0.255169959
##  [6]  0.017720191 -0.043403970 -0.012618238  0.079585543  0.025115598
## [11]  0.055758064  0.103222661  0.056010272  0.139912387  0.014012396
## [16] -0.030463805  0.075166343 -0.076075730  0.037107148  0.170960541
## [21]  0.050711494  0.185741384 -0.006829584  0.106026785  0.082627930
## [26]  0.001540095 -0.001842687 -0.023826818
## 
## $value
## [1] 0.7431854
## 
## $unconstrained.solution
##  [1] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## 
## $iterations
## [1] 3 0
## 
## $Lagrangian
## [1] 1.576049 3.587134
## 
## $iact
## [1] 1 2

Um effiziente Portfolioallokationen für verschiedene Niveaus der Rendite zu bestimmen, führen wir die Optimierung in einer Schleife durch. Zuletzt bestimmen wir die Sharpe-Ratio, wobei wir vereinfachend aufgrund des aktuellen Zinsniveaus \(r_f = 0.00\) verwenden.

##  [1]  0.143295028  0.134141422 -0.101835182 -0.101658612  0.171340274
##  [6]  0.096540545 -0.024689837 -0.170414097  0.115931222 -0.180007548
## [11]  0.111507991  0.050530340 -0.125584095  0.015797299  0.084986219
## [16] -0.059302066  0.053796890  0.014666841 -0.001367922  0.141248452
## [21]  0.155447312  0.260361471 -0.027854546  0.146839003  0.068272252
## [26] -0.095174359  0.059255632  0.063930072

8.2 Lineare Optimierung

Ganz analog kann die lineare Optimierung durch die Rglpk_solve_LP Funktion durchgeführt werden. Man sollte hierzu im Kopf haben, dass zwar nur über \(\boldsymbol{\omega}, \psi\) optimiert wird, jedoch auch für \(z_j, ~j = 1, ..., J\) Werte bei der Optimierung mit bestimmt werden. Daher gilt es diese beim Festlegen der Ziel- und Nebenfunktionen mit zu berücksichtigen. Eine detaillierte Erläuterung zur Verwendung der Funktion erfolgt in einem Lehrvideo.

n_assets <- ncol(stocks)
n_sample <- nrow(stocks)
conf_level <- 0.95

#objective function (asset weights, ..., z_1, z_2, ..., z_n, psi)
obj <- c(rep(0, n_assets), rep(1 / ((1 - conf_level) * n_sample), n_sample), 1)

#full investment                                                  #simple_triplet_format to save memory space
M1 <- cbind(matrix(rep(1, n_assets), nrow = 1, ncol = n_assets) , simple_triplet_zero_matrix(nrow = 1, ncol = n_sample + 1))

# -f(w_j, x_j) + alpha + z_j >= 0
M2 <- cbind(stocks, simple_triplet_diag_matrix(1, n_sample), matrix(1, nrow = n_sample) )

#z_j >= 0
M3 <- cbind(simple_triplet_zero_matrix(ncol = n_assets, nrow = n_sample), simple_triplet_diag_matrix(1, n_sample), matrix(0, nrow = n_sample))

#desired portfolio return
M4 <- cbind(matrix(apply(stocks, 2, mean), nrow = 1, ncol = n_assets),  simple_triplet_zero_matrix(nrow = 1, ncol = n_sample + 1))

#min weights
M5 <- cbind(simple_triplet_diag_matrix(1, nrow = n_assets), simple_triplet_zero_matrix(nrow = n_assets, ncol = n_sample + 1))

#max weights
M6 <- cbind(simple_triplet_diag_matrix(-1, nrow = n_assets), simple_triplet_zero_matrix(nrow = n_assets, ncol = n_sample + 1))

#constraints matrix
Amat <- rbind(M1, M2, M3, M4, M5, M6)

#directions of constraints
dirVec <- c("==", rep(">=", 2*n_sample), "==", rep(">=", n_assets), rep(">=", n_assets))

#bounds for optimization parameters
bounds <- list(lower = list(ind = c(1:n_assets,(n_assets+1):(n_assets+n_sample)), val = c(rep(0,n_assets),rep(-10,n_sample))),
               upper = list(ind = c(1:n_assets,(n_assets+1):(n_assets+n_sample)), val = c(rep(1,n_assets),rep(10,n_sample))))

#record weights, CVaR and corresponding standard deviation
weights_cvar <- matrix(ncol = n_assets)
CVaR <- c()
sd_CVaRpf <- c()

#desired expected portfolio return
mu_pf <- seq(0, 0.10, length.out = 50)

#minimum weights
min_weight <- -1

#maximum weights    #max weight constraint is introduced as -w_j >= -max_weight <==> max_weight >= w_j
max_weight <-  1

for(i in 1:length(mu_pf)){

  #constraints vector
  b_vec <- c(1, rep(0, 2 * n_sample), mu_pf[i], rep(min_weight, n_assets), rep(-max_weight, n_assets))

  #linear optimization routine
  results <- try(Rglpk_solve_LP(obj = obj, mat = Amat, dir = dirVec, rhs = b_vec, bounds = bounds, max = FALSE))

  #some solutions may not be attainable under constraints
  #if this is the case save NA
  if(class(results) == 'try-error'){
    CVaR[i] <- NA
    sd_CVaRpf[i] <- NA
    weights_cvar <- rbind(weights_cvar, rep(NA, n_assets))
  }else{

    #results
    r_opt <- as.vector(stocks %*% matrix(results$solution[1:n_assets], nrow = n_assets))
    #VaR <- tail(results$solution, 1)
    CVaR[i] <- results$optimum
    sd_CVaRpf[i] <- sd(r_opt)
    weights_cvar <- rbind(weights_cvar, results$solution[1:n_assets])

  }

  #print(i)

}


p <- plot_ly()%>%
  add_markers(x = CVaR, y = mu_pf, name = 'efficient frontier', marker = list(color = 'grey'))%>%
  layout(xaxis = list(title = 'expected shortfall', range = c(0, max(CVaR))),
         yaxis = list(title = 'mean'))

r_f <- 0
sharpe_CVaR <- (mu_pf - r_f) / CVaR
ind <- match(max(sharpe_CVaR, na.rm = TRUE), sharpe_CVaR)
weights_cvar[ind,]
##  [1] 0.48124322 0.00000000 0.00000000 0.00000000 0.00000000 0.00000000
##  [7] 0.00000000 0.00000000 0.00000000 0.00000000 0.00000000 0.00000000
## [13] 0.00000000 0.00000000 0.10100899 0.00000000 0.00000000 0.00000000
## [19] 0.00000000 0.05579814 0.07679953 0.00000000 0.00000000 0.09984039
## [25] 0.00000000 0.00000000 0.00000000 0.18530972