How to get Most recently Closed OrderClosePrice()?

 

Hello,

I am trying to get a last order close price (most recently closed order) based on filter Magic number and Order symbol.

Code :

double LastOrderClosePrice(int magic)
  {
   double LastOrderClosePrice_Price = 0; 
   for(int ClosePrice_i = 0; ClosePrice_i < OrdersHistoryTotal(); ClosePrice_i++)
     {
      OrderSelect(ClosePrice_i, SELECT_BY_POS, MODE_HISTORY);
      if(OrderSymbol() != Symbol() || OrderMagicNumber() != magic)
         continue;
      LastOrderClosePrice_Price = OrderClosePrice();
      //break; => Using break gives wrong value. Without break gives correct value
     }
   return LastOrderClosePrice_Price;
  }


My code is working fine as i want but the only problem is, if my account have 10,000+ Closed Order history, this will loop through all the 10,000 closed order and this will make EA slow. How to resolve this?


And one more confusion. Should i use for loop like this for(int ClosePrice_i = 0; ClosePrice_i < OrdersHistoryTotal(); ClosePrice_i++) or for(int ClosePrice_i = OrdersHistoryTotal() - 1; ClosePrice_i >= 0; ClosePrice_i--) ?

 
Cycle your history trades in the opposite way, and once you found a trade closed save information and break loop.

Of course there can be some problems in this approach, but consider to take some tests in this direction 

PS. It you use that LastOrderClosePrice multiple time into the same EA cycle, assign its value to a local variable and use that, instead of calling the calculations functions multiple time within same tick.
 
Fabio Cavalloni #:
Cycle your history trades in the opposite way, and once you found a trade closed save information and break loop.

Can you give me sample code. How to do this?

 

Change this

   for(int ClosePrice_i = 0; ClosePrice_i < OrdersHistoryTotal(); ClosePrice_i++)

to this

   for(int ClosePrice_i = OrdersHistoryTotal()-1; ClosePrice_i >=0; ClosePrice_i--)

And enable the break you commented on your code

 
  1. anuj71:I am trying to get a last order close price (most recently closed order) based on filter Magic number and Order symbol.My code is working fine as i want but the only problem is, if my account have

    MT4:

    1. Do not assume history has only closed orders. See № 4.
                OrderType() == 6, 7 in the history pool? - MQL4 programming forum #4 and #5 (2017)

    2. Do not assume history is ordered by date, it's not. See № 4.
                Could EA Really Live By Order_History Alone? (ubzen) - MQL4 programming forum (2012)
                Taking the last profit and storing it in a variable | MQL4 - MQL4 programming forum #3 (2020)

    3. Total Profit is OrderProfit() + OrderSwap() + OrderCommission(). Some brokers don't use the Commission/Swap fields. Instead, they add balance entries. (Maybe related to Government required accounting/tax laws.)
                "balance" orders in account history - Day Trading Techniques - MQL4 programming forum (2017)

      Broker History
      FXCM
      Commission - «TICKET»
      Rollover - «TICKET»

      >R/O - 1,000 EUR/USD @0.52

      #«ticket»  N/A
      OANDA
      Balance update
      Financing (Swap: One entry for all open orders.)

  2. anuj71:10,000+ Closed Order history, this will loop through all the 10,000 closed order and this will make EA slow. How to resolve this?

    Stop looping. Remember the last count and datetime. Only loop if the first has changed.

  3. anuj71:

    And one more confusion. Should i use for loop like this for(int ClosePrice_i = 0; ClosePrice_i < OrdersHistoryTotal(); ClosePrice_i++) or for(int ClosePrice_i = OrdersHistoryTotal() - 1; ClosePrice_i >= 0; ClosePrice_i--) ?

    Use meaningful variable names. OrdersHistoryTotal has nothing to do with prices.

  4.       if(OrderSymbol() != Symbol() || OrderMagicNumber() != magic)
    

    Always check the select. String comparison is the slowest opperation, always last. Find the latest. Order tests by frequency.

    int      lastHistoryCount    = EMPTY;
    double   lastOrderClosePrice = EMPTY;
    datetime lastOrderCloseTime  = 0;
    void update_last_order(int magic){
       int iPos = OrdersHistoryTotal(); if( iPos == lastHistoryCount) return; // No changes.
       lastHistoryCount = iPos;
       while(iPos > 0) if(
          OrderSelect(--iPos, SELECT_BY_POS, MODE_HISTORY)
       && OrderCloseTime()   >  lastOrderCloseTime
       && OrderMagicNumber() != magic
       &&(Ordertype() == OP_BUY || OrderType() == OP_SELL)
       && OrderSymbol()      != Symbol() 
       ){
          lastOrderClosePrice = OrderClosePrice();
          lastOrderCloseTime  = OrderCloseTime();
       }
    }
 
Fabio Cavalloni #:

Change this

to this

And enable the break you commented on your code

Second forloop won't take more time than first forloop?


William Roeder #:
  1. MT4:

    1. Do not assume history has only closed orders. See № 4.
                OrderType() == 6, 7 in the history pool? - MQL4 programming forum #4 and #5 (2017)

    2. Do not assume history is ordered by date, it's not. See № 4.
                Could EA Really Live By Order_History Alone? (ubzen) - MQL4 programming forum (2012)
                Taking the last profit and storing it in a variable | MQL4 - MQL4 programming forum #3 (2020)

    3. Total Profit is OrderProfit() + OrderSwap() + OrderCommission(). Some brokers don't use the Commission/Swap fields. Instead, they add balance entries. (Maybe related to Government required accounting/tax laws.)
                "balance" orders in account history - Day Trading Techniques - MQL4 programming forum (2017)

      Broker History
      FXCM
      Commission - «TICKET»
      Rollover - «TICKET»

      >R/O - 1,000 EUR/USD @0.52

      #«ticket»  N/A
      OANDA
      Balance update
      Financing (Swap: One entry for all open orders.)

  2. Stop looping. Remember the last count and datetime. Only loop if the first has changed.

  3. Use meaningful variable names. OrdersHistoryTotal has nothing to do with prices.

  4. Always check the select. String comparison is the slowest opperation, always last. Find the latest. Order tests by frequency.


Thanks for the code. You bymistake added != instead for == for OrderSymbol() and OrderMagicNumber()


Changed Code to double to return value (Is this correct?) :


double update_last_order(int magic)
{
   int      lastHistoryCount    = EMPTY;
   datetime lastOrderCloseTime  = 0;
   double   lastOrderClosePrice = EMPTY; 
   int iPos = OrdersHistoryTotal();
   if(iPos == lastHistoryCount)
      return lastOrderClosePrice; // Return the default value if there are no changes.
   lastHistoryCount = iPos;
   while(iPos > 0)
      if(
         OrderSelect(--iPos, SELECT_BY_POS, MODE_HISTORY)
         && OrderCloseTime()   >  lastOrderCloseTime
         && OrderMagicNumber() == magic
         && (OrderType() == OP_BUY || OrderType() == OP_SELL)
         && OrderSymbol() == Symbol()
      )
      {
         lastOrderClosePrice = OrderClosePrice();
         lastOrderCloseTime  = OrderCloseTime();
      }
   return lastOrderClosePrice; // Return the lastOrderClosePrice
}
 
anuj71 #:

Second forloop won't take more time than first forloop?



Thanks for the code. You bymistake added != instead for == for OrderSymbol() and OrderMagicNumber()


Changed Code to double to return value (Is this correct?) :


Why you changed its code? These should remain global variable OUTSIDE of the function.

   int      lastHistoryCount    = EMPTY;
   datetime lastOrderCloseTime  = 0;
   double   lastOrderClosePrice = EMPTY; 

Then, the function don't need to be (double) because it just calculate (when needed) and update global variables.

  • Put the "update_last_order" into the beginning of OnTick function.
  • Access the variable named lastOrderClosePrice for retreiving your desired information


Basically, fix typo error (!=) instead of (==) and you don't need to change anything else of his code.

 
Fabio Cavalloni #:
Why you changed its code? These should remain global variable OUTSIDE of the function.
Because i want Last OrderClosedPrice for 2 different magic number. In this case, i have to create 2 void function.
 
anuj71 #: Because i want Last OrderClosedPrice for 2 different magic number. In this case, i have to create 2 void function.

Irrelevant. You need the count and time remembered (global or static), so you don't have to process all of history each call.

 
anuj71 #:
Because i want Last OrderClosedPrice for 2 different magic number. In this case, i have to create 2 void function.

Bad idea to create 2 void functions, you will cycle all orders 2 times for no reasons.

Do a single function and inside the while/for cycle assign variables depending on the magic number of the order.

 
anuj71:

Hello,

I am trying to get a last order close price (most recently closed order) based on filter Magic number and Order symbol.

Code :


My code is working fine as i want but the only problem is, if my account have 10,000+ Closed Order history, this will loop through all the 10,000 closed order and this will make EA slow. How to resolve this?


And one more confusion. Should i use for loop like this for(int ClosePrice_i = 0; ClosePrice_i < OrdersHistoryTotal(); ClosePrice_i++) or for(int ClosePrice_i = OrdersHistoryTotal() - 1; ClosePrice_i >= 0; ClosePrice_i--) ?

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
{
    // Define filter parameters here
    int magicNumber = 123456; // Change this to your own magic number
    string symbolName = "EURUSD"; // Change this to your symbol name

    // Get total number of closed orders
    int totalOrders = OrdersHistoryTotal();

    // Iterate through closed orders to find the most recent one that matches the filter
    double lastClosePrice = 0.0;
    for (int i = totalOrders - 1; i >= 0; i--)
    {
        if (!OrderSelect(i, SELECT_BY_POS, MODE_HISTORY))
        {
            Print("Error selecting order: ", GetLastError());
            continue;
        }

        // Check if the order matches the filter criteria
        if (OrderMagicNumber() == magicNumber && OrderSymbol() == symbolName && OrderType() == OP_BUY || OrderType() == OP_SELL)
        {
            // Retrieve close price of the order
            lastClosePrice = OrderClosePrice();
            break; // Exit the loop after finding the most recent order
        }
    }

    // Display the last close price
    Print("Last closed order close price: ", lastClosePrice);
}

This will give you an idea of how it works

Reason: