Posts mit dem Label Mathematik werden angezeigt. Alle Posts anzeigen
Posts mit dem Label Mathematik werden angezeigt. Alle Posts anzeigen

Sonntag, 26. Juli 2015

Statistik des KGV im Dax30 von 2007 bis 2014


Wenn man sich mit Aktien beschäftigt wird man über kurz oder lang auf das sogenannte jährliche Kurs-Gewinn-Verhältnis (KGV oder P/E ratio) stoßen. Diese Kennzahl liegt meist irgendwo zwischen 6 und 28. Eine anschauliche Interpretation des KGV ist, wie viele Jahre das Unternehmen braucht um seinen Aktienwert zu erwirtschaften. Hier soll der Aktienwert einfach die Anzahl der ausgeschütteten Aktien multipliziert mit dem jetzigen Kurs sein. Der zukünftige jährlich erwartete Gewinn wird auch einfach dem jetzigen Gewinn gleichgesetzt.
Aus dem Bauch heraus bedeutet es also, dass ein Unternehmen mit großem KGV (z.B. 25) im Verhältnis zu seinem Aktienpreis nur geringen jährlichen Gewinn abwirft. Es braucht 25 Jahre bis es seinen Aktienwert als Gewinn erwirtschaftet hat. Dagegen gilt eine Aktie eines Unternehmens mit geringem KGV (z.B. 8) als günstig.
Dies ist aber nur vordergründig so. Es kann genausogut sein, dass bei einem Unternehmen mit KGV 8 in den letzten Jahren der Gewinn stark eingebrochen ist und der Markt dieses Unternehmen mit starken Kursverlusten bestraft. Hier würde man die Katze im Sack kaufen: Ein Unternehmen mit vermeintlich günstigem KGV, aber gesund ist es aufgrund einbrechender Gewinne nicht.
Anhand des KGV alleine sollte man daher keine Kaufentscheidung festmachen.
Um die Aussagefähigkeit des KGV zu erhöhen habe ich eine statistische Auswertung aller im DAX-30 enthaltetenen Unternehmen über die Jahre 2007 bis 2015 durchgeführt.
Die Fragestellung war, ob man anhand einer statistischen Auswertung des KGV trotzdem mithilfe des KGV eine Aussage über die zukünftige Kursentwicklung eines Börsenwertes machen kann. Dazu wurde der jährliche Kursgewinn/-verlust in % für jedes Jahr von 2008 bis 2015 zum Stichtag 1.1. für jedes der 30 Unternehmen ausgewertet und mit dem letztjährigen KGV (also 2007 bis 2014) ins Verhältnis gesetzt.
Zudem wurde das mittlere jährliche Wachstum aller DAX-30 Werte ermittelt. Dieses lag im betrachteten Zeitraum bei stolzen 7,8%. Seine Schwankung ist auch beträchtlich mit 34,4% (einfache Standardabweichung).



Abbildung 1
In Abbildung 1 ist das Ergebnis dieser Auswertung abbgebildet. In orange (durchgezogen) ist das mittlere jährliche Wachstum der DAX-30 Unternehmen aufgetragen (horizontal). Orange gestrichelt ist der Bereich der einfachen Standardabweichung eingezeichnet. Die vertikale orangene Linie zeigt den Median aller jährlichen KGV des DAX von 2007 bis 2014. Dieser liegt bei 16,5. In schwarz (durchgezogen) ist der Kursgewinn/-Verlust in Abhängigkeit des vorjährigen KGV eingezeichnet (auch hier in schwarz gestrichelt die zugehörige Standardabweichung).
Liegt die schwarze Kurve bei einem bestimmten KGV über der orangenen Linie, so lagen die Wachstumsraten von Aktien mit diesem KGV im Mittel über dem des DAX. Beispielsweise hatten Aktienkurse von DAX-30 Unternehmen mit einem KGV von 27,5 im Mittel der untersuchten Periode (2008 bis 2015) eine jährliche Wachstumsrate von etwa 25%. Dagegen hatten Aktienkurse von Unternehmen mit einem KGV von unter 9 einen durchschnittlichen jährlichen Kursverlust von etwa 5% zu verbuchen.
Anhand dieser statistischen Auswertung der letzten 7 Jahre des DAX-30 kann man folgende Aussagen zu zukünftigen Kursentwicklungen machen:
Aktien mit einem KGV von 10 bis 14 und 16 bis 33 hatten im Mittel eine Wachstumsrate die über dem Durchschnitt der untersuchten Periode von 7,8% lag. Das geringste Verlustrisiko liegt bei einem KGV von 25 bis 29. Eine leicht schlechtere Kursentwicklung als der DAX Durchschnitt ergibt sich ab einem KGV von 34. 38% aller jährlichen Kursänderungen im DAX stellten in der Periode einen Verlust dar. Die Hälfte aller jährlichen Kursverluste ergaben sich bei Aktien mit einem vorjährigen KGV von unter 13. Zudem war die jährliche Kursentwicklung bei Aktien mit einem vorjährigen KGV unter 9 im Mittel negativ (etwa 5%).

Abbildung 2


In Abbildung 2 sieht man die Schwankungen der oben diskutierten Mittelwerte. Diese sind beträchtlich (35% im Durchschnitt). Im Bereich eines KGV von 23 verringert sich die Schwankung. D.h. in diesem Bereich ist nicht nur der mittlere jährliche Kursgewinn sehr viel größer als 7,8%, sondern auch Kursschwankungen die stark von den 25% Kursgewinn abweichen viel geringer.

Bevor ich diese Statistik ausgewertet hatte, war ich eher der Meinung, dass die Wahrscheinlichkeit eines Kursgewinns nach einem Jahr gleichverteilt über den KGV ist. Im Mittel 7,8% pro Jahr, egal ob man ein vermeintlich günstiges (geringes KGV) oder gehyptes (hohes KGV) Unternehmen kauft. 
Diese Statistik zeigt das Gegenteil. Von Unternehmen mit einem KGV kleiner 9 sollte man eher die Finger lassen. Hier zeigt die Statistik einen gehäuften Kursrückgang. Eine mittlere positive Kursentwicklung ergibt sich dagegen bei Unternehmen mit einem KGV von 10 bis 33. Wobei der Bereich 25 bis 29 anscheinend überaus profitabel und mit weniger warscheinlichen Kursrückgängen ausgezeichnet ist.



Sonntag, 11. August 2013

Fouriertransformation in der Praxis

Als Physiker ist die Fouriertransformation „Bildungsstandard“ und ein Kinderspiel. Zumindest solange, bis man selber in der Praxis eine diskrete Fouriertransformation im Programmcode verwenden möchte.
In der Uni wird ständig mit der Fouriertransformation hantiert, aber zumeist nur in „formaler“ Weise, d.h. man löst z.B. die Wellengleichung im k-Raum oder stellt die Dirac-Funktion als Fouriertransformierte dar. Im 2. oder 3. Semester macht man auch die Spielchen, dass man eine Gaußfunktion per Hand transformiert und wieder eine Gaußfunktion herauskommt.
In der Praxis hat man ein Signal diskretisiert, wobei der Zeitabstand zwischen zwei Samplepunkten einer sinnvollen physikalischen Einheit entspricht. Nun möchte man „einfach mal kurz“ das Zeitsignal in seine Frequenzen zerlegen. Und genau hier wird der durchschnittliche Physiker durch die Implementation der FFT zur Weißglut getrieben. „Wie zur Hölle muss ich denn nun meine Frequenzachse konstruieren um physikalisch sinnvolle Frequenzen zu erhalten????“

Der Fallstrick ist eigentlich nicht die Implementation (z.B. in Python oder Matlab) selbst, sondern dass man glaubt alles - wirklich alles - über die Fouriertransformation zu wissen und daher liest man die zugehörige FFT-Dokumentation nicht richtig.

Im folgenden möchte ich diese Fallstricke anhand der Implementation der FFT im numpy-Paket in Python erläutern.


Das wichtigste:
  1. Die FFT spuckt ihr Ergebnis in einer „unintuitiven“ Ordnung aus („Standard Packing“)
  2. Die Normierung ist unsymmetrisch
  3. Im Exponenten ist ein Faktor 2pi versteckt

Zuerst erstellen wir ein Zeitsignal mit einer physikalisch sinnvollen Zeitachse. Die obige Grafik wird mit folgendem Code erstellt

import matplotlib.pyplot as plt
import numpy as np
from math import *
N = 200
deltaT = 0.01 #ms
timeseries = np.zeros(N)
tAxis = np.linspace(0,deltaT*N,N)
damping = 15.0
frequency1 = 10.0 # 10 kHz
frequency2 = 30.0 # 30 kHz
fNyquist =0.5/deltaT
for i in range(N):
 t = tAxis[i]
 timeseries[i] = exp(-t*t*damping/4.0)*(1.0-exp(-t*t*damping))*sin(2.0*pi*frequency1*t)+0.05*cos(2.0*pi*frequency2*t)

plt.xkcd() #rausnehmen, falls matplotlib version <1.3.0
plt.plot(tAxis,timeseries,label = "damped sine")
plt.xlabel("t in ms")
plt.ylabel("Amplitude")
plt.legend()
plt.savefig("damped_sine.png")
Wir haben also einen gedämpften Sinus als Zeitserie, mit der Mittenfrequenz 10 kHz, dargestellt mit 200 Samplepunkten, die jeweils 10 Mikrosekunden auseinander liegen. Die Samplefrequenz ist also 100 kHz Außerdem ist diese Schwingung mit einem Cosinus kleiner Amplitude mit der Frequenz 30 kHz überlagert. Somit liegt die Nyquist-Frequenz bei 50 kHz. Wenn man nun ganz frisch ans Werk geht und einfach die FFT berechnet, erhält man folgendes

Der Code zur Erzeugung dieser Grafik ist dieser:

FFTtimeseries = np.fft.fft(timeseries)
fMax = 1.0/deltaT
fAxis = np.linspace(0,fMax,N)
plt.clf()
plt.plot(fAxis,np.abs(FFTtimeseries),'-b',label="FFT")
plt.hold(True)
plt.plot(frequency1, max(np.abs(FFTtimeseries)),'ro',label="my guess!" )
plt.plot(frequency2, max(np.abs(FFTtimeseries)),'r+',label="my guess!" )
plt.plot(fNyquist, max(np.abs(FFTtimeseries)),'go',label="Nyquist frequency" )
plt.xlabel("f in kHz")
plt.ylabel("FFT")
plt.xlim([min(fAxis),max(fAxis)])
plt.savefig("wrong_axis.png")

Nun schaut man sich das an und krazt sich am Kopf: Was „zur Hölle“ sind das für 2 Peaks hinter der Nyquist-Frequenz? Ok, ich ignoriere die einfach, weil sie ja höher als die Nyquistfrequenz sind. Das ist falsch. Der Grund für die beiden hinteren Peaks ist die FFT-Implementation. Stichwort „Standard Packing“. Die Funktion np.fft.fft gibt ein Array der Länge N wieder (hier also 200 Elemente). Das 0. Element entspricht der Frequenz Null, die Elemente 1, 2, ..., N/2-1 entsprechen den DFT-Koeffizienten zur Frequenz deltaF, 2*deltaF, ..., (N/2-1)*deltaF. Wobei deltaF=1/(N*deltaT) ist. Also durch diejenige harmonische Schwingung definiert ist, die genau einmal in das vorgegebene Zeitfenster N*deltaT (hier 2 ms) passt. Die Elemente N/2,...,N-1 entsprechen dagegen den negativen Frequenzkomponenten -deltaF*(N-1), -deltaF*(N-2),... -deltaF. Um ein „erwartetes Ergebnis“ zu erhalten, muss man das Ergebnis der FFT umsortieren. Dazu ist schon die Funktion fft.fftshift implementiert.

Der Code:

FFTtimeseries = np.fft.fftshift(np.fft.fft(timeseries))
fMax = 1.0/deltaT
deltaF =1.0/(deltaT*N)
truefAxis = np.linspace(-fMax/2,fMax/2,N)
plt.clf()
plt.plot(truefAxis,np.abs(FFTtimeseries),'-b',label="FFT")
plt.hold(True)
plt.plot(frequency1, max(np.abs(FFTtimeseries)),'ro',label="my guess!" )
plt.plot(frequency2, max(np.abs(FFTtimeseries)),'r+',label="my guess!" )
plt.plot(fNyquist,max(np.abs(FFTtimeseries)) ,'go',label="Nyquist frequency" )
plt.xlabel("f in kHz")
plt.ylabel("FFT")
plt.xlim([min(truefAxis),max(truefAxis)])
plt.savefig("right_axis.png")  

Das Ergebnis:

Damit wäre der obige 1. Punkt der Liste der Fallstricke behoben.

Nochmal kurz die Rücktransformation austesten:

plt.clf()
plt.plot(tAxis,np.fft.ifft(np.fft.fft(timeseries)).real,'-r',label="back transformed")
plt.xlabel("t in ms")
plt.ylabel("Amplitude")
#plt.legend()
plt.savefig("back_transformed.png")

Das Ergebnis
...Schön. Kommt genau das Eingangssignal wieder heraus. Ist ja alles super!

Der zweite Punkt der Fallstrickliste soll anhand des Faltungstheorems diskutiert werden. Zur Erinnerung: Die Fouriertransformierte  eines Faltungsintegrals ist einfach die Multiplikation der Fouriertransformierten der beiden einzelnen Funktionen. Außerdem ist ja bekannt, das die Faltung der Rechtecksfunktion mit sich selbst (Autokorrekation) die Zeltfunktion/Dreiecksfunktion gibt. Also versuchen wir uns mal daran:
def rect(x, L):
 if np.abs(x) < L:
  return 1.0
 else: 
  return 0.0
tAxis = np.linspace(-5,5,N) 
rectW = np.zeros(N)
for i in range(N):
 rectW[i] = rect(tAxis[i],1.0)

deltaT =abs(tAxis[1]-tAxis[0])
plt.clf()
plt.plot(tAxis,rectW,'-b',label="rect window")
plt.xlabel("t in ms")
plt.ylabel("Amplitude")
plt.legend()
plt.ylim([0,1.25])
plt.savefig("rect.png")

iAmClever = np.fft.ifft(np.fft.fft(rectW)*np.fft.fft(rectW))

plt.clf()
plt.plot(tAxis,iAmClever,'-b',label="first try" )
plt.xlabel("t in ms")
plt.ylabel("Amplitude")
plt.legend()
plt.savefig("first_fft_conv.png")

Im obigen Code habe ich eine Funktion „rect“ definiert die uns ein Rechtecksfenster erzeugt und danach haben wir das Faltungstheorem angewendet. Die Ergebnisse sind...

 ...das Rechtecksfenster ist also 2 ms breit. Faltet man diese Rechteckfunktion mit sich selbst, so erwartet man von -unendlich bis -2 ms Null, da die beiden Rechteckfunktionen noch nicht überlappen. Von -2 ms bis 0 ms erwartet man einen linearen Anstieg, da der Überlapp linear anwächst. Bei 0 ms liegen beide Rechtecke übereinander und das Integral sollte 2 ms * 1 = 2 ms ergeben. Danach erwartet man einen linearen Abfall bis 2 ms und dann sollte die Faltung Null ergeben. Nun bekommen wir aber folgendes Ergebnis:


Einmal wurde wieder die fftshift-Funktion vergessen, aber zudem wurde die Unsymmetrie der implementierten Normierung ignoriert. Nur bei der Rücktransformation der FFT ist ein Normierungsfaktor berücksichtigt, so dass ifft(fft(A))=A ergibt. Nun wurde aber im Frequenzbereich multipliziert, so dass dort einmal zusätzlich der Normierungsfaktor berücksichtigt werden muss. Richtig geht es so

FFTConvTimeseries = np.fft.ifftshift(np.fft.ifft(np.fft.fft(rectW)*np.fft.fft(rectW))).real*deltaT
plt.clf()
plt.plot(tAxis,FFTConvTimeseries,'-r',label="right axis and normalization" )
plt.xlabel("t in ms")
plt.ylabel("Amplitude")
plt.ylim([0,1.5])
plt.legend()
plt.savefig("fft_conv.png")

und man erhält das erwartete Ergebnis

Abschließend: Sagt niemals zu eurem Chef: Jo, FFT, bin in einer Viertelstunde fertig. Das geht schief! Immer. FFT ist um Welten komplizierter und verwirrender als die Fouriertransformation mit Stift und Papier. Die Diskretisierung und die verwirrende Implementation birgt viele viele Fallstricke!