What it means
The server refused to modify an order or a position because the market is too close to it. Each symbol can have a freeze level: a distance from the current price inside which pending orders and the stops of open positions can't be changed.
Usual causes
- A trailing stop near the market. The position's current stop (or target) is within the freeze level of the price, so it can't be moved.
- A pending order about to trigger. Its price is within the freeze level of the market, so it can't be modified.
- No freeze check at all. The code checks the stops level but not
SYMBOL_TRADE_FREEZE_LEVEL.
The rules from MetaQuotes' checklist, with F the freeze distance (SYMBOL_TRADE_FREEZE_LEVEL × _Point):
| What you modify | Allowed only if |
|---|---|
| Buy position | TP − Bid ≥ F and Bid − SL ≥ F |
| Sell position | Ask − TP ≥ F and SL − Ask ≥ F |
| Buy limit | Ask − order price ≥ F |
| Buy stop | Order price − Ask ≥ F |
| Sell limit | Order price − Bid ≥ F |
| Sell stop | Bid − order price ≥ F |
A freeze level of 0 means no freeze zone.
How to detect it
trade.ResultRetcode()(orresult.retcode) is10029; the Experts tab shows the modify request followed by[frozen].- Read
SymbolInfoInteger(_Symbol, SYMBOL_TRADE_FREEZE_LEVEL)and log it with the Bid, Ask, stop and target when a modification fails.
Broken code
This EA compiles. When the Bid comes within the freeze level of the current stop or target, the modification fails with 10029.
#include <Trade/Trade.mqh>
input int InpTrailPoints = 100; // Trailing distance, points
CTrade trade;
void OnTick()
{
if(!PositionSelect(_Symbol) || PositionGetInteger(POSITION_TYPE) != POSITION_TYPE_BUY)
return;
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
double oldSl = PositionGetDouble(POSITION_SL);
double newSl = NormalizeDouble(bid - InpTrailPoints * _Point, _Digits);
// Checks that the stop improves, but not whether the position is frozen
if(newSl > oldSl)
trade.PositionModify(_Symbol, newSl, PositionGetDouble(POSITION_TP));
}Fixed code
The same program with the check that prevents the error. It compiles in MetaEditor with 0 errors and 0 warnings.
#include <Trade/Trade.mqh>
input int InpTrailPoints = 100; // Trailing distance, points
CTrade trade;
// True if a buy position's stop and target may be modified now (freeze level rules)
bool BuyStopsModifiable(const double sl, const double tp, const double bid)
{
double freeze = (double)SymbolInfoInteger(_Symbol, SYMBOL_TRADE_FREEZE_LEVEL) * _Point;
if(freeze <= 0.0)
return true;
if(sl != 0.0 && bid - sl < freeze)
return false;
if(tp != 0.0 && tp - bid < freeze)
return false;
return true;
}
void OnTick()
{
if(!PositionSelect(_Symbol) || PositionGetInteger(POSITION_TYPE) != POSITION_TYPE_BUY)
return;
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
double oldSl = PositionGetDouble(POSITION_SL);
double tp = PositionGetDouble(POSITION_TP);
double newSl = NormalizeDouble(bid - InpTrailPoints * _Point, _Digits);
double minDist = (double)SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL) * _Point;
if(newSl <= oldSl || bid - newSl < minDist)
return;
// Inside the freeze zone nothing can be changed: wait for the price to move away
if(!BuyStopsModifiable(oldSl, tp, bid))
return;
if(!trade.PositionModify(_Symbol, newSl, tp))
PrintFormat("Modify failed: retcode %u (%s)", trade.ResultRetcode(), trade.ResultRetcodeDescription());
}Why the fix works
Before sending, the EA applies the freeze rule for a buy position to the levels the position has now: when the Bid is within the freeze distance of the current stop or target, it waits for a later tick instead of sending a request the server will refuse. The new stop must also stay beyond the stops level, or the server answers with 10016. For sell positions, use the Ask and the mirrored conditions in the table.
Questions
What is the freeze level in MT5?
A distance in points, set by the broker per symbol (SYMBOL_TRADE_FREEZE_LEVEL), inside which pending orders and the stop-loss and take-profit of open positions can't be modified. 0 means there's no freeze zone.
What's the difference between the freeze level and the stops level?
The stops level is the minimum distance for new stops and pending orders. The freeze level forbids changing existing orders and stops that are already close to the price. A trailing stop has to respect both.
What was 10029 called in MT4?
MQL4's error 145, ERR_TRADE_MODIFY_DENIED: modification denied because the order is too close to the market.
The programs on this page are minimal examples written to show the error and its fix, not trading systems. Some of them send orders when they run: try them on a demo account. Trading involves substantial risk of loss and is not suitable for every investor. Edgoro is a software tool, not a broker or financial adviser: nothing it produces is investment advice, and past or backtested performance does not guarantee future results.