Einfaches MQL4 Handelssystem nachbauen - Schritt für Schritt Anleitung
Ich habe mir was überlegt. Wer sein eigenes Forex Trading System haben möchte, steht oft vor dem Problem: Wo fange ich an? Darum stelle ich hier ein "ganz einfaches Handelssystem" vor, mit dem man beginnen kann.
Wer richtig einsteigen möchte, kann sich links für den Gratis-Einstieg im Golden Goose Kurs eintragen, da starten wir mit DEM bereits funktionsfähigen (etwas verkürzten aber trotzdem profitablen) Handelssystem welches ich selbst live auf zwei meiner Echtgeld-Konten benutze (siehe Handelssysteme in der Grafik links).
Wie funktioniert das?
Das extrem vereinfachte System in diesem Beitrag dient dem besseren Verständnis der einzelnen Codezeilen. Es funktioniert nicht mit allen Währungspaaren (weil die Berechnung der Pips beispielsweise für USDJPY anders funktioniert als für EURUSD) und man sollte es nur im Backtesting einsetzen (weil noch kein Netz und kein doppelter Boden eingebaut ist), aber es funktioniert und ist als Grundbaustein für Deinen eigenen Bausatz durchaus ausbaufähig.
Das brauchst Du für Deinen eigenen Forex Trading Bausatz
- 1. Einen PC mit Windows oder Linux (bei Linux mit WINE)
- 2. Ein Demokonto bei einem der zahlreichen Forex-Broker
- 3. Die Software Metatrader 4 (ich bevorzuge die Originalversion von Metaquotes)
Die meisten Leser werden diese Vorraussetzungen wahrscheinlich bereits erfüllt haben. Allerdings weiß ich noch, wie misstrauisch ich war, als es darum ging mein erstes Demokonto zu eröffnen. Nimm Dir Zeit und triff eine Wahl nach Deinen Kriterien...
Nach der Installation des Metatraders wirst Du dazu aufgefordert, Dich in Deinem Konto anzumelden. Sobald das geschehen ist, kannst Du mit der Taste F4 den MetaEditor öffnen.
Die Vorarbeiten - eine neue Datei im Metaeditor erstellen
Wähle bitte File -> New aus, um eine neue Datei zu erstellen.
Im folgenden Dialog wählen wir "Expert Advisor aus"
Jetzt benenne Dein Testhandelssystem mit "ForexTradingBausatz1"
Jetzt löschen wir über Edit -> Delete den kompletten Inhalt des Programmcodes, denn wir wollen mit einer leeren Datei starten
So, das waren die ersten zwei Minuten. Jetzt geht es Zeile für Zeile weiter. Kopiere die Inhalte der einzelnen Zeilen und füge sie nacheinander ein, oder schreibe sie ab.
Hier kommt Zeile 1
int start() // das hier ist die Startfunktion, die bei jeder Kursveränderung aufgerufen wird. oder void OnTick() // gleiche Startfunktion nach neuer Konvention
Auch wenn Du auf Deinem Bildschirm jetzt einen Zweizeiler siehst, es handelt sich um eine einzelne Zeile.
Was macht Zeile 1?
Diese Codezeile macht nichts anderes als eine Funktion mit dem Namen start (oder OnTick) zu beschreiben, die keine Parameter braucht. Diese Funktion wird vom Metatrader immer dann aufgerufen, wenn eine Kursveränderung stattfindet. Alles hinter // sind Kommentartexte, die man für das Programm weglassen kann und die nur für Menschen die Lesbarkeit verbessern sollen.
Dein MetaEditorfenster sollte jetzt so aussehen
Zeile 2 sieht so aus
{ // Klammer auf, die Funktion startet
Eine öffnende geschweifte Klammer sagt dem Programm, dass die Funktion jetzt startet
Zeile 3 ist nur ein Kommentar
// ++++++++ Wir berechnen die grobe Trendrichtung: ist der aktuelle Kurs höher als vor 10 Kerzen?
Kommentare sind dem Expert Advisor egal. Früher habe ich sie oft weggelassen um Zeit zu sparen. Hinterher zahlt man die Zeit immer doppelt drauf, denn man weiß irgendwann nicht mehr, warum man bestimmte Sachen gemacht hat.
Kommen wir zu Zeile 4
double Durchschnitt = iMA(NULL, 0, 14, 5, 0, 0, 0); //packe den Durchschnitt der letzten 14 Kerzen in die DOUBLE-Variable Durchschnitt
double ist ein Variablentyp und kann Zahlen mit Nachkommastellen aufnehmen.
iMA berechnet einen "gleitenden Durchschnittswert", also ob im Durchschnitt der Kurs sinkt oder fällt. Wenn Du iMA im MetaEditor eingibst und F1 drückst, bekommst Du die Dokumentation dazu angezeigt.
Zeile 5 macht nochmal das gleiche für den "alten Durchschnitt"
double AlterDurchschnitt = iMA(NULL, 0, 14, 5, 0, 0, 10); // packe den Durchschnitt der 14 Kerzen ab der zehntletzten Kerze in die Double-Variable AlterDurchschnitt
In Zeile 5 hat sich nur der letzte Parameter geändert. Dort steht eine 10, weil wir den Durchschnitt berechnen wollen, wie er vor 10 Kerzen war.
Zeile 6 Trendrichtung berechnen
double TrendRichtung=Durchschnitt - AlterDurchschnitt; // zieh den AltenDurchschnitt vom aktuellen Durchschnitt ab und pack ihn in TrendRichtung
Wir ziehen den alten Durchschnitt vom aktuellen Durchschnitt ab und packen das Ergebnis in die double-Variable TrendRichtung
Zeile 7 Trendrichtung auf den Bildschirm schreiben
Comment ("TrendRichtung = "+ TrendRichtung); // Schreibe die aktuelle Trendrichtung auf den Bildschirm
Die Comment-Funktion sorgt dafür, dass der berechnete Trendwert später rechts oben im Chart angezeigt wird. So kannst Du kontrollieren, ob Dein Forex Trading System richtig rechnet...
Zeile 8 ist wieder ein Kommentar
// ++++++++ Wir prüfen, ob der Trend rauf geht und die Anzahl offener Trades für das Währungspaar 0 ist. Falls beides stimmt, kaufen wir
Zeile 9 - Prüfen ob der Trend positiv ist
if (TrendRichtung > 0.005) // wenn es rauf geht
In Zeile 9 prüfen wir ob der berechnete Wert "Trendrichtung" größer ist als "0.005". Man achte darauf, einen Punkt statt eines Kommas zu benutzen. Den Wert kannst Du später ändern, wenn Dein Handelssystem im Test zu früh oder zu spät kauft
Zeile 10 - Prüfen, ob wir schon offene Trades haben
if((OffeneTradesDieserWaehrung(Symbol())==0)) // und keine Trades für dieses Währungspaar offen sind
Das ist so ein Fall, bei dem man richtig Mist bauen kann! Wenn Du vergisst, zu prüfen ob Du schon gekauft hast, kann Dein System Dich innerhalb weniger Sekunden ruinieren, weil es unbegrenzt neue Trades eingeht. Wir rufen eine Funktion auf, die alle Trades durchgeht und überprüft, ob es sich um das gleiche Währungspaar handelt. Nur wenn die Anzahl offener Trades für dieses Währungspaar 0 ist, wird weitergemacht.
Zeile 11 - Nur im Testbetrieb weitermachen
if(IsTesting()) // NUR wenn wir im Backtesting sind
Auch Zeile 11 ist eine Absicherung, damit nicht versehentlich im Echtbetrieb gekauft wird.
Zeile 12 - Kaufen wenn alle Bedingungen erfüllt sind
OrderSend (Symbol(),OP_BUY,0.01,Ask,3, (Ask-0.0030),(Ask+0.0030), NULL,NULL,0,Green); // kaufe zum Marktpreis und setze Stoploss und Takeprofit auf 30 Punkte
Nur wenn der Trend aufwärts geht, wir keine offenen Trades für dieses Währungspaar haben und wir uns im Testbetrieb befinden, dann wird eine Position eröffnet. Es handelt sich dabei um einen KAUF mit 30 Punkten Stop Loss und 30 Punkten Take Profit. Diese beiden Werte und der Kaufkurs werden später so im Chart als Linien angezeigt
Zeile 13 bis 17 - Die gleichen Prüfungen für die andere Richtung
// ++++++++ Wir prüfen, ob der Trend runter geht und die Anzahl offener Trades für das Währungspaar 0 ist. Falls beides stimmt, verkaufen wir if (TrendRichtung < -0.005) // wenn es runter geht if((OffeneTradesDieserWaehrung(Symbol())==0)) // und keine Trades für dieses Währungspaar offen sind if(IsTesting()) // NUR wenn wir im Backtesting sind OrderSend (Symbol(),OP_SELL,0.01,Bid,3, (Bid+0.0030), (Bid-0.0030), NULL, NULL,0,Red); // kaufe zum Marktpreis und setze Stoploss und Takeprofit auf 30 Punkte
Unser Forex Trading System soll nicht nur handeln können, wenn der Preis rauf geht, sondern auch wenn er sinkt. Die Zeilen 13-17 prüfen die gleichen Bedingungen ab wie die Zeilen 8-12, allerdings in die andere Richtung. Verkauft wird nur, wenn der Kurs sinkt, keine offenen Trades existieren und wir uns im Testbetrieb befinden
Zeile 18 - Ende der Funktion
} // Klammer zu, die Funktion start() wird beendet
Das war es schon mit der Hauptfunktion start(). Immer wenn eine Preisänderung auftritt, wird der Code ausgeführt. Allerdings brauchen wir noch eine kleine Zusatzfunktion, die die einzelnen offenen Trades durchgeht und prüft, ob wir nicht schon gekauft oder verkauft haben. Andernfalls würde mit jeder Kursänderung eine neue Position eröffnet, wenn die Mindestkursstärke gegeben ist. Siehe Bild
Zeile 19 - bleibt leer
Die Zeile 19 lassen wir leer, um die beiden Funktionen optisch voneinander zu trennen
Zeile 20 - Die Funktion zur Prüfung offener Trades
int OffeneTradesDieserWaehrung(string Waehrungspaar) // Funktion berechnet eine Ganzzahl der offenen Trades eines Währungspaares
Hier deklarieren wir die Funktion OffeneTradesDieserWaehrung, die einen Parameter für die Währung entgegen nimmt. In den Zeilen 10 und 15 rufen wir diese Funktion auf und übergeben mit Symbol() das aktuelle Währungspaar von dem Chart, auf dem unser ForexTradingBausatz gerade läuft.
Zeile 21 - Die Funktion wird geöffnet
{ // Klammer auf, die Funktion startet
Zeile 22 - Anzahl vor dem Zählen auf Null setzen
int AnzahlOffeneTrades=0; // setze den Zählwert auf Null und fange bei Null an zu zählen
Da wir vor jedem Handel erneut prüfen möchten, ob wir bereits für dieses Währungspaar einen Buy oder Sell abgesetzt haben, setzen wir die Zählvariable für die Anzahl offener Trades am Anfang auf 0
Zeile 23 - Gehe alle offenen Trades mit einer Zählschleife durch
for(int i=OrdersTotal() -1; i >= 0; i--) // Nimm die Gesamtanzahl offener Trades und zieh jeweils 1 ab, bis wir bei 0 sind.
Hier zählen wir von der Anzahl der offenen Trades, die uns unser Konto mit der Funktion OrdersTotal() liefert runter, bis keine offenen Trades mehr übrig sind
Zeile 24 - Klammer auf für die Zählschleife
{ // Klammer auf, prüfe die offenen Trades
Unsere Zählschleife bekommt eigene Klammmern. So lange noch offene Trades geprüft werden müssen, werden alle Befehle innerhalb dieser Klammern ausgeführt
Zeile 25 - Prüfe eine Order nach der anderen
OrderSelect(i,SELECT_BY_POS,MODE_TRADES); // Prüfe jede Order der Trades
So lange offene Trades gefunden werden werden sie für die Überprüfung ausgewählt
Zeile 26 - AnzahlOffenerTrades erhöhen, wenn das Währungspaar gleich ist
if(OrderSymbol()== Waehrungspaar) AnzahlOffeneTrades++; // wenn es das aktuelle Währungspaar ist, addiere die Order zu den offenen Trades
Hier wird geprüft, ob das Währungspaar auf dem Chart mit dem Währungspaar einer offenen Order übereinstimmt. Falls ja, wird der Zähler für AnzahlOffeneTrades erhöht. Sobald dieser Zähler größer als 0 ist, kauft unser Handelssystem nichts mehr nach...
Zeile 27 - Klammer zu, die Schleife für die Prüfung ist beendet
} // Klammer zu, alle offenen Trades wurden geprüft
Zeile 28 - Wir geben den Wert zurück, ob offene Transaktionen für das aktuelle Währungspaar gefunden wurden
return (AnzahlOffeneTrades); //liefere die Anzahl für offene Trades dieses Währungspaares zurück
Mit return (AnzahlOffeneTrades) wird unser Ergebnis zu der Frage, wie viele offene Trades existieren und ob ein neuer Trade aufgemacht werden soll wieder an die Zeilen 10 und 15 zurückgeschickt
Zeile 29 - Geschafft, die letzte Klammer, das Programm ist fertig!
} // Klammer zu, Funktion OffeneTradesDieserWaehrung ist beendet
Das war es schon. In unter 30 Programmzeilen hast Du ein Forex Trading System geschrieben, das auf mehreren Währungspaaren im Metatrader unabhängig von Dir Positionen eröffnet, bei Unterschreitung Deiner Schmerzgrenze den Stoploss auslöst, wenn der Trade in die falsche Richtung läuft und den Gewinn einer Position einsackt, wenn die Linie für den Take Profit erreicht wird.
Dein Programmierfenster im MetaEditor sollte jetzt so aussehen
Wenn alle Zeilen korrekt eingefügt wurden, drücke F5 oder klicke auf COMPILE
In der Toolbox im unteren Bereich sollte jetzt folgende Nachricht auftauchen:
Compiling 'ForexTradingBausatz1.mq4'... 0 error(s), 0 warning(s)
Öffne den Metatrader und drücke STRG + R oder klicke auf Ansicht -> Strategietester
In Deinem Strategietester-Fenster wähle bitte alle Werte so aus, wie hier angezeigt. Dann klicke auf Anfangswert um mit dem Test zu starten. Nachdem die Daten für den Test gesammelt wurden (siehe Fusszeile im Metatrader "Sammeln M1") kannst Du den Test starten.
Klick zum Start auf den Play-Knopf rechts neben dem Schieberegler für die Geschwindigkeit
Ein paar Worte zum Abschluss
Natürlich könntest Du mit diesem System bereits echtes Geld handeln. Aber ich habe bewusst eine Überprüfung eingebaut, damit es nur im Backtesting funktioniert. Es soll als Grundlage dienen, um weitere Funktionen zu ergänzen. Dazu gehört eine Notfallsicherung, die dafür sorgt, dass Du im Ernstfall die Bremse ziehen kannst. Dazu gehört eine kontinuierliche Überprüfung, ob alle Positionen auch einen gültigen Stop Loss haben. Es kann nämlich immer mal vorkommen, dass bei der Übermittlung von Forex-Orderaufträgen Fehler auftreten. Und natürlich könnte ich den kompletten Quelltext auch zusammenhängend als Datei zur Verfügung stellen. Aber ich habe die einzelnen Zeilen bewusst getrennt, damit die grundlegende Funktionsweise jeder einzelnen Zeile klarer wird. Es ist aber kein Problem, die einzelnen Zeilen zu kopieren und selbst im MetaEditor zusammenzusetzen.
Viel Spass beim Testen!