From b5df20d05421a2761c3cca5cdc845f7ad748a843 Mon Sep 17 00:00:00 2001 From: Garfield Date: Tue, 24 Mar 2026 15:35:12 -0400 Subject: [PATCH] Fix invalid price errors - add stop level validation --- OrdersEA_Smart_Grid.mq5 | 169 ++++++++++++++++++++++++++++------------ 1 file changed, 121 insertions(+), 48 deletions(-) diff --git a/OrdersEA_Smart_Grid.mq5 b/OrdersEA_Smart_Grid.mq5 index 07601bd..ee99cb0 100644 --- a/OrdersEA_Smart_Grid.mq5 +++ b/OrdersEA_Smart_Grid.mq5 @@ -353,8 +353,23 @@ bool PlaceBuyStop(double priceLevel, int level) double lots = CalcLots(); double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT); - double sl = (StopLoss > 0) ? priceLevel - (StopLoss * point) : 0; - double tp = priceLevel + (TP * point); + double currentAsk = SymbolInfoDouble(_Symbol, SYMBOL_ASK); + double stopLevel = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL) * point; + + // Ensure price is above current Ask + stop level + double minDistance = currentAsk + stopLevel + (Entry * point); + if(priceLevel < minDistance) + { + Print("Buy Stop too close to price. Adjusting from ", priceLevel, " to ", minDistance); + priceLevel = minDistance; + } + + double sl = (StopLoss > 0) ? NormalizeDouble(priceLevel - (StopLoss * point), _Digits) : 0; + double tp = NormalizeDouble(priceLevel + (TP * point), _Digits); + + // Ensure TP is valid distance from price + if(tp <= priceLevel + stopLevel) + tp = NormalizeDouble(priceLevel + stopLevel + (TP * point), _Digits); MqlTradeRequest request = {}; MqlTradeResult result = {}; @@ -362,7 +377,7 @@ bool PlaceBuyStop(double priceLevel, int level) request.action = TRADE_ACTION_PENDING; request.symbol = _Symbol; request.volume = lots; - request.price = priceLevel; + request.price = NormalizeDouble(priceLevel, _Digits); request.sl = sl; request.tp = tp; request.deviation = 10; @@ -371,16 +386,18 @@ bool PlaceBuyStop(double priceLevel, int level) request.type = ORDER_TYPE_BUY_STOP; request.type_filling = ORDER_FILLING_IOC; - if(trade.OrderSend(request, result)) + if(!trade.OrderSend(request, result)) { - if(result.retcode == TRADE_RETCODE_DONE || result.retcode == TRADE_RETCODE_PLACED) - { - Print("Buy Stop Level ", level, " placed at ", priceLevel, " Ticket: ", result.order); - return true; - } + Print("Error placing buy stop: ", trade.ResultRetcodeDescription(), " (", result.retcode, ")"); + return false; + } + + if(result.retcode == TRADE_RETCODE_DONE || result.retcode == TRADE_RETCODE_PLACED) + { + Print("Buy Stop Level ", level, " placed at ", request.price, " TP: ", tp, " Ticket: ", result.order); + return true; } - Print("Error placing buy stop: ", trade.ResultRetcodeDescription()); return false; } @@ -393,8 +410,23 @@ bool PlaceSellStop(double priceLevel, int level) double lots = CalcLots(); double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT); - double sl = (StopLoss > 0) ? priceLevel + (StopLoss * point) : 0; - double tp = priceLevel - (TP * point); + double currentBid = SymbolInfoDouble(_Symbol, SYMBOL_BID); + double stopLevel = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL) * point; + + // Ensure price is below current Bid - stop level + double minDistance = currentBid - stopLevel - (Entry * point); + if(priceLevel > minDistance) + { + Print("Sell Stop too close to price. Adjusting from ", priceLevel, " to ", minDistance); + priceLevel = minDistance; + } + + double sl = (StopLoss > 0) ? NormalizeDouble(priceLevel + (StopLoss * point), _Digits) : 0; + double tp = NormalizeDouble(priceLevel - (TP * point), _Digits); + + // Ensure TP is valid distance from price + if(tp >= priceLevel - stopLevel) + tp = NormalizeDouble(priceLevel - stopLevel - (TP * point), _Digits); MqlTradeRequest request = {}; MqlTradeResult result = {}; @@ -402,7 +434,7 @@ bool PlaceSellStop(double priceLevel, int level) request.action = TRADE_ACTION_PENDING; request.symbol = _Symbol; request.volume = lots; - request.price = priceLevel; + request.price = NormalizeDouble(priceLevel, _Digits); request.sl = sl; request.tp = tp; request.deviation = 10; @@ -411,68 +443,109 @@ bool PlaceSellStop(double priceLevel, int level) request.type = ORDER_TYPE_SELL_STOP; request.type_filling = ORDER_FILLING_IOC; - if(trade.OrderSend(request, result)) + if(!trade.OrderSend(request, result)) { - if(result.retcode == TRADE_RETCODE_DONE || result.retcode == TRADE_RETCODE_PLACED) - { - Print("Sell Stop Level ", level, " placed at ", priceLevel, " Ticket: ", result.order); - return true; - } + Print("Error placing sell stop: ", trade.ResultRetcodeDescription(), " (", result.retcode, ")"); + return false; + } + + if(result.retcode == TRADE_RETCODE_DONE || result.retcode == TRADE_RETCODE_PLACED) + { + Print("Sell Stop Level ", level, " placed at ", request.price, " TP: ", tp, " Ticket: ", result.order); + return true; } - Print("Error placing sell stop: ", trade.ResultRetcodeDescription()); return false; } +//+------------------------------------------------------------------+ +//| Count pending orders | +//+------------------------------------------------------------------+ +int CountPendingOrders(int type) + { + int count = 0; + for(int i = OrdersTotal() - 1; i >= 0; i--) + { + ulong ticket = OrderGetTicket(i); + if(ticket <= 0) continue; + if(OrderGetString(ORDER_SYMBOL) != _Symbol) continue; + if(OrderGetInteger(ORDER_MAGIC) != MagicNum) continue; + if(OrderGetInteger(ORDER_TYPE) == type) count++; + } + return count; + } + //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { static datetime lastBarTime = 0; + static bool gridPlaced = false; datetime currentBarTime = iTime(_Symbol, PERIOD_CURRENT, 0); MqlDateTime dt; TimeToStruct(TimeCurrent(), dt); // Recalculate pivots at new day (hour 0, first 5 minutes) - if(dt.hour == 0 && dt.min < 5 && currentBarTime != lastBarTime) + if(dt.hour == 0 && dt.min < 5) { CalculatePivotPoints(); + gridPlaced = false; // Reset grid for new day } - if(currentBarTime != lastBarTime) + if(currentBarTime == lastBarTime) return; + lastBarTime = currentBarTime; + + // Check if we should trade + if(!IsRangingMarket()) { - lastBarTime = currentBarTime; + Print("Market not suitable for grid trading"); + return; + } + + // Only place grid once, then monitor + if(gridPlaced) + { + // Check if grid needs replenishing (orders filled) + int buyStops = CountPendingOrders(ORDER_TYPE_BUY_STOP); + int sellStops = CountPendingOrders(ORDER_TYPE_SELL_STOP); - // Check if we should trade - if(!IsRangingMarket()) + if(buyStops == 0 && sellStops == 0) { - Print("Market not suitable for grid trading"); - return; + Print("All grid orders filled or cancelled. Resetting grid."); + gridPlaced = false; } + return; + } + + // Get grid boundaries + double actualHigh = (HIGH > 0) ? HIGH : PivotR1; + double actualLow = (LOW > 0) ? LOW : PivotS1; + double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID); + double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT); + double entryPips = Entry * point; + + // Log status + Print("Smart Grid: Placing grid. Price=", currentPrice, " Range: ", actualLow, " - ", actualHigh); + + // Place grid orders + int buyCount = 0, sellCount = 0; + for(int i = 0; i < MaxLevels; i++) + { + double buyLevel = actualLow + (i * entryPips); + double sellLevel = actualHigh - (i * entryPips); - // Get grid boundaries - double actualHigh = (HIGH > 0) ? HIGH : PivotR1; - double actualLow = (LOW > 0) ? LOW : PivotS1; - double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID); - double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT); - double entryPips = Entry * point; - - // Log status - Print("Smart Grid: Price=", currentPrice, " Range: ", actualLow, " - ", actualHigh); - Print("RSI/ADX filters passed - Grid active"); - - // Example: Place grid orders (simplified) - // In full implementation, check existing orders first - for(int i = 0; i < MaxLevels; i++) + // Only place if valid distance from current price + if(buyLevel < currentPrice - (Entry * 2 * point)) { - double buyLevel = actualLow + (i * entryPips); - double sellLevel = actualHigh - (i * entryPips); - - if(buyLevel < currentPrice) - PlaceBuyStop(buyLevel, i); - if(sellLevel > currentPrice) - PlaceSellStop(sellLevel, i); + if(PlaceBuyStop(buyLevel, i)) buyCount++; + } + if(sellLevel > currentPrice + (Entry * 2 * point)) + { + if(PlaceSellStop(sellLevel, i)) sellCount++; } } + + Print("Grid placed: ", buyCount, " buy stops, ", sellCount, " sell stops"); + if(buyCount > 0 || sellCount > 0) gridPlaced = true; }