Der heutige Beitrag behandelt die Beschaffung, Transformation und Darstellung von Kursdaten mit Hilfe der Python-Bibliotheken yfinance (ermöglicht den Bezug von Daten von Yahoo Finance) und mplfinance (Visualisierung von Börsendaten). Das nachfolgende Tutorial eignet sich für alle die, welche schnell und effizient ein Kursdiagramm eines Wertpapiers zeichnen und mit verschiedenen zusätzlichen Information (zum Beispiel Volumen, Trendlinien oder Verkauf-/Kaufsignale) versehen wollen.
Voraussetzungen
Damit die nachfolgenden Befehle auch korrekt ausgeführt werden können, muss eine funktionierende Python-Umgebung vorhanden sein. Eine Möglichkeit (Anaconda) wurde in einem der ersten Beiträge auf diesem Blog vorgestellt. Zusätzlich müssen noch folgende Python-Pakete installiert werden:
- yfinance (Bezug von Daten der Webseite Yahoo Finance)
- mplfinance (Erstellung von Kursdiagrammen)
- ta (Technische Analysen)
Befehle
Die nachfolgenden Python-Anweisungen wurden ursprünglich mit Jupyter Notebook erstellt. Dabei handelt es sich um eine webbasierte, interaktive Plattform. Dabei werden die Ausgaben der einzelnen Befehle direkt im Anschluss an diese angezeigt. Auch Textpassagen können in Form von Markdown eingebaut werden. Die nachfolgenden Zeilen wurden direkt aus dieser Plattform exportiert.
Genug der Vorworte, nun sind wir startklar und können endlich mit dem spannenden Teil beginnen. Zuerst müssen alle benötigten Bibliotheken importiert werden:
1 | import yfinance as yf |
Danach kann eine beliebige Aktie beziehungsweise ein ETF gesucht werden. Um das Ticker-Symbol zu finden, kann auf der Seite Yahoo Finance im Suchfeld die gewünschte Aktie gesucht werden, wobei das Symbol in der ersten Spalte der Suchresultate steht (bei Tesla zum Beispiel TSLA). In diesem Beispiel wird der iShares MSCI ACWI UCITS ETF USD (Acc) verwendet, welcher unter anderem an der XETRA (in Euro) gehandelt wird:
1 | quote = yf.Ticker('IUSQ.DE') |
Nun können verschiedene Aktionen auf dem Ticker-Objekt durchgeführt werden. Eine davon ist der Bezug von historischen Kursen. Mit Hilfe der Periode kann die Anzahl der Resultate gesteuert werden (mit max werden alle verfügbaren Datensätze geladen):
1 | hist = quote.history(period='max') |
Das Ergebnis der Abfrage kann angezeigt werden. Dies ist wichtig, um allfällige Fehler in den Daten zu finden. Es kann manchmal vorkommen, dass Unregelmässigkeiten in den Werten von Yahoo Finance auftauchen.
1 | hist |
Open | High | Low | Close | Volume | Dividends | Stock Splits | |
---|---|---|---|---|---|---|---|
Date | |||||||
2011-10-21 | 21.370001 | 21.370001 | 21.370001 | 21.370001 | 0 | 0 | 0 |
2011-10-24 | 21.370001 | 21.370001 | 21.370001 | 21.370001 | 0 | 0 | 0 |
2011-10-25 | 21.370001 | 21.370001 | 21.370001 | 21.370001 | 0 | 0 | 0 |
2011-10-26 | 21.370001 | 21.370001 | 21.370001 | 21.370001 | 0 | 0 | 0 |
2011-10-27 | 21.370001 | 21.370001 | 21.370001 | 21.370001 | 0 | 0 | 0 |
… | … | … | … | … | … | … | … |
2022-03-31 | 65.050003 | 65.320000 | 64.959999 | 64.959999 | 158336 | 0 | 0 |
2022-04-01 | 64.900002 | 65.489998 | 64.820000 | 64.820000 | 198900 | 0 | 0 |
2022-04-04 | 65.220001 | 65.769997 | 65.000000 | 65.720001 | 83534 | 0 | 0 |
2022-04-05 | 65.970001 | 66.080002 | 65.660004 | 65.839996 | 114113 | 0 | 0 |
2022-04-06 | 65.620003 | 65.699997 | 64.489998 | 64.639999 | 77849 | 0 | 0 |
2651 rows × 7 columns
In der Ausgabe ist zu sehen, dass nicht nur die Schlusskurse mitgeliefert werden. Dividenden sowie das Handelsvolumen werden ebenfalls von der Datenquelle geliefert.
Nun soll der Kursverlauf in einem Diagramm visualisiert werden. Dazu sind einige Vorbereitungsarbeiten notwendig. Die nächsten beiden Zeilen definieren die Gestaltung des resultierenden Diagramms. Der dritte Befehl legt die Anzahl an Datenpunkten fest, welche in der Grafik gezeichnet werden sollen.
1 | mc = mpf.make_marketcolors(up='#00ff00', down='#ff0000', inherit=True) |
Die nachfolgende Anweisung generiert mit Hilfe von mplfinance ein Liniendiagramm inklusive Handelsvolumen. Die Werte für den Titel sowie die Y-Achse (Währungsinformation) des oberen Diagramms werden aus dem Attribut info des quote-Objektes entnommen. Mit Hilfe der Option figscale kann die Grösse der Grafik beeinflusst werden. Die Methode tail liefert die letzten x-Einträge des DataFrame’s (pandas Datenobjekt) zurück.
1 | mpf.plot(hist.tail(number_of_datapoints), type='line', title=quote.info['longName'], ylabel='Price (%s)' % quote.info['currency'], volume=True, style=s, figscale=1.5) |
Nun haben wir jedoch das Problem, dass wir nur einen sehr kleinen Datenbereich anzeigen können. Um alle Datenpunkte (ca. 2’600) visualisieren zu können, müssen die Datenpunkte zusammengelegt werden. Dazu werden pandas-Hilfsmethoden verwendet, um 5 Handelstage zu einem Datensatz zusammenzulegen.
1 | hist_1w = hist.asfreq('1D').resample('5D').agg({'Open': lambda x: x.bfill().iloc[0], 'High': max, 'Low': min, 'Close': lambda x: x.pad().iloc[-1], 'Volume': sum}) |
Danach wird das Resultat überprüft und die Anzahl der Datenpunkte erhöht:
1 | hist_1w |
Open | High | Low | Close | Volume | |
---|---|---|---|---|---|
Date | |||||
2011-10-21 | 21.370001 | 21.370001 | 21.370001 | 21.370001 | 0.0 |
2011-10-26 | 21.370001 | 21.370001 | 21.370001 | 21.370001 | 0.0 |
2011-10-31 | 21.370001 | 21.370001 | 21.370001 | 21.370001 | 0.0 |
2011-11-05 | 21.370001 | 21.370001 | 21.370001 | 21.370001 | 0.0 |
2011-11-10 | 21.370001 | 21.370001 | 21.370001 | 21.370001 | 0.0 |
… | … | … | … | … | … |
2022-03-17 | 62.720001 | 64.180000 | 62.200001 | 63.779999 | 242524.0 |
2022-03-22 | 64.309998 | 64.930000 | 64.209999 | 64.690002 | 309921.0 |
2022-03-27 | 64.989998 | 65.629997 | 64.839996 | 64.959999 | 567759.0 |
2022-04-01 | 64.900002 | 66.080002 | 64.820000 | 65.839996 | 396547.0 |
2022-04-06 | 65.620003 | 65.699997 | 64.489998 | 64.639999 | 77849.0 |
765 rows × 5 columns
1 | number_of_datapoints = 200 |
Die Python-Bibliothek mplfinance bietet auch die Möglichkeit, den bestehenden Graphen mit weiteren Informationen zu überlagern. Nun soll in einem nächsten Schritt ein Element der technischen Analyse integriert werden. In diesem Fall handelt es sich um den MACD Oszillator, welcher auf dem Schlusskurs berechnet wird:
1 | macd_obj = MACD(hist_1w['Close'].tail(number_of_datapoints)) |
Nun werden die zusätzlichen Datenpunkte in einem Array abgelegt. Mit dem Attribut panel wird der Ort angegeben, wo die Punkte gezeichnet werden sollen (wobei das erste Diagramm den Wert 0 hat):
1 | adps = [ |
Nach diesem Schritt kann die neue Grafik kreiert werden. Dieses Mal wird ein Kerzen-Diagramm mit einem gleitenden Durchschnitt (SMA, mit Fenstergrösse 14) erstellt. Darunter ist der MACD Oszillator zu finden:
1 | mpf.plot(hist_1w.tail(number_of_datapoints), addplot=adps, type='candle', mav=(14,), style=s, figscale=1.5) |
Als letzter Schritt sollen die Kauf- beziehungsweise Verkaufssignale berechnet und im Diagramm angezeigt werden. Dazu werden wieder Methoden der pandas-Bibliothek verwendet. Ändert das MACD-Histogramm von Zeitpunkt t-1 zu t das Vorzeichen (Plus zu Minus), handelt es sich um ein Verkaufssignal. Wechselt das Vorzeichen von Minus zu Plus, bedeutet dies ein Kaufsignal.
1 | sell_signal = macd_obj.macd_diff().rolling(2).apply(lambda x: 1 if x[0] > 0 and x[1] < 0 else 0).fillna(0).rename('Sell_Signal') |
Im Anschluss werden die Signale zu dem bestehenden Datenobjekt hinzugefügt und als Subgraph in das bereits bestehende Array aufgenommen
1 | hist_1w['Sell_Signal'] = hist_1w.join(sell_signal).apply(lambda x: x['High'] + 2 if x['Sell_Signal'] == 1 else np.nan, axis=1) |
Danach wird das finale Diagramm erstellt:
1 | mpf.plot(hist_1w.tail(number_of_datapoints), addplot=adps, type='candle', mav=(14,), style=s, figscale=1.5) |
Die verwendeten Bibliotheken bieten natürlich noch viele weitere Funktionalitäten an. Auf den Projekt-Webseiten sind weitere Beispiele und Ideen zu finden.