Summary: Advanced guide to MQL4 OrderSend function: parameters breakdown, common errors (130, 138), slippage handling, and backtest-safe implementation. Runnable code for market/pending orders.




The `OrderSend()` function is the heart of any MQL4 Expert Advisor. Despite its ubiquity, improper usage leads to order rejection, slippage loss, and backtest inaccuracies. This guide covers advanced parameter control, error diagnosis, and production patterns.

1. Function Signature & Hidden Parameters
```cpp
int OrderSend(string symbol, int cmd, double volume, double price, int slippage, double stoploss, double takeprofit, string comment, int magic, datetime expiration, color arrow_color)
```
  • `slippage`: Only applies to market orders (`OP_BUY`/`OP_SELL`). For pending orders, this parameter is ignored but still required.

  • `expiration`: Only for pending orders (`OP_BUYLIMIT`, `OP_BUYSTOP`, `OP_SELLLIMIT`, `OP_SELLSTOP`). Market orders ignore this.


  • 2. Advanced Error Handling Pattern
    Common error codes:
  • `130` - Invalid stops (too close to market)

  • `138` - Requote (price changed)

  • `145` - Modification denied (too frequent)


  • Production-ready wrapper:
    ```cpp
    int SafeOrderSend(int cmd, double volume, double price, int slippage, double sl, double tp) {
    int ticket = -1;
    int attempts = 0;
    while(attempts < 3 && ticket < 0) {
    ticket = OrderSend(Symbol(), cmd, volume, price, slippage, sl, tp, "EA", magic, 0, clrNONE);
    if(ticket < 0) {
    int err = GetLastError();
    if(err == 138) { // Requote: refresh prices
    RefreshRates();
    price = (cmd == OP_BUY) ? Ask : Bid;
    attempts++;
    continue;
    }
    if(err == 130) { // Invalid stops: recalculate SL/TP
    sl = NormalizeDouble((cmd == OP_BUY) ? price - 50*Point() : price + 50*Point(), Digits);
    tp = NormalizeDouble((cmd == OP_BUY) ? price + 100*Point() : price - 100*Point(), Digits);
    attempts++;
    continue;
    }
    break; // Unrecoverable error
    }
    }
    return ticket;
    }
    ```

    3. Slippage Calculation Model
    Slippage in points: actual execution price = requested price ± slippage. Formula for maximum acceptable deviation:
    ```
    acceptable_deviation = slippage * Point
    if(|execution_price - requested_price| <= acceptable_deviation) -> fill
    else -> requote (error 138)
    ```
    For volatile markets, dynamic slippage:
    ```cpp
    int DynamicSlippage() {
    double spread = (Ask - Bid) / Point;
    return (int)MathMax(spread * 2, 3);
    }
    ```

    4. Pending Orders & Expiration Math
    Set expiration based on bar count:
    ```cpp
    datetime expiration = TimeCurrent() + periods * Period() * 60;
    ```
    Example: 5-hour limit order on H1 chart:
    ```cpp
    int periods = 5;
    datetime expiry = TimeCurrent() + periods * 60 * 60;
    OrderSend(Symbol(), OP_BUYLIMIT, 0.1, price, 3, 0, 0, "Limit", magic, expiry, clrNONE);
    ```

    5. Backtest Accuracy Considerations
    Future function alert: Using `OrderSend()` inside `start()` with `Volume[0]` or `Close[0]` creates look-ahead bias. Correct pattern:
    ```cpp
    if(NewBar()) {
    double signal_price = Close[1]; // previous bar close, no future data
    if(signal_price > some_level)
    OrderSend(..., Ask, ...);
    }
    ```
    Never use `Close[0]` or `Open[0]` for decision before `OrderSend()` in same tick—this matches live market where current price is unknown for signal.

    6. OrderSend Alternative for Scalping
    For high-frequency EAs, `OrderSend()` with zero slippage may cause repeated requotes. Use `OrderSendAsync()` (MQL4 build 600+) for non-blocking placement:
    ```cpp
    int ticket = OrderSendAsync(Symbol(), OP_BUY, 0.1, Ask, 0, 0, 0, "Async", magic, 0, clrNONE);
    ```
    But note: async orders don't return ticket immediately; check orders pool later.

    Reference
  • MQL4 Documentation: "OrderSend" (docs.mql4.com/trading/OrderSend)

  • "MQL4 Programming for Traders" by Nikolay Kositsin, Chapter 5: Trade Functions.