Beim Devisenhandel verdienen wir normalerweise Geld, indem wir uns an Aufwärts- oder Abwärtspreistrends beteiligen und diese mit Gewinn nutzen. Aber was ist mit Zeiten, in denen der Markt seitwärts tendiert? Wenn es Ihnen keine Freude macht, diese schwankenden Märkte abzuwarten, könnte für Sie eine Strategie interessant sein, die speziell für den Handel in diesen Zeiten entwickelt wurde. Dies nennt man Grid-Trading. Sie können dieses unter schwankenden und trendigen Bedingungen verwenden.
Auf YouTube veröffentlicht
Was ist Grid-Trading?
Mit einer FX-Grid-Handelsstrategie richten Sie ein Raster aus ausstehenden Aufträgen über und unter dem aktuellen Preis ein. Wenn sich der Preis ändert, können diese Aufträge ausgeführt werden. Wenn mehr Aufträge ausgeführt werden, kann Ihre Position allmählich größer werden.
Grid-Trading mag zunächst kompliziert klingen. Aber wenn Sie sich ein paar Beispiele ansehen, werden Sie erkennen, dass es eigentlich ganz einfach ist.
Die grundlegende Grid-Trading-Strategie
So funktioniert die grundlegende Grid-Trading-Strategie.
- Identifizieren Sie, ob der Markt einen Trend aufweist oder schwankt.
- Wählen Sie einen Referenzpreis. Dies ist der Festpreis, über und unter dem Sie Ihre Bestellungen aufgeben.
- Erstellen Sie ein Auftragsraster über dem Referenzpunkt. In den meisten Fällen sollten Sie sie gleichmäßig verteilen.
- Erstellen Sie ein Auftragsraster unterhalb des Referenzpunkts. In den meisten Fällen sollten Sie diese auch gleichmäßig verteilen.
- Wenn der Markt einen Trend aufweist, erteilen Sie Kaufaufträge über dem Referenzpreis und Verkaufsaufträge unter dem Referenzpreis.
- Wenn der Markt schwankt, erteilen Sie Verkaufsaufträge über dem Referenzpreis und Kaufaufträge unter dem Referenzpreis.
Wie groß machst du das Gitter? Wodurch wird der höchste Preis für eine Kauforder und der niedrigste Preis für eine Verkaufsorder bestimmt? Um diese zu ermitteln, sehen Sie sich den höchsten Höchststand und den niedrigsten Tiefststand des jüngsten Zeitraums an (Sie können entscheiden, wie lang dieser Zeitraum sein wird). Sie können diese als Ihre höchsten und niedrigsten Orderwerte verwenden.
Wählen Sie für jede Order Ihre Positionsgröße. Dies erfordert sorgfältige Überlegung, da Sie sich überlegen müssen, wie hoch Ihr maximal mögliches Risiko sein soll, wenn alle Verkaufsaufträge oder alle Kaufaufträge ausgelöst werden.
Was ist mit Stop-Losses? Gute Frage. Es gibt zwei gängige Ansätze:
- Fester Stop-Loss: Manche Händler setzen einfach einen festen Stop-Loss auf der anderen Seite der Referenzlinie.
- Trailing Stop-Loss: Andere Händler entscheiden sich dafür, ihren Stop-Loss nachzuziehen, wenn sich der Trend fortsetzt.
Wie bei jeder anderen Art des Trendhandels können Sie entweder aussteigen, wenn Sie zufrieden sind oder die Sorge haben, dass es zu einer Trendwende kommt, oder Sie können versuchen, den Trend so lange wie möglich auszusitzen.
Manche Leute entscheiden sich dafür, nicht alle ihre Aufträge offen zu halten, wenn der Trend fortschreitet. Anstatt eine zunehmend größere Position anzuhäufen, schließen sie stattdessen jede ihrer Order jedes Mal, wenn sie eine neue eröffnen. Dadurch folgen sie weiterhin dem Trend, sichern sich aber zwischendurch einige Gewinne (vorausgesetzt, sie verwenden weiterhin angemessen Stop-Losses).
Best Practices für die Grid-Trading-Strategie
Hier sind ein paar kurze Tipps, die Ihnen dabei helfen, den größtmöglichen Nutzen aus der Forex-Grid-Trading-Strategie zu ziehen.
- Übertreiben Sie es nicht mit der Dichte Ihres Gitters! Wenn Sie das tun, lösen Sie so viele Aufträge aus, dass Sie in den Transaktionsgebühren ertrinken. Das heißt, Sie benötigen höhere Gewinne, um diese auszugleichen.
- Für die Ermittlung der Rasterabstände gibt es mehrere Ansätze. Manche Händler berechnen die Intervalle gerne mithilfe des Average True Range (ATR). Unabhängig von der Methode, die Sie verwenden, sollten Sie jedoch versuchen, die Abstände zwischen den einzelnen Teilen ungefähr gleichmäßig zu halten.
- Richten Sie immer eine Art Stop-Loss ein. Bedenken Sie: Wenn Sie mehrere offene Positionen haben, müssen Sie für alle davon Stopps einrichten.
- Achten Sie genau auf den Marktkontext, bevor Sie mit der Einrichtung einer Grid-Trading-Sitzung beginnen. Versuchen Sie, diese Strategie in den Situationen anzuwenden, in denen die größte Gewinnwahrscheinlichkeit besteht, und verwechseln Sie nicht die Ansätze, die für schwankende Märkte geeignet sind, mit denen, die sich für Trendmärkte eignen.
- Das Hinzufügen von Take-Profits zur Automatisierung günstiger Bedingungen kann sowohl bei Ranging- als auch Trending-Typen des Grid-Trading-Systems eine gute Idee sein.
- Wie bei jeder anderen Strategie müssen Sie Grid-Trading-Strategien gründlich studieren und anschließend Backtests und Demotests durchführen. Beginnen Sie nicht mit dem Live-Handel mit echtem Geld unter Verwendung der Grid-Strategie, bis Sie mit der Demo Gewinne erzielen.
Vor- und Nachteile der Forex Grid Trading Strategie
Damit Sie das Gelernte besser verstehen, gehen wir die Vor- und Nachteile des Handels mit der Devisenrasterstrategie durch.
Vorteile der Grid-Trading-Strategie
- Sie können vom Grid-Trading in schwankenden Märkten profitieren, in denen viele andere Handelsmethoden nicht funktionieren. Aber auch in Auf- und Abwärtstrends der Märkte können Sie davon profitieren.
- Sie müssen nicht wissen, in welche Richtung sich der Preis entwickeln wird, um vom Grid-Trading zu profitieren.
- Sie können den Grid-Handel mit minimalem Aufwand automatisieren.
- Theoretisch können Sie Ihre Verluste letztendlich durch Grid-Trading ausgleichen und dann im Plus stehen.
- Sie können Grid-Trading mit anderen Strategien kombinieren. Sie können zum Beispiel mithilfe der technischen Analyse oder der Preisbewegung den wahrscheinlichen Beginn eines Trends bestimmen und anschließend die Grid-Trading-Strategie zum Einstieg und zur Verwaltung Ihres Handels verwenden.
- Grid-Trading ist mit keinem anderen System vergleichbar. Dabei wird der Devisenhandel aus einer völlig anderen Perspektive betrachtet und an andere herangegangen, als es die meisten Händler gewohnt sind. Das allein kann schon ein ziemlicher Anreiz sein.
Diese haben einige überzeugende Vorteile. Bedenken Sie jedoch, dass Sie unbedingt von Stop-Losses Gebrauch machen müssen. Dieser Punkt kann nicht stark genug betont werden. Wenn Sie keine Stop-Losses verwenden, kann es passieren, dass Sie verheerende Verluste erleiden.
Risiken der Grid-Trading-Strategie
- Das Rastersystem kann kompliziert werden, insbesondere wenn Sie ein großes Raster haben. Das Verfolgen und Verwalten Ihrer Positionen kann ein komplizierter Prozess sein. Möglicherweise fällt es Ihnen schwer zu verstehen, was mit Ihrem Geld passiert und welche Auswirkungen die verschiedenen möglichen Ergebnisse hätten (z. B. Ausstieg jetzt oder nachdem sich der Markt in eine bestimmte Richtung bewegt).
- Ohne den richtigen Einsatz von Stop-Losses kann man beim Grid-Trading leicht und sehr schnell viel Geld verlieren.
- Zwar kann die Automatisierung des Grid-Handels effizient und effektiv sein, doch besteht bei einem System mit so vielen Aufträgen ein großes Potenzial für Fehlzündungen. Wenn Sie Ihre Trading-Bots unbeaufsichtigt lassen, kann sich Ihr Risiko erhöhen, da es in vielerlei Hinsicht zu Abweichungen von der von Ihnen programmierten Verhaltensweise kommen kann.
- Plötzliche Volatilität auf den Märkten könnte Ihr Vermögen ziemlich schnell ruinieren und/oder dazu führen, dass Sie mehrere Positionen unerwartet aufgeben.
- Bei dieser Methode entsteht viel visuelles „Rauschen“. Wir haben dies im Hinblick auf die Komplexität des Grid-Handels bereits angesprochen. Aber auch rein aus sensorischer Sicht kann es für manche Händler überwältigend sein. Sie verstehen zwar, was Sie sehen, fühlen sich jedoch überfordert und können sich nur schwer konzentrieren.
- Um erfolgreich zu sein, erfordert die Methode Geduld. Sie erzielen viele kleine Gewinne, erleiden auf dem Weg zur Profitabilität jedoch möglicherweise auch einige hohe Verluste.
- Um die großen Verluste zu verkraften, die beim Grid-Trading möglich sind, benötigen Sie eine Menge Kapital. Andernfalls kann es zu Margin Calls und Stop-Outs kommen.
- Grid-Trading in schwankenden Märkten, wie wir es in unserem ersten Beispiel besprochen haben, ähnelt der Martingale-Strategie. Die Martingale-Strategie ist dafür berüchtigt, Anleger und Spieler in den Ruin zu treiben. Wir werden dies weiter unten ausführlich besprechen.
Inwiefern die Grid-Strategie der Martingale-Strategie ähnelt
Möglicherweise sind Sie mit der Martingale-Strategie vertraut, insbesondere wenn Sie bereits Erfahrung mit Casinospielen oder Sportwetten haben. Wenn ja, ist Ihnen wahrscheinlich irgendwann während unserer Diskussion aufgefallen, dass die Ranging Market Grid-Strategie viel mit der Martingale-Strategie gemeinsam hat.
Falls Sie mit Martingale nicht vertraut sind: Es handelt sich um eine Strategie, bei der Sie jedes Mal, wenn Sie eine Wette verlieren, Ihren Einsatz für Ihre nächste Wette erhöhen. Dies machen Sie so lange, bis Sie eine Wette gewinnen. Zu diesem Zeitpunkt war Ihr letzter Einsatz theoretisch hoch genug, um alle Ihre vorherigen Verluste auszugleichen und Ihnen darüber hinaus einen Gewinn zu bescheren.
Die Martingale-Strategie ist für Wettende und Anleger attraktiv, da sie den Gewinn als sichere Sache erscheinen lässt. Sie müssen nur lange genug durchhalten, und irgendwann, so die Theorie, werden Sie es schaffen.
Allerdings gibt es bei der Martingale-Strategie mehrere Probleme:
- Die Martingale-Strategie geht davon aus, dass Sie über einen unbegrenzten Geldbetrag auf Ihrem Handelskonto verfügen. Wenn Ihre Mittel nicht unbegrenzt sind, wird die Strategie mit der Zeit scheitern.
- Beim Martingale-System kommt es normalerweise sehr schnell zu Verlusten, sodass Ihr Konto schneller leer ist als bei anderen Ansätzen.
- Sie müssen viel Geld riskieren, um potenziell einen vergleichsweise viel kleineren Geldbetrag zu gewinnen.
- Schließlich könnten Sie bei der maximalen Handelsgröße/Hebelwirkung an Grenzen stoßen.
Kommen wir nun zurück zur Diskussion der Grid-Trading-Strategie für Forex. Konzentrieren wir uns insbesondere auf die Grid-Trading-Strategie für Ranging-Märkte. Wenn Sie diese Strategie umsetzen, kaufen Sie, wenn der Preis fällt, oder verkaufen, wenn er steigt. Mit jeder neuen Bestellung vergrößern Sie die Größe Ihrer Gesamtposition, während sich der Markt weiterhin gegen Sie bewegt.
Wenn sich der Markt schließlich umkehrt und in die entgegengesetzte Richtung bewegt, kaufen oder verkaufen Sie nach Bedarf, um jede einzelne Position mit Gewinn zu verlassen.
Doch was passiert, wenn dies nicht oder nicht rechtzeitig geschieht? Was wäre, wenn Sie einfach die Gesamtgröße Ihrer Position immer weiter erhöhen, während sich Ihre Verluste immer weiter häufen? Ehe Sie es merken, kann es passieren, dass Sie mit einem Margin Call konfrontiert werden.
Durch die Verwendung der Grid-Trading-Strategie setzen Sie sich denselben Risiken aus, die Sie auch bei der Verwendung der Martingale-Strategie oder ähnlicher progressiver Positionsgrößensysteme eingehen würden.
Sollten Sie die Grid-Trading-Strategie verwenden?
Sie sollten jetzt eine ziemlich gute Vorstellung davon haben, was die Grid-Trading-Strategie ist, wie sie funktioniert und welche Vor- und Nachteile sie hat.
Die nächste Frage ist: Sollten Sie es verwenden?
Das hängt von Ihren individuellen Zielen und Ihrer Risikobereitschaft ab.
Zumindest kurzfristig scheinen einige Anleger mit dem Grid-Handel gute Ergebnisse zu erzielen. Wenn Sie alle Best Practices sorgfältig befolgen und sicherstellen, dass Sie Ihr Risiko begrenzen, gibt es keinen Grund, es nicht zu versuchen.
Insbesondere ist die Grid-Trading-Strategie für Trendmärkte möglicherweise nicht so gefährlich wie die für Ranging-Märkte verwendete. Sie kaufen/verkaufen in die Richtung, in die sich der Preis bewegt, und nicht dagegen.
Auf lange Sicht gibt es jedoch einige gute Gründe, die von uns für den Devisenhandel besprochene Strategie der schwankenden Märkte zu vermeiden. Wie bereits erläutert, steht Ihnen kein unbegrenztes Bankguthaben zur Verfügung. Wenn Sie die für schwankende Märkte konzipierte Version des Grid-Tradings verwenden möchten, werden Sie wahrscheinlich aus dem Markt gedrängt. Dies geschieht möglicherweise nicht sofort, aber wahrscheinlich mit der Zeit.
Außerdem macht es einfach keinen großen Sinn, viel Geld zu riskieren, um die Chance auf einen relativ kleinen Gewinn zu haben. Es gibt andere Forex-Strategien, die ein besseres Risiko-Ertrags-Verhältnis bieten.
Zusammenfassung
Wenn Sie zum ersten Mal mit Grid-Trading in Berührung kommen, erscheint es Ihnen möglicherweise ziemlich seltsam und unverständlich. Aber wenn Sie erst einmal die Grundlagen beherrschen, werden Sie erkennen, wie Sie diese Strategien möglicherweise in schwankenden und trendigen Märkten anwenden können.
Der Grid-Handel bietet einige Vorteile. Es lässt sich leicht automatisieren und Sie können handeln, ohne zu wissen, in welche Richtung sich der Preis entwickeln wird. Es kann in Verbindung mit anderen Strategien und unter unterschiedlichen Marktbedingungen verwendet werden, was es vielseitig macht. Wenn Sie Ihre Verluste durchstehen können, könnten Sie hypothetisch verlässliche Gewinne erzielen.
Doch der Grid-Handel kann auch Fallstricke bergen. Der sorgfältige Einsatz von Stopps kann Ihnen helfen, plötzliche, große Verluste beim Kauf oder Verkauf in Richtung der Preisbewegung während eines Trends zu vermeiden. Die Forex-Rasterstrategie für schwankende Märkte birgt jedoch noch weitere potenzielle Fallstricke, da sie ein hohes Risiko-Ertrags-Verhältnis aufweist und der unrentablen Martingale-Strategie ähnelt.
Ob Sie mit der Forex-Rasterstrategie handeln, bleibt letztendlich Ihnen überlassen. Gehen Sie dabei einfach mit äußerster Vorsicht vor.
Testen Sie den Goldmarkt!
Expert Advisor Grid Systems
Metatrader5 – Expert Advisor Codes
//+------------------------------------------------------------------+
//| GridSystems.mq5 |
//| Copyright Community |
//| https://www.mql5.com/en/users/sajidmahamud835 |
//+------------------------------------------------------------------+
#property copyright "Community"
#property link "https://multibank.cash"
#property version "1.00"
#property strict
//--- Input Parameters
input double LotSize = 0.1; // Lot size for each order
input int MaxOrders = 10; // Maximum number of orders in the grid
input int ATRPeriod = 14; // ATR period for dynamic grid adjustment
input double ATRMultiplier = 1.5; // Multiplier for ATR to calculate grid distance
input int TrendPeriod = 50; // Period for detecting market trend
input bool UseTakeProfit = true; // Enable/Disable Take Profit
input double DefaultTP = 100.0; // Default Take Profit in points
input bool UseStopLoss = true; // Enable/Disable Stop Loss
input double DefaultSL = 500.0; // Default Stop Loss in points
input double VolatilityThreshold = 20.0; // ATR threshold for volatility
input bool UseTrailingStop = true; // Enable/Disable Trailing Stop
input double TrailingStopPoints = 50; // Trailing Stop in points
input bool DebugMode = false; // Enable/Disable Debug Mode
//--- Global Variables
double gridLevels[]; // Array to store grid levels
int ordersCount = 0; // Counter for the number of orders placed
string successLogFile = "GridMasterPro_success_log.txt"; // Log file for successful actions
string errorLogFile = "GridMasterPro_error_log.txt"; // Log file for errors
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit() {
ArrayResize(gridLevels, MaxOrders); // Resize grid levels array to the maximum number of orders
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick() {
// Ensure the gridLevels array is correctly sized
if (ArraySize(gridLevels) != MaxOrders) {
ArrayResize(gridLevels, MaxOrders);
}
double lastPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID); // Current market price
double gridDistance = CalculateDynamicGridDistance(); // Calculate dynamic grid distance
double tp = 0, sl = 0; // Initialize Take Profit and Stop Loss variables
// Modify existing orders' SL and TP if necessary
for (int i = 0; i < PositionsTotal(); i++) {
if (PositionSelect(_Symbol)) {
ulong ticket = PositionGetInteger(POSITION_TICKET); // Get the position ticket
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN); // Get the open price of the position
DetermineTPAndSL(tp, sl, lastPrice, openPrice); // Determine Take Profit and Stop Loss levels
// Modify the order if the Stop Loss has changed
if (PositionGetDouble(POSITION_SL) != sl) {
ModifyOrder(ticket, openPrice, sl, tp);
}
} else {
Print("Failed to select position for symbol: ", _Symbol);
break;
}
}
// If no orders are placed yet, open the first order
if (ordersCount == 0) {
gridLevels[0] = lastPrice; // Set the first grid level at the current price
if (OpenOrder(ORDER_TYPE_BUY, LotSize, lastPrice, sl, tp)) {
ordersCount++;
}
}
// Check if new orders should be placed based on grid distance
for (int i = 0; i < ordersCount && i < MaxOrders - 1; i++) {
if (lastPrice > gridLevels[i] + gridDistance * _Point) {
gridLevels[i + 1] = lastPrice; // Set the next grid level
if (OpenOrder(ORDER_TYPE_BUY, LotSize, lastPrice, sl, tp)) {
ordersCount++;
}
}
}
}
//+------------------------------------------------------------------+
//| Calculate dynamic grid distance based on ATR |
//+------------------------------------------------------------------+
double CalculateDynamicGridDistance() {
double atr = iATR(_Symbol, 0, ATRPeriod); // Get ATR value
return atr * ATRMultiplier; // Calculate grid distance
}
//+------------------------------------------------------------------+
//| Determine Take Profit and Stop Loss levels |
//+------------------------------------------------------------------+
void DetermineTPAndSL(double& tp, double& sl, double lastPrice, double openPrice) {
tp = 0;
sl = 0;
if (UseTakeProfit) {
tp = lastPrice + DefaultTP * _Point; // Calculate Take Profit level
}
if (UseStopLoss) {
if (UseTrailingStop) {
double newSL = lastPrice - TrailingStopPoints * _Point; // Calculate Trailing Stop level
sl = MathMax(sl, newSL); // Set Stop Loss to the maximum of the existing or new SL
} else {
sl = openPrice - DefaultSL * _Point; // Set Stop Loss based on the default value
}
}
}
//+------------------------------------------------------------------+
//| Open a new order |
//+------------------------------------------------------------------+
bool OpenOrder(ENUM_ORDER_TYPE orderType, double lotSize, double price, double sl, double tp) {
long tradeAllowed;
// Check if trading is allowed for the symbol
if (!SymbolInfoInteger(_Symbol, SYMBOL_TRADE_MODE, tradeAllowed) || tradeAllowed != SYMBOL_TRADE_MODE_FULL) {
string errorMsg = "Trading not allowed for symbol: " + _Symbol;
Print(errorMsg);
WriteLog(errorLogFile, errorMsg, true);
return false;
}
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
if (bid == 0.0 || ask == 0.0) {
string errorMsg = "No prices available for symbol: " + _Symbol;
Print(errorMsg);
WriteLog(errorLogFile, errorMsg, true);
return false;
}
MqlTradeRequest request;
MqlTradeResult result;
ZeroMemory(request);
ZeroMemory(result);
// Fill the trade request
request.action = TRADE_ACTION_DEAL;
request.symbol = _Symbol;
request.volume = lotSize;
request.type = orderType;
request.price = price;
request.sl = sl;
request.tp = tp;
request.deviation = 50;
request.magic = GenerateMagicNumber();
request.comment = "Grid Order";
request.type_filling = ORDER_FILLING_IOC;
// Retry mechanism for order placement
const int maxRetries = 5;
int retries = 0;
int waitTime = 2000;
while (retries < maxRetries) {
if (OrderSend(request, result)) {
WriteLog(successLogFile, "Order placed successfully. Order ticket: " + IntegerToString(result.order), true);
return true;
} else {
int errorCode = GetLastError();
string errorMsg = "Order placement failed. Error code: " + IntegerToString(errorCode) + ". " + ErrorDescription(errorCode);
Print(errorMsg);
WriteLog(errorLogFile, errorMsg, true);
retries++;
waitTime = waitTime * 2 + (MathRand() % 1000); // Exponential backoff with some randomness
Sleep(waitTime);
}
}
// Log final failure after exhausting retries
string finalErrorMsg = "Order placement failed after " + IntegerToString(maxRetries) + " retries.";
Print(finalErrorMsg);
WriteLog(errorLogFile, finalErrorMsg, true);
return false;
}
//+------------------------------------------------------------------+
//| Modify an existing order's SL/TP |
//+------------------------------------------------------------------+
bool ModifyOrder(ulong ticket, double price, double sl, double tp) {
MqlTradeRequest request;
MqlTradeResult result;
ZeroMemory(request);
ZeroMemory(result);
// Fill the modification request
request.action = TRADE_ACTION_SLTP;
request.symbol = _Symbol;
request.sl = sl;
request.tp = tp;
request.deviation = 50;
request.order = ticket;
// Send the modification request
if (OrderSend(request, result)) {
WriteLog(successLogFile, "Order modified successfully. Order ticket: " + IntegerToString(ticket));
return true;
} else {
int errorCode = GetLastError();
string errorMsg = "Order modification failed. Error code: " + IntegerToString(errorCode) + ". " + ErrorDescription(errorCode);
Print(errorMsg);
WriteLog(errorLogFile, errorMsg);
return false;
}
}
//+------------------------------------------------------------------+
//| Generate a magic number for orders |
//+------------------------------------------------------------------+
int GenerateMagicNumber() {
if (StringLen(_Symbol) < 6) {
Print("Error: Symbol name too short");
return -1;
}
long symbolHash = 0;
for (int i = 0; i < StringLen(_Symbol); i++) {
symbolHash += StringToInteger(StringSubstr(_Symbol, i, 1)) * i;
}
return int(symbolHash) % 10000; // Return a 4-digit magic number
}
//+------------------------------------------------------------------+
//| Log function to write messages to a log file |
//+------------------------------------------------------------------+
void WriteLog(string filename, string message, bool addTimestamp = false) {
int handle = FileOpen(filename, FILE_WRITE | FILE_CSV | FILE_ANSI | FILE_COMMON, ';');
if (handle != INVALID_HANDLE) {
if (addTimestamp) {
message = TimeToString(TimeCurrent(), TIME_DATE | TIME_MINUTES) + " - " + message;
}
FileWrite(handle, message);
FileClose(handle);
} else {
Print("Failed to open log file: ", filename);
}
}
//+------------------------------------------------------------------+
//| Error Description helper function |
//+------------------------------------------------------------------+
string ErrorDescription(int errorCode) {
switch (errorCode) {
case 10004: return "Requote";
case 10006: return "Request rejected";
case 10008: return "Order placed";
case 10009: return "Request completed";
case 10012: return "Request canceled by timeout";
case 10017: return "Trade is disabled";
case 10018: return "Market is closed";
case 10019: return "Not enough money to complete the request";
case 10020: return "Prices changed";
case 10021: return "No quotes to process the request";
case 10024: return "Too frequent requests";
default: return "Unknown error";
}
}
Grid Systems mit SL und TP für Forex
//+------------------------------------------------------------------+
//| GridSystems.mq5 |
//| Copyright Community |
//| https://www.mql5.com/en/users/sajidmahamud835 |
//+------------------------------------------------------------------+
#property copyright "Community"
#property link "https://multibank.cash"
#property version "1.00"
#property strict
//--- Input Parameters
input double LotSize = 0.1; // Lot size for each order
input int MaxOrders = 10; // Maximum number of orders in the grid
input int ATRPeriod = 14; // ATR period for dynamic grid adjustment
input double ATRMultiplier = 1.5; // Multiplier for ATR to calculate grid distance
input int TrendPeriod = 50; // Period for detecting market trend
input bool UseTakeProfit = true; // Enable/Disable Take Profit
input double DefaultTP = 10.0; // Default Take Profit in points
input bool UseStopLoss = true; // Enable/Disable Stop Loss
input double DefaultSL = 3.5; // Default Stop Loss in points
input double VolatilityThreshold = 20.0; // ATR threshold for volatility
input bool UseTrailingStop = true; // Enable/Disable Trailing Stop
input double TrailingStopPoints = 500; // Trailing Stop in points
input bool DebugMode = false; // Enable/Disable Debug Mode
//--- Global Variables
double gridLevels[]; // Array to store grid levels
int ordersCount = 0; // Counter for the number of orders placed
string successLogFile = "GridMasterPro_success_log.txt"; // Log file for successful actions
string errorLogFile = "GridMasterPro_error_log.txt"; // Log file for errors
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit() {
ArrayResize(gridLevels, MaxOrders); // Resize grid levels array to the maximum number of orders
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick() {
// Ensure the gridLevels array is correctly sized
if (ArraySize(gridLevels) != MaxOrders) {
ArrayResize(gridLevels, MaxOrders);
}
double lastPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID); // Current market price
double gridDistance = CalculateDynamicGridDistance(); // Calculate dynamic grid distance
double tp = 10, sl = 3.5; // Initialize Take Profit and Stop Loss variables
// Modify existing orders' SL and TP if necessary
for (int i = 0; i < PositionsTotal(); i++) {
if (PositionSelect(_Symbol)) {
ulong ticket = PositionGetInteger(POSITION_TICKET); // Get the position ticket
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN); // Get the open price of the position
DetermineTPAndSL(tp, sl, lastPrice, openPrice); // Determine Take Profit and Stop Loss levels
// Modify the order if the Stop Loss has changed
if (PositionGetDouble(POSITION_SL) != sl) {
ModifyOrder(ticket, openPrice, sl, tp);
}
} else {
Print("Failed to select position for symbol: ", _Symbol);
break;
}
}
// If no orders are placed yet, open the first order
if (ordersCount == 0) {
gridLevels[0] = lastPrice; // Set the first grid level at the current price
if (OpenOrder(ORDER_TYPE_BUY, LotSize, lastPrice, sl, tp)) {
ordersCount++;
}
}
// Check if new orders should be placed based on grid distance
for (int i = 0; i < ordersCount && i < MaxOrders - 1; i++) {
if (lastPrice > gridLevels[i] + gridDistance * _Point) {
gridLevels[i + 1] = lastPrice; // Set the next grid level
if (OpenOrder(ORDER_TYPE_BUY, LotSize, lastPrice, sl, tp)) {
ordersCount++;
}
}
}
}
//+------------------------------------------------------------------+
//| Calculate dynamic grid distance based on ATR |
//+------------------------------------------------------------------+
double CalculateDynamicGridDistance() {
double atr = iATR(_Symbol, 0, ATRPeriod); // Get ATR value
return atr * ATRMultiplier; // Calculate grid distance
}
//+------------------------------------------------------------------+
//| Determine Take Profit and Stop Loss levels |
//+------------------------------------------------------------------+
void DetermineTPAndSL(double& tp, double& sl, double lastPrice, double openPrice) {
tp = 10;
sl = 3.5;
if (UseTakeProfit) {
tp = lastPrice + DefaultTP * _Point; // Calculate Take Profit level
}
if (UseStopLoss) {
if (UseTrailingStop) {
double newSL = lastPrice - TrailingStopPoints * _Point; // Calculate Trailing Stop level
sl = MathMax(sl, newSL); // Set Stop Loss to the maximum of the existing or new SL
} else {
sl = openPrice - DefaultSL * _Point; // Set Stop Loss based on the default value
}
}
}
//+------------------------------------------------------------------+
//| Open a new order |
//+------------------------------------------------------------------+
bool OpenOrder(ENUM_ORDER_TYPE orderType, double lotSize, double price, double sl, double tp) {
long tradeAllowed;
// Check if trading is allowed for the symbol
if (!SymbolInfoInteger(_Symbol, SYMBOL_TRADE_MODE, tradeAllowed) || tradeAllowed != SYMBOL_TRADE_MODE_FULL) {
string errorMsg = "Trading not allowed for symbol: " + _Symbol;
Print(errorMsg);
WriteLog(errorLogFile, errorMsg, true);
return false;
}
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
if (bid == 0.0 || ask == 0.0) {
string errorMsg = "No prices available for symbol: " + _Symbol;
Print(errorMsg);
WriteLog(errorLogFile, errorMsg, true);
return false;
}
MqlTradeRequest request;
MqlTradeResult result;
ZeroMemory(request);
ZeroMemory(result);
// Fill the trade request
request.action = TRADE_ACTION_DEAL;
request.symbol = _Symbol;
request.volume = lotSize;
request.type = orderType;
request.price = price;
request.sl = sl;
request.tp = tp;
request.deviation = 50;
request.magic = GenerateMagicNumber();
request.comment = "Grid Order";
request.type_filling = ORDER_FILLING_IOC;
// Retry mechanism for order placement
const int maxRetries = 5;
int retries = 0;
int waitTime = 2000;
while (retries < maxRetries) {
if (OrderSend(request, result)) {
WriteLog(successLogFile, "Order placed successfully. Order ticket: " + IntegerToString(result.order), true);
return true;
} else {
int errorCode = GetLastError();
string errorMsg = "Order placement failed. Error code: " + IntegerToString(errorCode) + ". " + ErrorDescription(errorCode);
Print(errorMsg);
WriteLog(errorLogFile, errorMsg, true);
retries++;
waitTime = waitTime * 2 + (MathRand() % 1000); // Exponential backoff with some randomness
Sleep(waitTime);
}
}
// Log final failure after exhausting retries
string finalErrorMsg = "Order placement failed after " + IntegerToString(maxRetries) + " retries.";
Print(finalErrorMsg);
WriteLog(errorLogFile, finalErrorMsg, true);
return false;
}
//+------------------------------------------------------------------+
//| Modify an existing order's SL/TP |
//+------------------------------------------------------------------+
bool ModifyOrder(ulong ticket, double price, double sl, double tp) {
MqlTradeRequest request;
MqlTradeResult result;
ZeroMemory(request);
ZeroMemory(result);
// Fill the modification request
request.action = TRADE_ACTION_SLTP;
request.symbol = _Symbol;
request.sl = sl;
request.tp = tp;
request.deviation = 50;
request.order = ticket;
// Send the modification request
if (OrderSend(request, result)) {
WriteLog(successLogFile, "Order modified successfully. Order ticket: " + IntegerToString(ticket));
return true;
} else {
int errorCode = GetLastError();
string errorMsg = "Order modification failed. Error code: " + IntegerToString(errorCode) + ". " + ErrorDescription(errorCode);
Print(errorMsg);
WriteLog(errorLogFile, errorMsg);
return false;
}
}
//+------------------------------------------------------------------+
//| Generate a magic number for orders |
//+------------------------------------------------------------------+
int GenerateMagicNumber() {
if (StringLen(_Symbol) < 6) {
Print("Error: Symbol name too short");
return -1;
}
long symbolHash = 0;
for (int i = 0; i < StringLen(_Symbol); i++) {
symbolHash += StringToInteger(StringSubstr(_Symbol, i, 1)) * i;
}
return int(symbolHash) % 10000; // Return a 4-digit magic number
}
//+------------------------------------------------------------------+
//| Log function to write messages to a log file |
//+------------------------------------------------------------------+
void WriteLog(string filename, string message, bool addTimestamp = false) {
int handle = FileOpen(filename, FILE_WRITE | FILE_CSV | FILE_ANSI | FILE_COMMON, ';');
if (handle != INVALID_HANDLE) {
if (addTimestamp) {
message = TimeToString(TimeCurrent(), TIME_DATE | TIME_MINUTES) + " - " + message;
}
FileWrite(handle, message);
FileClose(handle);
} else {
Print("Failed to open log file: ", filename);
}
}
//+------------------------------------------------------------------+
//| Error Description helper function |
//+------------------------------------------------------------------+
string ErrorDescription(int errorCode) {
switch (errorCode) {
case 10004: return "Requote";
case 10006: return "Request rejected";
case 10008: return "Order placed";
case 10009: return "Request completed";
case 10012: return "Request canceled by timeout";
case 10017: return "Trade is disabled";
case 10018: return "Market is closed";
case 10019: return "Not enough money to complete the request";
case 10020: return "Prices changed";
case 10021: return "No quotes to process the request";
case 10024: return "Too frequent requests";
default: return "Unknown error";
}
}