Weiter zum Inhalt

Algorithmic Trading in R Tutorial

In diesem R-Tutorial führst du Web-Scraping durch, greifst auf eine Finance-API zu und nutzt ein htmlwidget, um ein interaktives Zeitreihendiagramm für eine einfache algorithmische Handelsstrategie zu erstellen
Aktualisiert 18. Sept. 2026  · 15 Min. lesen

Mit KI erkunden

ChatGPTClaudePerplexity

In diesem Beitrag zeige ich, wie du mit R die bei loyal3 gelisteten Aktien einsammelst, historische Daten von Yahoo abrufst und dann eine einfache algorithmische Handelsstrategie umsetzt. Dabei lernst du Web-Scraping, eine Funktion, die eine Finance-API ansteuert, und ein htmlwidget für ein interaktives Zeitreihendiagramm.

Für diesen Beitrag definiere ich ein Trading-„Algo“ als eine Menge von Regeln, die einen Kauf- oder Verkaufsvorgang auslösen – nicht als Vorhersagemodell oder Zeitreihenprognose. Das ist die einfachste Form eines Trading-Algorithmus. Wenn du mit R tiefer in Finance einsteigen willst, empfehle ich dir DataCamps Kurs zum Modellieren einer quantitativen Trading-Strategie in R.

Hintergrund

2015 habe ich begonnen, ein wenig über loyal3 zu investieren. Der Service ist ungewöhnlich und ein guter Einstieg in die eigene Investmentreise. Anstatt den Anlegern Gebühren zu berechnen, nimmt loyal3 die gelisteten Unternehmen in die Pflicht. Die Idee dahinter: Wer den Service eines Unternehmens mag, kauft auch dessen Aktie und wird so zum starken Markenbotschafter. Besonders attraktiv: Du kannst Bruchteile von Aktien kaufen. So kommst du schon mit 10 $ in die 800 $-Amazon-Aktie rein und legst jedes Mal weitere 10 $ nach, wenn am Monatsende etwas übrig bleibt. Klar, es gibt Reibungsverluste, weil nur in Zeitfenstern gehandelt wird und das Portfolio auf rund 70 Titel begrenzt ist. Aber loyal3 ist eine günstige und spielerische Möglichkeit, den Aktienhandel zu erkunden. Du kannst schon mit 10 $ „Skin in the Game“ haben!

Zur Einordnung: Ich habe die üblichen Altersvorsorge- und Investmentkonten, aber mir gefällt loyal3s aufgeräumte App und die fehlenden Gebühren. Mein kleines loyal3-Spaßportfolio checke ich öfter als meine Fonds – einfach weil es leicht ist und Spaß macht zu sehen, wie sich die selbst ausgewählten Titel schlagen.

algorithmic trading R
Die Aktien, die auf www.loyal3.com verfügbar sind

Deine Arbeitsumgebung einrichten

Zu Beginn lädst du die Bibliotheken in deine Umgebung. Für Web-Scraping nutze ich fast immer rvest. Es gibt weitere Pakete wie RSelenium, aber rvest ist sehr einfach anzuwenden.

Das zweite Paket, pbapply, ist optional – es fügt den apply-Funktionen lediglich einen Fortschrittsbalken hinzu. Da du unter Umständen Hunderte Seiten scrapest, hilft das bei der Zeiteinschätzung.

Als Nächstes kommt TTR, ein Paket, das ich gerade erkunde. Es dient zum Aufbau „Technischer Handelsregeln“. Auch wenn du hier nur ein einfaches Trading-Algo lernst, kann TTR deutlich fortgeschrittenere Berechnungen durchführen und lohnt sich.

Die dygraphs-Bibliothek ist ein Wrapper für eine schnelle, Open-Source-JavaScript-Charting-Library. Als htmlwidget macht sie R-Charts dynamisch und direkt Teil einer HTML-Seite statt nur statischer Bilder. Zuletzt hilft lubridate bei der komfortablen Datumsverarbeitung.

library(rvest)
library(pbapply)
library(TTR)
library(dygraphs)
library(lubridate)

Datenerfassung

Alle loyal3-Aktien sind auf einer Seite gelistet. Bevor du einzelne Tageskurse für deinen Trading-Algorithmus abrufst, brauchst du alle verfügbaren Ticker. Zuerst definierst du stock.list als URL-String. Dann nutzt du read_html(), damit deine R-Session eine Internetsitzung öffnet und den HTML-Inhalt der Seite als XML-Knotenset lädt. Im CSS der Seite gibt es eine ID „.company-name“. Verwende sie als Parameter in html_nodes(), um nur die XML-Daten zu diesem Knoten zu selektieren. Mit html_text() holst du dir schließlich die eigentlichen Firmennamen als Text.

stock.list<-'https://www.loyal3.com/stocks'
stocks<-read_html(stock.list)
stocks.names<-html_nodes(stocks,'.company-name')
stocks.names<-html_text(stocks.names)

Um die verfügbaren Titel bei loyal3 anzusehen, gib das Objekt stocks.names in der Konsole aus. Es liefert die Firmennamen als Textvektor.

stocks.names 

Für die Kursrecherche brauchst du zuerst das Tickersymbol. Auf der loyal3-Seite kannst du auf die Firmenkachel klicken und gelangst auf eine Seite mit dem Ticker und weiteren Infos.

Mit html_nodes() auf stocks holst du alle mit „a“ markierten Knoten. In HTML definiert das <a>-Tag einen Hyperlink, der Seiten miteinander verbindet. Im Link-Tag steht in „href“ die genaue URL. html_attr() extrahiert daher die URL ALLER Links der Seite, wenn du „href“ übergibst.

Nach manueller Prüfung habe ich festgestellt: Die Links 54 bis 123 der Seite sind die Firmenseiten, von denen ich die Ticker hole. In der letzten Zeile fügt paste0() die Basis-URL ’http://www.loyal3.com` mit den spezifischen Firmenseiten wie „/WALMART“ zusammen. Beispiel: http://www.loyal3.com/WALMART:

loyal.links<-html_nodes(stocks, "a")
loyal.links<-html_attr(loyal.links, "href")
stock.links<-paste0('http://www.loyal3.com',loyal.links[54:123])

Auf jeder Firmenseite gibt es eine Beschreibung, den jüngsten Schlusskurs und den Ticker. Alle Seiten sind gleich aufgebaut, daher kannst du die Funktion get.ticker() schreiben, um das Tickersymbol zu ziehen.

Auf der Unternehmensseite steht eine Tabelle „ticker-price“. Die Funktion ruft die Seite auf, findet die Tabelle, extrahiert den Text mit html_text() und nutzt dann sub() mit dem regulären Ausdruck ^([[:alpha:]]*).* und \\1, um nur die Buchstaben zu behalten. So werden Sonderzeichen wie $ und Ziffern (z. B. der Schlusskurs) entfernt. Beim Einlesen der rund 70 Seiten sammelt die Funktion nur den Ticker.

 get.ticker<-function(url){
  x<-read_html(url)
  x<-html_node(x,'.ticker-price')
  x<-html_text(x)
  x<-sub("^([[:alpha:]]*).*", "\\1", x)
  return(x)
  } 
loyal3 stock page for Alibaba
Die loyal3-Aktienseite von Alibaba; die Tabelle mit dem Ticker der Aktie, BABA, steht unter dem fett gesetzten Text

Mit deiner Funktion kannst du pblapply() auf die stock.links anwenden, die jeweils auf die Firmenseite zeigen. Das Ergebnis, stock.tickers, ist eine Liste einzelner Ticker, pro Element ein Unternehmen.

stock.tickers<-pblapply(stock.links,get.ticker)

Eine Liste in ein flaches Objekt zu überführen, geht zum Beispiel mit do.call(). Hier wendest du rbind an, um die Listenelemente zu einem Vektor zu verbinden. Anschließend erstellst du ein Data Frame mit Symbol und Firmennamen.

stock.ticks<-do.call(rbind,stock.tickers)
stock.ticks<-data.frame(symbol=stock.ticks,name=stocks.names)

Für eine konsistente Analyse möchtest du den historischen Zeitraum je Aktie vielleicht begrenzen. Die Funktion Sys.Data() speichert ein Datumsobjekt als Jahr, Monat, Tag. Mit Jahren als Integer kannst du vom Objekt start.date eine bestimmte Zeitspanne subtrahieren.

start.date<-Sys.Date()
end.date<-Sys.Date()-years(3)

Für Yahoo Finance müssen die Datumsobjekte zu einfachen Zeichenketten ohne Bindestriche werden. Mit der globalen Ersetzungsfunktion gsub() auf start.date und end.date änderst du gleichzeitig die Klasse und entfernst die Bindestriche. In gsub() gibst du zuerst das Suchmuster, dann den Ersatz an. Hier ist der Ersatz eine leere Zeichenkette. Der letzte Parameter ist das Objekt, auf das gsub() angewandt wird.

start.date<-gsub('-','', start.date)
end.date<-gsub('-','', end.date)

Die TTR()-Funktion getYahooData() nimmt ein Symbol sowie Start- und Enddatum entgegen und liefert ein Data Frame mit Zeitreiheninformationen. Jede Zeile ist ein Datum, die Spalten enthalten u. a. „Open“, „High“, „Low“ und „Close“. Da du mehrere Unternehmen abfragst, nutzt du lapply() oder pblapply(). Übergebe den Vektor der Symbole, dann die Funktion getYahooData() und die Datumsangaben. Die date-Objekte werden bei jedem Aufruf an das jeweilige Symbol recycelt.

 stocks.ts<-pblapply(stock.ticks$symbol,getYahooData,end.date, start.date)

Damit sich die zurückgegebene Liste stocks.ts leichter navigieren lässt, kannst du die Listenelemente benennen. Weise mit names die Namen aus dem ursprünglichen $symbol-Vektor zu.

names(stocks.ts)<-stock.ticks$symbol

Bei großen Listen prüfe ich gern das Ergebnisobjekt, um sicherzugehen, dass alles wie erwartet ist. Jetzt, da die Elemente Namen haben, kannst du sie direkt referenzieren. Im Beispiel siehst du die ersten 6 Zeilen für AMC Entertainment Holdings (AMC). Ein head() auf die Liste mit Referenz $AMC gibt einen Ausschnitt der Zeitreihe zurück:

head(stocks.ts$AMC)

Aktiendaten untersuchen

Wenn ich Finanznachrichten höre, verweisen die Kommentatoren oft auf Charts. Trotz High-Frequency-Trading und aktivem Management orientieren sich viele Privatanleger an Charts, um ein Gefühl zu bekommen. Zeitreihenobjekte lassen sich schnell mit plot anzeigen. Übergebe das Listenelement, etwa $AMC, und dann die Spalte, die du darstellen willst, hier $Close.

plot(stocks.ts$AMZN$Close)
stocks plot

Der Plot oben ist statisch und nicht besonders spannend.

Lass uns eine JavaScript-Bibliothek nutzen und einen erkundbaren Chart bauen. Im Snippet siehst du den „%>%“- oder Pipe-Operator. Damit schreibst du kompakten Code, weil ein Objekt an die nächste Funktion weitergereicht wird, ohne dass du es ständig neu benennen musst.

In diesem Beispiel erstellst du einen Dygraph für die Twitter-Aktie $TWTR und die zu plottende Spalte $Close. Im dygraph setzt main den Titel. Mit „%>%“ geht das gesamte Objekt an dyRangeSelector() weiter. Mit c() definierst du eine Standarddatumsspanne. Das Ergebnis ist ein dynamischer HTML-Chart für Twitters Aktie mit Datumsregler unten.

Den angezeigten Titel änderst du, indem du in der Liste stocks.ts das Tickersymbol und den Graphtitel anpasst.

dygraph(stocks.ts$TWTR$Close, main = "TWTR Stock Price") %>%
  dyRangeSelector(dateWindow = c("2013-12-18", "2016-12-30"))

basic dygraph for Twitter’s stock
Ein einfacher Dygraph für Twitters Aktie

Eine einfache Trading-Strategie: Trendfolge

High-Frequency-Trader und Hedgefonds nutzen ausgefeilte Modelle und regelbasierte Ansätze für ihre Ausführungen. Wenn du mehr lernen willst, schau bei www.quantopian.com für fortgeschrittene Ansätze vorbei. Für einfachere Herangehensweisen starte mit dieser Seite auf www.Investopedia.com.

Im folgenden Code visualisierst du eine simple Momentum-Strategie. Im Kern berechnest du die 200- und 50-Tage-Gleitdurchschnitte eines Kurses. An Tagen, an denen der 50-Tage-Durchschnitt über dem 200-Tage-Durchschnitt liegt, würdest du kaufen oder halten. Liegt der 200er über dem 50er, würdest du verkaufen. Diese Strategie heißt Trendfolge. Das Vorzeichen der Differenz der beiden zeitbasierten Durchschnitte steht für das Momentum der Aktie.

Das Paket TTR stellt SMA() für Simple Moving Averages bereit. Im Snippet siehst du die ersten 6 Werte von Twitters 200- und 50-Tage-Durchschnitten. SMA() bekommt die Zeitreihe einer Aktie und eine konkrete Spalte wie Close – also den Vektor der Schlusskurse von TWTR. Der zweite Parameter ist die Zahl der Beobachtungen für den Durchschnitt. Ohne head() liefert SMA() alle Werte.

head(SMA(stocks.ts$TWTR$Close, 200))
head(SMA(stocks.ts$TWTR$Close, 50))

Nachdem du die Funktionsweise im Detail geprüft hast, musst du sie auf alle rund 70 Aktien anwenden. stocks.ts ist eine Liste aus 70 Data Frames mit einzelnen Aktiendaten. Die vierte Spalte enthält die Schlusskurse, die wir für die Durchschnitte brauchen.

Die Funktion mov.avgs() nimmt einen einzelnen Aktien-Data-Frame und berechnet die Gleitdurchschnitte. Zuerst wählt sie die Schlusskurse über [,4] und speichert sie in stock.close. Dann prüft ifelse die Zeilenzahl. Ist nrow kleiner als (2*260), erzeugt die Funktion ein Data Frame mit „NA“-Spalten für die Durchschnitte.

Die Wahl fällt auf diesen Schwellenwert, weil es pro Jahr etwa 250 Handelstage gibt. So stellst du sicher, dass die Zeitreihe ca. zwei Jahre oder länger ist. Loyal3 kommt teils an IPOs, und bei frisch gelisteten Aktien fehlt es an Daten für den 200-Tage-Durchschnitt. Ist nrow größer als 2*260, erstellt die Funktion ein Data Frame mit den Originaldaten plus 200- und 50-Tage-Durchschnitten als neue Spalten. Mit colnames setzt du die Spaltennamen. Am Ende verwendet die Funktion complete.cases auf der 200er-Spalte und entfernt Zeilen ohne Wert.

mov.avgs<-function(stock.df){
  stock.close<-stock.df[,4]
  ifelse((nrow(stock.df)<(2*260)),
         x<-data.frame(stock.df, 'NA', 'NA'),
         x<-data.frame(stock.df, SMA(stock.close, 200), SMA(stock.close, 50)))
  colnames(x)<-c(names(stock.df), 'sma_200','sma_50')
  x<-x[complete.cases(x$sma_200),]
  return(x)
  }

Mit mov.avgs() kannst du per pblapply() die Gleitdurchschnitte zu allen 70 Data Frames hinzufügen.

stocks.ts<-pblapply(stocks.ts, mov.avgs)

Mit dem folgenden Code visualisierst du die Gleitdurchschnitte einer Aktie in einem Dygraph. Wieder kommt der „%>%“-Operator zum Einsatz. dygraph() erhält das Data Frame stocks.ts$FOX und wird per Spaltennamen mit c('sma_200','sma_50') indiziert. Dieses Objekt geht an dySeries() in den nächsten zwei Zeilen weiter. Jeweils per Spaltenname zeichnet dySeries() eine Linie für „sma_50“ und „sma_200“. Anschließend passt dyRangeSelector() die Höhe des Selektors an. Zum Schluss habe ich Schattierungen ergänzt, um Phasen zu markieren, in denen du kaufen/halten würdest, und Phasen, in denen du verkaufen oder draußen bleiben solltest – je nach Position.

dygraph(stocks.ts$FOX[,c('sma_200','sma_50')],main = 'FOX Moving Averages') %>%
  dySeries('sma_50', label = 'sma 50') %>%
  dySeries('sma_200', label = 'sma 200') %>%
  dyRangeSelector(height = 30) %>%
  dyShading(from = '2016-4-28', to = '2016-7-27', color = '#CCEBD6') %>%
  dyShading(from = '2016-7-28', to = '2016-12-30', color = '#FFE6E6')

Hier ist das Endergebnis als interaktive Zeitreihe.

fox moving averages
Die FOX-Gleitdurchschnitte mit markierten Phasen für Kaufen/Halten vs. Verkaufen

Fazit

Als angehender Algorithmus-Trader musst du nicht alle 70 Aktien plotten. Sinnvoller ist es, den Code täglich laufen zu lassen und programmatisch die Titel zu identifizieren, die zur Regel passen: „Kaufe, wenn der 50-Tage-Durchschnitt über dem 200-Tage-Durchschnitt liegt.“ Im Chart oben markiert Grün eine Phase, in der du FOX gekauft hättest. Rot steht für die Zeit, in der du verkauft und draußen geblieben wärst.

Da der Chart interaktiv ist, kannst du die Ansicht mit dem Slider anpassen. Nach diesem einfachen Algo-Ansatz könnte jetzt ein guter Zeitpunkt sein, FOX zu kaufen! Am 30. Dezember 2016 lag der 50-Tage-Durchschnitt um 0,01 $ über dem 200-Tage-Durchschnitt!

fox equity
Der gezoomte Abschnitt der FOX-Aktie

Denk daran: Jedes Investment kann an Wert verlieren. Wenn du mehr zu Finance und Algo-Trading lernen willst, schau dir DataCamps Kurse hier an.

Wirf auch einen Blick in unser Tutorial Basic Programming Skills in R.

Themen
R
Datenwissenschaft

Mehr über R lernen

Kurs

Einführung in R

4 Std.
3.1M
Beherrsche die Grundlagen der Datenanalyse in R, einschließlich Vektoren, Listen und Datenrahmen, und übe R mit echten Datensätzen.
Details anzeigenRight Arrow
Kurs Starten
Mehr anzeigenRight Arrow