
Nachrichtenhandel leicht gemacht (Teil 5): Ausführen des Handels (II)
Einführung
In diesem Artikel geht es vor allem darum, den Code für die Implementierung von Stop-Order in den Nachrichtenhandelsexperten zu schreiben. Diese Stop-Order werden in einem späteren Artikel zum Handel mit Nachrichtenereignissen verwendet. Darüber hinaus werden wir Funktionen zur Verwaltung von Slippage für Stop-Order, zum Schließen von Handelsgeschäften und zur Durchführung von Validierungsprüfungen erstellen, um festzustellen, ob ein Handelsgeschäft oder eine Order eröffnet werden kann. Das Handelsmanagement ist in jedem algorithmischen Handelssystem von entscheidender Bedeutung, da es Aufgaben wie das Eröffnen und Schließen von Handelsgeschäften, die Anpassung von Stop-Loss und die Verwaltung von Take-Profit umfasst. Ein effizientes Handelsmanagement kann einem Händler helfen, mehr Gewinn zu erzielen und gleichzeitig das Risiko negativer Marktbewegungen zu minimieren.
Warum Stop-Aufträge verwenden?
Der Einsatz von Stop-Order beim Handel mit Nachrichtenereignissen ist eine gängige Strategie, da sie Händlern dabei helfen, von den starken Kursbewegungen zu profitieren, die häufig auf wichtige Wirtschaftsmeldungen folgen, und gleichzeitig bestimmte Risiken zu minimieren.
Erfassen von Ausbruchsbewegungen
Nachrichtenereignisse, wie z. B. Wirtschaftsberichte oder Ankündigungen der Zentralbanken, führen häufig zu plötzlichen und erheblichen Kursbewegungen. Diese werden als Ausbrüche bezeichnet. Mit einer Stop-Order kann ein Händler bei einem vordefinierten Kursniveau in den Markt einsteigen, wenn der Kurs einen bestimmten Schwellenwert überschreitet, was ideal ist, um diese Ausbruchsbewegungen abzufangen, ohne den Markt manuell überwachen zu müssen.
- Stop-Order um zu kaufen: Platziert über dem aktuellen Marktpreis. Das löst dann einen Kaufauftrag aus, wenn der Kurs steigt, um die Aufwärtsdynamik nach positiven Nachrichten zu erfassen.
- Stop-Order um zu verkaufen: Platziert unter dem aktuellen Marktpreis. Das löst dann einen Verkaufsauftrag aus, wenn der Kurs fällt, und nutzt so die negativen Nachrichten.
Kann helfen, Seitwärtsbewegungen des Marktes zu vermeiden
Nachrichtenbedingte Volatilität kann zu Kursschwankungen führen, bevor sich eine klare Richtung abzeichnet. Händler, die zu früh in eine Position einsteigen, können in eine „Seitwärtsbewegung“ geraten - eine schnelle Bewegungen in beide Richtungen, die den Stop-Loss auslösen. Stop-Order helfen, diese falsche Ausbrüche zu vermeiden, indem sie sicherstellen, dass der Handel nur dann ausgelöst wird, wenn der Markt sich über einen bestimmten Preispunkt hinaus in eine Richtung bewegt.
Übermäßiges Analysieren im Handel begrenzen
Der Handel im Umfeld von Nachrichtenereignissen kann aufgrund der schnellen Marktbewegungen stressig sein. Durch das Setzen von Stop-Order im Voraus können Händler Positionen ohne emotionale Beeinflussung oder die Notwendigkeit der Ereignisrichtung betreten und verlassen. Sobald die Aufträge erteilt sind, ist die Entscheidung des Händlers bereits gefallen, sodass er nicht mehr versucht ist, auf kurzfristige Kursschwankungen überzureagieren. Im Zusammenhang mit diesem Artikel bedeutet dies, dass Reden und andere Nachrichtenereignisse, die keine Auswirkung auf das Geschehen haben, mit Hilfe von Stop-Order gehandelt werden können, da die Richtung nur schwer oder gar nicht im Voraus vorhergesagt werden kann.
Slippage minimieren
Durch den Einsatz von Stop-Order können Händler Slippage vermeiden, die mit Marktaufträgen in Zeiten hoher Volatilität verbunden sind. Zwar kann es immer noch zu Kursverlusten kommen, doch hat ein Stop-Auftrag eine bessere Chance, nahe am angestrebten Niveau ausgeführt zu werden, als ein Marktauftrag, der erteilt wird, nachdem die Nachricht bereits eine erhebliche Kursänderung verursacht hat.
Risikomanagement
Stop-Order helfen, das Risikomanagement zu automatisieren. Wenn ein Händler zum Beispiel eine volatile Reaktion auf ein Nachrichtenereignis erwartet, kann er eine Stop-Order sowohl für einen Kauf als auch für einen Verkauf platzieren (Straddle-Strategie). Dieser Ansatz hilft dem Händler, in beide Richtungen in den Markt einzusteigen, je nachdem, wie sich der Kurs entwickelt. Nach Auslösung kann der entgegengesetzte Stop-Auftrag zur Risikosteuerung aufgehoben werden.
Szenario:
Sie handeln den US-Dollar rund um die Bekanntgabe der Non-Farm Payrolls (NFP), eines der marktbeeinflussendsten Nachrichtenereignisse. In der Erwartung, dass die Daten eine größere Bewegung im EUR/USD-Paar auslösen werden, platzieren Sie eine Buy-Stop-Order oberhalb des aktuellen Kurses und eine Sell-Stop-Order unterhalb des aktuellen Kurses (Straddle-Strategie).
- Positive NFP-Daten: Der Dollar wird stärker, wodurch EUR/USD fällt und Ihre Sell-Stop-Order ausgelöst wird.
- Negative NFP-Daten: Der Dollar schwächt sich ab, wodurch EUR/USD ansteigt und Ihr Buy-Stop-Order ausgelöst wird.
Durch den Einsatz von Stop-Order sind Sie auf Bewegungen in beide Richtungen vorbereitet und steigen automatisch in den Markt ein, sobald die Kursentwicklung die Ausbruchsrichtung bestätigt.
Klasse der Kontoeigenschaften
Die Klasse CAccountProperties, die von der CAccountInfo-Klasse in MQL5 erbt. Zweck dieser Klasse ist es, CAccountInfo um eine nutzerdefinierte Methode zum Abrufen der Gesamtzahl bestimmter Arten von Aufträgen im Handelskonto zu erweitern, z. B. Limit-/Stop-Aufträge für Kauf und Verkauf. Diese zusätzliche Funktion wird in der Handelsmanagementklasse verwendet, um sicherzustellen, dass der Experte die Limit-Order des Kontos einhält.
Ein Beispiel: Wenn das Limit für Aufträge bei 200 liegt, bedeutet dies, dass das Konto des Nutzers 200 Aufträge nicht überschreiten darf, einschließlich offener und schwebender Aufträge. Wenn wir also jeweils eine Stop-Order für Kauf und Verkauf eröffnen wollen, das Konto des Nutzers aber 199 Aufträge aufweist, wird der Experte feststellen, dass nicht genügend Aufträge übrig sind, um beide Stop-Order zu eröffnen. In diesem Fall werden dem Konto des Nutzers also keine zusätzlichen Aufträge hinzugefügt.
Kopfzeile und Einschlüsse:
Der folgende Code enthält die Datei AccountInfo.mqh aus der MQL5-Standardbibliothek. Diese Datei enthält vordefinierte Funktionen und Strukturen für den Zugriff auf Handelskontoinformationen.
#include <Trade/AccountInfo.mqh>
CAccountProperties Klassendefinition:
Vererbung: Die Klasse CAccountProperties erbt öffentlich von CAccountInfo. Durch Vererbung erhält CAccountProperties Zugriff auf die Funktionen und Datenelemente von CAccountInfo.
CAccountInfo liefert wichtige Kontodaten wie Saldo, Eigenkapital, freie Marge usw.
Zweck der Klasse: Die Klasse CAccountProperties fügt eine Methode (numOrders) hinzu, die bestimmte Arten von Aufträgen zählt.
class CAccountProperties: public CAccountInfo
Die Funktion numOrders:
Die Funktion numOrders() ist der Ort, an dem die meiste Action stattfindet. Diese Funktion zählt die Anzahl der spezifischen Auftragsarten (Limit- und Stop-Order), die derzeit im Handelskonto offen sind.
- Typ der Rückgabe: Die Funktion gibt eine ganze Zahl zurück.
- Initialisierung: Die Variable num wird auf 0 initialisiert. Hier wird die Anzahl der Aufträge gespeichert, die den gewünschten Typen entsprechen
int CAccountProperties::numOrders(void) { int num=0;
Iteration durch alle Order:
- OrdersTotal() ist eine MQL5-Funktion, die die Gesamtzahl der Aufträge zurückgibt.
- In einer Schleife werden alle Order von Index 0 bis OrdersTotal() - 1 durchlaufen.
for(int i=0; i<OrdersTotal(); i++)
Validierung der Order:
- OrderGetTicket(i) ist eine MQL5-Funktion, die die Ticketnummer für die Order bei Index i abruft. Jede Order hat eine eindeutige Ticketnummer.
- Wenn die Ticketnummer größer als 0 ist, bedeutet dies, dass die Order gültig ist, und der Code fährt mit der Überprüfung des Typs fort.
if(OrderGetTicket(i)>0)
Prüfen des Typs der Order:
- OrderGetInteger(ORDER_TYPE) ruft den Typ der Order bei Index i ab. Dieser Wert entspricht einem int, der verschiedene Arten von Order darstellt (Kauflimit, Sell-Stop usw.).
- Die switch-Anweisung prüft den Typ jeder Order und vergleicht ihn mit vordefinierten Auftragstyp-Konstanten.
switch(int(OrderGetInteger(ORDER_TYPE)))
Handhabung bestimmter Typen von Order:
- Order-Typen:
- ORDER_TYPE_BUY_LIMIT: Eine Buy-Limit-Order.
- ORDER_TYPE_BUY_STOP: Eine Buy-Stop-Order.
- ORDER_TYPE_BUY_STOP_LIMIT: Eine Buy-Stop-Limit-Order.
- ORDER_TYPE_SELL_LIMIT: Eine Sell-Limit-Order.
- ORDER_TYPE_SELL_STOP: Eine Sell-Stop-Order.
- ORDER_TYPE_SELL_STOP_LIMIT: Eine Sell-Stop-Limit-Order.
Für jede erkannte Auftragsart wird die Zählernummer inkrementiert. Handelt es sich um einen Auftrag anderer Art, wird der Standardfall ausgelöst, und es werden keine Maßnahmen ergriffen.
case ORDER_TYPE_BUY_LIMIT: num++; break; case ORDER_TYPE_BUY_STOP: num++; break; case ORDER_TYPE_BUY_STOP_LIMIT: num++; break; case ORDER_TYPE_SELL_LIMIT: num++; break; case ORDER_TYPE_SELL_STOP: num++; break; case ORDER_TYPE_SELL_STOP_LIMIT: num++; break; default: break;
Die Rückgabe der Anzahl:
- Nachdem die Funktion alle Order durchlaufen und die gültigen gezählt hat, gibt sie die in num ermittelte Gesamtzahl zurück.
return num;
}
Die Klasse für das Risikomanagement
Diese Klasse stellt sicher, dass das Marktrisiko des Händlers kontrolliert wird, indem potenzielle Verluste begrenzt werden und gleichzeitig Raum für Gewinne bleibt. Der folgende Code definiert eine Enumeration OrderTypeSelection, die zur Darstellung verschiedener Arten von Auftragsklassifizierungen verwendet wird. Der Nutzer kann wählen, mit welcher dieser Auftragsarten er lieber handeln möchte. //-- Enumeration for Order type enum OrderTypeSelection { MarketPositionType,//MARKET POSITION StopOrdersType,//STOP ORDERS StopOrderType,//SINGLE STOP ORDER } myOrderSelection;
Enumeration: OrderTypeSelection
Die Enumeration OrderTypeSelection besteht aus drei verschiedenen Werten:
MarktPositionsTyp:
- Steht für einen Marktauftrag einer Position.
- Dieser Typ eröffnet auf der Grundlage des aktuellen Marktpreises, der sofort zum aktuellen Preis ausgeführt wird.
- Erfordert Auswirkungen des Ereignisses.
StopOrdersType:
- Steht für Stop-Order.
- Stop-Aufträge sind bedingte Aufträge, die nur ausgeführt werden, wenn der Kurs ein bestimmtes Niveau erreicht. Es werden sowohl Kauf- als auch Sell-Stop-Aufträge eröffnet.
- Erfordert keine Auswirkungen auf das Ereignis.
StopOrderType:
- Steht für eine einzelne Stop-Order.
- Eine individuelle Kauf- oder Sell-Stop-Order wird eröffnet.
- Erfordert Auswirkungen des Ereignisses.
Variablen-Deklaration: myOrderSelection
- myOrderSelection ist eine Variable, die den vom Händler ausgewählten Auftragstyp speichert.
Normalisierung der Losgröße
In der folgenden Funktion ändert sich das Volumenlimit in Abhängigkeit von der OrderTypeSelection. Wenn myOrderSelection StopOrdersType(STOP ORDERS) ist, wird das Volumenlimit halbiert, um die Stop-Order sowohl für einen Kauf wie einen Verkauf unterzubringen, da beide gleichzeitig geöffnet werden müssen, während MarketPositionType(MARKET POSITION) und StopOrderType(SINGLE STOP ORDER) nur einzelne Orders öffnen.
void CRiskManagement::NormalizeLotsize(double &Lotsize) { // Adjust lot size to match symbol's step size or minimum size if (Lotsize <= 0.0) return; double VolumeLimit = (myOrderSelection != StopOrdersType) ? CSymbol.LotsLimit() : CSymbol.LotsLimit() / 2; // Check and adjust if volume exceeds limits // ... }
Die Klasse der Handelssitzungen
Der folgende Code definiert die Klasse CSessions, die für die Verwaltung und Verfolgung der Handelssitzungszeiten für ein bestimmtes Handelssymbol verantwortlich ist. Er verwendet Methoden der Basisklasse CTimeManagement (eingebunden über Timemanagement.mqh), um festzustellen, ob eine Handelssitzung begonnen oder beendet wurde, und um die Endzeit der Sitzung zu ermitteln. Wir müssen wissen, wann die Börsensitzung endet, um den Handel vorher zu schließen und das Verfallsdatum der Aufträge festzulegen, damit wir nicht über Nacht handeln.
Warum sollte man den Übernacht-Handel vermeiden?
Das erhöhte Marktrisiko aufgrund der Volatilität
Die Märkte können über Nacht sehr volatil sein, insbesondere als Reaktion auf wirtschaftliche Ereignisse, geopolitische Entwicklungen oder Nachrichten von anderen globalen Märkten. Da wichtige Ereignisse außerhalb der normalen Handelszeiten eintreten können, sind die über Nacht gehaltenen Positionen unvorhersehbaren Kursbewegungen ausgesetzt. Diese Bewegungen können dazu führen:
- Erhebliche Kursunterschiede bei Markteröffnung am nächsten Tag, was zu erheblichen Gewinnen oder Verlusten führen kann.
- Eingeschränkte Fähigkeit, auf schnelle Veränderungen zu reagieren, da die Liquidität gering sein kann und Ihre Möglichkeiten, Positionen schnell zu ändern oder zu verlassen, eingeschränkt sein können.
Begrenzte Liquidität
Während des Nachthandels ist die Liquidität tendenziell geringer, da weniger Marktteilnehmer aktiv sind. Das kann zu Folgendem führen:
- Größere Spannen zwischen Geld- und Briefkursen, was die Transaktionskosten erhöht.
- Slippage, d. h. Handelsgeschäfte werden aufgrund mangelnder Markttiefe zu einem anderen Preis als erwartet ausgeführt.
- Schwierigkeit, große Positionen zu schließen, ohne den Markt zu bewegen, was zu einer ungünstigen Preisausführung führen kann.
Erhöhtes Risiko von Preissprüngen
Beim Nachthandel kann es zu Kurssprüngen kommen, d. h. der Kurs bei Markteröffnung weicht erheblich vom Schlusskurs des Vortages ab. Lücken können aufgrund von Pressemitteilungen oder anderen Ereignissen entstehen und können zu:
- Größere Verluste als erwartet, insbesondere wenn sich der Kurs gegen Ihre Position bewegt.
- Stop-Loss-Order sind unwirksam, da Gaps die von Ihnen festgelegten Stop-Levels überspringen können und Ihr Auftrag zu einem viel schlechteren Preis als erwartet ausgeführt wird.
Zinskosten (Swap-Gebühren)
Bei bestimmten Instrumenten wie Devisen kann das Halten von Positionen über Nacht zu Swap-Gebühren oder Zinskosten führen, je nach der Zinsdifferenz zwischen den beteiligten Währungen. Diese Kosten können sich mit der Zeit ansammeln und die Rentabilität verringern. Swap-Gebühren können:
- Aus gewinnbringenden Handelsgeschäften werden Verlustgeschäfte, insbesondere wenn sie über einen längeren Zeitraum gehalten werden.
- Sie schwanken je nach Marktbedingungen und sind daher schwieriger vorherzusagen und zu planen.
Geringere Kontrolle über die Ausführung von Handelsgeschäften
Während der Nacht, insbesondere auf Märkten mit begrenzten oder unregelmäßigen Öffnungszeiten, kann die Ausführung von Handelsgeschäften langsamer oder weniger präzise sein:
- Betriebszeiten des Maklers: Einige Broker unterstützen bestimmte Handelsaktionen oder Änderungen möglicherweise nicht außerhalb ihrer regulären Handelsgeschäftszeiten, was Ihre Möglichkeiten einschränkt, auf Marktbedingungen zu reagieren.
//+------------------------------------------------------------------+ //| NewsTrading | //| Copyright 2024, MetaQuotes Ltd. | //| https://www.mql5.com/en/users/kaaiblo | //+------------------------------------------------------------------+ #include "Timemanagement.mqh" //+------------------------------------------------------------------+ //|Sessions Class | //+------------------------------------------------------------------+ class CSessions:CTimeManagement { public: CSessions(void) {} ~CSessions(void) {} //--- Check if trading Session has began bool isSessionStart(int offsethour=0,int offsetmin=0); //--- Check if trading Session has ended bool isSessionEnd(int offsethour=0,int offsetmin=45); //--- Get Session End datetime datetime SessionEnd(int offsethour=0,int offsetmin=45); }; //+------------------------------------------------------------------+ //|Check if trading Session has started | //+------------------------------------------------------------------+ bool CSessions::isSessionStart(int offsethour=0,int offsetmin=0) { //--- Declarations datetime datefrom,dateto,DateFrom[],DateTo[]; //--- Find all session times for(int i=0; i<10; i++) { //--- Get the session dates for the current symbol and Day of week if(SymbolInfoSessionTrade(Symbol(),DayOfWeek(TimeTradeServer()),i,datefrom,dateto)) { //--- Check if the end date's hour is at midnight if(ReturnHour(dateto)==00||ReturnHour(dateto)==24) { //--- Adjust the date to one minute before midnight dateto = Time(TimeTradeServer(),23,59); } //--- Re-adjust DateFrom Array size ArrayResize(DateFrom,int(ArraySize(DateFrom))+1,int(ArraySize(DateFrom))+2); //--- Assign the last array index datefrom value DateFrom[int(ArraySize(DateFrom))-1] = datefrom; //--- Re-adjust DateTo Array size ArrayResize(DateTo,int(ArraySize(DateTo))+1,int(ArraySize(DateTo))+2); //--- Assign the last array index dateto value DateTo[int(ArraySize(DateTo))-1] = dateto; } } //--- Check if there are session times if(DateFrom.Size()>0) { /* Adjust DateFrom index zero date as the first index date will be the earliest date from the whole array, we add the offset to this date only*/ DateFrom[0] = TimePlusOffset(DateFrom[0],MinutesS(offsetmin)); DateFrom[0] = TimePlusOffset(DateFrom[0],HoursS(offsethour)); //--- Iterate through the whole array for(uint i=0; i<DateFrom.Size(); i++) { //--- Check if the current time is within the trading session if(TimeIsInRange(Time(Today(ReturnHour(DateFrom[i]),ReturnMinute(DateFrom[i]))) ,Time(Today(ReturnHour(DateTo[i]),ReturnMinute(DateTo[i]))))) { return true; } } } else { //--- If there are no trading session times return true; } return false; } //+------------------------------------------------------------------+ //|Check if trading Session has ended | //+------------------------------------------------------------------+ bool CSessions::isSessionEnd(int offsethour=0,int offsetmin=45) { //--- Declarations datetime datefrom,dateto,DateTo[],lastdate=0,sessionend; //--- Find all session times for(int i=0; i<10; i++) { //--- Get the session dates for the current symbol and Day of week if(SymbolInfoSessionTrade(Symbol(),DayOfWeek(TimeTradeServer()),i,datefrom,dateto)) { //--- Check if the end date's hour is at midnight if(ReturnHour(dateto)==00||ReturnHour(dateto)==24) { //--- Adjust the date to one minute before midnight dateto = Time(TimeTradeServer(),23,59); } //--- Re-adjust DateTo Array size ArrayResize(DateTo,int(ArraySize(DateTo))+1,int(ArraySize(DateTo))+2); //--- Assign the last array index dateto value DateTo[int(ArraySize(DateTo))-1] = dateto; } } //--- Check if there are session times if(DateTo.Size()>0) { //--- Assign lastdate a default value lastdate = DateTo[0]; //--- Iterate through the whole array for(uint i=0; i<DateTo.Size(); i++) { //--- Check for the latest date in the array if(DateTo[i]>lastdate) { lastdate = DateTo[i]; } } } else { //--- If there are no trading session times return false; } /* get the current time and modify the hour and minute time to the lastdate variable and assign the new datetime to sessionend variable*/ sessionend = Time(Today(ReturnHour(lastdate),ReturnMinute(lastdate))); //--- Re-adjust the sessionend dates with the minute and hour offsets sessionend = TimeMinusOffset(sessionend,MinutesS(offsetmin)); sessionend = TimeMinusOffset(sessionend,HoursS(offsethour)); //--- Check if sessionend date is more than the current time if(TimeTradeServer()<sessionend) { return false; } return true; } //+------------------------------------------------------------------+ //|Get Session End datetime | //+------------------------------------------------------------------+ datetime CSessions::SessionEnd(int offsethour=0,int offsetmin=45) { //--- Declarations datetime datefrom,dateto,DateTo[],lastdate=0,sessionend; //--- Find all session times for(int i=0; i<10; i++) { //--- Get the session dates for the current symbol and Day of week if(SymbolInfoSessionTrade(Symbol(),DayOfWeek(TimeTradeServer()),i,datefrom,dateto)) { //--- Check if the end date's hour is at midnight if(ReturnHour(dateto)==00||ReturnHour(dateto)==24) { //--- Adjust the date to one minute before midnight dateto = Time(TimeTradeServer(),23,59); } //--- Re-adjust DateTo Array size ArrayResize(DateTo,int(ArraySize(DateTo))+1,int(ArraySize(DateTo))+2); //--- Assign the last array index dateto value DateTo[int(ArraySize(DateTo))-1] = dateto; } } //--- Check if there are session times if(DateTo.Size()>0) { //--- Assign lastdate a default value lastdate = DateTo[0]; //--- Iterate through the whole array for(uint i=0; i<DateTo.Size(); i++) { //--- Check for the latest date in the array if(DateTo[i]>lastdate) { lastdate = DateTo[i]; } } } else { //--- If there are no trading session times return 0; } /* get the current time and modify the hour and minute time to the lastdate variable and assign the new datetime to sessionend variable*/ sessionend = Time(Today(ReturnHour(lastdate),ReturnMinute(lastdate))); //--- Re-adjust the sessionend dates with the minute and hour offsets sessionend = TimeMinusOffset(sessionend,MinutesS(offsetmin)); sessionend = TimeMinusOffset(sessionend,HoursS(offsethour)); //--- return sessionend date return sessionend; } //+------------------------------------------------------------------+
Erläuterung der Schlüsselkomponenten
Definition der Klasse: CSessions
- Vererbung:
- Die Klasse CSessions wird von CTimeManagement abgeleitet, sodass sie Zugriff auf alle zeitmanagementbezogenen Methoden und Attribute hat, die in dieser Basisklasse definiert sind.
- Methoden:
- isSessionStart(int offsethour=0, int offsetmin=0):
- Ermittelt, ob eine Handelssitzung begonnen hat, indem die aktuelle Serverzeit mit den Startzeiten der Sitzungen verglichen wird. Es erlaubt auch optionale Zeitverschiebungen.
- isSessionEnd(int offsethour=0, int offsetmin=45):
- Ermittelt, ob eine Handelssitzung beendet ist, indem die aktuelle Serverzeit mit den Endzeiten der Sitzungen verglichen wird. Wie isSessionStart nimmt es optionale Offsets (45 Minuten Standard).
- SessionEnd(int offsethour=0, int offsetmin=45):
- Gibt den Datumswert des Endes der aktuellen Handelssitzung zurück, der mit den angegebenen Offsets angepasst wird (Standard: 45 Minuten).
Details der Methode
isSessionStart(int offsethour=0, int offsetmin=0)
Diese Methode prüft, ob die Handelssitzung anhand der Serverzeit und des Sitzungsplans des Handelssymbols begonnen hat.
Variablen:
- datefrom, dateto: Diese werden verwendet, um die Start- und Endzeiten der Sitzungen für jeden Handelstag zu speichern.
- DateFrom[], DateTo[]: Arrays, die die Start- und Endzeiten der Sitzungen nach den Anpassungen enthalten.
Logik:
- Abruf der Sitzung:
- Die Funktion SymbolInfoSessionTrade ruft die Start- (datefrom) und Endzeiten (dateto) der Handelssitzung für das aktuelle Symbol und den aktuellen Wochentag ab (abgerufen durch DayOfWeek(TimeTradeServer())).
- Wenn die Endzeit der Sitzung (dateto) um Mitternacht (00:00 oder 24:00) liegt, wird die Zeit auf eine Minute vor Mitternacht (23:59) eingestellt.
- Array-Manipulation:
- Die Startzeiten der Sitzung (datefrom) werden in dem Array DateFrom[] gespeichert, die Endzeiten (dateto) in dem Array DateTo[].
- Offset-Anwendung:
- Die Methode passt die Startzeit der ersten Sitzung mit Hilfe der Hilfsfunktionen MinutesS() und HoursS() um die angegebene Offsethour und Offsetmin an.
- Prüfen der aktuellen Zeit:
- Die Methode iteriert dann durch die Sitzungszeiten in DateFrom[] und DateTo[] und überprüft, ob die aktuelle Serverzeit (TimeTradeServer()) in eines der Sitzungsintervalle fällt.
- Wenn eine gültige Sitzung gefunden wird, wird true zurückgegeben, was bedeutet, dass die Sitzung begonnen hat. Andernfalls wird false zurückgegeben.
isSessionEnd(int offsethour=0, int offsetmin=45)
Diese Methode prüft, ob die Handelssitzung beendet ist.
Variablen:
- Ähnlich wie isSessionStart(), aber mit dem Schwerpunkt auf Endzeiten (dateto).
- lastdate: Speichert die letzte Zeit des Sitzungsendes zum Vergleich.
- sessionend: Enthält die endgültige berechnete Endzeit der Sitzung mit den angewandten Offsets.
Logik:
- Abruf der Sitzung:
- Ruft die Sitzungszeiten (datefrom, dateto) wie in isSessionStart() ab.
- Sie prüft, ob es gültige Sitzungszeiten in DateTo[] gibt und ermittelt die letzte Sitzungsendzeit (lastdate).
- Offset-Anwendung:
- Passt die Endzeit der Sitzung durch Anwendung der Offsets (offsethour und offsetmin) an.
- Vergleich mit der Serverzeit:
- Liegt die aktuelle Zeit vor der eingestellten Endzeit der Sitzung, wird false zurückgegeben, was bedeutet, dass die Sitzung noch läuft. Wenn die Sitzung beendet ist (die aktuelle Zeit liegt nach sessionend), wird true zurückgegeben.
SessionEnd(int offsethour=0, int offsetmin=45)
Diese Methode gibt den Datumswert für das Ende der aktuellen Sitzung zurück, wobei die angegebenen Zeitabweichungen angewendet werden.
Logik:
- Ähnlich wie isSessionEnd() ruft sie Sitzungszeiten ab, wendet Offsets an und gibt die endgültige angepasste Sitzungsendzeit (sessionend) zurück.
- Erhöhte Volatilität und unvorhersehbare Marktbewegungen.
- Geringe Liquidität, was zu größeren Spreads und höheren Kosten führt.
- Risiko von Kurslsprüngen, die zu großen Verlusten führen können.
- Exposition gegenüber globalen Ereignissen und deren Auswirkungen auf die Märkte.
- Zinskosten oder Swap-Gebühren auf den Devisenmärkten.
- Geringere Kontrolle über Handelsausführung und Entscheidungsfindung.
Handelsmanagement-Klasse
Die Klasse CTradeManagement erweitert CRiskManagement und enthält Funktionen für die Verwaltung von Handelsgeschäften, wie z.B. die Platzierung von Kauf-/Verkaufsaufträgen, die Handhabung von Stop-Loss- und Take-Profit-Levels und die Verwaltung von Stop-Order.
Flussdiagramm zur Eröffnung eines Kauf- oder Verkaufsauftrags:
+---------------------------+
| Receive Trade Signal |
+---------------------------+
|
V
+---------------------------+
| Check for Available Margin|
+---------------------------+
|
V
+---------------------------+
| Place Buy/Sell Order |
+---------------------------+
|
V
+----------------------------+
| Set Stop Loss & Take Profit|
+----------------------------+
|
V
+----------------------------+
| Monitor Open Position |
+----------------------------+
|
If conditions met:
|
V
+----------------------------+
| Adjust SL/TP or Close Trade|
+----------------------------+
//+------------------------------------------------------------------+ //| NewsTrading | //| Copyright 2024, MetaQuotes Ltd. | //| https://www.mql5.com/en/users/kaaiblo | //+------------------------------------------------------------------+ #include <Trade\Trade.mqh> #include <Trade\OrderInfo.mqh> #include <Trade\SymbolInfo.mqh> #include "RiskManagement.mqh" #include "TimeManagement.mqh" #include "Sessions.mqh" //+------------------------------------------------------------------+ //|TradeManagement class | //+------------------------------------------------------------------+ class CTradeManagement:CRiskManagement { private: CTrade Trade;//Trade class object CSymbolProperties CSymbol;//SymbolProperties class object CTimeManagement CTime;//TimeManagement class object CSessions CTS;//Sessions class object bool TradeResult;//boolean to store trade result double mySL;//double variable to store Stoploss double myTP;//double variable to store Takeprofit uint myDeviation;//store price deviation for stop orders double myOpenPrice;//store open price for stop orders //--- Will retrieve if there are any open trades bool OpenTrade(ENUM_POSITION_TYPE Type,ulong Magic,string COMMENT=NULL); //--- Will retrieve if there are any deals bool OpenedDeal(ENUM_DEAL_TYPE Type,ulong Magic,string COMMENT=NULL); //--- Will retrieve if there are any open orders bool OpenOrder(ENUM_ORDER_TYPE Type,ulong Magic,string COMMENT=NULL); //-- Check if trade is valid bool Valid_Trade(ENUM_POSITION_TYPE Type,double Price,double SL,double TP); //-- Check if stop order is valid bool Valid_Order(ENUM_ORDER_TYPE Type,double Price,double SL,double TP); //--- Will attempt to open buy trade bool Buy(double SL,double TP,ulong Magic,string COMMENT=NULL); //--- Will attempt to open sell trade bool Sell(double SL,double TP,ulong Magic,string COMMENT=NULL); //--- class to set and retrieve an order's properties class OrderSettings { private: struct TradeProperties { //store open-price,take-profit,stop-loss for stop orders double Open,Take,Stop; } myTradeProp; public: OrderSettings() {} //--- Set order properties void Set(double myOpen,double myTake,double myStop) { //--- Set open-price myTradeProp.Open=myOpen; //--- Set take-profit myTradeProp.Take=myTake; //--- Set stop-loss myTradeProp.Stop=myStop; } TradeProperties Get() { //--- retrieve order properties return myTradeProp; } }; //--- Declare variables for different order types OrderSettings myBuyStop,mySellStop,myBuyTrade,mySellTrade; //--- Will set buy-stop order properties void SetBuyStop(int SL,int TP); //--- Will set buy position properties void SetBuyTrade(int SL,int TP,double OP); //--- Will set sell-stop order properties void SetSellStop(int SL,int TP); //--- Will set sell position properties void SetSellTrade(int SL,int TP,double OP); public: //--- Class constructor CTradeManagement(uint deviation,string SYMBOL=NULL) :myDeviation(deviation)//Assign deviation value { //--- Set symbol name CSymbol.SetSymbolName(SYMBOL); } //--- Class destructor ~CTradeManagement(void) { } //--- Will attempt to open buy trade bool Buy(int SL,int TP,ulong Magic,string COMMENT=NULL); //--- Will attempt to open sell trade bool Sell(int SL,int TP,ulong Magic,string COMMENT=NULL); /*This function will delete a pending order if the previous opposing pending order is opened into a position, this function is used when trading with StopOrdersType(STOP ORDERS)*/ void FundamentalMode(string COMMENT_COMMON); /* Function will attempt to re-adjust stop-losses or take-profit values that have been changed due to slippage on an order when opening. */ void SlippageReduction(int SL,int TP,string COMMENT_COMMON); //--- This function will open both buy-stop and sell-stop orders for StopOrdersType(STOP ORDERS) bool OpenStops(int SL,int TP,ulong Magic,string COMMENT=NULL); //--- Will attempt to open a sell-stop order bool OpenSellStop(int SL,int TP,ulong Magic,string COMMENT=NULL); //--- Will attempt to open a buy-stop order bool OpenBuyStop(int SL,int TP,ulong Magic,string COMMENT=NULL); //--- Function will attempt to close all trades depending on the position comment void CloseTrades(string COMMENT_COMMON); }; // ...
Private Mitglieder:
- Objekte und Variablen:
- CTrade Trade: Verwaltet die Handelsausführung (Kauf-/Verkaufsaufträge) usw.
- CSymbolProperties CSymbol: Verwaltet die Symboleigenschaften.
- CTimeManagement CTime: Verarbeitet die zeitbezogene Logik.
- CSessions CTS: Verwaltet Sitzungen, die sich auf die Handelszeiten beziehen.
- bool TradeResult: Ein boolesches Flag für das Ergebnis eines Handels (Erfolg/Misserfolg).
- double mySL: Stop-Loss-Wert.
- double myTP: Take-Profit-Wert.
- uint myDeviation;: Preisabweichung bei Stop-Aufträgen.
- double myOpenPrice: Speichert den Eröffnungspreis für Stop-Aufträge.
OrderSettings Innere Klasse:
class OrderSettings { private: struct TradeProperties { double Open, Take, Stop; } myTradeProp; public: OrderSettings() {} void Set(double myOpen, double myTake, double myStop) { myTradeProp.Open = myOpen; myTradeProp.Take = myTake; myTradeProp.Stop = myStop; } TradeProperties Get() { return myTradeProp; } };
- Zweck: Diese innere Klasse kapselt die Handelseigenschaften (offener Preis, Take-Profit, Stop-Loss). Es ermöglicht das einfache Einstellen und Abrufen dieser Eigenschaften.
- myTradeProp: Eine Struktur zum Bereithalten der Handelseigenschaften.
- Set(): Methode zum Festlegen von Take-Profit- und Stop-Loss- und Eröffnungs-Werte.
- Get(): Ruft die gespeicherten Handelseigenschaften ab.
- Variablen mit OrderSettings:
OrderSettings myBuyStop, mySellStop, myBuyTrade, mySellTrade;
- In diesen Objekten werden die Eigenschaften der verschiedenen Auftragstypen (Buy-Stop, Sell-Stop, Buy, Sell).
Die Funktion FundamentalMode im nachstehenden Code dient dazu, eine ausstehende Stop-Order zu löschen, wenn die entgegengesetzte Order ausgeführt und als Position eröffnet wurde. Diese Funktion ist für Strategien relevant, die Stop-Order sowohl für Kauf- als auch für Verkauf verwenden (z. B. Straddle-Strategien), um Positionen in volatilen Märkten einzugehen. Sobald eine der Stop-Order ausgelöst und eine Position eröffnet wird, wird die verbleibende, entgegengesetzte Order (die nun überflüssig ist) gelöscht, um unnötige Handelsgeschäfte zu vermeiden.
Beispiel:
Der Buy-Stop wird bei 1,13118 und der Sell-Stop bei 1,12911 eröffnet. Der Buy-Stop wird zuerst ausgeführt mit der Journalmeldung „deal performed [#2 buy 0.01 EURUSD at 1.13134]“. In diesem Fall löscht die Funktion die verbleibende Sell-Stop-Order mit der Journalmeldung „order canceled [#3 sell stop 0.01 EURUSD at 1.12911]“, wie in der Abbildung unten zu sehen.
//+------------------------------------------------------------------+ //|This function will delete a pending order if the previous opposing| //|pending order is opened into a position, this function is used | //|when trading with StopOrdersType(STOP ORDERS) | //+------------------------------------------------------------------+ void CTradeManagement::FundamentalMode(string COMMENT_COMMON) { //--- Iterate through all open positions if Orders are more than zero for(int P=0; P<PositionsTotal()&&OrdersTotal()>0; P++) { //--- Check if Position ticket is above zero if(PositionGetTicket(P)>0) { //--- Check if the Position's Symbol,Magic,Type,Comment is correct if(PositionGetString(POSITION_SYMBOL)==CSymbol.GetSymbolName()&& StringFind(PositionGetString(POSITION_COMMENT),COMMENT_COMMON)>=0) { //--- Iterate through all open orders for(int O=0; O<OrdersTotal(); O++) { //--- Check if Order ticket is above zero if(OrderGetTicket(O)>0) { //--- Check if the Order's Symbol,Magic,Comment is correct if(OrderGetString(ORDER_SYMBOL)==CSymbol.GetSymbolName() &&OrderGetInteger(ORDER_MAGIC)==PositionGetInteger(POSITION_MAGIC) &&StringFind(OrderGetString(ORDER_COMMENT),COMMENT_COMMON)>=0 &&OrderGetString(ORDER_COMMENT)==PositionGetString(POSITION_COMMENT)) { //--- Identify Position type switch(int(PositionGetInteger(POSITION_TYPE))) { /* In the case that the Position type is a buy and if the corresponding order type is a sell-stop then delete this order*/ case POSITION_TYPE_BUY: if(OrderGetInteger(ORDER_TYPE)==ORDER_TYPE_SELL_STOP) { //--- Delete the sell-stop order Trade.OrderDelete(OrderGetTicket(O)); } break; /* In the case that the Position type is a sell and if the corresponding order type is a buy-stop then delete this order*/ case POSITION_TYPE_SELL: if(OrderGetInteger(ORDER_TYPE)==ORDER_TYPE_BUY_STOP) { //--- Delete the sell-stop order Trade.OrderDelete(OrderGetTicket(O)); } break; default: break; } } } } } } } }
Zweck der Funktion:
Die Funktion stellt sicher, dass bei der Eröffnung eines schwebenden Auftrags (z.B. eines Buy-Stop- oder Sell-Stop-Order) der gegnerische Auftrag (z.B. Sell-Stop oder Buy-Stop) gelöscht wird. Dadurch wird verhindert, dass beide Aufträge ausgeführt werden, was zur Eröffnung unerwünschter Positionen führen könnte.
void CTradeManagement::FundamentalMode(string COMMENT_COMMON)
- FundamentalMode: Diese Funktion soll eine ausstehende Stop-Order entfernen, wenn die entgegengesetzte Position eröffnet worden ist.
- COMMENT_COMMON: Eine Zeichenkette, die zur Identifizierung von Handelsgeschäften/Aufträgen auf der Grundlage des mit ihnen verbundenen Kommentars verwendet wird.
Schleife über offene Positionen:
for(int P = 0; P < PositionsTotal() && OrdersTotal() > 0; P++)
- PositionsTotal(): Gibt die Gesamtzahl der offenen Positionen zurück.
- OrdersTotal(): Gibt die Gesamtzahl der schwebenden Aufträge zurück.
- Diese for-Schleife durchläuft alle offenen Positionen und stellt sicher, dass es schwebende Aufträge gibt, die bearbeitet werden müssen.
Position Ticket Validierung:
if(PositionGetTicket(P) > 0)
- PositionGetTicket(P): Ruft die Ticketnummer der Position bei Index P ab.
- Stellt sicher, dass das Positionsticket gültig ist (d.h. über Null).
Prüfen der Positionseigenschaften:
if(PositionGetString(POSITION_SYMBOL) == CSymbol.GetSymbolName() && StringFind(PositionGetString(POSITION_COMMENT), COMMENT_COMMON) >= 0)
- PositionGetString(POSITION_SYMBOL): Ruft das Symbol der offenen Position ab.
- CSymbol.GetSymbolName(): Ruft den Symbolnamen für das im Konstruktor festgelegte Symbol ab.
- PositionGetString(POSITION_COMMENT): Ruft den mit der Position verbundenen Kommentar ab.
- StringFind(PositionGetString(POSITION_COMMENT), COMMENT_COMMON): Prüft, ob die Teilzeichenkette COMMENT_COMMON im Kommentar der Position vorhanden ist. Damit wird sichergestellt, dass die Position zur Strategie/zum Experten gehört.
Schleife über offene Aufträge:
for(int O = 0; O < OrdersTotal(); O++)
- Iteriert durch alle offenen schwebenden Aufträge.
Validierung der Order:
if(OrderGetTicket(O) > 0)
- OrderGetTicket(O): Ruft die Ticketnummer des Auftrags mit dem Index O ab.
- Stellt sicher, dass die Order gültig ist.
Prüfen der Eigenschaften der Order:
if(OrderGetString(ORDER_SYMBOL) == CSymbol.GetSymbolName() && OrderGetInteger(ORDER_MAGIC) == PositionGetInteger(POSITION_MAGIC) && StringFind(OrderGetString(ORDER_COMMENT), COMMENT_COMMON) >= 0 && OrderGetString(ORDER_COMMENT) == PositionGetString(POSITION_COMMENT))
- OrderGetString(ORDER_SYMBOL): Ruft das mit dem Auftrag verbundene Symbol ab.
- OrderGetInteger(ORDER_MAGIC): Ruft die magische Nummer der Order ab (die hilft, Order für jedes Ereignis zu identifizieren).
- PositionGetInteger(POSITION_MAGIC): Ruft die magische Zahl der Position ab, um sie mit der magischen Zahl der Order abzugleichen.
- OrderGetString(ORDER_COMMENT): Ruft den Kommentar der Order ab.
- Stellt sicher, dass das Symbol, die magische Zahl und der Kommentar der Order mit den Eigenschaften der Position übereinstimmen. Dadurch wird sichergestellt, dass der schwebende Auftrag mit der offenen Position verbunden ist.
Widersprüchliche Aufträge identifizieren und löschen:
switch(int(PositionGetInteger(POSITION_TYPE))) { case POSITION_TYPE_BUY: if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_STOP) { Trade.OrderDelete(OrderGetTicket(O)); } break; case POSITION_TYPE_SELL: if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_STOP) { Trade.OrderDelete(OrderGetTicket(O)); } break; default: break; }
- PositionGetInteger(POSITION_TYPE): Liefert den Typ der offenen Position (entweder POSITION_TYPE_BUY oder POSITION_TYPE_SELL).
- OrderGetInteger(ORDER_TYPE): Ruft den Typ des schwebenden Auftrags ab (entweder ORDER_TYPE_BUY_STOP oder ORDER_TYPE_SELL_STOP).
Switch .. Case:
- Handelt es sich bei der Position um eine Kaufposition (POSITION_TYPE_BUY), prüft die Funktion, ob eine Sell-Stop-Order (ORDER_TYPE_SELL_STOP) vorliegt. Wenn sie gefunden wird, wird dieser Sell-Stop-Order gelöscht, da sie nicht mehr benötigt wird.
- Wenn es sich bei der Position um eine Verkaufsposition (POSITION_TYPE_SELL) handelt, prüft die Funktion, ob eine Buy-Stop-Order (ORDER_TYPE_BUY_STOP) vorliegt. Wenn er gefunden wird, wird dieser Buy-Stop-Order gelöscht.
Trade.OrderDelete(OrderGetTicket(O)): Diese Methode löscht den schwebenden Auftrag unter Verwendung seiner Ticketnummer, wodurch der unnötige gegnerische Auftrag entfernt wird, nachdem die entsprechende Position eröffnet worden ist.
Die Funktion SlippageReduction soll sicherstellen, dass die Stop-Loss (SL) und Take-Profit (TP) einer offenen Position korrekt auf ihre erwarteten Werte gesetzt werden. Wenn ein Slippage (die Differenz zwischen dem erwarteten und dem tatsächlichen Preis einer Auftragsausführung) dazu geführt hat, dass SL und TP von ihren beabsichtigten Werten bei der Auftragsausführung abweichen, passt die Funktion die Position an, um die erwarteten SL und TP zu berücksichtigen.
Beispiel: Ein Händler möchte einen Buy-Stop- und einen Sell-Stop-Order für den Handel des NFP eröffnen. Der Händler möchte für zwei schwebende Aufträge eine Preisabweichung von 100 Pips vom aktuellen Preis platzieren. Er möchte außerdem ein Risiko-Ertrags-Verhältnis von 1:6, also einen Stop-Loss von 100 Pips und einen Take-Profit von 600 Pips realisieren. In diesem Fall wird der Buy-Stop bei 1,13118, der SL bei 1,13018 und der TP bei 1,13718 platziert, um den ROI von 1:6 beizubehalten (siehe Abbildung unten). Aufgrund der Volatilität des NFP-Ereignisses wird der Kauf zu einem ungünstigen Preis von 1,13134 ausgeführt, was durch die Journal-Meldung „order performed buy 0.01 at 1.13134 [#2 buy stop 0.01 EURUSD at 1.13118]“ angezeigt wird.
Für den Buy-Stop-Order aufgetretener Slippage:
Die Abweichung für den Eröffnungspreis wird berechnet als - [tatsächlicher Preis - erwarteter Preis]/Punkt
Erwarteter Preis: 1.13118 | tatsächlicher Preis: 1.13134 | Slippage: (1,13134 - 1,13118)/0,00001 -> 16 Pips (Preisunterschied)
Um den ROI und den Stop-Loss aufrechtzuerhalten, werden daher sowohl SL als auch der TP um 16 Pips entsprechend angepasst.
//+------------------------------------------------------------------+ //|Function will attempt to re-adjust stop-losses or take-profit | //|values that have been changed due to slippage on an order when | //|opening. | //+------------------------------------------------------------------+ void CTradeManagement::SlippageReduction(int SL,int TP,string COMMENT_COMMON) { //--- Iterate through all open positions for(int i=0; i<PositionsTotal(); i++) { ulong ticket = PositionGetTicket(i); //--- Check if Position ticket is above zero if(ticket>0) { //--- Check if the Position's Symbol,Comment is correct if(PositionGetString(POSITION_SYMBOL)==CSymbol.GetSymbolName() &&StringFind(PositionGetString(POSITION_COMMENT),COMMENT_COMMON)>=0) { //--- Identify Position type switch(int(PositionGetInteger(POSITION_TYPE))) { case POSITION_TYPE_BUY: //--- set expect buy trade properties SetBuyTrade(SL,TP,PositionGetDouble(POSITION_PRICE_OPEN)); //--- assign sl price mySL = PositionGetDouble(POSITION_SL); //--- assign tp price myTP = PositionGetDouble(POSITION_TP); //--- Normalize sl price CSymbol.NormalizePrice(mySL); mySL = double(DoubleToString(mySL,CSymbol.Digits())); //--- Normalize tp price CSymbol.NormalizePrice(myTP); myTP = double(DoubleToString(myTP,CSymbol.Digits())); //--- check if expected properties match actual trade properties if((myBuyTrade.Get().Stop!=mySL|| myBuyTrade.Get().Take!=myTP) &&Valid_Trade(POSITION_TYPE_BUY,myBuyTrade.Get().Open, myBuyTrade.Get().Stop,myBuyTrade.Get().Take)) { //--- Modify position to respect expected properties Trade.PositionModify(ticket,myBuyTrade.Get().Stop,myBuyTrade.Get().Take); } break; case POSITION_TYPE_SELL: //--- set expect sell trade properties SetSellTrade(SL,TP,PositionGetDouble(POSITION_PRICE_OPEN)); //--- assign sl price mySL = PositionGetDouble(POSITION_SL); //--- assign tp price myTP = PositionGetDouble(POSITION_TP); //--- Normalize sl price CSymbol.NormalizePrice(mySL); mySL = double(DoubleToString(mySL,CSymbol.Digits())); //--- Normalize tp price CSymbol.NormalizePrice(myTP); myTP = double(DoubleToString(myTP,CSymbol.Digits())); //--- check if expected properties match actual trade properties if((mySellTrade.Get().Stop!=mySL|| mySellTrade.Get().Take!=myTP) &&Valid_Trade(POSITION_TYPE_SELL,mySellTrade.Get().Open, mySellTrade.Get().Stop,mySellTrade.Get().Take)) { //--- Modify position to respect expected properties Trade.PositionModify(ticket,mySellTrade.Get().Stop,mySellTrade.Get().Take); } break; default: break; } } } } }
Zweck der Funktion:
Das Ziel dieser Funktion ist es:
- Überprüfen von jeder offenen Position.
- Überprüfen, ob Stop-Loss und Take-Profit für die Position mit den erwarteten Werten übereinstimmen.
- Wenn sie aufgrund von Slippage nicht übereinstimmen, wird die Position geändert, um die korrekten Werte von SL und TP widerzuspiegeln.
void CTradeManagement::SlippageReduction(int SL, int TP, string COMMENT_COMMON)
- SlippageReduction: Der Name der Funktion spiegelt ihren Zweck wider - die Anpassung von SL und TP, wenn diese durch Slippage während der Auftragsausführung beeinflusst wurden.
Parameter:
- SL: Erwarteter Stop-Loss.
- TP: Erwarteter Take-Profit.
- COMMENT_COMMON: Eine Zeichenfolge, die zum Filtern und Identifizieren von Handelsgeschäften die zu diesem Experten gehören.
Schleife durch offene Positionen:
for (int i = 0; i < PositionsTotal(); i++) { ulong ticket = PositionGetTicket(i);
- PositionsTotal(): Diese Funktion gibt die Anzahl der offenen Positionen zurück.
- PositionGetTicket(i): Ruft die Ticketnummer für die Position bei Index i ab. Ein Ticket identifiziert eindeutig eine offene Position.
Position Ticket Validierung:
if (ticket > 0)
- Vergewissert sich, dass die Position eine gültige Ticketnummer hat, bevor er mit den nächsten Schritten fortfährt.
Prüfen der Positionseigenschaften:
if (PositionGetString(POSITION_SYMBOL) == CSymbol.GetSymbolName() && StringFind(PositionGetString(POSITION_COMMENT), COMMENT_COMMON) >= 0)
- PositionGetString(POSITION_SYMBOL): Ruft das mit der offenen Position verbundene Symbol ab.
- CSymbol.GetSymbolName(): Ruft den Symbolnamen für die Handelsstrategie ab (z. B. „EURUSD“).
- PositionGetString(POSITION_COMMENT): Ruft den an die offene Position angehängten Kommentar ab.
- StringFind(): Prüft, ob COMMENT_COMMON Teil des Positionskommentars ist, um sicherzustellen, dass die Funktion nur Positionen verarbeitet, die sich auf die aktuelle Strategie beziehen.
Identifizierung und Handhabung von Positionsarten (Kauf oder Verkauf):
Fall 1: Position kaufen
case POSITION_TYPE_BUY:
- Die Funktion behandelt Positionen des Typs BUY.
Festlegen der erwarteten Eigenschaften eines Kaufs:
SetBuyTrade(SL, TP, PositionGetDouble(POSITION_PRICE_OPEN));
- SetBuyTrade(SL, TP, PositionGetDouble(POSITION_PRICE_OPEN)): Legt den erwarteten Stop-Loss, Take-Profit und Eröffnungskurs für den Kauf fest. Die Funktion SetBuyTrade weist diese erwarteten Werte dem Objekt myBuyTrade zu.
Aktuelle Werte für SL und TP zuordnen:
mySL = PositionGetDouble(POSITION_SL); myTP = PositionGetDouble(POSITION_TP);
- PositionGetDouble(POSITION_SL): Ruft den aktuellen Stop-Loss der offenen Position ab.
- PositionGetDouble(POSITION_TP): Ruft den tatsächlichen Wert von Take-Profit der offenen Position ab.
Normalisieren von SL- und TP:
CSymbol.NormalizePrice(mySL); mySL = double(DoubleToString(mySL, CSymbol.Digits())); CSymbol.NormalizePrice(myTP); myTP = double(DoubleToString(myTP, CSymbol.Digits()));
- NormalizePrice(mySL): Normalisiert den Stop-Loss-Wert auf die richtige Anzahl von Dezimalstellen (basierend auf den Eigenschaften des Symbols, z. B. können Währungspaare 4 oder 5 Dezimalstellen haben).
- DoubleToString(mySL, CSymbol.Digits()): Konvertiert den normalisierten SL-Wert in eine Zeichenkette und dann zurück in einen Double, um die Genauigkeit zu gewährleisten.
- Das gleiche Verfahren wird auf Take-Profit (myTP) angewandt.
Vergleichen von erwarteten und tatsächlichen SL/TP:
if ((myBuyTrade.Get().Stop != mySL || myBuyTrade.Get().Take != myTP) && Valid_Trade(POSITION_TYPE_BUY, myBuyTrade.Get().Open, myBuyTrade.Get().Stop, myBuyTrade.Get().Take)) { Trade.PositionModify(ticket, myBuyTrade.Get().Stop, myBuyTrade.Get().Take); }
- myBuyTrade.Get().Stop: Ruft den erwarteten Stop-Loss ab.
- mySL: Der tatsächliche Stop-Loss, der aus der Position abgerufen wird.
- Wenn die tatsächlichen Werte von SL- und TP nicht mit den erwarteten Werten übereinstimmen, ruft die Funktion Trade.PositionModify auf, um die Position zu aktualisieren und die korrekten Stop-Loss- und Take-Profit-Werte zu setzen.
- Valid_Trade(): Überprüft, ob die Handelsparameter (Preis, SL, TP) für eine Änderung gültig sind, bevor versucht wird, die Position zu ändern.
Position ändern:
Trade.PositionModify(ticket, myBuyTrade.Get().Stop, myBuyTrade.Get().Take);
- Diese Funktion ändert die mit dem Ticket verknüpfte Position, um die korrekten Werte von Stop-Loss- und Take-Profit auf der Grundlage der erwarteten Werte wiederzugeben.
Fall 2: Verkaufsposition
- Das Verfahren ist ähnlich wie bei den Kaufpositionen.
Die Funktion Valid_Trade prüft, ob die Parameter eines Handelsgeschäfts (z.B. Preis, Stop-Loss und Take-Profit) gültig sind, basierend auf der Art des Handelsgeschäfts (Kauf oder Verkauf) und den Regeln für Stop-Loss und Take-Profit in Bezug auf die Eigenschaften des aktuellen Symbols. Die Funktion gibt true zurück, wenn der Handel gültig ist, und false, wenn er es nicht ist.
//+------------------------------------------------------------------+ //|Check if a trade is valid | //+------------------------------------------------------------------+ bool CTradeManagement::Valid_Trade(ENUM_POSITION_TYPE Type,double Price,double SL,double TP) { //--- Identify Position type switch(Type) { case POSITION_TYPE_BUY: if((Price<TP||TP==0)&&(Price>SL||SL==0)&& ((int((Price-SL)/CSymbol.Point())>=CSymbol.StopLevel()) ||(SL==0))&& ((int((TP-Price)/CSymbol.Point())>=CSymbol.StopLevel()) ||(TP==0))&& Price>0 ) { //--- Trade properties are valid. return true; } break; case POSITION_TYPE_SELL: if((Price>TP||TP==0)&&(Price<SL||SL==0)&& ((int((Price-TP)/CSymbol.Point())>=CSymbol.StopLevel()) ||(TP==0))&& ((int((SL-Price)/CSymbol.Point())>=CSymbol.StopLevel()) ||(SL==0))&& Price>0 ) { //--- Trade properties are valid. return true; } break; default://Unknown return false; break; } //--- Trade properties are not valid. Print("Something went wrong, SL/TP/Open-Price is incorrect!"); return false; }
Zweck der Funktion:
Der Zweck dieser Funktion ist es,:
- Validieren der Handelsparameter (Preis, SL und TP) für Kauf- oder Verkaufspositionen.
- Vergewissern, dass Stop-Loss und Take-Profit im Verhältnis zum Eröffnungskurs korrekt gesetzt sind und den Anforderungen des Symbols entsprechen.
Parameter:
bool CTradeManagement::Valid_Trade(ENUM_POSITION_TYPE Type, double Price, double SL, double TP)
- Art: Die Art der Position, entweder POSITION_TYPE_BUY (Kaufposition) oder POSITION_TYPE_SELL (Verkaufsposition).
- Preis: Der Eröffnungskurs des Handelsgeschäfts.
- SL: Das Stop-Loss für das Handelsgeschäft.
- TP: Take-Profit für ein Handelsgeschäft.
Switch:
Die Funktion verwendet eine Switch-Anweisung, um verschiedene Arten von Positionen (Kauf oder Verkauf) zu behandeln und wendet für jeden Fall eine andere Validierungslogik an.
Fall 1: Kaufposition
case POSITION_TYPE_BUY:
Die Logik für eine Kaufposition prüft die folgenden Bedingungen:
Take-Profit (TP) Validierung:
if ((Price < TP || TP == 0)
- Take-Profit muss größer sein als der Eröffnungskurs (Price < TP), oder es kann auf Null gesetzt werden (kein Take-Profit).
Stop-Loss (SL) Validierung:
(Price > SL || SL == 0)
- Stop-Loss muss unter dem Eröffnungskurs liegen (Preis > SL), oder es kann auf Null gesetzt werden (kein Stop-Loss).
Validierung der Stopp-Level des Symbols:
- Das Stop-Level des Symbols definiert den Mindestabstand zwischen dem Kurs und Stop-Loss/Take-Profit.
- Stop-Loss- und Take-Profit müssen einen Mindestabstand (gleich oder größer als die Stop-Ebene) zum Eröffnungskurs haben.
Validierung des Abstands von Stop-Loss:
((int((Price - SL) / CSymbol.Point()) >= CSymbol.StopLevel()) || SL == 0)
- Die Differenz zwischen dem Kurs und Stop-Loss muss mindestens den Stop-Level des Symbols (in Punkten) entsprechen. Wenn Stop-Loss auf Null gesetzt ist, wird diese Bedingung ignoriert.
Validierung des Abstands von Take-Profit:
((int((TP - Price) / CSymbol.Point()) >= CSymbol.StopLevel()) || TP == 0)
- Die Differenz zwischen dem Take-Profit und dem Kurs muss auch der Bedingung des Stop-Levels entsprechen.
Abschließende Validierung:
&& Price > 0
- Der Preis muss größer als Null sein.
Wenn alle diese Bedingungen erfüllt sind, wird der Handel als gültig angesehen und die Funktion gibt true zurück.
Fall 2: Verkaufsposition
Bei einer Verkaufsposition ist die Logik ähnlich, aber umgekehrt.
Standardfall:
default: return false;
Wenn die Positionsart weder POSITION_TYPE_BUY noch POSITION_TYPE_SELL ist, gibt die Funktion false zurück, was bedeutet, dass der Handel nicht entspricht.
Ungültige Handelseigenschaften:
Wenn eine der Validierungsprüfungen fehlschlägt, gibt die Funktion eine Fehlermeldung aus und false zurück.
Print("Something went wrong, SL/TP/Open-Price is incorrect!"); return false;
Diese Meldung weist darauf hin, dass der Stop-Loss-, Take-Profit- oder offene Preis falsch ist.
Der folgende Code definiert eine Methode, Valid_Order, die prüft, ob eine Stop-Order (entweder eine BUY STOP- oder eine SELL STOP-Order) gültig ist, indem sie die Bedingungen für Stop-Loss (SL), Take-Profit (TP), Preis und Orderabweichung überprüft. Die Funktion gibt true zurück, wenn die Order gültig ist, und false, wenn nicht.
//+------------------------------------------------------------------+ //|Check if stop order is valid | //+------------------------------------------------------------------+ bool CTradeManagement::Valid_Order(ENUM_ORDER_TYPE Type,double Price,double SL,double TP) { //--- Identify Order type switch(Type) { case ORDER_TYPE_BUY_STOP: if((Price<TP||TP==0)&&(Price>SL||SL==0)&&(Price>CSymbol.Ask())&& ((int((Price-SL)/CSymbol.Point())>=CSymbol.StopLevel()) ||(SL==0))&& ((int((TP-Price)/CSymbol.Point())>=CSymbol.StopLevel()) ||(TP==0))&& myDeviation>=uint(CSymbol.StopLevel()) ) { //--- Order properties are valid. return true; } break; case ORDER_TYPE_SELL_STOP: if((Price>TP||TP==0)&&(Price<SL||SL==0)&&(Price<CSymbol.Bid())&& ((int((Price-TP)/CSymbol.Point())>=CSymbol.StopLevel()) ||(TP==0))&& ((int((SL-Price)/CSymbol.Point())>=CSymbol.StopLevel()) ||(SL==0))&& myDeviation>=uint(CSymbol.StopLevel()) ) { //--- Order properties are valid. return true; } break; default://Other return false; break; } //--- Order properties are not valid. Print("Something went wrong, SL/TP/Deviation/Open-Price is incorrect!"); return false; }
Überblick:
Die Funktion führt eine Validierung auf der Grundlage der Art der Stop-Order durch:
- BUY STOP: Ein Buy-Stop-Order wird über dem aktuellen Marktpreis (dem Briefkurs bzw. Ask) platziert und wird ausgelöst, wenn der Marktpreis dieses Niveau erreicht oder überschreitet.
- SELL STOP: Ein Sell-Stop-Order wird unterhalb des aktuellen Marktpreises (des Geldkurses bzw. Bid) platziert und wird ausgelöst, wenn der Marktpreis auf oder unter dieses Niveau fällt.
Parameter:
bool CTradeManagement::Valid_Order(ENUM_ORDER_TYPE Type, double Price, double SL, double TP)
- Art: Der Typ der Stop-Order (entweder ORDER_TYPE_BUY_STOP oder ORDER_TYPE_SELL_STOP).
- Preis: Der Preis, zu dem die Stop-Order platziert wird.
- SL: Der Stop-Loss, der mit der Stop-Order verbunden ist.
- TP: Der mit der Stop-Order verbundene Take-Profit.
Switch:
Die switch-Anweisung behandelt verschiedene Auftragsarten und wendet für jede unterschiedliche Validierungsregeln an.
Fall 1: BUY STOP Order
case ORDER_TYPE_BUY_STOP:
Für einen BUY STOP-Auftrag müssen die folgenden Bedingungen erfüllt sein:
Validierung von Take-Profit (TP):
(Price < TP || TP == 0)
Der Take-Profit-Preis muss größer sein als der Orderpreis (Price < TP), oder er kann auf Null gesetzt werden (kein Take-Profit).
Validierung von Stop-Loss (SL):
(Price > SL || SL == 0)
Der Stop-Loss muss unter dem Auftragskurs liegen (Preis > SL), oder er kann auf Null gesetzt werden (kein Stop-Loss).
Preis über dem Briefkurs:
(Price > CSymbol.Ask())
Der Auftragskurs muss über dem aktuellen Briefkurs liegen, was eine wichtige Bedingung für einen BUY STOP-Auftrag ist.
Validierung der Stopp-Level des Symbols: Validierung des Abstands von Stop-Loss:
((int((Price - SL) / CSymbol.Point()) >= CSymbol.StopLevel()) || SL == 0)
Die Differenz zwischen dem Auftragskurs und dem Stop-Loss muss das Stop-Level des Symbols erreichen oder überschreiten. Wenn Stop-Loss auf Null gesetzt ist, wird diese Bedingung ignoriert.
Validierung des Abstands von Take-Profit:
((int((TP - Price) / CSymbol.Point()) >= CSymbol.StopLevel()) || TP == 0)
Die Differenz zwischen dem Take-Profit und dem Auftragskurs muss ebenfalls der Stop-Level-Anforderung entsprechen, oder der Take-Profit kann gleich Null sein.
Validierung der Preisabweichung:
myDeviation >= uint(CSymbol.StopLevel())
Die Preisabweichung (Slippage-Toleranz) muss größer oder gleich dem Stop-Level des Symbols sein. Die Abweichung ermöglicht es, den Auftrag auch dann auszuführen, wenn sich der Marktpreis geringfügig über das festgelegte Stopp-Niveau hinaus bewegt.
Wenn alle diese Bedingungen erfüllt sind, gilt der BUY STOP-Order als gültig, und die Funktion gibt true zurück.
Fall 2: SELL STOP Order
Bei einer SELL STOP-Order ist die umgekehrte Validierungslogik im Vergleich zu einer BUY STOP-Order.
Standardfall:
default: return false;
Wenn die Auftragsart weder ORDER_TYPE_BUY_STOP noch ORDER_TYPE_SELL_STOP ist, gibt die Funktion false zurück, was bedeutet, dass der Auftrag nicht gültig ist.
Fehlerbehandlung:
Wenn die Bedingungen nicht erfüllt sind und die Funktion den Auftrag nicht validieren kann, wird eine Fehlermeldung ausgegeben:
Print("Something went wrong, SL/TP/Deviation/Open-Price is incorrect!");
Diese Meldung informiert den Nutzer, dass etwas mit dem Stop-Loss, dem Take-Profit, der Preisabweichung oder dem Auftragspreis nicht stimmt und der Auftrag daher ungültig ist.
Der nachstehende Code definiert die Funktion SetBuyStop, die für die Einstellung der Eigenschaften einer Buy-Stop-Order verantwortlich ist. Er berechnet den Stop-Loss (SL) und den Take-Profit (TP) auf der Grundlage der gegebenen Eingaben und ordnet sie dem Auftrag zu. Die Funktion führt die folgenden Schritte aus:
- Berechnet den Eröffnungspreis für den Buy-Stop-Order.
- Berechnet und setzt Stop-Loss und Take-Profit relativ zum Eröffnungskurs.
- Normalisiert die Preise, um sicherzustellen, dass sie mit der Genauigkeit des Symbols (Anzahl der Dezimalstellen) übereinstimmen.
//+------------------------------------------------------------------+ //|Will set buy-stop order properties | //+------------------------------------------------------------------+ void CTradeManagement::SetBuyStop(int SL,int TP) { //-- Get Open-price myOpenPrice=CSymbol.Ask()+myDeviation*CSymbol.Point(); CSymbol.NormalizePrice(myOpenPrice); NormalizeDouble(myOpenPrice,CSymbol.Digits()); //--- Get SL value mySL=SL*CSymbol.Point(); mySL=myOpenPrice-mySL; //--- Normalize the SL Price CSymbol.NormalizePrice(mySL); NormalizeDouble(mySL,CSymbol.Digits()); //--- Get TP value myTP=TP*CSymbol.Point(); myTP+=myOpenPrice; //--- Normalize the TP Price CSymbol.NormalizePrice(myTP); NormalizeDouble(myTP,CSymbol.Digits()); //--- Set BuyStop properties myBuyStop.Set(myOpenPrice,myTP,mySL); }
Parameter:
- SL: Der Stop-Loss in Form von Punkten.
- TP: Der Take-Profit in Form von Punkten.
void CTradeManagement::SetBuyStop(int SL, int TP)
Sowohl SL als auch TP sind ganzzahlige Werte, die die Anzahl der Punkte (Kursinkremente) vom Eröffnungskurs bis zum Stop-Loss oder Take-Profit angeben.
Schritt 1: Berechnung des Eröffnungskurses für die Buy-Stop-Order
myOpenPrice = CSymbol.Ask() + myDeviation * CSymbol.Point();
- CSymbol.Ask() ruft den aktuellen Briefkurs für das Symbol (Währungspaar oder Vermögenswert) ab.
- myDeviation * CSymbol.Point() fügt eine Abweichung (Preispuffer) in Form von Punkten hinzu, um sicherzustellen, dass der Eröffnungskurs über dem aktuellen Briefkurs liegt. CSymbol.Point() gibt die Größe eines Punktes (kleinste Kursänderung) für das Symbol zurück.
Normalisierung:
CSymbol.NormalizePrice(myOpenPrice); NormalizeDouble(myOpenPrice, CSymbol.Digits());
- CSymbol.NormalizePrice(myOpenPrice) passt den Preis an die Genauigkeit des Symbols an (d. h. an ein gültiges Preisformat).
- NormalizeDouble(myOpenPrice, CSymbol.Digits()) stellt sicher, dass der Preis auf die richtige Anzahl von Dezimalstellen gerundet wird, die durch die Genauigkeit des Symbols (CSymbol.Digits()) definiert ist.
Schritt 2: Berechnung und Normalisierung des Stop-Loss (SL)
mySL = SL * CSymbol.Point();
mySL = myOpenPrice - mySL;
- SL * CSymbol.Point() wandelt den ganzzahligen Stop-Loss (in Punkten) in eine Kursdifferenz um.
- myOpenPrice - mySL berechnet den Stop-Loss-Kurs durch Subtraktion des Stop-Loss-Wertes (in Punkten) vom Open Price. Der Grund dafür ist, dass ein Stop-Loss für eine Buy-Stop-Order unter dem Eröffnungskurs platziert wird.
Normalisierung:
CSymbol.NormalizePrice(mySL); NormalizeDouble(mySL, CSymbol.Digits());
- Der Stop-Loss wird normalisiert und auf die richtige Genauigkeit gerundet, wie oben erläutert.
Schritt 3: Berechnung und Normalisierung des Take-Profit (TP).
myTP = TP * CSymbol.Point();
myTP += myOpenPrice;
- TP * CSymbol.Point() wandelt den ganzzahligen Wert von Take-Profit (in Punkten) in eine Kursdifferenz um.
- myTP += myOpenPrice addiert diesen Wert zum Eröffnungskurs, da der Take-Profit für eine Buy-Stop-Order oberhalb des Eröffnungskurses platziert wird.
Normalisierung:
CSymbol.NormalizePrice(myTP); NormalizeDouble(myTP, CSymbol.Digits());
- Der Take-Profit wird normalisiert und gerundet, ähnlich wie Stop-Loss und der Eröffnungskurs.
Schritt 4: Zuweisen der berechneten Werte zur Buy-Stop-Order
myBuyStop.Set(myOpenPrice, myTP, mySL);
- myBuyStop.Set(myOpenPrice, myTP, mySL) weist dem Auftragsobjekt myBuyStop den berechneten Eröffnungskurs, Take-Profit und Stop-Loss zu.
- Das Objekt myBuyStop enthält nun die Eigenschaften, die erforderlich sind, um die Buy-Stop-Order auf dem Markt zu platzieren.
Die Funktion SetBuyTrade legt die Eigenschaften einer Kaufposition fest. Es berechnet und weist den korrekten Eröffnungskurs, Stop-Loss (SL) und Take-Profit (TP) für den Handel zu. Diese Funktion wird verwendet, um die Parameter für eine Kaufposition zu konfigurieren (nicht für einen schwebenden Auftrag wie einen Buy-Stop). Eine Kaufposition wird zum aktuellen Marktpreis eröffnet, mit festgelegten Stop-Loss und Take-Profit in Bezug auf den Eröffnungskurs.
Parameter:
- SL: Stop-Loss in Punkten (Kursabstufungen).
- TP: Take-Profit in Punkten.
- OP: Der Eröffnungskurs des Handelsgeschäfts (der Kurs, zu dem die Position eröffnet wird).
Schritt 1: Festlegung des Eröffnungspreises
myOpenPrice = OP; CSymbol.NormalizePrice(myOpenPrice); myOpenPrice = double(DoubleToString(myOpenPrice, CSymbol.Digits()));
- myOpenPrice = OP: Die Funktion nimmt den angegebenen Eröffnungskurs (OP) und weist ihn myOpenPrice zu.
- CSymbol.NormalizePrice(myOpenPrice): Dadurch wird der Eröffnungskurs entsprechend der Genauigkeit des Symbols normalisiert, sodass er mit der richtigen Anzahl von Dezimalstellen übereinstimmt.
- myOpenPrice = double(DoubleToString(myOpenPrice, CSymbol.Digits())): Der Preis wird in eine Zeichenkette umgewandelt und wieder zurück in ein Double mit der richtigen Anzahl von Dezimalstellen (Präzision) für das Symbol. Dies gewährleistet eine konsistente Handhabung von Preiswerten und vermeidet Probleme mit der Fließkommagenauigkeit.
Schritt 2: Berechnung und Normalisierung des Stop-Loss (SL)
mySL = SL * CSymbol.Point();
mySL = myOpenPrice - mySL;
- SL * CSymbol.Point(): Wandelt den Stop-Loss in Punkten in eine tatsächliche Preisdifferenz um. CSymbol.Point() gibt die Größe eines Punktes zurück (die kleinstmögliche Kursstufe des Symbols).
- myOpenPrice - mySL: Der Stop-Loss wird festgelegt, indem der berechnete Stop-Loss vom Eröffnungspreis abgezogen wird. Bei einer Kaufposition wird der Stop-Loss unterhalb des Eröffnungskurses gesetzt, um den Handel vor übermäßigen Verlusten zu schützen.
Normalisierung:
CSymbol.NormalizePrice(mySL); mySL = double(DoubleToString(mySL, CSymbol.Digits()));
- Der Stop-Loss wird normalisiert, um sicherzustellen, dass er die richtige Genauigkeit hat, und dann auf die entsprechende Anzahl von Dezimalstellen gerundet.
Schritt 3: Berechnung und Normalisierung des Take-Profit (TP).
myTP = TP * CSymbol.Point();
myTP += myOpenPrice;
- TP * CSymbol.Point(): Wandelt den Take-Profit in Punkten in eine Preisdifferenz um.
- myTP += myOpenPrice: Der Take-Profit wird zum Eröffnungskurs addiert, da bei einer Kaufposition der Take-Profit über dem Eröffnungskurs liegt.
Normalisierung:
CSymbol.NormalizePrice(myTP); myTP = double(DoubleToString(myTP, CSymbol.Digits()));
- Der Take-Profit wird normalisiert und gerundet, damit er der Genauigkeit des Symbols entspricht.
Schritt 4: Zuweisung der berechneten Werte zur Kaufposition
myBuyTrade.Set(myOpenPrice, myTP, mySL);
- myBuyTrade.Set(myOpenPrice, myTP, mySL): Die berechneten Werte für den Eröffnungspreis, den Stop-Loss und den Take-Profit werden dem Objekt myBuyTrade zugewiesen. Dieses Objekt enthält nun alle relevanten Eigenschaften der Kaufposition, die geöffnet oder geändert werden soll.
Die Funktion OpenBuyStop versucht, eine Buy-Stop-Order mit angegebenem Stop-Loss (SL), Take-Profit (TP), magischer Zahl und optionalem Kommentar zu eröffnen.
Parameter:
- SL: Stop-Loss in Punkten.
- TP: Take-Profit in Punkten.
- Magic: Eindeutige magische Zahl zur Identifizierung des Auftrags, die in der Regel für Expert Advisors verwendet wird.
- COMMENT: (Optional) Ein Text-Kommentar, der zur Identifizierung an die Order angehängt wird.
//+------------------------------------------------------------------+ //|Will attempt to open a buy-stop order | //+------------------------------------------------------------------+ bool CTradeManagement::OpenBuyStop(int SL,int TP,ulong Magic,string COMMENT=NULL) { SetBuyStop(SL,TP); //--- Set the order type for Risk management calculation SetOrderType(ORDER_TYPE_BUY); //--- Set open price for Risk management calculation OpenPrice = myBuyStop.Get().Open; //--- Set close price for Risk management calculation ClosePrice = myBuyStop.Get().Stop; //--- Set Trade magic number Trade.SetExpertMagicNumber(Magic); //--- Check if there are any open trades or opened deals or canceled deals already if(!OpenOrder(ORDER_TYPE_BUY_STOP,Magic,COMMENT)&&!OpenedDeal(DEAL_TYPE_BUY,Magic,COMMENT) //--- Check if the buy-stop properties are valid &&Valid_Order(ORDER_TYPE_BUY_STOP,myBuyStop.Get().Open,myBuyStop.Get().Stop,myBuyStop.Get().Take)) { //--- Iterate through the Lot-sizes if they're more than max-lot for(double i=Volume();i>=CSymbol.LotsMin()&& /* Check if current number of orders +1 more orders is less than account orders limit.*/ (PositionsTotal()+Account.numOrders()+1)<Account.LimitOrders() ;i-=CSymbol.LotsMax()) { //--- normalize Lot-size NormalizeLotsize(i); /* Open buy-stop order with a Lot-size not more than max-lot and set order expiration to the Symbol's session end time for the current day. */ if(!Trade.BuyStop((i>CSymbol.LotsMax())?CSymbol.LotsMax():i,myBuyStop.Get().Open, CSymbol.GetSymbolName(),myBuyStop.Get().Stop,myBuyStop.Get().Take, ORDER_TIME_SPECIFIED,CTS.SessionEnd(),COMMENT)) { //--- Order failed to open return false; } } } else { //--- Order failed return false; } //--- Return trade result. return true; }
Schritt 1: Die Eigenschaften für ein Buy-Stop festlegen
SetBuyStop(SL, TP);
- Diese Zeile ruft die Methode SetBuyStop auf (siehe oben), um den Eröffnungskurs, den Stop-Loss und den Take-Profit für die Buy-Stop-Order zu berechnen und festzulegen.
- Das Ergebnis wird im myBuyStop-Objekt gespeichert, das die Schlüsseleigenschaften der Buy-Stop-Order (Eröffnungskurs, SL und TP) enthält.
Schritt 2: Auftragsart für Risikomanagement festlegen
SetOrderType(ORDER_TYPE_BUY);
- Damit wird die interne Auftragsart auf ORDER_TYPE_BUY gesetzt. Obwohl es sich hierbei um einen Buy-Stop-Order handelt, handelt es sich im Grunde genommen immer noch um einen Kaufauftrag, der zur Berechnung von Risikomanagement-Kennzahlen wie Stop-Loss, Take-Profit und Positionsgröße verwendet wird.
Schritt 3: Festlegen von Eröffnungs- und Schlusskursen für das Risikomanagement
OpenPrice = myBuyStop.Get().Open; ClosePrice = myBuyStop.Get().Stop;
- OpenPrice: Dieser wird der berechnete Eröffnungskurs der Buy-Stop-Order (myBuyStop.Get().Open) zugewiesen.
- ClosePrice: Dieser wird der berechnete Stop-Loss der Buy-Stop-Order (myBuyStop.Get().Stop) zugewiesen.
Schritt 4: Magische Zahl einstellen
Trade.SetExpertMagicNumber(Magic);
- Damit wird die magische Zahl für den Auftrag mit Trade.SetExpertMagicNumber festgelegt. Die magische Zahl identifiziert den Auftrag eindeutig, was bei der Verwaltung der Handelsgeschäfte, die von einem Expert Advisor eröffnet wurden, hilfreich ist.
Schritt 5: Nach offenen Handelsgeschäfte oder Deals suchen
if (!OpenOrder(ORDER_TYPE_BUY_STOP, Magic, COMMENT) && !OpenedDeal(DEAL_TYPE_BUY, Magic, COMMENT)
- OpenOrder: Es wird geprüft, ob bereits Buy-Stop-Order mit der gleichen magischen Nummer und dem gleichen Kommentar eröffnet wurden. Wenn eine solche vorhanden ist, überspringt die Funktion das Eröffnen eines neuen Auftrags.
- OpenedDeal: Dabei wird geprüft, ob bereits eine Kaufposition mit derselben magischen Zahl und demselben Kommentar eröffnet wurde. Wenn ein solches Handelsgeschäft existiert, vermeidet die Funktion die Eröffnung eines neuen Handelsgeschäfts.
Schritt 6: Eigenschaften der Buy-Stop-Order validieren
&& Valid_Order(ORDER_TYPE_BUY_STOP, myBuyStop.Get().Open, myBuyStop.Get().Stop, myBuyStop.Get().Take))
- Dabei wird geprüft, ob die berechneten Eigenschaften der Buy-Stop-Order mit Hilfe der Methode Valid_Order (siehe oben) gültig sind. Die Methode prüft, ob der Eröffnungskurs, der Stop-Loss und der Take-Profit korrekt sind und ob der Auftrag die Regeln des Symbols einhält (z. B. Mindestabstand, Punktwert usw.).
Schritt 7: Durch Losgrößen iterieren
for (double i = Volume(); i >= CSymbol.LotsMin() && (PositionsTotal() + Account.numOrders() + 1) < Account.LimitOrders(); i -= CSymbol.LotsMax())
- Volume(): Hiermit wird das aktuelle Handelsvolumen (Losgröße) für den Auftrag abgerufen.
- Die Schleife beginnt mit dem aktuellen Volumen (i = Volume()), und zwar so lange, bis:
- Die Losgröße ist größer als oder gleich der Mindestlosgröße (CSymbol.LotsMin()).
- Die Gesamtzahl der Positionen plus der bestehenden Aufträge des Kontos ist kleiner als das Auftragslimit des Kontos (Account.LimitOrders()).
Es wird die Losgröße in Schritten der maximalen Losgröße (CSymbol.LotsMax()) bei jeder Iteration reduziert, um sicherzustellen, dass der Auftrag die Volumengrenzen einhält.
Schritt 8: Losgröße normalisieren
NormalizeLotsize(i);
- Die Losgröße (i) wird normalisiert, um sicherzustellen, dass sie den Präzisionsregeln des Symbols entspricht.
Schritt 9: Versuch, eine Buy-Stop-Order zu eröffnen
if (!Trade.BuyStop((i > CSymbol.LotsMax()) ? CSymbol.LotsMax() : i, myBuyStop.Get().Open, CSymbol.GetSymbolName(), myBuyStop.Get().Stop, myBuyStop.Get().Take, ORDER_TIME_SPECIFIED, CTS.SessionEnd(), COMMENT))
- Trade.BuyStop(): Damit wird versucht, den Buy-Stop-Order mit den folgenden Parametern zu platzieren:
- Losgröße: Die Losgröße i ist auf CSymbol.LotsMax() (die maximal zulässige Losgröße des Symbols) begrenzt. Wenn i größer als die maximale Losgröße ist, wird die maximale Losgröße verwendet; andernfalls wird die aktuelle Losgröße i verwendet.
- Eröffnungspreis: Der Preis, zu dem der Buy-Stop-Order ausgeführt werden soll.
- Symbolname: Der Name des Handelssymbols (Währungspaar usw.).
- Stop-Loss: Der berechnete Stop-Loss für den Auftrag.
- Take-profit: Der berechnete Take-Profit für die Order.
- Verfallszeit der Order: Der Auftrag wird so eingestellt, dass er am Ende der Handelssitzung des Symbols am aktuellen Tag abläuft (CTS.SessionEnd()).
- Comment: Ein optionaler Kommentar von oben.
Wenn der Auftrag nicht erteilt werden kann, gibt die Funktion den Wert false zurück, was bedeutet, dass der Buy-Stop-Order nicht erfolgreich platziert wurde.
Schritt 10: Rückgabe des Ergebnisses
return true;
- Wenn der Auftrag erfolgreich geöffnet wurde, gibt die Funktion den Wert true zurück und zeigt damit an, dass die Buy-Stop-Order erfolgreich platziert wurde.
Die Funktion OpenSellStop
Bei der Funktion OpenSellStop ist die Funktionslogik ähnlich wie bei der zuvor erläuterten Funktion OpenBuyStop.
Die Funktion OpenStops versucht, sowohl Buy-Stop- als auch Sell-Stop-Order zu eröffnen.
//+------------------------------------------------------------------+ //|This function will open both buy-stop and sell-stop orders for | //|StopOrdersType(STOP ORDERS) | //+------------------------------------------------------------------+ bool CTradeManagement::OpenStops(int SL,int TP,ulong Magic,string COMMENT=NULL) { //--- Set buy-stop properties SetBuyStop(SL,TP); //--- Set sell-stop properties SetSellStop(SL,TP); //--- Set the order type for Risk management calculation SetOrderType(ORDER_TYPE_BUY); //--- Set open price for Risk management calculation OpenPrice = myBuyStop.Get().Open; //--- Set close price for Risk management calculation ClosePrice = myBuyStop.Get().Stop; //--- Set Trade magic number Trade.SetExpertMagicNumber(Magic); //--- Check if there are any open trades or opened deals or canceled deals already if(!OpenOrder(ORDER_TYPE_BUY_STOP,Magic,COMMENT)&&!OpenedDeal(DEAL_TYPE_BUY,Magic,COMMENT) &&!OpenedDeal(DEAL_TYPE_BUY_CANCELED,Magic,COMMENT) //--- Check if the buy-stop properties are valid &&Valid_Order(ORDER_TYPE_BUY_STOP,myBuyStop.Get().Open,myBuyStop.Get().Stop,myBuyStop.Get().Take) &&!OpenOrder(ORDER_TYPE_SELL_STOP,Magic,COMMENT) &&!OpenedDeal(DEAL_TYPE_SELL,Magic,COMMENT)&&!OpenedDeal(DEAL_TYPE_SELL_CANCELED,Magic,COMMENT) //--- Check if the sell-stop properties are valid &&Valid_Order(ORDER_TYPE_SELL_STOP,mySellStop.Get().Open,mySellStop.Get().Stop,mySellStop.Get().Take)) { //--- Iterate through the Lot-sizes if they're more than max-lot for(double i=Volume();i>=CSymbol.LotsMin()&& /* Check if current number of orders +2 more orders is less than account orders limit.*/ (PositionsTotal()+Account.numOrders()+2)<Account.LimitOrders() ;i-=CSymbol.LotsMax()) { //--- normalize Lot-size NormalizeLotsize(i); /* Open orders with a Lot-size not more than max-lot and set order expiration to the Symbol's session end time for the current day. */ if(!Trade.BuyStop((i>CSymbol.LotsMax())?CSymbol.LotsMax():i,myBuyStop.Get().Open, CSymbol.GetSymbolName(),myBuyStop.Get().Stop,myBuyStop.Get().Take, ORDER_TIME_SPECIFIED,CTS.SessionEnd(),COMMENT) ||!Trade.SellStop((i>CSymbol.LotsMax())?CSymbol.LotsMax():i,mySellStop.Get().Open, CSymbol.GetSymbolName(),mySellStop.Get().Stop,mySellStop.Get().Take, ORDER_TIME_SPECIFIED,CTS.SessionEnd(),COMMENT)) { //--- one or more orders failed to open. return false; } } } else { //--- Orders failed return false; } //--- Return trade result. return true; }
Schritt 1: Die Eigenschaften von Buy-Stop- und Sell-Stop-Oder festlegen.
SetBuyStop(SL, TP); SetSellStop(SL, TP);
- SetBuyStop: Mit dieser Methode werden der Eröffnungskurs, der Stop-Loss und der Take-Profit für die Buy-Stop-Order berechnet und festgelegt. Diese Werte werden in dem Objekt myBuyStop gespeichert.
- SetSellStop: In ähnlicher Weise berechnet und setzt diese Methode den Eröffnungskurs, den Stop-Loss und den Take-Profit für den Sell-Stop-Order, der im Objekt mySellStop gespeichert ist.
Schritt 2: Auftragsart für Risikomanagement festlegen
SetOrderType(ORDER_TYPE_BUY);
- Dadurch wird der interne Auftragstyp für die Berechnung des Risikomanagements auf einen Kaufauftrag festgelegt, obwohl sowohl Buy- als auch Sell-Stop-Order erteilt werden. Diese Einstellung wird später zur Bewertung des Risikos auf der Grundlage von Stop-Loss und Take-Profit des Kaufauftrags verwendet.
Schritt 3: Festlegen von Eröffnungs- und Schlusskursen für das Risikomanagement
OpenPrice = myBuyStop.Get().Open; ClosePrice = myBuyStop.Get().Stop;
- OpenPrice: Der berechnete Eröffnungskurs für den Buy-Stop-Order.
- ClosePrice: Der berechnete Stop-Loss-Kurs für den Buy-Stop-Order. Diese Preise werden für interne Risikomanagementberechnungen verwendet.
Schritt 4: Magische Zahl einstellen
Trade.SetExpertMagicNumber(Magic);
- Dadurch wird dem Handel die magische Nummer zugewiesen, die die vom Expert Advisor (EA) verwalteten Aufträge eindeutig identifiziert.
Schritt 5: Nach bestehenden Aufträgen oder Angeboten suchen
if(!OpenOrder(ORDER_TYPE_BUY_STOP, Magic, COMMENT) && !OpenedDeal(DEAL_TYPE_BUY, Magic, COMMENT) && !OpenedDeal(DEAL_TYPE_BUY_CANCELED, Magic, COMMENT)
- OpenOrder: Prüft, ob bereits ein offener Buy-Stop-Order mit der gleichen magischen Nummer und dem gleichen Kommentar vorliegt. Ist ein solcher vorhanden, wird kein neuer Buy-Stop-Order eröffnet.
- OpenedDeal: Prüft, ob es bereits eine aktive oder abgebrochene Kaufposition mit derselben magischen Nummer und demselben Kommentar gibt. Wenn ein solcher vorhanden ist, wird kein neuer Buy-Stop-Order erteilt.
Schritt 6: Eigenschaften der Buy-Stop-Order validieren
&& Valid_Order(ORDER_TYPE_BUY_STOP, myBuyStop.Get().Open, myBuyStop.Get().Stop, myBuyStop.Get().Take)
- Gültige_Order: Dadurch werden die Eigenschaften der Buy-Stop-Order (Eröffnungskurs, Stop-Loss, Take-Profit) validiert, um sicherzustellen, dass sie den Regeln des Symbols entsprechen (z. B. Mindest-Stop-Level). Wenn die Validierung erfolgreich ist, wird der Sell-Stop-Auftrag geprüft.
Schritt 7: Nach bestehenden Verkaufsaufträgen oder Handelsgeschäften suchen
&& !OpenOrder(ORDER_TYPE_SELL_STOP, Magic, COMMENT) && !OpenedDeal(DEAL_TYPE_SELL, Magic, COMMENT) && !OpenedDeal(DEAL_TYPE_SELL_CANCELED, Magic, COMMENT)
- Ähnlich wie bei den Buy-Stop-Prüfungen wird hier geprüft, ob bereits eine Sell-Stop-Order, ein aktives Verkaufsgeschäft oder ein abgebrochenes Verkaufsgeschäft mit derselben magischen Zahl und demselben Kommentar vorliegt. Wenn eine solche vorhanden ist, vermeidet die Funktion die Platzierung eines neuen Sell-Stop-Order.
Schritt 8: Eigenschaften der Sell-Stop-Order validieren
&& Valid_Order(ORDER_TYPE_SELL_STOP, mySellStop.Get().Open, mySellStop.Get().Stop, mySellStop.Get().Take))
- Gültige_Order: Dadurch werden die Eigenschaften der Sell-Stop-Order (Eröffnungspreis, Stop-Loss, Take-Profit) bestätigt. Wenn die Validierung erfolgreich ist, werden sowohl Buy- als auch Sell-Stop-Order eröffnet.
Schritt 9: Iteration durch Losgrößen
for (double i = Volume(); i >= CSymbol.LotsMin() && (PositionsTotal() + Account.numOrders() + 2) < Account.LimitOrders(); i -= CSymbol.LotsMax())
- Volume(): Ruft das aktuelle Handelsvolumen (Losgröße) ab.
- Die Schleife beginnt mit dem vollen Volumen (i = Volumen()) und verringert die Losgröße (i -= CSymbol.LotsMax()), wenn sie die maximal zulässige Losgröße (CSymbol.LotsMax()) überschreitet.
- Er stellt sicher, dass die Gesamtzahl der offenen Positionen und ausstehenden Aufträge innerhalb des Kontolimits liegt (Account.LimitOrders()).
Die Schleife sorgt dafür, dass die Aufträge in mehrere kleinere Aufträge aufgeteilt werden, wenn die Losgröße die maximal zulässige Losgröße des Symbols überschreitet.
Schritt 10: Losgröße normalisieren
NormalizeLotsize(i);
- Die Losgröße (i) wird so normiert, dass sie mit der zulässigen Genauigkeit des Symbols übereinstimmt.
Schritt 11: Versuch der Eröffnung von Buy-Stop- und Sell-Stop-Order
if(!Trade.BuyStop((i > CSymbol.LotsMax()) ? CSymbol.LotsMax() : i, myBuyStop.Get().Open, CSymbol.GetSymbolName(), myBuyStop.Get().Stop, myBuyStop.Get().Take, ORDER_TIME_SPECIFIED, CTS.SessionEnd(), COMMENT) || !Trade.SellStop((i > CSymbol.LotsMax()) ? CSymbol.LotsMax() : i, mySellStop.Get().Open, CSymbol.GetSymbolName(), mySellStop.Get().Stop, mySellStop.Get().Take, ORDER_TIME_SPECIFIED, CTS.SessionEnd(), COMMENT))
- Trade.BuyStop: Versucht, einen Buy-Stop-Order mit den folgenden Parametern zu platzieren:
- Lot size: Wenn die aktuelle Losgröße (i) die maximal zulässige Losgröße (CSymbol.LotsMax()) überschreitet, wird der Auftrag mit der maximal zulässigen Losgröße erteilt.
- Open price: Der berechnete Eröffnungskurs für den Buy-Stop-Order.
- Symbol name: Der Name des Handelsinstruments.
- Stop-loss: Der Stop-Loss-Kurs für den Buy-Stop-Order.
- Take-profit: Der Take-Profit für die Buy-Stop-Order.
- Expiration time: Wird auf das Ende der Handelssitzung des Symbols für den aktuellen Tag gesetzt (CTS.SessionEnd()).
- Comment: Ein optionaler Kommentar zur Beschreibung der Order.
- Trade.SellStop: In ähnlicher Weise wird versucht, einen Sell-Stop-Order mit der gleichen Logik wie den Buy-Stop-Order zu platzieren.
Wenn eine der beiden Order nicht geöffnet werden kann, gibt die Funktion false zurück.
Schritt 12: Rückgabe des Ergebnisses
return true;
- Wenn sowohl die Buy-Stop- als auch die Sell-Stop-Order erfolgreich eröffnet wurden, gibt die Funktion true zurück. Wenn ein Teil des Prozesses fehlschlägt, gibt die Funktion false zurück.
Die Funktion CloseTrades dient dazu, alle offenen Positionen zu schließen, die einem bestimmten Kommentar (COMMENT_COMMON) entsprechen.
//+------------------------------------------------------------------+ //|Function will attempt to close all trades depending on the | //|position comment | //+------------------------------------------------------------------+ void CTradeManagement::CloseTrades(string COMMENT_COMMON) { //--- Iterate through all open positions for(int i=0; i<PositionsTotal(); i++) { ulong ticket = PositionGetTicket(i); //--- Check if Position ticket is above zero if(ticket>0) { //--- Check if the Position's Symbol,Comment is correct if(PositionGetString(POSITION_SYMBOL)==CSymbol.GetSymbolName() &&StringFind(PositionGetString(POSITION_COMMENT),COMMENT_COMMON)>=0) { //--- close trade. Trade.PositionClose(ticket); } } } }
Schritt 1: Iterieren durch alle offenen Positionen:
for (int i = 0; i < PositionsTotal(); i++)
- PositionsTotal(): Gibt die Gesamtzahl der offenen Positionen zurück.
- Diese Schleife durchläuft alle derzeit offenen Positionen. Die Variable i ist der Index der Position und reicht von 0 bis PositionsTotal() - 1.
Schritt 2: Abrufen der Ticketnummer der Position:
ulong ticket = PositionGetTicket(i);
- PositionGetTicket(i): Ruft die Ticketnummer der offenen Position bei Index i ab. Die Ticketnummer ist eine eindeutige Kennung für jede Position.
- Die Ticketnummer wird in der Variablen ticket gespeichert.
Schritt 3: Prüfen, ob das Ticket gültig ist:
if (ticket > 0)
- Dabei wird geprüft, ob die Ticketnummer größer als Null ist, um sicherzustellen, dass das abgerufene Ticket gültig ist, bevor es weitergeht. Eine Ticketnummer von 0 würde bedeuten, dass an dem angegebenen Index keine Position existiert, was kein gültiger Zustand wäre.
Schritt 4: Positionssymbol und Kommentar validieren:
if (PositionGetString(POSITION_SYMBOL) == CSymbol.GetSymbolName() && StringFind(PositionGetString(POSITION_COMMENT), COMMENT_COMMON) >= 0)
- PositionGetString(POSITION_SYMBOL): Ruft den Symbolnamen der Position bei Index i ab (z. B. Währungspaar).
- CSymbol.GetSymbolName(): Ruft den Symbolnamen ab, der mit dem CSymbol-Objekt verbunden ist.
- Die erste Bedingung prüft, ob das Symbol der Position mit dem von CSymbol verwalteten Symbol übereinstimmt.
- PositionGetString(POSITION_COMMENT): Ruft den Text des Kommentars ab, die an die offene Position angehängt ist.
- StringFind(PositionGetString(POSITION_COMMENT), COMMENT_COMMON): Prüft, ob die angegebene Zeichenkette COMMENT_COMMON im Kommentar der Position vorhanden ist.
- Wenn der Kommentar COMMENT_COMMON enthält, gibt die Funktion einen Index zurück, an dem die Übereinstimmung beginnt.
- Die Bedingung >= 0 stellt sicher, dass die Prüfung nur dann erfolgreich ist, wenn der Kommentar die Teilzeichenkette enthält.
Dadurch wird sichergestellt, dass nur Positionen mit dem passenden Symbol und Kommentar für den Abschluss ausgewählt werden.
Schritt 5: Schließen des Handelsgeschäfts:
Trade.PositionClose(ticket);
- Trade.PositionClose(ticket): Versucht, die durch die Ticketnummer identifizierte offene Position zu schließen.
- Erfüllt die Position die Bedingungen (korrektes Symbol und enthält den angegebenen Kommentar), wird sie mit dieser Methode geschlossen.
Schlussfolgerung
In diesem Artikel haben wir den Code implementiert, um Stop-Order zu öffnen und die Gültigkeit von Handelsgeschäften und Orders zu prüfen, bevor sie geöffnet werden. Wir haben eine Funktion namens FundamentalModewelche einen speziellen Handelsmodus durch die Verwaltung von gegenläufigen Stop-Order handhabt. Darüber hinaus wurde eine Slippage-Reduzierung für Stop-Aufträge eingeführt, um das Risiko von Kursverlusten bei volatilen Marktbedingungen aufgrund von Nachrichtenmeldungen zu verringern.
Wichtigste Erkenntnisse:
- Präzision in der Ausführung: Die Klasse für das Handelsmanagement befasst sich mit allen Aspekten des Platzierens, Änderns und Schließens von Handelsgeschäften und stellt sicher, dass der Handel präzise ausgeführt wird, selbst in volatilen Märkten.
- Anpassungen in Echtzeit: Die Möglichkeit, Stop-Losses und Gewinnmitnahmen dynamisch anzupassen, stellt sicher, dass der EA auf Marktveränderungen in Echtzeit reagiert und ermöglicht so ein besseres Risikomanagement.
- Slippage-Management: Durch die Berücksichtigung von Slippage und die Implementierung von Logik zur dynamischen Anpassung von Handelsparametern stellt die Klasse für das Handelsmanagement sicher, dass die Handelsgeschäfte so nah wie möglich an den beabsichtigten Bedingungen ausgeführt werden, wodurch potenzielle Verluste reduziert werden.
Vielen Dank für Ihre Zeit, ich freue mich darauf, im nächsten Artikel mehr Wert zu bieten :)
Übersetzt aus dem Englischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/en/articles/16169





- Freie Handelsapplikationen
- Über 8.000 Signale zum Kopieren
- Wirtschaftsnachrichten für die Lage an den Finanzmärkte
Sie stimmen der Website-Richtlinie und den Nutzungsbedingungen zu.
Hallo Kabelo,
sehr interessant!!
Leider ist die Zip-Datei(NewsTrading_Part5.zip )die gleiche wie die in Artikel 4(NewsTrading_Part4.zip )??
Hallo Hamid, leider kann ich nicht den ganzen Code in einen Artikel packen. Der News-Teil 5 hat mehr Code als Teil 4, aber er ist nicht vollständig. In Teil 6 wird der verbleibende Code implementiert werden, damit alles zusammen funktioniert.
Vielen Dank für Ihre Zeit und Ihr Verständnis.
Hallo,
Gibt es eine einfache Möglichkeit, vor den Nachrichten die Auftragsart, buy, sel oder NAN anzuzeigen?
Dankeschön
Dankeschön
Hallo Hamid Rabia, danke für die Anregung. Ich werde mich bemühen, eine Lösung zu implementieren und Ihnen eine private Nachricht schicken, sobald sie fertig ist.
Dies ist ein faszinierender Artikel, den Sie verfasst haben.
Ich freue mich auf Teil 6 und den vollständigen Code.
Dies ist ein faszinierender Artikel, den Sie verfasst haben.
Ich freue mich auf Teil 6 und den vollständigen Code.
Hallo Veeral10, vielen Dank für deine netten Worte!