🚀 AI One-Click Generation of mql4 Strategy Code

Mql4 Guide: Advanced Trade Management with OrderModify()

mql4 | Published on: 2025/12/8
The following content is generated by EasyQuant .

Problem Description

How can I change the entry price of a pending limit order if the market moves away from it?

Solution

To change the entry price of a pending limit order when the market moves away from it, you need to use the OrderModify() function. This logic is often referred to as a "Trailing Pending Order."

The concept works similarly to a Trailing Stop, but instead of modifying the Stop Loss of an open position, it modifies the Open Price of a pending order to maintain a specific distance from the current market price.

Logic Implementation

  1. Identify the Order: Loop through the order pool to find your specific pending order (Buy Limit or Sell Limit).
  2. Calculate Distance: Compare the current market price (Ask for Buy Limits, Bid for Sell Limits) with the order's current open price.
  3. Check Threshold: If the gap between the market price and the order price exceeds your defined TrailDistance, calculate the new entry price.
  4. Modify: Use OrderModify() to update the entry price.

MQL4 Code Example

Here is a complete Expert Advisor (EA) script that monitors pending limit orders and drags them along if the market moves away, keeping them at a fixed distance.

//+------------------------------------------------------------------+
//|                                       TrailingPendingOrder.mq4   |
//|                        Copyright 2023, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict

//--- Input Parameters
input int      TrailDistancePips = 20;    // Distance to maintain from market price (Pips)
input int      MagicNumber       = 12345; // Magic number to filter orders
input bool     ModifyStopLoss    = true;  // Move SL relative to new price?
input bool     ModifyTakeProfit  = true;  // Move TP relative to new price?

//--- Global variables
double m_point;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
   // Adjust point for 3/5 digit brokers
   if(Digits == 3 || Digits == 5) m_point = Point * 10;
   else                           m_point = Point;
   
   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
   // Loop through all orders
   for(int i = OrdersTotal() - 1; i >= 0; i--)
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
      {
         // Filter by Symbol and Magic Number
         if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
         {
            // Handle Buy Limits
            if(OrderType() == OP_BUYLIMIT)
            {
               ProcessBuyLimit();
            }
            // Handle Sell Limits
            if(OrderType() == OP_SELLLIMIT)
            {
               ProcessSellLimit();
            }
         }
      }
   }
}

//+------------------------------------------------------------------+
//| Logic to trail Buy Limit orders                                  |
//+------------------------------------------------------------------+
void ProcessBuyLimit()
{
   // Current market price is Ask. 
   // If Ask moves up (away), we want to pull the Buy Limit up.
   
   double targetPrice = Ask - (TrailDistancePips * m_point);
   
   // Check if the calculated target price is higher than the current order price
   // We add Point to ensure we don't modify for tiny fluctuations (floating point errors)
   if(targetPrice > OrderOpenPrice() + Point)
   {
      // Ensure we are not too close to market (FreezeLevel check)
      double stopLevel = MarketInfo(Symbol(), MODE_STOPLEVEL) * Point;
      if(Ask - targetPrice < stopLevel) return;

      double newPrice = NormalizeDouble(targetPrice, Digits);
      double newSL    = OrderStopLoss();
      double newTP    = OrderTakeProfit();
      
      // Calculate relative SL/TP shift
      if(ModifyStopLoss && OrderStopLoss() > 0)
      {
         double diff = newPrice - OrderOpenPrice();
         newSL = NormalizeDouble(OrderStopLoss() + diff, Digits);
      }
      
      if(ModifyTakeProfit && OrderTakeProfit() > 0)
      {
         double diff = newPrice - OrderOpenPrice();
         newTP = NormalizeDouble(OrderTakeProfit() + diff, Digits);
      }

      // Modify the order
      if(!OrderModify(OrderTicket(), newPrice, newSL, newTP, OrderExpiration(), clrBlue))
      {
         Print("Error modifying Buy Limit: ", GetLastError());
      }
   }
}

//+------------------------------------------------------------------+
//| Logic to trail Sell Limit orders                                 |
//+------------------------------------------------------------------+
void ProcessSellLimit()
{
   // Current market price is Bid.
   // If Bid moves down (away), we want to pull the Sell Limit down.
   
   double targetPrice = Bid + (TrailDistancePips * m_point);
   
   // Check if the calculated target price is lower than the current order price
   if(targetPrice < OrderOpenPrice() - Point)
   {
      // Ensure we are not too close to market (FreezeLevel check)
      double stopLevel = MarketInfo(Symbol(), MODE_STOPLEVEL) * Point;
      if(targetPrice - Bid < stopLevel) return;

      double newPrice = NormalizeDouble(targetPrice, Digits);
      double newSL    = OrderStopLoss();
      double newTP    = OrderTakeProfit();
      
      // Calculate relative SL/TP shift
      if(ModifyStopLoss && OrderStopLoss() > 0)
      {
         double diff = newPrice - OrderOpenPrice(); // diff is negative here
         newSL = NormalizeDouble(OrderStopLoss() + diff, Digits);
      }
      
      if(ModifyTakeProfit && OrderTakeProfit() > 0)
      {
         double diff = newPrice - OrderOpenPrice(); // diff is negative here
         newTP = NormalizeDouble(OrderTakeProfit() + diff, Digits);
      }

      // Modify the order
      if(!OrderModify(OrderTicket(), newPrice, newSL, newTP, OrderExpiration(), clrRed))
      {
         Print("Error modifying Sell Limit: ", GetLastError());
      }
   }
}
//+------------------------------------------------------------------+

Key Components of the Code

  1. TrailDistancePips: This input determines the gap you want to maintain. For example, if set to 20 pips, the Buy Limit will always try to stay 20 pips below the current Ask price as the price rises.
  2. ProcessBuyLimit:
    • It calculates targetPrice = Ask - Distance.
    • It checks if (targetPrice > OrderOpenPrice()). This ensures we only move the order up (following the market away). We do not move it down if the market comes closer to the order (that would prevent the order from ever filling).
  3. ProcessSellLimit:
    • It calculates targetPrice = Bid + Distance.
    • It checks if (targetPrice < OrderOpenPrice()). This ensures we only move the order down as the market drops away.
  4. SL/TP Adjustment: The code calculates the difference between the old open price and the new open price, then applies that difference to the Stop Loss and Take Profit. This ensures your risk/reward ratio remains exactly the same as the order moves.
  5. Normalization: NormalizeDouble(..., Digits) is crucial. Without it, OrderModify will fail with Error 129 (Invalid Price) because calculated doubles often have invisible trailing decimals (e.g., 1.12345000001).

Q&A: Modifying Pending Orders

Q: Why does OrderModify return Error 130 (Invalid Stops) when moving a pending order?
A: This usually happens if you move the entry price too close to the current market price, violating the broker's MODE_STOPLEVEL (Freeze Level). The code provided includes a check for stopLevel to prevent this. It can also happen if you move the entry price but fail to move the SL/TP, causing the SL/TP to end up on the "wrong side" of the current market price relative to the new entry.

Q: Can I use this logic for Stop Orders (Buy Stop / Sell Stop)?
A: Yes, but the logic must be inverted. For a Buy Stop (which is above price), if the price moves down (away), you would calculate Ask + Distance and move the Buy Stop down. The provided code is specifically for Limit orders.

Q: Does this code work on 5-digit brokers?
A: Yes. The OnInit function detects 3 or 5 digit brokers and adjusts the m_point multiplier automatically so that TrailDistancePips represents standard pips (e.g., 0.0001) rather than points (0.00001).