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:
@@ -475,6 +475,72 @@ int CountPendingOrders(int type)
|
||||
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 |
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -489,6 +555,9 @@ void OnTick()
|
||||
// Recalculate pivots at new day (hour 0, first 5 minutes)
|
||||
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();
|
||||
gridPlaced = false; // Reset grid for new day
|
||||
}
|
||||
@@ -499,7 +568,19 @@ void OnTick()
|
||||
// Check if we should trade
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -509,8 +590,52 @@ void OnTick()
|
||||
// Check if grid needs replenishing (orders filled)
|
||||
int buyStops = CountPendingOrders(ORDER_TYPE_BUY_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.");
|
||||
gridPlaced = false;
|
||||
|
||||
Reference in New Issue
Block a user