3 Random Walk

Zunächst wollen wir uns mit dem einfachsten Modell für Log-Returns von Aktienkursen beschäftigen - dem Random Walk.

3.1 Daten beziehen

Im ersten Schritt laden wir uns Zeitreihen von Aktienkursen herunter. Hierbei verwenden wir das Paket tidyverse, mit dem wir unter anderem Daten über yahoo-Finance beziehen können. Hierfür müssen wir die Ticker der Unternehmen von Interesse von yahoo finance vorab herausfinden. Damit ist es sehr leicht Daten zu beziehen.

Dec 222019Jan 52020Jan 19Feb 2Feb 16270280290300310320330
Basic OHLC Chartdate
Dec 222019Jan 52020Jan 19Feb 2Feb 16270280290300310320330
Basic Candlestick Chartdate

Wir wollen uns jedoch nun auf die Kurse zum Ende jedes Handelstages beschränken und für die zugehörigen Log-Returns ein Modell schätzen. Beispielsweise für die Apple-Aktie über den Verlauf der letzten 10 Jahre.

201520205010015020025030020152020−0.1−0.0500.05
Kurs (Close)Log-ReturnApple Aktiedateclose

3.2 Modell schätzen

Im folgenden schätzen wir für die Log-Returns der Apple-Aktie. Hierbei verwenden wir wieder die ‘fun_fun’-Funktion. Beispielsweise können wir eine Normalverteilung folgendermaßen schätzen,

#Funktion, welche die angegebene Verteilung schätzt, ll, aic, hmi, pp- und qq-plot ausgibt
library(rugarch)

fun_fun <- function(x, distr = 'norm'){

  distr_set <- c('norm', 'snorm', 'std', 'sstd', 'ged', 'sged')
  
  if(!(any(distr == distr_set))){
    stop(paste('Bitte verwenden Sie eine dieser Verteilungen: norm, snorm, std, sstd, ged, sged'))
  }
  
  
  fit <- fitdist(distribution = distr, x)
  
  
  if(distr == 'norm'){
    
    ll <- sum(log(ddist(distribution = distr, x, mu = fit$pars[1], sigma = fit$pars[2])))
    aic <- -2*ll + 2 * length(fit$pars)
    hmi <- 2 * integrate(function(p1, m, s, data){abs(p1 - pdist(distribution = distr, quantile(data, p1), mu = m, sigma = s))},
                         lower = 0, upper = 1, m = fit$pars[1], s = fit$pars[2], data = x, subdivisions = 1000)$value
    
    p_theor <- pdist(distribution = distr, sort(x), mu = fit$pars[1], sigma = fit$pars[2])
    p_emp <- rank(sort(x))/length(x)
    
    pp_plot <- plot_ly() %>%
      add_markers(x = p_theor, y = p_emp, name = 'pp-plot', marker = list(color = 'grey', symbol = 'x')) %>%
      add_lines(x = c(0, 1), y = c(0, 1), line = list(color = 'black'), showlegend = FALSE) %>%
      layout(
        xaxis = list(title = 'Theoretische Verteilung'),
        yaxis = list(title = 'Empirische Verteilung')
      )
    
    q_theor <- qdist(distribution = distr, rank(sort(x))/(length(x) + 1), mu = fit$pars[1], sigma = fit$pars[2])
    q_emp <- quantile(x, rank(sort(x))/(length(x) + 1))
  
    qq_plot <- plot_ly() %>%
      add_markers(x = q_theor, y = q_emp, name = 'qq-plot', marker = list(color = 'skyblue', symbol = 'x')) %>%
      add_lines(x = c(min(x), max(x)), y = c(min(x), max(x)), line = list(color = 'black'), showlegend = FALSE) %>%
      layout(
        xaxis = list(title = 'Theoretische Verteilung'),
        yaxis = list(title = 'Empirische Verteilung')
      )
    
    p <- subplot(pp_plot, qq_plot, margin = 0.05, titleX = TRUE, titleY = TRUE, which_layout = 1)
    
    list_out <- list(ll = ll, aic = aic, hmi = hmi, p = p, params = fit$pars)
    
  }
  
  if(any(distr == c('std', 'ged'))){
    
    ll <- sum(log(ddist(distribution = distr, x, mu = fit$pars[1], sigma = fit$pars[2], shape = fit$pars[3])))
    aic <- -2*ll + 2 * length(fit$pars)
    hmi <- 2 * integrate(function(p1, m, s, nu, data){abs(p1 - pdist(distribution = distr, quantile(data, p1), mu = m, sigma = s, shape = nu))},
                         lower = 0, upper = 1, m = fit$pars[1], s = fit$pars[2], nu = fit$pars[3], data = x, subdivisions = 1000)$value
    
    p_theor <- pdist(distribution = distr, sort(x), mu = fit$pars[1], sigma = fit$pars[2], shape = fit$pars[3])
    p_emp <- rank(sort(x))/length(x)
    
    pp_plot <- plot_ly() %>%
      add_markers(x = p_theor, y = p_emp, name = 'pp-plot', marker = list(color = 'grey', symbol = 'x')) %>%
      add_lines(x = c(0, 1), y = c(0, 1), line = list(color = 'black'), showlegend = FALSE) %>%
      layout(
        xaxis = list(title = 'Theoretische Verteilung'),
        yaxis = list(title = 'Empirische Verteilung')
      )
    
    q_theor <- qdist(distribution = distr, rank(sort(x))/(length(x) + 1), mu = fit$pars[1], sigma = fit$pars[2], shape = fit$pars[3])
    q_emp <- quantile(x, rank(sort(x))/(length(x) + 1))
    
    qq_plot <- plot_ly() %>%
      add_markers(x = q_theor, y = q_emp, name = 'qq-plot', marker = list(color = 'skyblue', symbol = 'x')) %>%
      add_lines(x = c(min(x), max(x)), y = c(min(x), max(x)), line = list(color = 'black'), showlegend = FALSE) %>%
      layout(
        xaxis = list(title = 'Theoretische Verteilung'),
        yaxis = list(title = 'Empirische Verteilung')
      )
    
    p <- subplot(pp_plot, qq_plot, margin = 0.05, titleX = TRUE, titleY = TRUE, which_layout = 1)
    
    list_out <- list(ll = ll, aic = aic, hmi = hmi, p = p, params = fit$pars)
    
  }
  
  if(any(distr == c('snorm', 'sstd', 'sged'))){
    
    ll <- sum(log(ddist(distribution = distr, x, mu = fit$pars[1], sigma = fit$pars[2], skew = fit$pars[3], shape = fit$pars[4])))
    aic <- -2*ll + 2 * length(fit$pars)
    hmi <- 2 * integrate(function(p1, m, s, skew, nu, data){abs(p1 - pdist(distribution = distr, quantile(data, p1), mu = m, sigma = s, skew = skew, shape = nu))},
                         lower = 0, upper = 1, m = fit$pars[1], s = fit$pars[2], skew = fit$pars[3], nu = fit$pars[4], data = x, subdivisions = 1000)$value
    
    p_theor <- pdist(distribution = distr, sort(x), mu = fit$pars[1], sigma = fit$pars[2], skew = fit$pars[3], shape = fit$pars[4])
    p_emp <- rank(sort(x))/length(x)
    
    pp_plot <- plot_ly() %>%
      add_markers(x = p_theor, y = p_emp, name = 'pp-plot', marker = list(color = 'grey', symbol = 'x')) %>%
      add_lines(x = c(0, 1), y = c(0, 1), line = list(color = 'black'), showlegend = FALSE) %>%
      layout(
        xaxis = list(title = 'Theoretische Verteilung'),
        yaxis = list(title = 'Empirische Verteilung')
      )
    
    q_theor <- qdist(distribution = distr, rank(sort(x))/(length(x) + 1), mu = fit$pars[1], sigma = fit$pars[2], skew = fit$pars[3], shape = fit$pars[4])
    q_emp <- quantile(x, rank(sort(x))/(length(x) + 1))
    
    qq_plot <- plot_ly() %>%
      add_markers(x = q_theor, y = q_emp, name = 'qq-plot', marker = list(color = 'skyblue', symbol = 'x')) %>%
      add_lines(x = c(min(x), max(x)), y = c(min(x), max(x)), line = list(color = 'black'), showlegend = FALSE) %>%
      layout(
        xaxis = list(title = 'Theoretische Verteilung'),
        yaxis = list(title = 'Empirische Verteilung')
      )
    
    p <- subplot(pp_plot, qq_plot, margin = 0.05, titleX = TRUE, titleY = TRUE, which_layout = 1)
    
    list_out <- list(ll = ll, aic = aic, hmi = hmi, p = p, params = fit$pars)
    
  }
  
return(list_out)
  
}
## $ll
## [1] 6882.14
## 
## $aic
## [1] -13760.28
## 
## $hmi
## [1] 0.06486762
## 
## $p
## 
## $params
##           mu        sigma 
## 0.0008568798 0.0163519700
00.5100.20.40.60.81−0.1−0.0500.05−0.1−0.0500.05
pp-plotqq-plotTheoretische VerteilungTheoretische VerteilungEmpirische VerteilungEmpirische Verteilung

Wir wollen jedoch eine Bandbreite verschiedenener Funktionen schätzen und anschließend die Güte der Anpassung visuell und mittels Kennzahlen überprüfen.

Table 3.1: Übersicht des Datenfits
AIC HMI
Normal -13760.28 0.0648676
Normal (schief) -13766.37 0.0646243
Student -14116.23 0.0103100
Student (schief) -14115.38 0.0106401
GED -14091.40 0.0156534
GED (schief) -14089.57 0.0162033

Gemäß dem AIC und dem HMI scheint die (symmetrische) Student t Verteilung am besten geeignet, um die Log-Returns der Apple Aktie zu modellieren. Wir können uns die Güte dieser Schätzung erneut auch visuell ansehen.

00.5100.20.40.60.81−0.100.1−0.1−0.0500.05
pp-plotqq-plotTheoretische VerteilungTheoretische VerteilungEmpirische VerteilungEmpirische Verteilung

Mit diesem Modell könnten wir z.B. bestimmen, wie hoch die Wahrscheinlichkeit ist, dass die Log-Rendite bis morgen größer als 2% ist.

## [1] 0.09073137

Oder welcher Wert innerhalb eines Tages maximal mit einer Wahrscheinlichkeit von 5% unterschritten wird.

## [1] -0.02386804

Und wir können uns zukünfige Aktienkursverläufe simulieren, gehen wir hierbei vom letzten verfügbaren Kurs aus.

102030405060200250300350400450500550
Simulation des Aktienkursverlaufs von AppleAnzahl der PrognosetageKursverlauf

Immerhin liegt der tatsächliche Verlauf innerhalb der simulierten Verläufe!

24026028030032000.010.020.030.040.05
Tag 3Tag 8Verteilung des Aktienkurses

Mit höherem Zeithorizont wird die Prognose volatiler, was sich in einer breiteren Vereteilung der prognostizierten Werte äußert!