Nutze die lemon.markets API, um Deine Cost Averaging Strategie umzusetzen
Mit anderen Worten: Du kannst eine "faule" Automatisierung für Deine regelmäßig geplanten Trades einrichten.
Hallo! Ich bin Joanne und gehöre zu lemon.markets 🍋, einem Start-up, das Entwickler:innen einen neuen Zugang zum Traden bietet. Wir entwickeln eine API, die es Dir ermöglicht, im Aktienmarkt aktiv zu sein und mit ihm zu interagieren. Zum Beispiel, indem Du eine automatisierte Trading Strategie implementierst oder ein Dashboard erstellst, das Dein Portfolio visualisiert.
In diesem Artikel zeige ich Dir eine einfache Dollar-Cost-Averaging-Strategie, mit der Du Deinen Sparplan automatisieren kannst. Nichts Besonderes - aber es macht Dein Leben etwas einfacher 😉. Außerdem zeige ich Dir, wie Du einen Telegram-Bot einrichtest, der Dich benachrichtigt, wenn eine Order platziert wird. Wenn Du noch nicht weißt, was Du mit der API bauen sollst, wird dieser Artikel Deine Kreativität mit Sicherheit anregen. Starte am Besten damit, Dich bei lemon.markets anzumelden.
Was ist "Dollar-Cost-Averaging"?
Wenn Du z. B. bereits 10% Deines monatlichen Gehalts in einen ETF oder Investmentfonds investiert, betreibst Du Dollar-Cost-Averaging (vielleicht sollten wir es Euro-Cost-Averaging nennen). Viele ETF-Sparpläne sind ähnlich aufgebaut. Wie sieht diese Strategie also konkret aus? Stell Dir vor, Du hast eine große Summe Geld, beispielsweise 10.000€, die Du anlegen möchtest. Beim Dollar-Cost-Averaging (DCA) würdest Du Deine Einzahlungen verteilen, indem Du z.B. über einen Zeitraum von 10 Monaten monatlich 1.000€ investierst. Das Gegenteil von DCA ist die Einmalanlage, bei der Du den gesamten Betrag auf einmal investierst.
Warum sollte man eines der beiden bevorzugen? Viele Anleger entscheiden sich für DCA statt für eine Einmalanlage, um das Risiko zu mindern. Du kannst davon ausgehen, dass der Preis des von Dir gewählten Wertpapiers im Laufe der 10 Monate variieren wird. Wenn Du hingegen kontinuierlich investierst, mittelst Du Deine Kostenbasis (d.h. Du kaufst zu dem Durchschnittspreis). Idealerweise würdest Du natürlich nur den “Dip” kaufen, aber angeblich kann man den Markt ja nicht vorhersagen.🤷♀ Warum solltest Du also jemals etwas anderes nutzen als DCA? Der Vorteil von Einmalanlagen ist, dass Dein Geld sofort für Dich arbeitet. Andererseits, besteht die Gefahr, dass Du ein schlechtes Timing hast und einen hohen Einstiegspreis erwischst.
Weshalb also nicht eine Plattform nutzen, die einen vorgefertigten Sparplan anbietet? Ganz einfach: Personalisierung und Transparenz. Bei einem vorgefertigten Sparplan fehlt Dir die Flexibilität, Datum und Uhrzeit der Order-Ausführung anzugeben - welche oft zu ungünstigen Momenten geschehen, und zu Deinem Nachteil werden können. Wenn Du hingegen Deine Sparstrategie mit der lemon.markets API erstellst, hast Du die volle Kontrolle und kannst gängige Kauftermine, wie z. B. Anfang und Ende des Monats, vermeiden. Dadurch erzielst Du einen Preisvorteil gegenüber anderen DCA Nutzern. Du kannst wählen, was, wann, an welcher Börse, wie oft und wie lange Du traden möchtest. Außerdem bist Du nicht nur auf ETFs beschränkt - sondern kannst die DCA Strategie auch für Aktien verwenden, z. B. von Pinterest. Aber das bleibt Dir überlassen.
Automatisierung der DCA-Strategie 💵
Natürlich kannst Du Dich bei Deinem Depot anmelden und jede Woche manuell eine Order platzieren. Du kannst diesen Vorgang allerdings auch automatisieren. Ich weiß nicht, wie es Dir geht, aber letzteres klingt irgendwie besser (und Dein Zukunfts-Ich wird es Dir wahrscheinlich danken). Lass uns also mit dem Programmieren starten.
Ich habe mich entschieden, für diese Anwendung Python zu verwenden. Aber es bleibt natürlich Dir überlassen, welche Sprache Du verwendest - die Logik bleibt dieselbe.
Setting the Scene
In diesem Skript müssen wir GET-, PUT- und POST-Requests an die API von lemon.markets stellen. Aus diesem Grund erstellen wir eine helper.py-Datei mit der Klasse RequestHandler, die, Du ahnst es, alle unsere Requests bearbeiten wird. Wir erstellen zwei separate GET-Funktionen, da wir GET-Requests sowohl an die Trading- als auch an die Marktdaten-API 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 bemerkt, dass wir os.environ.get() verwenden, um auf diverse Environment Variablen zuzugreifen? Wir müssen diese Variablen entweder in einer separaten .env-Datei, lokal in Deiner IDE oder auf der Cloud-Anwendungsplattform definieren, die Du zum Hosten Deines Skripts verwendest (z. B. Heroku).
Dies sind die Environment Variablen, die Du angeben musst, wenn Du dieses Skript ausführen möchtest:
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 namens "models" definiert haben, das drei Dateien enthält: Order.py, Token.py und TradingVenue.py. Dies sind alles Objekte mit spezifischen Eigenschaften und Verhaltensweisen - sie spiegeln zudem die Struktur unserer API wider. Mehr dazu gibt es in unserer Dokumentation zu lesen.
Order Klasse
Eine Order wird u.a. durch ihre ISIN charakterisiert - auch hier findest Du in unserer Dokumentation eine ausführliche Erläuterung. Eine Order muss platziert, aktiviert und abgerufen werden. Diese Funktionen sind in der unten definierten Order Klasse zu finden.
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 Funktionen durch Anfragen an unsere API umgesetzt werden. Indem wir Order zu einer Unterklasse der Klasse RequestHandler machen, erweitern wir die Funktionen, die wir in der vorherigen Klasse definiert haben. Dadurch können wir einfach und problemlos mit der lemon.markets API interagieren.
Trading Venue Klasse
Ein Handelsplatz (Trading Venue) wird durch seinen "Market Identifier Code" (MIC) charakterisiert, der es Dir ermöglicht die Börse anzugeben, an der Du Deine Orders platzieren möchtest. Wir haben übrigens einen Artikel über unseren Trading Venue-Endpunkt geschrieben, den Du hier lesen kannst. Ein Handelsplatz kann entweder offen oder geschlossen sein. Mit dem folgenden Skript können wir prüfen, ob ein Trading Venue geöffnet ist, die allgemeinen Öffnungszeiten abfragen und die Anzahl der Sekunden bis zur nächsten Öffnungszeit bestimmen (falls 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
Schließlich brauchen wir noch einen Token, um Anfragen zu authentifizieren. In der .env-Datei legen wir einen Start-Token fest. Da Token jedoch ablaufen, müssen wir in der Lage sein, einen neuen Token abzurufen. Aus diesem Grund hat die Klasse Token nur eine Funktion: das Abrufen eines neuen Tokens (und das anschließende Aktualisieren der Environment Variable).
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')
Auch hier ist Token eine Unterklasse von RequestHandler, da wir einen GET-Request an unsere API stellen müssen.
Das sind soweit alle Modelle, die wir brauchen, um diese spezielle Strategie zu erstellen. Lasst uns jetzt alles zusammenfügen.
Alles zusammenfügen
Nachdem wir unsere Hilfsfunktionen und API-Objekte definiert und unseren Telegram-Bot eingerichtet haben, ist es an der Zeit, alle Teile zusammenzufügen.
Im ersten Schritt definieren wir die Funktion buy_order(). Diese platziert und aktiviert eine Kauforder für eine Aktie, die durch ihre ISIN festgelegt wird. Unsere API ist so aufgebaut, dass eine Order zunächst platziert (Status: inactive), dann aktiviert (Status: activated) und schließlich ausgeführt (Status: executed) werden muss. Die Funktion prüft ständig den Status der Order. Sobald die Order schließlich ausgeführt wird, verwenden wir telegram-send, um eine Zusammenfassung des Trades zu senden. Sobald dies geschehen ist, lassen wir das Skript eine Woche lang ruhen, bis die nächste Order platziert wird.
Dann definieren wir unsere Hauptfunktion dollar_cost_averaging(). Hier prüfen wir zunächst, ob der Handelsplatz geöffnet ist. Falls ja, holen wir uns einen neuen Zugangstoken und rufen die Funktion buy_order() für unser gewähltes Wertpapier auf. Wenn der Handelsplatz nicht geöffnet ist, lassen wir das Skript ruhen, bis die Börse wieder geöffnet wird, dann wird der Trade platziert. Wir raten eigentlich von der Funktion time.sleep() ab, da sie Dein Skript für die Dauer, die in der Funktion angegeben ist, unzugänglich macht. Um das Skript so einfach und lesbar wie möglich zu halten, haben wir uns dennoch dazu entschieden, die Funktion hier zur Veranschaulichung zu verwenden. In einem späteren Abschnitt schlagen wir dann 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 ein weltweites Aktienportfolio abbildet. Dadurch können wir unser Risiko weiter verringern. Die Strategie kann aber natürlich auch auf einzelne Aktien oder verschiedene ETFs angewendet werden.
Vielleicht ist Dir die Zeile mit telegram_send() aufgefallen und Du fragst Dich, was es damit auf sich hat? Wir müssen den Telegram-Bot erst noch einrichten, um sicherzustellen, dass der obige Code funktioniert. Lass uns das jetzt tun.
Einen Telegram Bot einrichten 🤖
Falls Du Telegram noch nicht kennst: Es ist eine Messaging-Software, die Bots unterstützt. Wir werden die Telegram-API nutzen, um einen Bot zu konfigurieren, der Dir automatisch eine Kurznachricht aufs Handy schickt, sobald ein Trade ausgeführt wurde.
Im folgenden Abschnitt zeige ich, wie Du Telegram-Benachrichtigungen wie diese einrichtest.
Zunächst musst Du Deinen neuen Bot registrieren, indem Du /newbot an BotFather sendest, weitere Erklärungen dazu findest Du hier. Das Ergebnis ist ein Token, ähnlich wie der Token, das Du von der lemon.markets API kennst.
Um den Prozess zu vereinfachen, verwende ich das Command-line Tool telegram-send, das Du mit pip wie folgt installieren kannst:
1$ pip install telegram-send
2$ telegram-send --configure
Dein Terminal wird Dich auffordern, den Token einzugeben, der Dein Skript mit Deinem Bot verbindet. Sende dann das angezeigte Passwort an Deinen neuen Bot und schon hast Du telegram-send erfolgreich eingerichtet. Falls etwas unklar ist, findest Du die vollständige Anleitung hier.
Mit folgendem Befehl können wir Nachrichten versenden:
1import telegram_send
2telegram_send.send(messages=["Hello!"])
Im folgenden Abschnitt zeige ich Dir, wie Du Deinen Telegram-Bot zum Leben erweckst (nicht wörtlich).
Hinweis: Viele Aspekte dieses Skripts können verändert werden, zum Beispiel die Menge, Häufigkeit und Art der gehandelten Wertpapiere. Sieh es doch einfach als einen guten Ausgangspunkt und füge Deine eigenen Funktionen hinzu. Den obigen Code findest Du in diesem GitHub Repo.
Mögliche Erweiterungen
Idealerweise möchtest Du Dein Skript einrichten und dann nicht mehr darüber nachdenken. Damit das funktioniert, muss es ständig laufen, auch wenn Dein Computer ausgeschaltet ist. Deshalb empfehlen wir Dir, Dein Skript in der Cloud zu hosten, zum Beispiel auf einer Plattform wie Heroku, die Du bequem mit GitHub verbinden kannst. Wie Du Heroku nutzt, haben wir in diesem Artikel beschrieben oder Du folgst dieser oder dieser Schritt-für-Schritt-Anleitung.
Wenn Du eine Order platzierst, während der Handelsplatz geschlossen ist, wird der Trade zum nächstmöglichen Zeitpunkt platziert: wenn der Markt wieder geöffnet ist. Du solltest es jedoch vermeiden, eine Order bei Marktöffnung zu platzieren, da die Volatilität zu Beginn eines Handelstages normalerweise höher ist. Du könntest beispielsweise das Skript so anpassen, dass Orders nie vor 15:30 Uhr platziert werden, um die Öffnungszeiten der NSYE/NASDAQ zu berücksichtigen.
Du kannst sogar leicht von der DCA-Strategie abweichen - indem Du beispielsweise tägliche Marktdaten einbeziehst. Wenn der Kurs Deines Wertpapiers zum Beispiel um 10% fällt, kannst Du Deinen Telegram-Bot so programmieren, dass er Dich benachrichtigt. Wenn Du dann mit dem Bot interagierst, kannst Du entweder zusätzliche Anteile kaufen oder Deinen Trade früher als geplant abschließen. Für Telegram-Funktionen, die über das Versenden von Nachrichten hinausgehen, empfehle ich Dir den python-telegram-bot Wrapper. Du kannst beispielsweise eine Funktion hinzufügen, die Dich benachrichtigt, wenn mehr Geld in Deinen Space eingezahlt werden muss.
Um ein wirklich robustes Skript zu erstellen, empfehlen wir außerdem, die Funktion time.sleep() in Python nicht mehr zu verwenden. Warum? Wenn das Skript ruht, ist die Laufzeit vollständig blockiert und Du kannst es nicht aufwecken 💤. Stattdessen schlagen wir vor, eine Aufgaben-Warteschlange einzurichten, mit der Du regelmäßige Ereignisse, wie zum Beispiel eine Order, planen kannst. Wir empfehlen Celery und diesen Artikel, um Dich damit vertraut zu machen.
Deine eigene automatische Dollar-Cost-Averaging-Strategie einzurichten ist flexibler als einen normal Sparplan einzurichten, weil Du zum Beispiel die Ausführungszeit frei gestalten kannst. Du kannst außerdem sicherstellen, dass der ETF zum besten Zeitpunkt des Tages gekauft wird und nicht, wenn es für die Bank am günstigsten ist. Du kannst zudem mehrere Wertpapiere in einen Sparplan einbeziehen, sodass Du nicht für jeden ETF einen eigenen anlegen musst, wie es bei vielen Sparplänen der Fall ist. Die Möglichkeiten sind endlos - wie würdest Du machen?
Ich hoffe, dieser Artikel hat Dich dazu inspiriert, die lemon.markets API zu nutzen. Wenn Du Dich noch nicht bei lemon.markets angemeldet hast, kannst Du das hier tun. Wenn Du mit uns reden möchtest: Schreibe uns eine E-Mail an support@lemon.markets oder tritt unserer Slack-Community bei. Wir freuen uns, Dich schon bald dort zu sehen!
Dein Lemoneer 🍋,
Joanne
Das könnte Dich auch interessieren
Using Time Series Forecasting to predict stock prices 🔮
In this article you will learn what time series forecasting is and how its application in finance looks like. Then you'll also dive into Facebook's Prophet Model for Time Series Forecasting and use it together with the lemon.markets Market Data API to forecast the development of the Tesla Stock.
Dummies Guide to Trading with Machine Learning
Ever wonder how a trader with decades of experience on thousands of stocks and lightning fast reaction times might perform in the market? With some machine learning knowledge, you might be able to automate such a trader yourself! 💻 📈
4 reasons why YOU should automate your trading strategy
In the current volatile market conditions, everyone is trying to find ways to minimise portfolio loss. In that context, have you ever thought about automating your trading strategy? In this article, we will dive into 4 reasons for doing so. Expect to learn how it can save you time, make your trading more efficient and lead to data-based decisions.
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.
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.