Kursdaten: Import und Visualisierung#

In diesem Kapitel beschäftigen wir uns damit, wie wir Kursdaten in Python verwenden können. Dabei sollen folgende Lerninhalte vermittelt werden:

  1. Einbettung und Anzeigen von Kursdaten

  2. Visualisierung und Analyse von Kursen unter Einbeziehung von Charttechnik

Einbettung und Anzeigen von Kursdaten#

Grundsätzlich gibt es zwei Möglichkeiten Kurse in ein Python-Skript zu implementieren:

        a) Kursdaten werden in einer seperaten Datei aufbereitet (z.B. in .csv oder .xlsx Format)
        b) Direkter Abruf von Kursdaten aus dem Internet

Beginnen wir mit Variante a). Vorteilhaft ist es stets, die Datei der Kursdaten im gleichen Ordner zu haben. In diesem Fall verwenden wir das pandas-Package.

Hinweise:

Dies dann wie folgt aus:

import pandas as pd

#df1 = pd.read_csv("./../../Data/Allianz_Schlusskurse_2020_2025.csv")
df1 = pd.read_csv("./../../Data/Allianz_Schlusskurse_2020_2025.csv", 
                       skiprows = 3, names = ["Datum", "Schlusskurs"])
#Achtung: bitte passen Sie den relativen Pfad an Ihre eigene Ordner-Struktur an


# Falls die xlsx-Datei im gleichen Ordner liegt, dann würde der Code wiefolgt aussehen
# df = pd.read_excel("Kurse Allianz.xlsx")

print(df1)
           Datum  Schlusskurs
0     2020-01-02   163.322479
1     2020-01-03   161.515991
2     2020-01-06   160.520554
3     2020-01-07   160.889252
4     2020-01-08   160.962997
...          ...          ...
1270  2024-12-19   284.622162
1271  2024-12-20   282.417297
1272  2024-12-23   282.033844
1273  2024-12-27   282.896606
1274  2024-12-30   283.663513

[1275 rows x 2 columns]

Abruf von Kursdaten direkt aus Internet#

Kommen wir nun zu unserer Variante b) und rufen Kursdaten direkt aus dem Internet ab. Dazu verwenden wir das Package yfinance.

Hinweise:

  • Das Ticker-Symbol einer Aktie finden wir auf der Yahoo Finance-Webseite hinter dem jeweiligen Aktientitel.

  • Ab und zu hat Yahoo-Finance technische Probleme und der Kursabruf wie im direkt folgendem Beispiel funktioniert trotz fehlerfreien Codes nicht! Aus diesem Grund fangen wir im weiteren Beispiel dieses Problem ab, um unnötige Programmabbrüche zu vermeiden.

  • Manchmal gibt es leider Probleme mit den aktuell installierten Paketen, so dass offensichtlich richtiger Code (hier beispielsweise zum Abrufen von Kursdaten mittels yfinance – in einigen Fällen hilft ein Update des Paketes und manchmal eine De- und Neuinstallation. Bei der Erstellung dieses Notebooks stellte sich beispielsweise heraus, dass die installierte yfinance Version 0.2.54 Probleme beim Download hatte, während die alte Version 0.2.31 sowie die neue Version 0.2.65 problemlos funktionierte. Falls die Download-Probleme also trotz richtigen Code anhalten, ist ein Wechsel auf eine ältere stabile Version oder auch neue Version möglich. Hierzu in der aktuellen Environment (myenv) erstmals die installierte Version überprüfen

      pip show yfinance
    

    und mittels pip auf die gewünsche Version zurücksetzen oder aktuallisieren (eine kurze Internetrecherche in diversen Foren ist hier sicherlich hilfreich), beispielsweise

      pip install yfinance==0.2.31
    
import yfinance as yf

alz = yf.Ticker("ALV.DE")

#### Erstelle einen Dataframe, der die Kursdaten der letzten 12 Monate enthält
df2 = alz.history(period="1y", interval = "1d")


print(df2.tail(5))
# Gibt die letzten fünf Zeilen der Kursdaten aus – ideal zur Kontrolle.
                                 Open        High         Low       Close  \
Date                                                                        
2025-09-23 00:00:00+02:00  349.899994  350.100006  347.100006  348.200012   
2025-09-24 00:00:00+02:00  347.000000  347.600006  345.700012  346.000000   
2025-09-25 00:00:00+02:00  345.600006  350.799988  345.100006  349.299988   
2025-09-26 00:00:00+02:00  352.600006  358.799988  352.299988  358.100006   
2025-10-01 00:00:00+02:00  355.000000  358.399994  354.600006  357.799988   

                           Volume  Dividends  Stock Splits  
Date                                                        
2025-09-23 00:00:00+02:00  335118        0.0           0.0  
2025-09-24 00:00:00+02:00  362950        0.0           0.0  
2025-09-25 00:00:00+02:00  408063        0.0           0.0  
2025-09-26 00:00:00+02:00  676522        0.0           0.0  
2025-10-01 00:00:00+02:00   50650        0.0           0.0  
#speichern der Daten in CSV-Datei
df2.to_csv('alz_12months.csv')

Manchmal gibt es beim Download der Daten über YahooFinance leider Probleme und sobald der Code deshalb Fehler verursacht, stoppt ein Script. Will man dies vermeiden, kann man mittels try: .. except... diesen Fehler abfangen

import yfinance as yf
import pandas as pd
import pandas_datareader as web   #siehe https://pandas-datareader.readthedocs.io/en/latest/#
from datetime import datetime
#to do: Import bereinigen, da yf und pd bereits oben... 
#       am besten immer import aller verwendeten Pakete am Anfang des Notebooks gesammelt, bzw. je subsection... 

ticker = ["TSLA"]
tickers = ["AAPL","ALV.DE"]
#prices = yf.Ticker(ticker).history('5y')  #aktuell Fehlermeldung wegen Problemen bei Yahoo-Finance

#Versuch: Fehler abzufangen mit Ausgabe des Prroblems, ohne dass es zu Abbruch des Programms kommt !
#to do: alle Beispiele zu Graphen usw. erst mit csv-Daten (und diese zum Download für Studies integrieren, 
#       dann ist sichergestellt, dass mind. 1 funktionierdende Code-Bsp als Vorlage da ist!

print("Versuche Yahoo Finance für %s:\n" % (ticker))
try:
    data = yf.download(ticker, period = "5y", interval = "1d")
except Exception as e:
    print("Fehler bei Yahoo Daten Download: %s \n" % (e))

if not data.empty:
    print("Daten für %s geladen auf Yahoo-Finance" % ticker)
    print(data.head())
    print("Datentyp Rückgabe yfinance: %s:\n" % type(data))
else:
    print("Probleme mit Yahoo-Finance - keine Daten für %s geladen" % (ticker))

#to do: check if not data.empty part - aktuell nicht moeglich, da immer Fehler beim Download!!!
print("\nVersuche Yahoo Finance für mehrere Assets %s :\n" % (tickers))
all_prices = {}
try:
    data2 = yf.download(tickers, period = "5y", interval = "1d", group_by = "ticker")     
except Exception as e:    
    print("Fehler bei Yahoo Daten Download: %s \n" % (e))

if not data2.empty:                            
    print(data2.head())
    #print(type(data2))
    print("Datentyp Rückgabe yfinance: %s\n"  % (type(data2)))
    print("Infos DataFrame:\n" )
    print(data2.info())
Versuche Yahoo Finance für ['TSLA']:
/tmp/ipykernel_3382572/1829185406.py:18: FutureWarning: YF.download() has changed argument auto_adjust default to True
  data = yf.download(ticker, period = "5y", interval = "1d")
[*********************100%***********************]  1 of 1 completed
/tmp/ipykernel_3382572/1829185406.py:33: FutureWarning: YF.download() has changed argument auto_adjust default to True
  data2 = yf.download(tickers, period = "5y", interval = "1d", group_by = "ticker")
Daten für ['TSLA'] geladen auf Yahoo-Finance
Price            Close        High         Low        Open     Volume
Ticker            TSLA        TSLA        TSLA        TSLA       TSLA
Date                                                                 
2020-10-01  149.386673  149.626663  144.806671  146.919998  152224500
2020-10-02  138.363327  146.376663  138.333328  140.463333  214290000
2020-10-05  141.893326  144.546661  139.776672  141.116669  134168400
2020-10-06  137.993332  142.926666  135.350006  141.263336  147438900
2020-10-07  141.766663  143.300003  137.949997  139.956665  129383100
Datentyp Rückgabe yfinance: <class 'pandas.core.frame.DataFrame'>:


Versuche Yahoo Finance für mehrere Assets ['AAPL', 'ALV.DE'] :
[                       0%                       ]
[*********************100%***********************]  2 of 2 completed
Ticker          ALV.DE                                                 \
Price             Open        High         Low       Close     Volume   
Date                                                                    
2020-10-01  130.029624  130.217781  126.219519  127.144600  1321453.0   
2020-10-02  126.109761  127.646351  125.153314  127.630669  1046682.0   
2020-10-05  129.214293  130.688152  128.054005  130.547043   928832.0   
2020-10-06  130.923331  133.196845  129.810092  132.506958   898369.0   
2020-10-07  132.648080  133.055749  129.919860  130.641113   914196.0   

Ticker            AAPL                                                   
Price             Open        High         Low       Close       Volume  
Date                                                                     
2020-10-01  114.430530  114.508350  112.669913  113.603722  116120400.0  
2020-10-02  109.810096  112.222439  109.158377  109.936546  144712000.0  
2020-10-05  110.802274  113.467519  110.452095  113.321609  106243800.0  
2020-10-06  112.543451  112.951998  109.187577  110.072754  161498200.0  
2020-10-07  111.492919  112.397547  111.016282  111.940369   96849000.0  
Datentyp Rückgabe yfinance: <class 'pandas.core.frame.DataFrame'>

Infos DataFrame:

<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 1292 entries, 2020-10-01 to 2025-10-01
Data columns (total 10 columns):
 #   Column            Non-Null Count  Dtype  
---  ------            --------------  -----  
 0   (ALV.DE, Open)    1274 non-null   float64
 1   (ALV.DE, High)    1274 non-null   float64
 2   (ALV.DE, Low)     1274 non-null   float64
 3   (ALV.DE, Close)   1274 non-null   float64
 4   (ALV.DE, Volume)  1274 non-null   float64
 5   (AAPL, Open)      1255 non-null   float64
 6   (AAPL, High)      1255 non-null   float64
 7   (AAPL, Low)       1255 non-null   float64
 8   (AAPL, Close)     1255 non-null   float64
 9   (AAPL, Volume)    1255 non-null   float64
dtypes: float64(10)
memory usage: 111.0 KB
None

Neben dem Abruf von Kursdaten von Yahoo-Finance besteht ebenfalls die Möglichkeit mittels API-Schnittstellen auf Kursinformationen zuzugreifen. Ein API-Schnittstellen Provider ist Alpha Vantage. Nach Registrierung und Erhalt des API-Keys können wir nun auf Börsenkurse zugreifen. Dafür verwenden wir folgenden Code:

from alpha_vantage.timeseries import TimeSeries
import pandas as pd

#### API-Key für Alpha Vantage angeben
api_key = 'DasistkeinechterAPI-Key'

#### Verbindung zu Alpha Vantage aufbauen
ts = TimeSeries(key=api_key, output_format='pandas')
# Erstellt ein TimeSeries-Objekt ts, über das du dann Methoden wie get_daily verwenden kannst.
# Mit output_format='pandas' bekommst du die Daten direkt als pandas DataFrame. Pandas ist sehr praktisch und einfach von der Handhabung

####  Tagesdaten abrufen
data, meta_data = ts.get_daily(symbol='AAPL', outputsize='compact')
# symbol='AAPL' fragt die Daten für die Apple-Aktie ab.
# data enthält die eigentlichen Kurse (Open, High, Low, Close, Volume), meta_data enthält Zusatzinfos (z. B. Abfragezeitpunkt, Symbol).

print(data.head())
# Gibt die ersten fünf Zeilen der Kursdaten aus.
            1. open  2. high   3. low  4. close   5. volume
date                                                       
2025-09-30  254.855  255.919  253.110    254.63  37704259.0
2025-09-29  254.560  255.000  253.010    254.43  40127687.0
2025-09-26  254.095  257.600  253.780    255.46  46076258.0
2025-09-25  253.205  257.170  251.712    256.87  55202075.0
2025-09-24  255.220  255.740  251.040    252.31  42303710.0

Werden mehrere Aktien gleichzeitig abgerufen… - Type!

Mithilfe des Parameters outputsizekönnen wir festlegen, wie viele Daten wir anfordern. Mit dem Wert compactwerden nur die letzten 100 Datenpunkte angefordert. Verwenden wir full fordern wir hingegen den gesamten Datenbestand an.

1. Hinweis: In der Regel haben kostenlose API-Schnittstellen die Tücke, nur ein begrenztes Limit an Abfragen pro Minute oder Tag anfordern zu können. Somit kann der Parameterwert full demnach dazu führen, dass dieses Limit schneller erreicht ist. Aber auch yfinance blockiert in der Regel bei zu vielen Anfragen temporär die IP-Adresse. Zur Lösung dieses Problems können die Schlusskurse als csv-Datei abgespeichert werden, somit stehen sie lokal zur Verfügung. Das kann mithilfe des nachfolgenden Codes durchgeführt werden. (Der Code ist auskommentiert, da verhindert werden soll, dass bei jedem Durchlauf dieses Jupyter-Skriptes ein download erfolgt.)

# import yfinance as yf
# import pandas as pd

# Ticker-Symbol für Allianz SE an der Börse Frankfurt/Xetra
# ticker = "ALV.DE"

# Daten abrufen (01.01.2020 bis 01.01.2025)
# data = yf.download(ticker, start="2020-01-01", end="2025-01-01")

# Nur Schlusskurse extrahieren
# schlusskurse = data[["Close"]].rename(columns={"Close": "Schlusskurs"})

# Als CSV-Datei speichern
# schlusskurse.to_csv("Allianz_Schlusskurse_2020_2025.csv")

# print("CSV-Datei wurde gespeichert: Allianz_Schlusskurse_2020_2025.csv")

2. Hinweis: Alpha Vantage liefert in der kostenlosen Version nur Daten für US-Börsen. Dies ist auch der Grund, wieso wir in dem letzten Code Kursdaten von Apple angefordert haben.

Darstellung der Kursentwicklung#

Visualisierung mit Matplotlib oder Seaborn#

import yfinance as yf
import matplotlib.pyplot as plt
import seaborn as sns
from datetime import datetime


start_date = datetime(year = 2024, month=1, day = 1)

ticker1 = "AAPL"
stock1 = yf.download(ticker1, start = start_date)
stock1.head()
stock1.tail()

stock1['Close']

plt.figure()
plt.plot(stock1['Close'], label='Closing Price', color='blue')
plt.xlabel("Date")
#plt.xticks(rotation=90)
plt.xticks(rotation=45, ha='right')
plt.legend()
plt.grid()
plt.title(ticker1)
plt.show()
/tmp/ipykernel_3382572/2413817120.py:10: FutureWarning: YF.download() has changed argument auto_adjust default to True
  stock1 = yf.download(ticker1, start = start_date)
[*********************100%***********************]  1 of 1 completed

_images/73bec666c8ce5c5c2999a2e2a78438528039a489b529247fa661bd1d66893471.png
#multiple stocks
### Multiple Stocks: Achtung group_by hat Einfluss auf die Struktur des "Doppelarrays"

tickers = ["AAPL","NVDA","META"]
stocks_v1 = yf.download(tickers, start_date,   group_by='ticker') #place ticker name as the top-level column
stocks_v2 = yf.download(tickers, start_date,   group_by='column') # place the OHLCV values as the top-level columns

last_date = stocks_v1[tickers[0]]['Close'].index[-1].date() #.strftime("")
/tmp/ipykernel_3382572/2376945377.py:5: FutureWarning: YF.download() has changed argument auto_adjust default to True
  stocks_v1 = yf.download(tickers, start_date,   group_by='ticker') #place ticker name as the top-level column

[                       0%                       ]
[**********************67%*******                ]  2 of 3 completed
[*********************100%***********************]  3 of 3 completed
/tmp/ipykernel_3382572/2376945377.py:6: FutureWarning: YF.download() has changed argument auto_adjust default to True
  stocks_v2 = yf.download(tickers, start_date,   group_by='column') # place the OHLCV values as the top-level columns

[                       0%                       ]
[**********************67%*******                ]  2 of 3 completed
[*********************100%***********************]  3 of 3 completed

Darstellung mittels Seaborn: Aktie für Aktie mittels For-Loop

plt.figure()
sns.set(style='whitegrid')

for tick in tickers:
    sns.lineplot(data = stocks_v1[tick]["Close"],label=tick)

plt.title("Stock Closing Prices %s -- %s" % (start_date.date(), last_date))
plt.xticks(rotation=45, ha='right')
plt.xlabel("Date")
plt.ylabel("Closing Price ($)")
plt.tight_layout()
plt.show()
_images/345ff8c38902e946ae3b351d770a12bca5b8205769a6bac32698c88065e7c879.png

Darstellung mehrere Aktienkurse (bei Multi-Abruf group_by='ticker') mittels Seaborn

plt.figure()
sns.set(style='whitegrid')
sns.relplot(data=stocks_v2['Close'], kind="line",  dashes=False)
plt.title("Stock Closing Prices %s -- %s" % (start_date.date(), last_date))
plt.xticks(rotation=45, ha='right')
plt.xlabel("Date")
plt.ylabel("Closing Price ($)")
plt.tight_layout()

plt.show()
/HOME1/users/personal/dana/miniconda3/envs/finance/lib/python3.11/site-packages/seaborn/axisgrid.py:123: UserWarning: The figure layout has changed to tight
  self._figure.tight_layout(*args, **kwargs)
/tmp/ipykernel_3382572/3982091666.py:8: UserWarning: The figure layout has changed to tight
  plt.tight_layout()
<Figure size 640x480 with 0 Axes>
_images/5ade93e9f4e2899bf86cbf7b3bcac96e476cb29ec4f8fd1c58a9d1881abdf871.png

Visualisierung und technische Chartanalyse von Kursdaten mittels Mplchart#

Das Pakte mplchart, siehe Webseite oder Github, liefert eine einfache Möglichkeit Charts der technischen Analyse zu erstellen.

from mplchart.chart import Chart
from mplchart.primitives import Candlesticks, Volume
from mplchart.indicators import SMA, RSI, MACD

#Achtung: input mplchart sind OHLCV-DataFrames (also Open, High, Low, Close, Volume mit Datetime-Index, wie yfinance liefert!!!!

# Konfiguration
max_bars = 252 #Beschränkung auf das letzte Börsenjahr (in Deutschland gibt es 252 Handelstage) 
indicators = [
    Candlesticks(),
    Volume(),
    SMA(50), 
    SMA(200),
    RSI(), 
    MACD(), 
]


# Daten von Yahoo-Finance abrufen
ticker = "ALV.DE"

print("Versuche Yahoo Finance für %s:\n" % (ticker2))
try:
    data = yf.Ticker(ticker2).history('2y')  #hier ggf. Zeiten anpassen
except Exception as e:
    print("Fehler bei Yahoo Daten Download: %s \n" % (e))

if not data.empty:
    print(data.head())
    chart = Chart(title = ticker, max_bars=max_bars)
    chart.plot(data, indicators)
    chart.show()
   
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[13], line 22
     19 # Daten von Yahoo-Finance abrufen
     20 ticker = "ALV.DE"
---> 22 print("Versuche Yahoo Finance für %s:\n" % (ticker2))
     23 try:
     24     data = yf.Ticker(ticker2).history('2y')  #hier ggf. Zeiten anpassen

NameError: name 'ticker2' is not defined

Frage: Wir können wir diesen Chart nun interpretieren?

Der Relative Strenght Index ist ein sogenannter Momentum-Indikator, der in der technischen Analyse verwendet wird und das Ausmaß der jüngsten Kursveränderungen misst. Ein RSI-Wert von 70 oder mehr deutet darauf hin, dass ein Wertpapier überkauft oder überbewertet ist und möglicherweise für eine Trendumkehr oder einen korrigierenden Kursrückgang bereit ist. Ein RSI-Wert von 30 oder darunter weist auf einen überverkauften oder unterbewerteten Zustand hin. Dabei dient zur Berechnung üblicherweise ein Zeitraum über 14 Tage, mitunter auch über acht oder 38 Tage.

Der Moving Average Convergence/Divergence ist ein Indikator für Trendwechsel. Kreuzt die schwarze Linie über die blaue Linie, entsteht ein Kaufsignal. Kreuzt die blaue Linie über die schwarze Linie, entsteht ein Verkaufssignal.

Der Simple Moving Average ist das artithmetische Mittel der letzten t-Handelstage (in unserem Fall der letzten 50 und 200 Handelstage). Ein steigender SMA deutet auf einen Aufwärtstrend hin, während ein fallender SMA auf einen Abwärtstrend schließen lässt (Trendbestimmungsfunktion). Wenn der Kurs von unten an den SMA stößt und von dort abprallt, kann dies als Kaufsignal interpretiert werden. Umgekehrt kann ein Stoß von oben und ein Abprallen nach unten als Verkaufssignal gelten. (Funktion als Wiederstands- und Unterstützungszone).

👉 Weitere Informationen zu Indikatoren finden Sie auf folgender Webseite.

💡 Aufgabe: Versuchen Sie im Selbststudium weitere Chartindiaktoren zu verwenden und interpretieren.

Analyse der Kursentwicklung: Renditen und Returns - to do#

  • Renditen = prozentualer Wertzuwachs von a nach t: \(R_{a,t} = \frac{S_{a} - S_{t}}{S_a}= \frac{S_a}{S_t}-1\)

  • Log-Returns von a nach t: \(r_{a,t} = \log{\left( \frac{S_a}{S_t} \right)} = \log {\left(S_t \right)} - \log {\left(S_a \right)}\)

  • Zusammenhang: \(R_{a,t}=e^{r_{a,t}}-1 \Leftrightarrow r_{a,t} = \log{\left( R_{a,t}+1\right)}\)

  • Taylorapproximation liefert für kurze Zeitabstände \(\triangleq t = t-a\) wegen \(S_a \approx S_t\) und folglich \(\frac{S_t}{S_a} \approx 1\), dass \(r_{a,t} = \log{\left( R_{a,t}+1\right)} = \log{\left( \frac{S_t}{S_a} \right)} \approx \frac{S_t}{S_a} -1 = R_{a,t}\) beide Rendite-Begriffe kaum unterscheiden.

  • Vergleiche Graphik zur Taylorentwicklung (1. Ordnung) der Funktion \(f(x)= ln(x) \approx x -1\) in \(x_0 = 1\)

import numpy as np

# x-Werte
x = np.linspace(0.01, 2, 400)     # für f(x) = ln(x), nur positive x

# Funktionen
f = np.log(x)
t = x - 1  #Taylor-Approximation

# Plot
plt.figure(figsize=(7,5))
plt.plot(x, f, label="f(x) = ln(x)", color="blue")
plt.plot(x, t, label="t(x) = x - 1", color="red")

# Achsen und Details
plt.axhline(0, color="black", linewidth=0.8)   # x-Achse
plt.axvline(0, color="black", linewidth=0.8)   # y-Achse
plt.title("f(x) = ln(x) und Taylorapproximation t(x) = x - 1")
plt.xlabel("x")
plt.ylabel("y")
plt.ylim([-2,1])
plt.legend()
plt.grid(True)
plt.show()
_images/08dc896cd29d73ac79e2d2fa72198b48435548ad2c832672019b070602f3103f.png

Portfolio-Rendite#

Die prozentualen Potrtfolio-Renditen ergeben sich als gewichtete Summe der Aktienrenditen:

Wird in \(t=0\) das Portfolio aus jeweils \(a_i\) Stocks zum Preis \(S_{i,0}\) zusammengesetzt (\(i=1, \ldots,n\)), gilt für den jeweiligen Portfolioanteil der \(i\)-ten Aktie \(w_i = \frac{S_{i,0}}{P_0}\) und \(\sum\limits_{i=1}^n w_i = 1\), wobei \(P_0 = a_1 S_{1,0} + \ldots + a_n S_{n,0}\) der investierte Gesamtbetrag beträgt. Wird das Portfolio bis zum Zeitpunkt \(t>0\) nicht umgeschichtet, hat das Portfolio dann den Wert \(P_t = \sum\limits_{i=1}^n a_i S_{i,t}\), so dass für die Portfolio-Rendite, also den prozentualen Zuwachs bis zum Zeitpunkt \(t\) des Portfolios gerade \(R^P_t = \frac{P_t}{P_0}-1 = \sum\limits_{i=1}^n a_i \frac{S_{i,t}}{P_0} - 1 = \sum\limits_{i=1}^n a_i \frac{S_{i,0}}{P_0} \frac{S_{i,t}}{S_{i,0}} - 1 = \sum\limits_{i=1}^n w_i \left(\frac{S_{i,t}}{S_{i,0}} - 1 \right) = \sum\limits_{i=1}^n w_i R_{i,t}\) also die gewichtete Summe der Aktien-Renditen \(R_{i,t}=\frac{S_{i,t}}{S_{i,0}} - 1\).

to do: 
* siehe Beispiel-Code: finance-pandas.ipynb
* Wiederholung wichtiger Pandas Grundlagen: Index als Datum anstalt Spalte und Umwandlung, sowie von Pandas vorgegebene Funktionen wie `plot()` oder `pct_change()` usw.) und als Übungsaufgabe 
* mit aktuellen Datensatz mit einigen DAX-Aktien von oben / csv 
* Renditen vs. Returns -- Berechnung mit Hilfsfunktionen vs. eigene Berechnungen
* Portfoliowert und Rendite
* Berechnung empirischer Kennzahlen: mean, var, std, skewness, kurtosis...
* Portfoliovarianz
* einfache Grafiken: Zeitreihen, Hist, Scatterplots ...
* statistische Tests auf Normalverteilung...
* Kovarianzmatrix / Korrelationsmatrix für Zusammenhang
* evt. in Anhang aufnehmen Grundlagen statistisches Testen und Arbeiten mit verschiedenen Verteilungen??? sowie multivariate Normalverteilung???

Es ist deutlich zu erkennen, dass für x nahe 1 kaum ein Unterschied zwischen beiden Funktionen zu erkennen ist. Zusammenfassend: Log-Returns und arithmetische Renditen unterscheiden sich, allerdings nur minimal für entsprechend kleine Zeitabstände. Beide Rendite-Begriffe haben aus finanzmathematischer Sicht Vor- und Nachteile. Wie oben gezeigt ergibt sich die arithmetische Portfolio-Rendite als gewichtete Summe der Aktienrenditen, was für die Log-Returns nicht gilt. Allerdings kumulieren sich die täglichen Log-Returns wegen \(r_{0,t} = \log(S_t) - \log(S_0) = \log(S_t) - \log(S_{t-1}) + \log(S_{t-1}) \pm \ldots + \log(S_1)-\log(S_0)=r_{t-1,t} + \ldots + r_{0,1}\) gerade zum Return über die gesamte Zeit, d.h. von 0 bis t. Somit gilt dann automatisch auch \(R_{0,t}+1 = \frac{S_t}{S_0}=e^{r_0,t}=e^{\sum\limits_{k=1}^t r_{k-1,k}} = \prod\limits_{k=1}^t e^{r_{k-1,k}} = \prod\limits_{k=1}^t \left(R_{k-1,k} +1 \right)\) gilt - also ähnlich wie beim (geometrischen) Verzinsen.

to do: code von finance-pandas.ipynb anpassen!!!

Statistische Analyse der Returns bzw. Renditen#