Close open positions - partial close, close by ticket, close all positions.
bool ClosePosition(ulong ticket) {
if(!PositionSelectByTicket(ticket)) {
Print("Position not found: ", ticket);
return false;
}
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_DEAL;
request.position = ticket;
request.symbol = PositionGetString(POSITION_SYMBOL);
request.volume = PositionGetDouble(POSITION_VOLUME);
request.deviation = 10;
// Opposite order type
ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
request.type = (posType == POSITION_TYPE_BUY) ? ORDER_TYPE_SELL : ORDER_TYPE_BUY;
// Get close price
if(request.type == ORDER_TYPE_SELL) {
request.price = SymbolInfoDouble(request.symbol, SYMBOL_BID);
} else {
request.price = SymbolInfoDouble(request.symbol, SYMBOL_ASK);
}
bool success = OrderSend(request, result);
if(success && result.retcode == TRADE_RETCODE_DONE) {
Print("✅ Position closed: ", ticket);
return true;
} else {
Print("❌ Close failed: ", result.retcode);
return false;
}
}
int CloseAllPositions(long magic = 0) {
int closedCount = 0;
// Loop backward (important!)
for(int i = PositionsTotal() - 1; i >= 0; i--) {
ulong ticket = PositionGetTicket(i);
if(ticket == 0) continue;
// Check magic number
if(magic > 0 && PositionGetInteger(POSITION_MAGIC) != magic)
continue;
if(ClosePosition(ticket)) {
closedCount++;
}
}
Print("Closed ", closedCount, " positions");
return closedCount;
}
bool PartialClose(ulong ticket, double volumeToClose) {
if(!PositionSelectByTicket(ticket)) return false;
double currentVolume = PositionGetDouble(POSITION_VOLUME);
// Validate volume
if(volumeToClose >= currentVolume) {
return ClosePosition(ticket); // Close entire position
}
double minVol = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
if(volumeToClose < minVol) {
Print("Volume too small");
return false;
}
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_DEAL;
request.position = ticket;
request.symbol = PositionGetString(POSITION_SYMBOL);
request.volume = NormalizeDouble(volumeToClose, 2);
request.deviation = 10;
ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
request.type = (posType == POSITION_TYPE_BUY) ? ORDER_TYPE_SELL : ORDER_TYPE_BUY;
if(request.type == ORDER_TYPE_SELL) {
request.price = SymbolInfoDouble(request.symbol, SYMBOL_BID);
} else {
request.price = SymbolInfoDouble(request.symbol, SYMBOL_ASK);
}
return OrderSend(request, result);
}
// Usage: Close 50% of position
double currentVol = PositionGetDouble(POSITION_VOLUME);
PartialClose(ticket, currentVol * 0.5);