Summary: Advanced exploration of MQL4 OrderSend function covering all parameters, return value handling, slippage protection, magic number strategies, and pending order modification with production-ready code.
The `OrderSend()` function is the heart of every MQL4 Expert Advisor. While basic usage appears simple, advanced order management requires deep understanding of its parameters, return value handling, and error recovery patterns.
1. Complete OrderSend Parameter Breakdown
```cpp
int OrderSend(
string symbol, // symbol name
int cmd, // trade operation (OP_BUY, OP_SELL, OP_BUYLIMIT, etc.)
double volume, // lot size
double price, // opening price
int slippage, // maximum slippage in points
double stoploss, // stop loss level
double takeprofit, // take profit level
string comment, // order comment
int magic, // EA identifier
datetime expiration, // pending order expiration (0 = no expiration)
color arrow_color // arrow color on chart
);
```
Critical insight: The `slippage` parameter only applies to market orders (OP_BUY/OP_SELL). For pending orders, slippage is irrelevant but the price must be placed correctly relative to current market.
2. Return Value and Error Handling Pattern
Never assume OrderSend succeeds. Always capture ticket and validate immediately:
```cpp
int SendOrderWithRetry(string sym, int cmd, double lot, double price, int slip, double sl, double tp) {
int ticket = -1;
int attempts = 0;
int maxAttempts = 3;
while(attempts < maxAttempts && ticket < 0) {
ticket = OrderSend(sym, cmd, lot, price, slip, sl, tp, "EA_Advanced", 12345, 0, clrNONE);
if(ticket < 0) {
int error = GetLastError();
Print("OrderSend failed. Error: ", error, " Attempt: ", attempts + 1);
// Handle specific recoverable errors
switch(error) {
case 146: // ERR_TRADE_BUSY
Sleep(1000); // Wait 1 second
break;
case 129: // ERR_INVALID_PRICE
price = RefreshPrice(sym, cmd); // Refresh price
break;
case 130: // ERR_INVALID_STOPS
sl = AdjustStopLevel(sym, sl); // Adjust stop to minimum distance
tp = AdjustStopLevel(sym, tp);
break;
default:
return ticket; // Non-recoverable, exit
}
attempts++;
}
}
return ticket;
}
double RefreshPrice(string symbol, int command) {
double price = (command == OP_BUY) ? Ask : Bid;
RefreshRates();
return price;
}
```
3. Magic Number Strategies for Multiple Strategies
A robust magic number scheme enables running multiple EAs on the same symbol:
```cpp
// Magic number encoding: [MMDD][StrategyID][Variant]
// Example: 1208001001 = Dec 8, Strategy 001, Variant 01
int EncodeMagicNumber(int month, int day, int strategyID, int variant) {
return month * 10000000 + day * 100000 + strategyID * 100 + variant;
}
// Check if order belongs to current EA instance
bool IsMyOrder(int orderMagic, int myMagicBase, int strategyID) {
int extractedStrategy = (orderMagic % 10000) / 100;
return extractedStrategy == strategyID;
}
```
4. Pending Order Modification Without Re-creation
Modifying existing pending orders is more efficient than deleting and recreating:
```cpp
bool ModifyPendingOrder(int ticket, double newPrice, datetime newExpiration) {
if(OrderSelect(ticket, SELECT_BY_TICKET)) {
double oldPrice = OrderOpenPrice();
// Only modify if price actually changed
if(MathAbs(newPrice - oldPrice) < Point * 0.5) {
return true; // No modification needed
}
return OrderModify(ticket, newPrice, OrderStopLoss(), OrderTakeProfit(), newExpiration, clrNONE);
}
return false;
}
```
5. Complete Order Opening Function with Slippage Protection
```cpp
bool OpenMarketOrder(int cmd, double lot, int slippagePoints, double slPoints, double tpPoints) {
RefreshRates();
double price = (cmd == OP_BUY) ? Ask : Bid;
double sl = 0, tp = 0;
if(slPoints > 0) {
sl = (cmd == OP_BUY) ? price - slPoints * Point : price + slPoints * Point;
sl = NormalizeDouble(sl, Digits);
}
if(tpPoints > 0) {
tp = (cmd == OP_BUY) ? price + tpPoints * Point : price - tpPoints * Point;
tp = NormalizeDouble(tp, Digits);
}
// Validate stop levels
double minStop = MarketInfo(Symbol(), MODE_STOPLEVEL) * Point;
if(slPoints > 0 && MathAbs(price - sl) < minStop) {
Print("Stop loss too close to market");
return false;
}
int ticket = OrderSend(Symbol(), cmd, lot, price, slippagePoints, sl, tp, "EA_Trade", 12345, 0, Green);
if(ticket < 0) {
Print("Order failed. Error: ", GetLastError());
return false;
}
Print("Order opened. Ticket: ", ticket);
return true;
}
```
Reference: MQL4 Documentation (docs.mql4.com/trading/OrderSend), "Expert Advisor Programming for MetaTrader 4" by Andrew R. Young, 2021.