Closing all open trades automatically results in losing price value even when the difference is positive profits

 

Hi guys,


A noob programmer here in MQL4, though I have successfully made a few EAs and indicators.


I have somewhat of a dilemma and some of you might find it of interest, and most likely have encountered this as well, though I trried to find a similar topic and can't find anything close to it.


Description:

I made an EA that basically does the following -

1 - Search a viable Entry through EA crossovers (or whatever strategy you might find feasible and gives better probability) and create one once found,

2 - Monitor existing trade/s - just leave it to run until it reach your desired TP; trail stop it once it goes into positive profits - with that approach you'll earn either way,

3 - Run a hedge detection routine - if it went on the opposite direction of your trade, hedge it at a specified distance of your preference and increase lot size a step above the previous entry, that way whichever direction it breaks out, you still win

4 - As per above, once it breaks out, compute all running trades, considering the lot size in the equation as well to compute the actual amount; if it is still in the negative, leave it as is, otherwise depending on the desired level of positive difference you set, close all orders since it's already on the positive (that is, difference of all trades results in winning profit)


I've successfully done all three with no hitches - obviously my problem is the last step - it WON'T allow me to close it at a profit. My method is to convert the pip value to dollars (this EA is being tested on EUR/USD) and once the difference is extracted from all trades and converted it to dollars as well, I do an IF comparison of the resulting amount against a reference point, say, let's call it Profit Amount Reference (PAR). If I set my PAR at $10, once the difference of the trade reaches or exceeds PAR, then it will close all open trades, resulting in a gain of $10, or whatever reference you set the PAR with.However, it doesn't work as expected, Regardless what value I set my PAR to, it always ends up my trade losing a certain amount of $, though individual normal trades closed either by TP or SL is just fine or if a trade running alone is closed automatically by my PAR reference. The problem is *only* when there are several open trades simultaneously closed altogether. My conversion of the pip value to $ is very simple, e.g., a price point of .00888 is multiplied by 10000 resulting in $88.8. Take note that I strictly only run my EA on EUR/USD and no other pairs (for now).  Manually I can close it myself to get my profits, but I want it automated.

Here's the exact code  on the last part. I will not include the first three steps as I said, they are working perfectly, and my program are all modularised that I can easily change each module for improvements when needed without touching the others. It's only when I get to the last part that I get stumped. Let's call the last part's module CloseAllTrades function.


//We create a function to close all trades for this pair
// ======================================================================================= 
// ======================================================================================= 
// ======================================================================================= 
// ======================================================================================= 
// ======================================================================================= 
// ======================================================================================= 
double CloseAllTrades()
{
   //Go through all open orders
   Print(">>>>>>>>>>>>>>>>>>>>>>>>Inside CloseAllTrades function<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
   int TotalRunningTrades = OrdersTotal();
   int BuyOrSell = OrderType();
   bool r = false;
   
   for (int i=TotalRunningTrades-1;  i >= 0; i--)
   {
      //Select each trade to close
      if (OrderSelect(i,SELECT_BY_POS) == true)
      {
         if (OrderSymbol() == Symbol())
         {
            if(BuyOrSell == 0) //It's a BUY
            {  //Close the trade orders
               //               ticket        lot volume          close price                 slippage   arrow color
               r = OrderClose(OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), MODE_ASK),   15,     clrAliceBlue);
            }
            if(BuyOrSell == 1) //It's a SELL
            {  //Close the trade orders
               //               ticket        lot volume          close price                 slippage   arrow color
               r = OrderClose(OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), MODE_BID),   15,     clrAliceBlue);
            }
            Print(r);
         }
      }  
   } // End of for (int i=TotalRunningTrades-1; Loop
   return(r);
}   //End of CloseAllTrades() function


After I've done all the three steps, that function is the last one to be called to close the trade orders,  They close normally with no errors (not even a 130), but it will always close on a negative result, reducing my account balance.


See attached for example results from my demo test. If you have additional questions, or items that you need to know, let me know. Thanks in advance everyone.

Documentation on MQL5: Constants, Enumerations and Structures / Environment State / Account Properties
Documentation on MQL5: Constants, Enumerations and Structures / Environment State / Account Properties
  • www.mql5.com
, then each symbol positions will be closed in the same order, in which they are opened, starting with the oldest one. In case of an attempt to close positions in a different order, the trader will receive an appropriate error. There are several types of accounts that can be opened on a trade server. The type of account on which an...
Files:
new_problem.png  81 kb
 
Close buys with bid, and close sells with ask. 
 
tompips2018:- obviously my problem is the last step - it WON'T allow me to close it at a profit................................................................

After I've done all the three steps, that function is the last one to be called to close the trade orders,  They close normally with no errors (not even a 130), but it will always close on a negative result, reducing my account balance.

First of all, your function is not the reason for the trades closing at a loss. The reason is whatever logic you use to call the function.

They close normally with no errors

I don't believe that, if they close normally that is more luck than judgement.

int BuyOrSell = OrderType();

BuyOrSell is assigned a random value depending on whatever order was selected last. It makes absolutely no sense to have it outside of the loop as it will hold the same value throughout the execution of the function.

Why do you even need it? You don't if the intention is to close all trades. It doesn't matter if the trade is a buy or a sell, just close it at OrderClosePrice().

Why do you use the variable "r"? Is it just to stop the compiler from telling you that the return value should be checked? When the OrderClose() fails you should print the reasons to the log.

 
Keith Watford:

First of all, your function is not the reason for the trades closing at a loss. The reason is whatever logic you use to call the function.

I don't believe that, if they close normally that is more luck than judgement.

BuyOrSell is assigned a random value depending on whatever order was selected last. It makes absolutely no sense to have it outside of the loop as it will hold the same value throughout the execution of the function.

Why do you even need it? You don't if the intention is to close all trades. It doesn't matter if the trade is a buy or a sell, just close it at OrderClosePrice().

Why do you use the variable "r"? Is it just to stop the compiler from telling you that the return value should be checked? When the OrderClose() fails you should print the reasons to the log.

"First of all, your function is not the reason for the trades closing at a loss. The reason is whatever logic you use to call the function."

The logic is very simple too really. It's just..... calling it. :-)

         Grand_Total = ComputeTrades(); //The function ComputeTrades throws a double value and pass it to the global Grand_Total
         Print("Grand_Total = $ ",Grand_Total);//Just to make sure I got the value right, and I have confirmed it during run time it's getting the right value
         Print("PriceReferenceToCloseAllTrades = $ ",PriceReferenceToCloseAllTrades); // <-- This is an extern variable set currently at 10.00.
         
         if(Grand_Total >= PriceReferenceToCloseAllTrades) // Is Grand_Total equal or greater than the reference currently set at 10.00?
         {
            Print(">>>>>>>>>>>>>>>>>>>>>>>>Going Inside CloseAllTrades function<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
            Print("Return Value = ",ComputeTrades());
            Print("Grand_Total = ",Grand_Total);
            Print("Yes, ",Grand_Total," is greater or equal than ",PriceReferenceToCloseAllTrades);
           
            CloseAllTrades(); // <---- if YES, call this guy here
         
         }

Only that function above give me that loss when I close them all. As mentioned the other methods (Normal hitting of TP/SL, only one trade running getting closed by the above function, etc.) are fine. So the logic of my previous modules/steps have no problem at all. Only on that one above.


"I don't believe that, if they close normally that is more luck than judgement."

I'm not out here to convince anybody/anyone, and I can't blame you either, I am not convinced myself :D :D :D. Before I got that luck I went through a lot of erroneous judgment ;-). But I'm still not convinced because of what I encountered. I'm currently looking at other angles (high slippage, because 15 is the only value that won't give me an Error 138 at runtime, the ComputeTrades() function takes time to calculate the Grand_Total that by the time it finishes its job, the real-time data of the running price action to close it has already moved on several paces, etc.).


The logs are not giving a good job at catching all the messages so I'll just send the screenshot of the results of the output, however, it just shows the point where it close with the Grand Total at negative (summing them up results in -66.89, which corresponds to the remaining total of 9933.11 you are seeing on my previous screenshot), during run time I am pausing it at a point where it satisfies the If condition, it did several times, but I was wondering why it doesn't seem to exit out at the value that I want them to exit. If you want to see the logs of what I'm saying, just let me know and I'll screenshot them for your convenience.


"BuyOrSell is assigned a random value depending on whatever order was selected last. It makes absolutely no sense to have it outside of the loop as it will hold the same value throughout the execution of the function."


I checked on the steps to see if it indeed gets a random value (that is, it occasionally gets a 0(buy) or a 1(sell) at any point in time) but several runs made consistently shows  all the same results and they are saved correctly on the array, I even assigned it initially a 1 (subsequently a 0 and re-test it) but result is still the same nonetheless, but I'm digressing now. I know they are getting the data as expected. It's just that the time it goes inside the last module and closing the trades gives a different result. Somehow it seems my first hypothesis of a possible outdated data could be the culprit, but I'm not sure how to make my program run faster than the changes the price action makes.


"Why do you even need it? You don't if the intention is to close all trades. It doesn't matter if the trade is a buy or a sell, just close it at OrderClosePrice()."

The reason, is the difference of the Ask and Bid price at closing.

               //               ticket        lot volume          close price                 slippage   arrow color
               r = OrderClose(OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), MODE_ASK),   15,     clrAliceBlue);
            }
            if(BuyOrSell == 1) //It's a SELL
            {  //Close the trade orders
               //               ticket        lot volume          close price                 slippage   arrow color
               r = OrderClose(OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), MODE_BID),   15,     clrAliceBlue);

I want to make sure it closes at the correct symbol for the last Market Info it's showing (MODE_ASK or MODE_BID). Initially, when I noticed it and I thought about it I made a variable getting the average of the two, but it seems it's an incorrect way of getting a result since the actual output the program will give obviously will not reflect the actual price when it closes.


Why do you use the variable "r"? Is it just to stop the compiler from telling you that the return value should be checked? When the OrderClose() fails you should print the reasons to the log.


I guess the force of habit made me do so. Yes, I am annoyed by the warning sign that appears and I'm a bit OC when it comes to errors or warning messages that I know could be preventable.  As you can see from the program, it throws back the value of 'r' if the action is a true or false, just for checking on my end, so that 'r' has indeed a purpose for me; but I will revise and made another snippet of a function to close it without that IF decision if it's a Buy or a Sell. I'm collating all suggestions given right now including the one given by the other guy above (though logically it runs contrary opposite to what I've learned to associate Buy with Ask and Bid with Sell). 


Thanks for your output. Any further suggestions are appreciated. :-)

 
Seng Joo Thio:
Close buys with bid, and close sells with ask. 

Just done it, but gets the same result, so I guess we can rule out that one too. Thanks for your suggestions though, one less possible cause to zero out from my list. 

 
tompips2018:

Just done it, but gets the same result, so I guess we can rule out that one too. Thanks for your suggestions though, one less possible cause to zero out from my list. 

What about swap/commission? You need to add them when computing your potential profits. 
 

tompips2018:

"Why do you even need it? You don't if the intention is to close all trades. It doesn't matter if the trade is a buy or a sell, just close it at OrderClosePrice()."

The reason, is the difference of the Ask and Bid price at closing. 

You're not listening.

You do not need to know whether it is a buy or a sell. You don't need to know what the current Ask or Bid is.

When you have selected an order and are going to close it immediately just close it at OrderClosePrice().

 
Keith Watford:

You're not listening.

You do not need to know whether it is a buy or a sell. You don't need to know what the current Ask or Bid is.

When you have selected an order and are going to close it immediately just close it at OrderClosePrice().

With all due respect, you're not listening either.

The exact amount of OrderClosePrice()  could spell a difference between my computed close price and the actual one done by FOREX because of the gap between the two. Hence, I have inserted those small details to make sure it's not it, and have confirmed it's not the cause. But it's not the gist of my current challenge right now regardless I follow your advice or not - besides, OrderClosePrice() can only be taken if the trade has been closed already, and the trade order amount I am checking is still running. I confirmed the amount would be minute enough to affect the profit, but the $68 difference  could definitely be caused by something else that would eat a significant chunk of it. BTW, I've inserted the "if(BuyOrSell == 1)" within the loop - same result, FYI. So that's one out of my checklist as well. Nevertheless, thanks for your feedback. ;-)

 
Seng Joo Thio:
What about swap/commission? You need to add them when computing your potential profits. 

Yes! You're right! I've been thinking about it too, and yes, the negative amount of the swap would definitely be a factor considering the increased amount of lots would correlate to a bigger swap. But how can I add it to the program? Is there a way for me to know the swap/commission figures to incorporate to the EA's computation?

I'm inserting a screenshot of my runtime. That's at the moment before it hit's the reference of $10.00 (the one currently set on my extern variable right now) where it should close at that particular amount. Yes, now I suspect the swap amount could be the culprit, and I need to add it to the EA. Appreciate any suggestions.

Thanks for the feedback. :-D

Files:
 
tompips2018:

With all due respect, you're not listening either.

Whether I like it or not the exact amount of OrderClosePrice()  could spell a difference between my computed close price and the actual one done by FOREX because of the gap between the two. Hence, I have inserted those small details to make sure it's not it, and have confirmed it's not the cause. But it's not the gist of my current challenge right now regardless I follow your advice or not because the amount would be minute enough to affect the profit, but the $68 difference  could definitely be caused by something else that would eat a significant chunk of it. BTW, I've inserted the "if(BuyOrSell == 1)" within the loop - same result, FYI. So that's one out of my checklist as well. Nevertheless, thanks for your feedback. ;-)

I am listening but you are making no sense at all.

I am trying to help you write better code.

Your code

// ======================================================================================= 
double CloseAllTrades()
{
   //Go through all open orders
   Print(">>>>>>>>>>>>>>>>>>>>>>>>Inside CloseAllTrades function<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
   int TotalRunningTrades = OrdersTotal();
   int BuyOrSell = OrderType();
   bool r = false;
   
   for (int i=TotalRunningTrades-1;  i >= 0; i--)
   {
      //Select each trade to close
      if (OrderSelect(i,SELECT_BY_POS) == true)
      {
         if (OrderSymbol() == Symbol())
         {
            if(BuyOrSell == 0) //It's a BUY
            {  //Close the trade orders
               //               ticket        lot volume          close price                 slippage   arrow color
               r = OrderClose(OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), MODE_ASK),   15,     clrAliceBlue);
            }
            if(BuyOrSell == 1) //It's a SELL
            {  //Close the trade orders
               //               ticket        lot volume          close price                 slippage   arrow color
               r = OrderClose(OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), MODE_BID),   15,     clrAliceBlue);
            }
            Print(r);
         }
      }  
   } // End of for (int i=TotalRunningTrades-1; Loop
   return(r);
}   //End of CloseAllTrades() function

My suggestion (Assuming that you don't use pending orders)

//+------------------------------------------------------------------+
#include <stdlib.mqh>
//+------------------------------------------------------------------+
void CloseAll()
{
   for(int x=OrdersTotal()-1; x>=0; x--)
     {
      if(OrderSelect(x,SELECT_BY_POS) && OrderSymbol()==_Symbol)
        {
         if(!OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),15,clrNONE))
            Print(TimeCurrent()," Error with Closing Order #"+(string)OrderTicket()+ErrorDescription(GetLastError()));
        }
     }
}
//+------------------------------------------------------------------+

Can you not see how much simpler it is?

 
tompips2018:

Yes! You're right! I've been thinking about it too, and yes, the negative amount of the swap would definitely be a factor considering the increased amount of lots would correlate to a bigger swap. But how can I add it to the program? Is there a way for me to know the swap/commission figures to incorporate to the EA's computation? Thanks for the feedback. :-D

For every open order, when you sum up OrderProfit()+OrderSwap()+OrderCommission(), you will get very close to the resulting profit if you close the order there and then (negligible variation due to tick-wise fluctuation, if you have to call RefreshRates() in between).

Reason: