#---------------------------------------# # # # week11: Typische Eigenschaften # # von Finanzzeitreihen # # # #---------------------------------------# Die Returns von liquide handelbaren Assets wie Aktien, Aktienindizes, Waehrungswechselkursen oder Rohstoffen wie Oel, Gold oder Silber haben einige typische, ge- meinsame Eigenschaften. Ist S_k der Preis eines Assets am Ende von Tag t_k, so ist der return ret(t_k) fuer den Tag t_k definiert durch ret(t_k) := (S_k - S_{k-1}) / S_{k-1} (1) Der d-Tages Mittelwert zum Tag t_k ist definiert durch mean_d(t_k) := 1/d sum_{j=0}^{d-1} ret(t_{k-j}) (2) Stylized Fact 1) Fuer beliebige Zeithorizonte d (groe- sser als 2 oder 3 Wochen) sind die d-Tages Mittelwerte nahe bei Null. Wegen Stylized Fact1 kann man die d-Tages Standard- abweichung (auch d-Tages Volatilitaet genannt) am Tag t_k definieren durch stddev_d(t_k) := sqrt{ 1/d sum_{j=0}^{d-1} ret(t_{k-j})^2 } (3) Die normierten returns (fuer den Zeithorizont d Tage) sind dann definiert durch normret_d(t_k) := ret(t_k) / stddev_d(t_{k-1}) (4) Man schaut sich dann ein Histogramm, also die Verteilung, der normierten returns an und vergleicht sie mit der Nor- malverteilung. Man stellt fest: Stylized Fact 2a) Waehlt man d sehr gross (etwa d>=250, das entspricht einem Jahr), dann ist die Verteilung der normierten returns "leptokurtisch", das heisst, sie hat einen hoeheren peak bei 0 und faellt dafuer steiler ab als die Normalverteilung. Weiterhin hat man `heavy tails': es treten einige sehr grosse (positive und negative) normierte returns auf, die man bei der Annahme einer Normalverteilung nicht sehen wuerde. Stylized Fact 2b) Macht man das d langsam kleiner und setzt es schliesslich auf d=15 oder d=20 (3 oder 4 Wochen), naehert sich die Verteilung der normierten returns mehr und mehr einer Normalverteilung an. Das Aufteten von 'heavy tails' nimmt ab. Dafuer nimmt die Variabilitaet der d-Tages Volatilitaet stddev_d(t_{k-1}) mehr und mehr zu. Diese Beobachtung ist die Grundmotivation fuer Modelle mit stochastischer Volatilitaet. Weiterhin stellt man noch folgendes fest: Stylized Fact 3) returns an unterschiedlichen Tagen t_k und t_{k-1}, t_{k-2},... sind annaehernd unkorreliert, jedoch haben der Absolutbetrag oder das Quadrat von sol- chen returns eine deutlich positive Korrelation (etwa 10%-20%). Stylized Fact 4) "volatility clustering": returns tendie- ren dazu, cluster zu bilden: grosse und kleine returns sind nicht gleichmaessig ueber die Zeit verteilt, sondern grosse returns finden sich zu Gruppen mit grossen returns zusammen und analoges gilt fuer kleine returns. Das ist ebenfalls Motivation fuer Modelle mit stochastischer Volatilitaet. Schauen wir uns das jetzt an konkreten Zeitreihendaten an: das file SPX.txt enthaelt die Schlusskurse des S&P500, die 500 groessten amerikanischen Unternehmen, von 1950 bis 2015, das sind etwa 16500 Beobachtungstage. # # Start R Session: # # Daten nach R einlesen: spx = read.table("C:/Users/detlef/OneDrive/hochschule/Vorlesungen/SS2025/Wirtschaftsmathematik3/SPX.txt",header=TRUE,sep=";") spx # ACHTUNG: die Schraegstriche muessen / sein, nicht \ # wenn man den Pfadnamen aus Windows kopiert, bekommt man die falschen Schraegstriche # sehr komfortabel ist auch die folgende Sache: spx = read.table(file.choose(),header=TRUE,sep=";") # ..und dann das file auswaehlen # just for info: head(spx) tail(spx) summary(spx) str(spx) # ist vom Typ 'dataframe' # in R gibt es im Wesentlichen 4 verschiedene Datentypen, # Vektoren, Matrizen, Tabellen oder Dataframes und Listen. # spx ist vom Typ dataframe # die einzelnen Spalten eines dataframes kann man in separate # Vektoren schreiben: names(spx) S = spx$Adj.Close # ist aequivalent zu S = spx[,2] S str(S) plot(S) plot(S,type="l") S[1] S[0] # Vektoren starten immer mit dem Index 1, nicht mit 0 plot( log(S/S[1],2), type="l") # constant line would be exponential growth n = length(S) n S[n] S[n+1] # jetzt berechnen wir die returns: ret = rep(0,n) # Vektor der Laenge n mit lauter Nullen for(i in 2:n) # ret[1] lassen wir auf 0 { ret[i] = (S[i]-S[i-1])/S[i-1] } plot(ret) plot(ret,type="l") # zum Berechnen der d-day means, stddevs und normrets schreiben # wir drei Funktionen: dDayMean = function( d , ret ) { n = length(ret) result = rep(0,n) summe = 0 for(i in 1:n) { summe = summe + ret[i] if(i > d) { summe = summe - ret[i-d] result[i] = summe/d } if(i<=d) { result[i] = summe/i } } return(result) } # let's take a look at Stylized Fact 1: mean15 = dDayMean(15,ret) mean60 = dDayMean(60,ret) mean250 = dDayMean(250,ret) mean_all = dDayMean(n,ret) plot(mean15) points(mean60, col="red") points(mean250, col="yellow") points(mean_all, col="green") dDayStdDev = function( d , ret ) { n = length(ret) result = rep(0,n) summe = 0 for(i in 1:n) { summe = summe + ret[i]*ret[i] if(i > d) { summe = summe - ret[i-d]*ret[i-d] result[i] = summe/d } if(i<=d) { result[i] = summe/i } } result = sqrt(result) # square root element by element return(result) } # let's check: stddev15 = dDayStdDev(15,ret) stddev60 = dDayStdDev(60,ret) stddev250 = dDayStdDev(250,ret) stddev_all = dDayStdDev(n,ret) plot(stddev15) points(stddev60, col="red") points(stddev250, col="yellow") points(stddev_all, col="green") # apparently: volatility is not constant # Normalized Returns: dDayNormRet = function( d , ret ) { stddev = dDayStdDev(d,ret) # normret(t_k) := ret(t_k) / stddev(t_{k-1}) , wir muessen den Nenner um 1 shiften: stddev = c( 0 , stddev[1:(n-1)] ) stddev = pmax(stddev,0.00000001) # paarweises Maximum result = ret/stddev # division element by element # die ersten zwei sind special, ueberschreiben wir mit 0: result[1] = 0 result[2] = 0 return(result) } normret5 = dDayNormRet(5,ret) normret15 = dDayNormRet(15,ret) normret60 = dDayNormRet(60,ret) normret250 = dDayNormRet(250,ret) par( mfrow = c(2,2) ) # set up 2 time 2 plot array, 4 diagrams in 1 picture, # mfrow = 'make frame by row' (not by column): # 1 2 1 3 # 3 4 , not 2 4 hist(normret250,breaks=100,xlim=c(-5,5),ylim=c(0,0.6),prob=TRUE) curve(dnorm(x),from=-5,to=5,add=TRUE,col="red") hist(normret60,breaks=100,xlim=c(-5,5),ylim=c(0,0.6),prob=TRUE) curve(dnorm(x),from=-5,to=5,add=TRUE,col="red") hist(normret15,breaks=100,xlim=c(-5,5),ylim=c(0,0.6),prob=TRUE) curve(dnorm(x),from=-5,to=5,add=TRUE,col="red") hist(normret5,breaks=150,xlim=c(-5,5),ylim=c(0,0.6),prob=TRUE) curve(dnorm(x),from=-5,to=5,add=TRUE,col="red") # thus: if returns are normalized with more recent volatility # data, then normalized returns are more Gaussian: # # Grosse Ausreisser, `heavy tails', kommen weniger haeufig vor, # da bei der Normierung durch eine groessere Zahl, das aktuelle # Volatilitaetsniveau nur der letzten 2 oder 3 Wochen und nicht # der letzten 10 Jahre, geteilt wird. #----------------------------# # # # Main Conclusion: # # # #----------------------------# Die normierten returns normret_d(t_k) = ret(t_k) / stddev_d(t_{k-1}) (4) lassen sich recht gut durch eine Normalverteilung approximieren, wenn man das d hinreichend klein waehlt, etwa d=15 oder d=20. Wir koennen also schreiben: ret(t_k) / stddev_d(t_{k-1}) = phi_k (5) wobei phi_k eine standard-normalverteilte Zufallszahl ist. Gleichung (5) ist aequivalent zu: S_k = S_{k-1} * [ 1 + stddev_d(t_{k-1}) * phi_k ] (6) Mit Hilfe von Gleichung (6) kann man aus den Daten, die zum Zeit- punkt t_{k-1} bekannt sind, und dem Ziehen einer normalverteilten Zufallszahl den Preis bei Zeit t_k berechnen. Ist das ein sinnvolles stochastisches Modell? Wenn man ein paar Pfade simulieren tut, stellt man fest, dass man diese Frage nicht so ohne weiteres mit "ja" beantworten kann. Eine genauere Analyse des Sach- verhalts fuehrt dann auf die Klasse der ARCH- und GARCH-Zeitreihen- modelle, das waere dann etwa Gegenstand einer Oekonometrie-Vorlesung.