Wie man auf Daten im Netz zugreift

In vielen Fällen sind Daten, die man gerne verarbeiten möchte, nicht auf der lokalen Maschine, sondern befinden sich in einem Online-Repository. Das kann entweder ein File Host sein oder es ist eine API, über die man mittels einer URL die gewünschten und ggf. sogar schon vorgefilterten Daten erhalten kann. Wie man da ran kommen kann, zeigen wir, weil es ein leicht verständliches Beispiel ist, mit den Daten des DAX, die wir aus der Yahoo Finance API beziehen.

Die Basics: Wie kommt man an Online-Daten heran?

Viele Anbieter im Netz stellen ihre Daten über eine API bereit, die meist auch mehr oder weniger leicht gefunden werden kann. Gelegentlich findet man auch eine Dokumentation, wie man diese zu verwenden hat, meist reicht aber auch ein Blick auf die zugehörige URL. In unserem Beispiel möchten wir historische Daten des DAX aus der Yahoo Finance API beziehen. Diese finden wir (für den DAX, für andere Aktienindices ist das aber analog) unter https://de.finance.yahoo.com/quote/%5EGDAXI/history?p=%5EGDAXI. Yahoo macht es uns einfach, indem sie einen Downloadbutton anbieten, dessen Link direkt eine lesbare URL anzeigt:

https://query1.finance.yahoo.com/v7/finance/download/%5EGDAXI?period1=1663484464&period2=1695020464&interval=1d&events=history&includeAdjustedClose=true

Der erste Teil bis einschließlich /download/ beschreibt den Typ der API. Das ist für uns nebensächlich und muss einfach so verwendet werden. Die Parameter, die danach auftreten, sind für uns viel interessanter. %5EGDAXI ist der Name des Aktienindices und enthält einen HEX-enkodierten Zirkumflex (diese Zeichen sind nicht als Teil einer URL erlaubt), ist also als ^GDAXI zu lesen. Als ein weiteres Beispiel wird der EuroSTOXX50 als %5ESTOXX50E, als ^STOXX50E dargestellt.

period1 und period2 beschreiben zwei Zeitpunkte in Sekunden seit der Epoche, also seit dem 1.1.1970. interval enthält die Zeitauflösung, in unserem Fall 1 Tag, events=history besagt, dass wir historische Daten wollen und includeAdjustedClose=true ergänzt die erhaltenen Daten um eine weitere Spalte mit den angepassten Schlusskursen.

Verwenden wir diesen Link, so sendet die API uns eine CSV-Datei, was sehr charmant und einfach zu handeln ist. Folglich können wir das Kommando url verwenden, um direkt Daten aus dieser API zu erhalten. Dabei wird die CSV-Datei mit der folgenden Zeile als dax.csv in <loadpath> gespeichert:

url "https://query1.finance.yahoo.com/v7/finance/download/%5EGDAXI?period1=1663484464&period2=1695020464&interval=1d&events=history&includeAdjustedClose=true" -file="<loadpath>/dax.csv";

Aber natürlich wollen wir nicht jedes Mal die Daten zwischen den gleichen zwei Zeitpunkten, sondern zum Beispiel immer vom letzten Jahr bezogen auf das aktuelle Datum. Dazu müssen wir das entsprechende Datum in Sekunden enkodieren, was wir mit der Funktion as_date(nYear, nMonth, nDay) einfach erreichen können. Den erhaltenen Wert wandeln wir dann mittels des String-Parsers direkt in einen String um: #as_date(...)

(Der komplette Code bereit zum Kopieren und Ausführen kann unten gefunden werden)

Führen wir das Kommando aus, laden die Daten herunter und laden sie anschließen in NumeRe, können wir sie z.B. mit der candlestick Plotoption plotten. Dabei erhalten wir das folgende Ergebnis:

Wie können wir diese Daten weiterverarbeiten?

Beim genauen Hinschauen fällt auf, dass manche der Balken in dem Candlestick-Plot breiter sind als alle anderen Balken. Untersucht man die zugehörigen Daten, so findet man, dass nur die Werktage, also die Börsenhandelstage darin zu finden sind. Da die Breite der Balken vom Abstand zum jeweils folgenden Datenpunkt abhängt, indizieren diese zufälligerweise also immer die Tage vor Wochenenden und Feiertagen.

Wir können das beheben, indem wir die fehlenden Wochenenden in die Daten mit dem Wert NaN einfügen. Dabei wollen wir die Reihenfolge der Daten möglichst beibehalten und die Wochenenden an den korrekten Positionen vorfinden. Hier bringt der matop Modus die hilfreiche Funktion coordstogrid() ins Spiel, mit deren Hilfe man Koordinaten aus einem Datengitter in ein anderes Datengitter interpolieren kann (bzw. das Ganze eben auch eindimensional), also damit bestimmen kann, an welchem Rasterpunkt eines anderen Gitters sich die übergebenen Punkte befinden würden. Um das zu verwenden, erzeugen wir zunächst eine vollständige Koordinatenachse inklusive der Wochenenden mithilfe {as_date(nYear-1, nMonth, nDay):86400:as_date(nYear, nMonth, nDay)}, wobei 86400 genau die Zahl der Sekunden je Tag ist. In diese Achse bilden wir nun die vorhandenen Datenpunkte mit coordstogrid() ab.

Das Ganze sieht jetzt schon deutlich ansehnlicher aus. Doch wir können noch mehr machen, um die Daten noch zugänglicher zu machen: wir können den langfristigen Trend durch das gleitende Mittel herausstellen. Eine mögliche Funktion dafür ist die Matrix-Funktion movavg(). Diese kommt auch mit Datenreihen zurecht, die NaNs enthalten. Allerdings können wir auch mit dem Kommando retouch die fehlenden Punkte in die Daten einfach hinein retuschieren. Das ist natürlich nicht perfekt, kann aber lückenhafte Daten in manchen Fällen deutlich leichter zu verarbeiten machen.

Im Folgenden sieht man den bereinigten Datensatz zusammen mit dem gleitenden Mittel, einmal direkt berechnet und einmal nach dem vorherigen Anwenden von retouch.

Bereit zum Nachmachen? Hier ist der Code: