Baue Deinen eigenen Cost Averaging ETF-Sparplan mit der lemon.markets API


Veröffentlicht von undefined am Invalid Date
Trading


Oder mit anderen Worten, richte eine "faule" Automatisierung für Deine wiederkehrenden Trades ein.

Hey! Ich bin Joanne und ich bin Teil von lemon.markets 🍋  Wir sind ein Startup, das eine Brokerage Infrastruktur für Entwickler:innen baut. Mit unserer API kannst Du an der Börse partizipieren und mit ihr interagieren, indem Du beispielsweise eine automatisierte Trading-Strategie implementierst oder dein personalisiertes Dashboard für Dein Portfolio baust.

In diesem Blogpost führe ich Dich durch eine einfache Dollar-Cost-Averaging Strategie, mit der Du Deinen Sparplan automatisieren kannst. Nichts Ausgefallenes - sie soll nur Dein Leben einfacher machen 😉. Und um das Ganze abzurunden, zeige ich Dir auch, wie Du einen Telegram-Bot einrichtest, der Dir Trade-Benachrichtigungen schickt. Selbst wenn Du Dir noch nicht sicher bist, was Du mit der API bauen möchtest, wird dieser Blog Post Deine kreative Ader anregen. Meld Dich hier bei lemon.markets an und leg direkt los.

Was ist "Dollar-Cost-Averaging"?

Wenn Du bereits regelmäßig investierst, indem Du z.B. 10% Deines monatlichen Gehalts in einen ETF oder Investmentfonds steckst, dann machst Du bereits Dollar-Cost-Averaging (oder eher Euro-Cost-Averaging). Aber was bedeutet diese Strategie nun eigentlich? Stell Dir vor, Du hast eine große Summe Geld, sagen wir 10.000 €, die Du investieren möchtest. Wenn Du Dollar-Cost-Averaging (DCA) betreiben möchtest, würdest Du Deine Einzahlungen verteilen. Also beispielsweise indem Du 1.000 € monatlich über einen Zeitraum von 10 Monaten investierst. Das Gegenteil von DCA ist Lump-Sum-Investing (Einmalanlage), was bedeutet, dass Du die gesamte Summe auf einmal investierst.

Aber welche dieser Strategien ist nun besser? Viele Investoren wählen DCA gegenüber der Einmalanlage, weil es das Risiko senkt. Man kann davon ausgehen, dass der Preis eines Wertpapiers über diese 10 Monate mal steigen und mal fallen wird. Indem Du konsequent investierst, kaufst Du mehr oder weniger den durchschnittlichen Kurs und hast somit einen Durchschnittspreis. Idealerweise würdest Du dabei nur “günstig” kaufen, aber man kann den Markt nunmal nicht vorhersagen 🤷‍♀  Warum solltest Du also jemals etwas anderes als DCA machen? Der Vorteil von Einmalanlagen ist, dass Dein Geld sofort für Dich arbeitet und nicht noch monatelang auf dem Sparbuch liegt. Auf der anderen Seite läufst Du Gefahr, den Markt schlecht zu timen und “teuer” zu kaufen...

Aber warum nicht eine Plattform nutzen, die einen vorgefertigten Sparplan anbietet? Ganz einfach: Individualisierung und Transparenz. Bei einem vorgefertigten Sparplan fehlt Dir die Flexibilität, das Datum und die Uhrzeit der Handelsausführung anzugeben - das führt oft zu ungünstigen Konditionen für Dich. Wenn Du Deine Sparstrategie mit der lemon.markets API baust, hast Du die volle Kontrolle über alle Parameter. Du kannst gängige Kauftermine, wie den Monatsanfang und das Monatsende, vermeiden. Auf diese Weise hast Du einen Preisvorteil gegenüber den anderen DCA-Investoren. Ganz allgemein bist du viel flexibler und kannst wählen, was Du wann an welcher Börse wie oft und wie lange handelst. Außerdem bist Du nicht nur auf ETFs beschränkt - vielleicht möchtest Du auch Pinterest-Aktien besparen. Mit lemon.markets steht Dir steht alles offen.

Die DCA-Strategie automatisieren 💵.

Klar, Du könntest Dich einfach in Dein Depot einloggen und wöchentlich manuell einen Trade platzieren. Aber Du kannst diesen Prozess auch automatisieren. Ich weiß nicht, wie es Dir geht, aber letzteres klingt irgendwo cooler (und Dein Zukunfts-Ich wird es Dir wahrscheinlich danken). Also, lass uns gleich mit dem Programmieren beginnen.

Ich habe mich bei dieser Anwendung für Python entschieden, aber Du kannst natürlich auch eine andere Sprache verwenden - die Logik bleibt dieselbe.

Einrichten der Szenerie

In diesem Skript werden wir GET, PUT und POST Requests an die lemon.markets API stellen müssen. Aus diesem Grund erstellen wir eine helper.py Datei mit der Klasse RequestHandler, die alle unsere Requests bearbeiten wird. Wir erstellen zwei separate GET-Funktionen, da wir GET Requests sowohl an unsere Trading- als auch an unsere Marktdaten-APIs stellen müssen.

1import os
2import requests
3from dotenv import load_dotenv
4class RequestHandler:
5    def __init__(self):
6        load_dotenv()
7        self.headers = {'Authorization': 'Bearer ' + os.environ.get('TOKEN_KEY')}
8        self.url_trading: str = os.environ.get("TRADING_URL")
9        self.url_market: str = os.environ.get("MARKET_URL")
10        self.auth_url: str = os.environ.get("AUTH_URL")
11    def get_token(self, endpoint: str, data):
12        response = requests.post(self.auth_url + endpoint, data)
13        return response
14    def get_data_trading(self, endpoint: str):
15        response = requests.get(self.url_trading + endpoint, headers=self.headers)
16        return response.json()
17    def get_data_market(self, endpoint: str):
18        response = requests.get(self.url_market + endpoint, headers=self.headers)
19        return response.json()
20    
21    def put_data(self, endpoint: str):
22        response = requests.put(self.url_trading + endpoint, headers=self.headers)
23        return response.json()
24    def post_data(self, endpoint: str, data):
25        response = requests.post(self.url_trading + endpoint, data, headers=self.headers)
26        return response.json()

Environment-Variablen

Hast Du gesehen, dass wir os.environ.get() verwenden, um auf verschiedene Environment-Variablen zuzugreifen? Wir müssen diese Variablen entweder in einer separaten .env Datei definieren, lokal in Deiner IDE oder auf der Cloud Plattform, die Du für Dein Skript verwendest (z.B. Heroku).

Die folgenden Umgebungsvariablen brauchst du, wenn Du dieses Skript ausführen willst:

1Environment Variable, Description
2TOKEN_KEY, Your access token
3CLIENT_ID, Your client ID
4CLIENT_SECRET, Your client secret
5MIC, Market identifier code of Trading Venue
6TRADING_URL, URL of our trading API
7MARKET URL, URL of our market-data API
8AUTH_URL, URL of our authentication API

Modelle

Im GitHub Repository für dieses Projekt wirst Du feststellen, dass wir ein Verzeichnis mit dem Namen "models" definiert haben, das drei Dateien enthält: Order.py, Token.py und TradingVenue.py. Das sind alles Objekte mit spezifischen Eigenschaften - sie spiegeln außerdem direkt die Struktur unserer API wieder. Mehr dazu in unserer Dokumentation.

Order Klasse

Eine Order wird u.a. durch ihre ISIN charakterisiert - auch hier findest Du in unserer Dokumentation eine ausführliche Beschreibung. Für unseren Use Case muss eine Order platziert, aktiviert und anschließend abgerufen werden. Diese Funktionalitäten können in der Order Klasse gesehen werden, wie unten definiert.

1import os
2from dotenv import load_dotenv
3from helpers import RequestHandler
4class Order(RequestHandler):
5    def place_order(self, isin: str, valid_until: float, quantity: int, side: str):
6        order_details = {
7            "isin": isin,
8            "valid_until": valid_until,
9            "side": side,
10            "quantity": quantity,
11        }
12        load_dotenv()
13        space_uuid = os.getenv("SPACE_UUID")
14        endpoint = f'spaces/{space_uuid}/orders/'
15        response = self.post_data(endpoint, order_details)
16        return response
17    def activate_order(self, order_uuid):
18        load_dotenv()
19        space_uuid = os.getenv("SPACE_UUID")
20        endpoint = f'spaces/{space_uuid}/orders/{order_uuid}/activate/'
21        response = self.put_data(endpoint)
22        return response
23    def get_order(self, order_uuid):
24        load_dotenv()
25        space_uuid = os.getenv("SPACE_UUID")
26        endpoint = f'spaces/{space_uuid}/orders/{order_uuid}/'
27        response = self.get_data_trading(endpoint)
28        return response

Wie Du siehst, können diese drei Funktionalitäten durch Requests an unsere API realisiert werden. Indem wir Order zu einer Unterklasse der RequestHandler Klasse machen, erweitern wir die Funktionen, die wir in der letzteren definiert haben. So können wir einfach (und sauber) mit der lemon.markets API interagieren.

Trading Venue Klasse

Jeder Handelsplatz hat einen MIC (Market Identifier Code) mit dem Du in unserer API die Börse, an der Du Deine Trades platzieren möchtest, spezifizieren kannst. Wir haben einen Blogpost über unseren Trading Venue Endpoint geschrieben, den Du hier lesen kannst. Grundsätzlich kann ein Handelsplatz natürlich entweder offen oder geschlossen sein. Mit dem folgenden Skript wollen wir prüfen, ob ein Handelsplatz geöffnet ist, die allgemeinen Öffnungszeiten abfragen und die Anzahl der Sekunden bis zur nächsten Marktöffnung bestimmen (für den Fall, dass der Handelsplatz geschlossen ist).

1import datetime
2import os
3from helpers import RequestHandler
4class TradingVenue(RequestHandler):
5    _is_open: bool = False
6    @property
7    def is_open(self) -> bool:
8        mic = os.environ.get("MIC")
9        endpoint = f'venues/?mic={mic}'
10        response = self.get_data_market(endpoint)
11        return response['results'][0].get('is_open', None)
12    def check_opening_times(self):
13        mic = os.environ.get("MIC")
14        endpoint = f'venues/?mic={mic}'
15        response = self.get_data_market(endpoint)
16        return response
17    def seconds_till_tv_opens(self):
18        times_venue = self.check_opening_times()
19        today = datetime.datetime.today()
20        opening_days_venue = times_venue['results'][0].get('opening_days', None)
21        next_opening_day = datetime.datetime.strptime(opening_days_venue[0], '%Y-%m-%d')
22        next_opening_hour = datetime.datetime.strptime(times_venue['results'][0]['opening_hours'].get('start', None),                                            '%H:%M')
23        date_difference = next_opening_day - today
24        days = date_difference.days + 1
25        if not self.check_if_open():
26            print('Trading Venue not open')
27            time_delta = datetime.datetime.combine(
28                datetime.datetime.now().date() + timedelta(days=1), next_opening_hour.time()
29            ) - datetime.datetime.now()
30            print(time_delta.seconds + (days * 86400))
31            return time_delta.seconds
32        else:
33            print('Trading Venue is open')
34            return 0

Token Klasse

Als letztes brauchen wir einen Token, um unsere Requests zu authentifizieren. In der .env Datei definieren wir zwar einen 'starting' Token, aber da Tokens ablaufen, müssen wir auf Dauer neue Tokens erhalten. Aus diesem Grund hat die Token Klasse nur eine Funktion: Das Abrufen eines neuen Tokens (und das anschließende Aktualisieren der Umgebungsvariable).

1import os
2from dotenv import load_dotenv
3from helpers import RequestHandler
4class Token(RequestHandler):
5    def get_new_token(self):
6        load_dotenv()
7        token_details = {
8            "client_id": os.getenv("CLIENT_ID"),
9            "client_secret": os.getenv("CLIENT_SECRET"),
10            "grant_type": "client_credentials",
11        }
12        endpoint = f'oauth2/token/'
13        response = self.get_token(endpoint, token_details)
14        os.environ['TOKEN_KEY'] = response.json().get('access_token', None)
15        return os.getenv('TOKEN_KEY')

Token ist wiederum eine Unterklasse von RequestHandler, da wir einen GET-Request an unsere API stellen müssen.

Das sind alle Modelle, die wir brauchen, um diese spezielle Strategie zum Laufen zu bringen. Dann lass uns nun alles zusammenfügen.

Die Zusammenkunft

Nachdem wir unsere Hilfsfunktionen und API-Objekte definiert und unseren Telegram-Bot eingerichtet haben, ist es nun an der Zeit, Puzzleteile zusammenzubringen.

Als ersten Schritt definieren wir die Funktion buy_order(), die mithilfe der ISIN eine Kauforder für eine Aktie platziert und aktiviert. Unsere API ist so aufgebaut, dass eine Order zuerst platziert wird (Status: inaktiv), anschließend aktiviert werden muss (Status: aktiviert) und letztendlich ausgeführt wird (Status: ausgeführt). Die Funktion prüft dabei kontinuierlich den Status der Order. Wenn sie schließlich ausgeführt wird, verwenden wir telegram-send, um eine Nachricht mit den Details des Trades zu verschicken. Anschließend lassen wir das Skript eine Woche lang schlafen bevor die nächste Order platziert wird.

Danach definieren wir unsere Hauptfunktion dollar_cost_averaging(). Hier prüfen wir zunächst, ob der Handelsplatz geöffnet ist und holen uns einen neuen Access-Token bevor wir die Funktion buy_order() mit unserem gewählten Wertpapier aufrufen. Sollte der Handelsplatz geschlossen sein, lassen wir das Skript schlafen bis die Börse wieder öffnet und platzieren anschließend unseren Trade. Von der Verwendung der time.sleep() Funktion raten wir generell ab, da sie Dein Skript für die Dauer der in der Funktion angegebenen Zeit unzugänglich macht. Um das Skript so einfach und lesbar wie möglich zu halten, haben wir uns hier dennoch dafür entschieden. Weiter unten schlagen wir diesbzeüglich nochmal eine Alternative vor

1from models.Order import Order
2from models.Token import Token
3from models.TradingVenue import TradingVenue
4import datetime
5import time
6import telegram_send
7def buy_order(isin: str):
8    """
9    This method places and activates a buy order for 1 unit of the specified instrument every week.
10    :param isin: isin of the instrument you want to buy
11    """
12    try:
13        placed_order = Order().place_order(
14            isin=isin,
15            valid_until=(datetime.datetime.now() + datetime.timedelta(hours=1)).timestamp(),
16            side="buy",
17            quantity=1,
18        )
19        order_uuid = placed_order.get('uuid')
20        activated_order = Order().activate_order(order_uuid)
21        print(activated_order)
22        while True:
23            order_summary = Order().get_order(order_uuid)
24            if order_summary.get('status') == 'executed':
25                print('executed')
26                break
27        average_price = order_summary.get('average_price')
28        amount_bought = order_summary.get('processed_quantity')
29        name_stock = order_summary.get('instrument').get('title')
30        telegram_send.send(messages=[f'Your automated trading strategy just purchased {amount_bought} share(s) of'
31                                     f' {name_stock} at €{average_price} per share.'])
32        time.sleep(604800)  # sleep for a week
33    except Exception as e:
34        print(e)
35        time.sleep(60)
36def dollar_cost_averaging():
37    while True:
38        if TradingVenue().is_open:
39            Token().get_new_token()
40            buy_order(
41                isin="LU0274208692",  # XTRACKERS MSCI WORLD SWAP
42            )
43        else:
44            time.sleep(TradingVenue().seconds_till_tv_opens())
45if __name__ == '__main__':
46    dollar_cost_averaging()

Im obigen Code-Snippet habe ich mich für einen ETF entschieden, der Aktien aus allen Teilen der Welt beinhaltet. Auf diese Weise verringern wir unser Risiko weiter. Aber natürlich kann man diese Strategie auch auf einzelne Aktien oder verschiedene ETFs anwenden.

Vielleicht ist Dir die Zeile mit dem telegram_send() aufgefallen und Du fragst Dich, was das zu bedeuten hat. Wir müssen noch einen Telegram-Bot einrichten, um sicherzustellen, dass der obige Code funktioniert. Also, auf geht’s!

Einen Telegram Bot einrichten 🤖

Falls Du Telegram noch nicht kennst, das ist eine Messaging Software, die es einem auch erlaubt Bots zu bauen. Wir werden die Telegram API nutzen, um einen Bot zu konfigurieren, der Dir automatisch Nachrichten auf Dein Smartphone sendet, sobald ein Trade ausgeführt wurde.

In der folgenden Sektion lernst du wie du Telegram Notifikation einrichtest.

Zunächst musst Du Deinen Bot registrieren, indem Du /newbot an BotFather sendest (weitere Erklärungen findest Du hier). Das Ergebnis ist ein Token, ähnlich wie der Token der lemon.markets API.

Um den Prozess zu vereinfachen, verwende ich das telegram-send Kommandozeilentool, das Du mit pip wie folgt installieren kannst:

1$ pip install telegram-send
2$ telegram-send --configure

Anschließend wirst Du aufgefordert Deinen Token einzugeben, der Dein Skript mit Deinem Bot verbindet. Nachdem Du dann das Passwort an Deinen neuen Bot geschickt hast, ist telegram-send erfolgreich eingerichtet. Falls Du dazu noch Fragen hast, findest Du hier die komplette Anleitung.

Anschließend können wir mit folgendem Befehl Nachrichten versenden:

1import telegram_send
2telegram_send.send(messages=["Hello!"])

Im folgenden Abschnitt werde ich Dir zeigen, wie Du Deinen Telegram-Bot zum Leben erweckst.

Hinweis: Das Skript kann an vielen Stellen noch angepasst werden, wie z.B. die Menge, Häufigkeit und Art der gehandelten Wertpapiere. Sieh es einfach als ersten Startpunkt, zu dem Du Deine eigenen Funktionalitäten hinzufügen kannst. Den obigen Code findest übrigens Du in diesem GitHub Repo.

Mögliche Erweiterungen

Idealerweise richtest Du Dein Skript einmal ein und denkst anschließend nicht mehr darüber nach - damit das funktioniert, muss es ständig laufen, auch wenn Dein Computer ausgeschaltet ist. Hierfür empfehlen wir Dir, Dein Skript in der Cloud zu hosten und eine Plattform wie Heroku zu nutzen, die Du bequem mit GitHub verbinden kannst. In diesem Blog Post haben wir beschrieben, wie Du Heroku nutzen kannst, aber Du kannst auch dieser oder dieser Schritt-für-Schritt-Anleitung folgen.

Wenn Du einen Trade platzierst, während der Handelsplatz geschlossen ist, wird der Trade zum nächsten verfügbaren Zeitpunkt platziert. Du solltest es jedoch vermeiden, Trades zum Zeitpunkt der Markteröffnung zu platzieren, da die Volatilität zu Beginn eines Handelstages normalerweise deutlich höher ist. Vielleicht möchtest Du ja das Skript einfach so anpassen, dass Trades nie vor 15.30 Uhr platziert werden, um die NSYE/NASDAQ-Öffnungszeiten zu berücksichtigen.

Du kannst sogar leicht von der DCA-Strategie abweichen - zum Beispiel, indem Du tägliche Marktdaten einbeziehst. Wenn der Preis Deines Wertpapiers um beispielsweise 10% fällt, könntest Du Deinen Telegram-Bot so programmieren, dass er Dich benachrichtigt. Indem Du mit dem Bot interagierst, kannst Du dann entweder zusätzliche Anteile kaufen oder Deinen Trade früher als geplant platzieren. Für Telegram-Funktionen, die über das einfache Versenden von Nachrichten hinausgehen, empfehle ich Dir den python-telegram-bot Wrapper. Vielleicht möchtest Du ja beispielsweise eine Funktion hinzufügen, die Dich benachrichtigt, wenn mehr Geld zu Deinem Space hinzugefügt werden muss.

Um das Skript robuster zu machen, sollten wir von der time.sleep() Funktion in Python weggehen. Warum? Wenn das Skript schläft, ist die Laufzeit komplett blockiert und Du kannst es nicht aufwecken 💤. Stattdessen schlagen wir eine Task-Warteschlange vor, mit der man periodische Ereignisse, wie z.B. eine Bestellung, planen kann. Wir empfehlen Celery als Tool, hier kannst Du Dich damit vertraut machen.

Mit Deiner eigenen Dollar-Cost-Averaging Strategie hast du deutlich mehr Flexibilität  als mit Standard-Sparplänen. Du kannst zum Beispiel den Ausführungszeitpunkt flexibler einstellen. Du kannst sicherstellen, dass der ETF zum besten Zeitpunkt des Tages gekauft wird und nicht, wenn es für die Bank am günstigsten ist. Außerdem kannst Du mehrere Wertpapiere in einen Sparplan aufnehmen und musst nicht für jeden ETF einen eigenen anlegen, wie es bei vielen Anbietern üblich ist. Die Möglichkeiten sind quasi endlos! Also, wie sieht Deine Strategie aus?

Ich hoffe, dieser Blog Post hat Dich ein wenig inspiriert, wie Du die lemon.markets API nutzen kannst. Wenn Du Dich noch nicht angemeldet hast, kannst Du das hier tun. Wir freuen uns über jede Art von Feedback! Hinterlasse uns gerne einen Kommentar, schreibe uns eine E-Mail an [email protected] oder tritt unserer Slack Community bei. Wir freuen uns darauf!

Dein Lemoneer 🍋,

Joanne

Das könnte Dich auch interessieren

Mit OpenFIGI und lemon.markets ein Tickersymbol einer ISIN zuordnen

blog photo

Wenn Du an verschiedenen Börsen tradest, wirst Du feststellen, dass diese meist unterschiedliche Methoden haben um Wertpapiere zu identifizieren. Die US-Börsen verwenden beispielsweise häufig Ticker, während die deutschen Börsen auf eine ISIN verweisen. Und manchmal ist das Wechseln zwischen diesen Identifiern nicht so einfach, wie man es erwarten würde. Stattdessen kannst Du den Prozess automatisieren, indem Du einen (weniger als 10 Zeilen) Code schreibst, der die "Übersetzung" für Dich übernimmt. Lies weiter, um zu erfahren, wie Du die OpenFIGI- und lemon.markets-APIs nutzen kannst, um einem Ticker die entsprechenden ISIN zuzuordnen.

10 Fehler beim (automatisierten) Trading und wie Du sie vermeidest

blog photo

Hallo! Mein Name ist Joanne und ich bin Teil des lemon.markets-Teams in Berlin. Wir bauen eine Trading API, mit der Entwickler:innen ihre eigene Trading Experience gestalten können. Außerdem wollen wir eine Umgebung schaffen, in der Nutzer:innen sich zu der Schnittmenge von  Algorithmus-Entwicklung und dem Aktienmarkt austauschen können. Wir wollen zu dieser Diskussion auch etwas beitragen und haben deshalb eine Liste mit zehn Fehlern zusammengestellt, die Anfänger im automatisierten Handel (um ehrlich zu sein, manchmal auch erfahrene Profis) machen können. Damit sie Dir nicht passieren, haben wir zusätzlich erklärt, wie Du sie vermeiden kannst.

Integration von lemon.markets in Deinen Telegram-Bot (Teil 2 von 2)

blog photo

Hallo! Ich bin Joanne und gehöre zum Team von lemon.markets. Wir sind ein Berliner Start-up, das automatisiertes Trading über APIs ermöglicht. Unser Ziel ist es, Entwicklern und Entwicklerinnen alle Werkzeuge zur Verfügung zu stellen, mit denen sie ihre eigene Trading Experience an der Börse bauen können. Dabei gibt es hunderte Use-Cases für unser Produkt, wie beispielsweise ein eigenes Frontend zum Platzieren von Orders. Dafür kannst Du bei Null anfangen oder einen bereits existierenden Dienst wie beispielsweise Telegram nutzen. In diesem Artikel erweitere ich das Projekt, das wir in unserem letzten Artikel vorgestellt haben.

Tiefer eintauchen

Finde weitere Ressourcen für einen einfachen Einstieg

In unserer Dokumentation erfahrt Ihr mehr über unsere API-Struktur, die verschiedenen Endpunkte und spezifische Anwendungsfälle.

Austauschen

Tritt der lemon.markets Community bei

Tritt unserem Slack-Channel bei, um Dich aktiv an unserer Community zu beteiligen, Fragen an andere Nutzer:innen zu stellen und immer auf dem Laufenden zu bleiben.

Team unterstützen

Lust lemon.markets mit uns zu bauen?

Wir sind immer auf der Suche nach großartigen Ergänzungen für unser Team, die uns beim Aufbau einer Brokerage Infrastruktur für das 21. Jahrhundert helfen.

Products
Pricing
For Developers
SlackGithubBlog
© lemon.markets 2021Privacy PolicyImprint
All systems normal