Add order cancellation logic to OrdersEA_Smart_Grid

New functions:
- CancelAllOrders(reason): Cancels all pending orders with logging
- CloseAllPositions(reason): Closes all open positions
- IsBreakout(): Detects when price breaks S2/R2

Order cancellation triggers:
1. ADX rises (trend starts) - Cancel all, wait for ranging
2. Price breaks S2/R2 (breakout) - Cancel all, close positions
3. Buy positions fill - Cancel remaining buy stops (avoid overexposure)
4. Sell positions fill - Cancel remaining sell stops
5. End of day (00:00) - Cancel all, close positions, reset grid

This prevents:
- Orphaned orders when trend starts
- Overexposure when one side fills
- Old orders from previous day causing issues
This commit is contained in:
2026-03-24 21:53:44 -04:00
parent b5df20d054
commit 15cd0153e3

View File

@@ -475,6 +475,72 @@ int CountPendingOrders(int type)
return count; return count;
} }
//+------------------------------------------------------------------+
//| Cancel all pending orders |
//+------------------------------------------------------------------+
void CancelAllOrders(string reason)
{
int cancelled = 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(trade.OrderDelete(ticket))
{
cancelled++;
Print("Cancelled order #", ticket, " - Reason: ", reason);
}
}
if(cancelled > 0)
Print("Cancelled ", cancelled, " orders. Reason: ", reason);
}
//+------------------------------------------------------------------+
//| Close all positions |
//+------------------------------------------------------------------+
void CloseAllPositions(string reason)
{
int closed = 0;
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(ticket <= 0) continue;
if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
if(PositionGetInteger(POSITION_MAGIC) != MagicNum) continue;
if(trade.PositionClose(ticket))
{
closed++;
Print("Closed position #", ticket, " - Reason: ", reason);
}
}
if(closed > 0)
Print("Closed ", closed, " positions. Reason: ", reason);
}
//+------------------------------------------------------------------+
//| Check if price broke out of range |
//+------------------------------------------------------------------+
bool IsBreakout()
{
double actualHigh = (HIGH > 0) ? HIGH : PivotR1;
double actualLow = (LOW > 0) ? LOW : PivotS1;
double s2 = PivotS2;
double r2 = PivotR2;
double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);
// If price breaks S2 or R2, it's a breakout
if(currentPrice < s2 || currentPrice > r2)
{
Print("BREAKOUT detected! Price=", currentPrice, " S2=", s2, " R2=", r2);
return true;
}
return false;
}
//+------------------------------------------------------------------+ //+------------------------------------------------------------------+
//| Expert tick function | //| Expert tick function |
//+------------------------------------------------------------------+ //+------------------------------------------------------------------+
@@ -489,6 +555,9 @@ void OnTick()
// Recalculate pivots at new day (hour 0, first 5 minutes) // Recalculate pivots at new day (hour 0, first 5 minutes)
if(dt.hour == 0 && dt.min < 5) if(dt.hour == 0 && dt.min < 5)
{ {
Print("NEW DAY - Cancelling old grid and recalculating pivots");
CancelAllOrders("End of day - new pivot calculation");
CloseAllPositions("End of day - close positions");
CalculatePivotPoints(); CalculatePivotPoints();
gridPlaced = false; // Reset grid for new day gridPlaced = false; // Reset grid for new day
} }
@@ -499,7 +568,19 @@ void OnTick()
// Check if we should trade // Check if we should trade
if(!IsRangingMarket()) if(!IsRangingMarket())
{ {
Print("Market not suitable for grid trading"); Print("Market not suitable for grid trading - Cancelling all orders");
CancelAllOrders("ADX or RSI filter - no longer ranging");
gridPlaced = false;
return;
}
// Check for breakout (price beyond S2/R2)
if(IsBreakout())
{
Print("BREAKOUT! Cancelling grid orders");
CancelAllOrders("Price broke S2/R2 - breakout");
CloseAllPositions("Breakout - close positions");
gridPlaced = false;
return; return;
} }
@@ -509,8 +590,52 @@ void OnTick()
// Check if grid needs replenishing (orders filled) // Check if grid needs replenishing (orders filled)
int buyStops = CountPendingOrders(ORDER_TYPE_BUY_STOP); int buyStops = CountPendingOrders(ORDER_TYPE_BUY_STOP);
int sellStops = CountPendingOrders(ORDER_TYPE_SELL_STOP); int sellStops = CountPendingOrders(ORDER_TYPE_SELL_STOP);
int buyPositions = 0, sellPositions = 0;
if(buyStops == 0 && sellStops == 0) // Count open positions
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(ticket <= 0) continue;
if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
if(PositionGetInteger(POSITION_MAGIC) != MagicNum) continue;
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) buyPositions++;
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) sellPositions++;
}
// If buy positions opened, cancel remaining buy stops (avoid overexposure)
if(buyPositions > 0 && buyStops > 0)
{
Print("Buy positions filled (", buyPositions, "). Cancelling remaining buy stops.");
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) == ORDER_TYPE_BUY_STOP)
trade.OrderDelete(ticket);
}
}
// If sell positions opened, cancel remaining sell stops
if(sellPositions > 0 && sellStops > 0)
{
Print("Sell positions filled (", sellPositions, "). Cancelling remaining sell stops.");
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) == ORDER_TYPE_SELL_STOP)
trade.OrderDelete(ticket);
}
}
// If all orders filled, reset for next grid
if(buyStops == 0 && sellStops == 0 && buyPositions == 0 && sellPositions == 0)
{ {
Print("All grid orders filled or cancelled. Resetting grid."); Print("All grid orders filled or cancelled. Resetting grid.");
gridPlaced = false; gridPlaced = false;