How to Close Orders with MQL4 Code

In previous articles we saw how to open new market orders and how to scan the account for open orders, to close the cycle we also need to learn how to close orders with the function OrderClose() . At this point the order could be a winner, loser or breakeven but we only want to see how to close the order using MQL4 code. OrderClose()  is the MQL4 function that allows you to close open market orders entirely or partially. This function requires a few parameters, we can see them in the following specification. The parameters expected are (bold the required):
  • ticket to specify the ticket number, to identify which order to close
  • lots is the size in lots to close, example if order 1234 is a BUY order or 1 lot of EURUSD you can close the entire position specifying 1 lot or only close it partially, for example 0.6 lots, the remaining 0.4 will remain open
  • price is the close price, must be the current price or very close to it
  • slippage is the allowed difference between the requested close price and the one actually on the broker’s side
  • arrow_color is the color of the arrow in the chart
We can apply what we learned in how to Open Orders and Scan open Orders to close orders, usually orders are closed manually or during the process of Order Management of an EA. In our example we will scan for order and close all of them, with some more advanced coding you will be able to become more selective and choose what orders to close but for the moment we will keep it simple. Most of the information necessary to close an order can be retrieved easily selecting the order, this is why the scan of the orders is so useful. When you use the OrderSelect()  function many details about the order can be retrieved with native MQL4 functions, in particular:
  • OrderTicket()  returns the ticket number of the order
  • OrderLots()  returns the position size of the order
The above are the strictly necessary however there are more functions to retrieve even more details about an order, we will see them in some other article. The function CloseOrder()  is of type boolean and returns true if the order is successfully closed, false if the order is not closed for some error. We can see an example of script that closes all the open market orders If we run the script in any chart it will close all the orders, not limited to the currency pair in the chart metaeditor-mql4-closeorder-1 metaeditor-mql4-closeorder-2 Applying more filters we could restrict the selection of the orders and close only specific ones. With this article you learned how to close an order with MQL4 language, do some experiment and test it yourself. I remember when I first started to learn MQL coding, although I had some knowledge of coding many concept were still unclear. To speed up your learning process I would recommend to follow a quick MQL course that will give you the fundamentals you need to create functional Trading Robot. You can check out the following two course, Udemy often has sales on to make the courses even more affordable, and if you subscribe to my newsletter (top and bottom of the page) I will let you know when this happens.

MQL4 Programming for Traders: Build Robust Trading Robots!

Black Algo Trading: Build Your Trading Robot

Please leave a comment if you have any feedback or doubt and remember to like us on Social Media!

If you want to save hours of research and coding and you want to see some professional code check this out! You can use it to build your own EA!

12 thoughts on “How to Close Orders with MQL4 Code”

  1. Hello i’m new on MT4 EA.
    I would like to ask some question about OrderClose.

    Is it possible to close a position at price i want?
    Eg: (OrderClose( ticket, lot, priceIwant, 10 )?

    If yes, please what is the syntax, i’m trying and look many examples on internet, Everybody uses Bid Or Ask.

    • Hi Franck,
      Sorry I am not sure I understand well the question.
      OrderClose() is a function that closes the order immediately using the market price, which is either Ask or Bid.
      If you want to set a price of closure you can use the function OrderModify() where you can set a stop loss and take profit price.

      Is this what you were looking for?

      Luca

  2. Good afternoon….
    I have an EA, simple crossing of moving averages, which buys when it crosses for up.
    Sells when it crosses for down, respectively.
    When the EMA crosses for up and it buys, I would like this order to be closed when the moviment inverted down and the robot sold.
    Like, one closes when the other one opens.
    It’s possible?

    Below, my EA.

    ===================================

    extern int TakeProfit = 50;
    extern int StopLoss = 25;
    extern int MediaRapida = 3;
    extern int MediaLenta = 21;
    extern double Lote = 0.10;
    extern int MagicNumber = 1234;
    double pips;

    //+——————————————————————+
    //| Expert initialization function |
    //+——————————————————————+
    int init()
    {
    double ticksize = MarketInfo(Symbol(),MODE_TICKSIZE);
    if (ticksize == 0.00001 || ticksize == 0.001)
    pips = ticksize*10;
    else pips = ticksize;

    return(0);
    }

    //+——————————————————————+
    //| Expert deinitialization function |
    //+——————————————————————+
    int deinit()
    {
    return(0);
    }
    //+——————————————————————+
    //| Expert start function |

    //+——————————————————————+

    int start()
    {
    int ticket;

    double RapidaAtual = iMA(NULL, 0, MediaRapida,0,MODE_EMA,PRICE_CLOSE,0);
    double LentaAtual = iMA(NULL, 0, MediaLenta,0,MODE_EMA, PRICE_CLOSE,0);

    //—-
    //Order buy
    //—-
    if (RapidaAtual > LentaAtual && Open[1] > LentaAtual)
    if (OrdersTotal()==0){
    ticket = OrderSend(Symbol(),OP_BUY,Lote,Ask,3,Ask-(StopLoss*pips),Ask+(TakeProfit*pips),NULL,MagicNumber,0,Lime);

    }
    //—-
    //Order sell
    //—-

    if (RapidaAtual > LentaAtual && Close[1] < LentaAtual)
    if (OrdersTotal()==1){
    ticket = OrderSend(Symbol(),OP_SELL,Lote,Bid,3,Bid+(StopLoss*pips),Bid-(TakeProfit*pips),NULL,MagicNumber,0,Red);
    }

    return(0);
    }

    • Hi Leonardo,
      It is surely possible to do what you want.
      In the code you attached I believe there is an issue with if (OrdersTotal()==1){ first, that says to your expert to sell only if there is 1 open order already.
      The suggestion that I can give you is:
      1) Build a function that returns the number of open orders for the current currency, this will allow you to apply the experts to different symbols concurrently
      2) Build a order management function that checks if there is an open order and, in case, it checks if the requirement to stay open is still valid, if the MA crossed in the opposite direction, close the order

      It’s not hard at all to do but you will need several more lines of code to do it.
      I hope this helps.
      Let me know if it doesn’t make sense

      Luca

    • Hello,

      Most of the code in the article can be reused for your purpose, you will just need a condition to trigger it.
      I wouldn’t use a specific price but rather a comparison if price is above or below depending on what you need to do.
      something like this, assuming you are in a EURUSD chart
      if(close[0]>=1.32565) CloseOpenOrders()
      or
      if(close[0]< =1.32565) CloseOpenOrders()

      This is very simple and I use parameters instead of hard coding the price
      Let me know if it helps
      Luca

  3. Hi Luca,
    Thanks a lot for sharing your knowledge with us.
    I have been trying to create the code to close the trade if the trend changes. ie: Conditional close.
    In a sell trade – if(close_1>close_2 && close_1>close_3 && Ask==High_1+30*Point) and in a buy trade – if(close_1<close_2 && close_1<close_3 && Bid==High_1-30*Point)
    They do not seem to be doing the job.
    Could you kindly enlighten me as to where I have gone wrong.
    Kind Regards.

    • Hi Billy,
      Thanks for the comment and feedback.

      Probably the first thing I would try is changing
      Ask==High_1+30*Point with Ask>=High_1+30*Point
      Bid==High_1-30*Point with Bid<=Low_1-30*Point But I can only assume what you are meaning with High_1 and Close_x... I guess you are trying to test if the price is going above or below the values in the last three candles, depending if buy or sell Luca

  4. Hi Luca, Thanks for your response. A few minutes ago I sent you a message with the wrong code. This is my EA code for closing orders. Kindly let me know where I have gone wrong. Kind Regards. Billy.
    //+——————————————————————+
    //| Check for close order conditions |
    //+——————————————————————+
    void CheckForClose()
    {
    //—-
    int cnt, ticket, total;
    // Get the current total orders
    total = OrdersTotal();

    // Manage open orders for exit criteria
    for(cnt = 0; cnt < total; cnt++)
    {
    OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
    if(OrderType() <= OP_SELL && OrderSymbol() == Symbol())
    {
    if(OrderType()==OP_BUY)// Look for long positions
    {
    if(Close30M_1<Low30M_2 && Close30M_1<Low30M_3 && BidHigh30M_2 && Close30M_1>High30M_3 && Ask>=High30M_1+30*Point)// Check for Exit criteria on sell – change of direction
    {
    OrderClose(OrderTicket(), OrderLots(), Ask, 3, Violet); // Close the position
    return(0);
    }
    }
    }
    }
    }

    • Hi Billy,
      Can definitely suggest some adjustments:

      1. The for loop should go backwards from last to 0 as I do in my code, this is because if you start from 0 and you close an order the array changes and the for loop skips orders
      2. Use “if(OrderSymbol() != Symbol()) continue;” if you only want to apply the rule to the current instrument on chart, if the instrument of the trade is not the same as the chart the code skips to the next order
      3. What is this “if(OrderType() < = OP_SELL && OrderSymbol() == Symbol())" ? use "if(OrderType() == OP_SELL)" to apply the rule only to SELL order, OP_BUY for buy orders
      4. You are not comparing BidHigh30M_2 to anything so that’s going to be always false and exit the if
      5. You are using both the exit for the buy and for the sell in the same if, you need to separate them

      A few things to fix but that would be a start.
      Let me know if anything unclear

      Luca

  5. Hello Luca Spinello.
    Good Day,

    I am trying to convert a custom indicator to an EA.
    the logic is when green arrow appears on chart it will place buy order and when red arrow appears on chart it will place sell order. Here are the codes but its not working at all. can you help me to fix it.

    #property copyright “Copyright 2019, MetaQuotes Software Corp.”
    #property link “https://www.mql4.com”
    #property version “1.00”
    #property strict

    extern int TakeProfit=50;
    extern int StopLoss=15;
    extern double LotSize = 0.01;

    // custom indicator input

    extern int FasterMovingAverage = 5;
    extern int SlowerMovingAverage = 12;
    extern int RSIPeriod = 12;
    extern int MagicFilterPeriod = 1;
    extern int BollingerbandsPeriod = 10;
    extern int BollingerbandsShift = 0;
    extern double BollingerbandsDeviation = 0.5;
    extern int BullsPowerPeriod = 50;
    extern int BearsPowerPeriod = 50;
    extern bool Alerts = TRUE;
    extern int Utstup = 10;

    extern int MagicNumber=1234;
    int MaxTrade=5;
    double pips;

    //+——————————————————————+
    //| Expert initialization function |
    //+——————————————————————+
    int OnInit()
    {
    double ticksize = MarketInfo(Symbol(), MODE_TICKSIZE);
    if (ticksize == 0.00001 || ticksize == 0.001)
    pips = ticksize*10;
    else pips =ticksize;
    return(0);
    }
    //+——————————————————————+
    //| Expert deinitialization function |
    //+——————————————————————+
    void OnDeinit(const int reason)
    {
    //—

    }
    //+——————————————————————+
    //| Expert tick function |
    //+——————————————————————+
    void OnTick()
    {
    if(IsNewCandle()) CheckForSignal();
    }

    void CheckForSignal()
    {
    //Did it make a up arrow on candle 1?
    double UpArrow=iCustom(NULL,0,”super-arrow-indicator”,0,1); // o for green color
    Print(“Up arrow value “,UpArrow);
    if(UpArrow!=EMPTY_VALUE)OrderEntry(0);

    //Did it make a down arrow on candle 1?
    double DownArrow=iCustom(NULL,0,”super-arrow-indicator”,1,1); // 1 for red color
    Print(“Down arrow value “,DownArrow);
    if(DownArrow!=EMPTY_VALUE)OrderEntry(1);
    }

    //+——————————————————————+
    //Call for order.
    //+——————————————————————+

    void OrderEntry(int direction)
    {
    double tp=0,sl=0;
    int buyticket=0,sellticket=0;
    if(direction==0)
    {
    tp=Ask+TakeProfit*pips;
    sl=Ask-StopLoss*pips;
    if(OpenOrdersThisPair(Symbol())0)
    if(OrderModify(buyticket,OrderOpenPrice(),sl,tp,0,CLR_NONE))
    Print(“Order “,buyticket,” was successfully modified.”);
    else Print(“Order “,buyticket,” was successfully modified.”,GetLastError());
    }

    if(direction==1)
    {
    tp=Bid-TakeProfit*pips;
    sl=Bid+StopLoss*pips;
    if(OpenOrdersThisPair(Symbol())0)
    if(OrderModify(sellticket,OrderOpenPrice(),sl,tp,0,CLR_NONE))
    Print(“Order “,sellticket,” was successfully modified.”);
    else Print(“Order “,sellticket,” was successfully modified.”,GetLastError());
    }

    }

    //+——————————————————————+
    //checks to see if any orders open on this currency pair.
    //+——————————————————————+
    int OpenOrdersThisPair(string pair)
    {
    int total=0;
    for(int i=OrdersTotal()-1; i>0; total–)
    {
    if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
    if(OrderSymbol()== pair) total++;
    }
    return (total);
    }

    //+——————————————————————+
    //insuring its a new candle function
    //+——————————————————————+
    bool IsNewCandle()
    {
    static int BarsOnChart=0;
    if (Bars == BarsOnChart)
    return (false);
    BarsOnChart = Bars;
    return(true);
    }

    //+——————————————————————+

Leave a Comment