MQL Empty4 CODE FOR PROFIT CHECK BEFORE CLOSE

User avatar
keydcuk
Trader
Posts: 104
Joined: Tue Dec 04, 2012 8:01 pm

MQL Empty4 CODE FOR PROFIT CHECK BEFORE CLOSE

Post by keydcuk »

Dear Coders,

Although I am not a coder myself, I do know the basics of computer language and how formulae work.

I have been experimenting with an EA that I think does a wonderful job at what it does but closes some trades at a loss. Personally, I think this can be avoided but I don't know how to modify the code to do this.

Is there anybody out there that has a piece of code that I could use in the close conditions that would tell the EA: If the sum of orders about to close is < 0 DON'T CLOSE or only close if the sum of orders about to close > 0?

Many Thanks & Best Regards,

Daniel
Radar
Trader
Posts: 437
Joined: Fri Mar 23, 2012 5:39 pm
Location: Round the bend ;)

MQL Empty4 CODE FOR PROFIT CHECK BEFORE CLOSE

Post by Radar »

Hey Keydcuk,

Sounds like you're looking for Basket Management...

Check out Baluda's MPBM (Multi-Purpose Basket Manager), found here.

Have fun!

Radar =8^)
Check out my new, (well, old now), manual trade & automatic scale-in manager,
StackManV2
User avatar
keydcuk
Trader
Posts: 104
Joined: Tue Dec 04, 2012 8:01 pm

MQL Empty4 CODE FOR PROFIT CHECK BEFORE CLOSE

Post by keydcuk »

Radar » Wed Apr 06, 2016 3:38 pm wrote:Hey Keydcuk,

Sounds like you're looking for Basket Management...

Check out Baluda's MPBM (Multi-Purpose Basket Manager), found here.

Have fun!

Radar =8^)
Hi Radar,

Thanks for your help. It is not a basket manager I am looking for. It is actually code to set a condition before closing trades.

Basically in this EA I am looking at, it chooses certain positions to close while leaving others open. The conditions of closing the group of trades have already been determined but even though most trade groups close profitable, a select few close at a loss.

I was thinking to myself if there was a condition I could add to the existing code to only close a group of trades if the sum of the group is in profit, then I would drop this in the EA.

Many Thanks & Best Regards,

Daniel
Radar
Trader
Posts: 437
Joined: Fri Mar 23, 2012 5:39 pm
Location: Round the bend ;)

MQL Empty4 CODE FOR PROFIT CHECK BEFORE CLOSE

Post by Radar »

Hey Keydcuk,

So, your EA opens a bunch of trades, then eventually selects a sub-set of those trades to close at once, and you want a final filter (sub-set_total_profit) before closing them? If that sub-set fails the profit test, then what? Does it get broken up and a new sub-set created, or is the original one re-tested until it passes?

The concepts from basket management can be applied to sub-sets (target profit, average profit, etc), but the implementation would need some massaging to fit.

Break the EA down and find where it creates the sub-set... From there, we put those trades' ticket numbers into an array, and pass the array to a function to get their total profit... If there's enough profit, close those trades, and kill the array. If there's not enough profit then...?

Have fun!

Radar =8^)
Check out my new, (well, old now), manual trade & automatic scale-in manager,
StackManV2
User avatar
keydcuk
Trader
Posts: 104
Joined: Tue Dec 04, 2012 8:01 pm

MQL Empty4 CODE FOR PROFIT CHECK BEFORE CLOSE

Post by keydcuk »

Radar » Wed Apr 06, 2016 5:22 pm wrote:Hey Keydcuk,

So, your EA opens a bunch of trades, then eventually selects a sub-set of those trades to close at once, and you want a final filter (sub-set_total_profit) before closing them? If that sub-set fails the profit test, then what? Does it get broken up and a new sub-set created, or is the original one re-tested until it passes?

The concepts from basket management can be applied to sub-sets (target profit, average profit, etc), but the implementation would need some massaging to fit.

Break the EA down and find where it creates the sub-set... From there, we put those trades' ticket numbers into an array, and pass the array to a function to get their total profit... If there's enough profit, close those trades, and kill the array. If there's not enough profit then...?

Have fun!

Radar =8^)
Now your getting into something slightly complex for me.

I don't know how to code MQL. I only know enough of how to read it because I have dealt with basic programming a couple decades ago when there was a dinosaur called a Commodore 64 :o

You are right though. There is a set of trades that close under condition and they are suppose to close only at profit but at the moment they are not for some reason. It is too complicated for me to understand within the code of why this is not happening so I thought that I could filter out the closure with some sort of line that says if these trades closing don't close in sum for a profit, then don't close.

I think due to the nature of the EA, the trades would keep going and eventually fall into meeting a closure condition under profit, but you have given me something to think about. "What happens after the check and if it fail?" I can assume what I just stated but it might not work. I don't know.

Maybe it's not as simple as I would have hoped it to be.

Thanks anyway,

Daniel
Radar
Trader
Posts: 437
Joined: Fri Mar 23, 2012 5:39 pm
Location: Round the bend ;)

MQL Empty4 CODE FOR PROFIT CHECK BEFORE CLOSE

Post by Radar »

Hey Keydcuk,

I'll pull out some of my old code and modify it over the next few days...
It'll work on the assumption that the sub-set is created on each loop of the EA, so it will create & populate the array, do the test, and close the trades if required. Whether the trades are closed or not, it will kill the array, ready for the next loop.

You'll just have to plug it in (unless you want to post the EA either here or in a PM).

Have fun!

Radar =8^)
Check out my new, (well, old now), manual trade & automatic scale-in manager,
StackManV2
User avatar
keydcuk
Trader
Posts: 104
Joined: Tue Dec 04, 2012 8:01 pm

MQL Empty4 CODE FOR PROFIT CHECK BEFORE CLOSE

Post by keydcuk »

Radar » Thu Apr 07, 2016 10:20 am wrote:Hey Keydcuk,

I'll pull out some of my old code and modify it over the next few days...
It'll work on the assumption that the sub-set is created on each loop of the EA, so it will create & populate the array, do the test, and close the trades if required. Whether the trades are closed or not, it will kill the array, ready for the next loop.

You'll just have to plug it in (unless you want to post the EA either here or in a PM).

Have fun!

Radar =8^)
Thanks for your help. It is greatly appreciated!
Radar
Trader
Posts: 437
Joined: Fri Mar 23, 2012 5:39 pm
Location: Round the bend ;)

MQL Empty4 CODE FOR PROFIT CHECK BEFORE CLOSE

Post by Radar »

Hey Keydcuk,

Code's done! ;)

First off add this to your external variables..

Code: Select all

extern double SubSetTargetProfit = 0;
extern double SubSetAverageProfit = 0;
Then add this below your external variables...

Code: Select all

int SubSet[]; // Global-Scope dynamic array to hold ticket numbers of sub-set trades.
Throw this at the bottom of your code...

Code: Select all

void CloseTradesOnTargetProfit(int& Managed[])
{
	int SizeOfArray = 0;
	double SubSetProfit = 0;
	
	SubSetProfit = LockedInProfit(Managed);
	
	if (SubSetProfit >= SubSetTargetProfit) CloseSubSet(Managed);
	
	SizeOfArray = ArrayRange(Managed, 0);
	Alert(string(SizeOfArray), " trades closed with ", DoubleToString(SubSetProfit, 2), " total profit. Target profit is ", DoubleToString(SubSetTargetProfit, 2), ".");
	Print(string(SizeOfArray), " trades closed with ", DoubleToString(SubSetProfit, 2), " total profit. Target profit is ", DoubleToString(SubSetTargetProfit, 2), ".");
	return;
} // End void CloseTradesOnTargetProfit(int& Managed[])

void CloseTradesOnAverageProfit(int& Managed[])
{
	int SizeOfArray = 0;
	double AverageProfit = 0;
	double SubSetProfit = 0;
	
	SizeOfArray = ArrayRange(Managed, 0);
	SubSetProfit = LockedInProfit(Managed);
	AverageProfit = SubSetProfit / SizeOfArray;
	
	if (AverageProfit >= SubSetAverageProfit) CloseSubSet(Managed);
	Alert(string(SizeOfArray), " trades closed with an average profit of ", DoubleToString(AverageProfit, 2), ".");
	Print(string(SizeOfArray), " trades closed with an average profit of ", DoubleToString(AverageProfit, 2), ".");
	return;
} // End void CloseTradesOnAverageProfit(int& Managed[])

double LockedInProfit(int& Managed[])
{
   int ticket;
	int SizeOfArray = 0;
   double LotSize = 0;
   double LockedPips = 0;
   double TradeProfit = 0;
   double CashProfit = 0;
	
	// Loop through the aray
   for (int index = ArrayRange(Managed, 0) - 1 ; index >= 0 ; index--)
   {
      ticket = 0;
		ticket = Managed[index];
      if ((OrderSelect(ticket,SELECT_BY_TICKET) != true) || ((OrderSelect(ticket,SELECT_BY_TICKET) == true) && (OrderCloseTime() != 0))) continue;
      if ((OrderSelect(ticket,SELECT_BY_TICKET) == true) && (OrderCloseTime() == 0))
      if (OrderMagicNumber() == MagicNumber)
      if (OrderSymbol() == Symbol())
      {
         if (OrderType() == OP_BUY)
         {
            LockedPips = (OrderStopLoss() - OrderOpenPrice()) * factor; // Get the trade's profit/loss in Pips.
            LotSize = OrderLots();
            TradeProfit = (Pips2Cash(LockedPips) * LotSize) + OrderSwap() + OrderCommission(); // Get the trade's profit/loss in cash.
         } // End if (OrderType() == OP_BUY)

         if (OrderType() == OP_SELL)
         {
            LockedPips=(OrderOpenPrice() - OrderStopLoss()) * factor;
            LotSize=OrderLots();
            TradeProfit = (Pips2Cash(LockedPips) * LotSize) + OrderSwap() + OrderCommission();
         } // End if (OrderType() == OP_SELL)
         CashProfit = CashProfit + TradeProfit; // Get running total profit/loss in cash.
      } // End if (OrderSymbol() == Symbol())
   } // End for (int index = ArrayRange(Managed, 0) - 1 ; index >= 0 ; index--)
	return(CashProfit);
} // End LockedInProfit

double Pips2Cash(double Pips)
{
   double TickValue = 0;
   double PipsCashValue = 0;

   TickValue = MarketInfo(Symbol(), MODE_TICKVALUE);
   PipsCashValue = (TickValue  * 10) * Pips; // Since TickValue gives us the value of 1 Point, we multiply TickValue by 10 to get Pip Value.
   return(PipsCashValue);
} // End Pips2Cash

void CloseSubSet(int& Managed[])
{

   int ticket;
   int index;
   bool result = false;

   for (index = ArrayRange(Managed,0) - 1; index >= 0; index--)
   {
      ticket = 0;
		ticket = Managed[index];
      if ((OrderSelect(ticket,SELECT_BY_TICKET) != true) || ((OrderSelect(ticket,SELECT_BY_TICKET) == true)  && (OrderCloseTime() !=0))) // Gotta keep my arrays clean
      {
         Managed[index] = 0;
         continue;
      } // End if ((OrderSelect(ticket,SELECT_BY_TICKET) != true) || ((OrderSelect(ticket,SELECT_BY_TICKET) == true)  && (OrderCloseTime() !=0)))
      if (OrderMagicNumber() != MyMagicNumber) continue;
      if (OrderSymbol() != Symbol()) continue;
      if ((OrderSelect(ticket,SELECT_BY_TICKET) == true) && (OrderCloseTime() == 0))
      if (OrderMagicNumber() == MagicNumber)
      if (OrderSymbol() == Symbol())
      {
         while(IsTradeContextBusy()) Sleep(100);
         if (OrderType() == OP_BUY || OrderType() == OP_SELL)
         {
            result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 1000, CLR_NONE);
         } // End if (OrderType() == OP_BUY || OrderType() == OP_SELL)
      } // End if (OrderSymbol() == Symbol())
   }// End for (index = ArrayRange(Managed,0) - 1; index >= 0; index--)
   return;
}//End void CloseSubSet()

bool CloseEnough(double num1, double num2)
{
   /*
   This function addresses the problem of the way in which mql4 compares doubles. It often messes up the 8th
   decimal point.
   For example, if A = 1.5 and B = 1.5, then these numbers are clearly equal. Unseen by the coder, mql4 may
   actually be giving B the value of 1.50000001, and so the variable are not equal, even though they are.
   This nice little quirk explains some of the problems I have endured in the past when comparing doubles. This
   is common to a lot of program languages, so watch out for it if you program elsewhere.
   Gary (garyfritz) offered this solution, so our thanks to him.
   */
   
   if (num1 == 0 && num2 == 0) return(true); //0==0
   if (MathAbs(num1 - num2) / (MathAbs(num1) + MathAbs(num2)) < 0.00000001) return(true);
   
   //Doubles are unequal
   return(false);

}//End bool CloseEnough(double num1, double num2)
Now, inside the loop that tests for the closing conditions...

Code: Select all

int SizeOfArray = ArrayRange(SubSet, 0);
ArrayResize(SubSet, SizeOfArray + 1);
SubSet[SizeOfArray] = OrderTicket();
If you have a command to close a trade that passes the previous tests, comment it out.

Straight after the testing loop, put the following...

Code: Select all

if (!(CloseEnough(SubSetTargetProfit, 0))) CloseTradesOnTargetProfit(SubSet);
if (!(CloseEnough(SubSetAverageProfit, 0)))CloseTradesOnAverageProfit(SubSet);
ArrayResize(SubSet, 0); // Kill the array, ready for the next loop of the EA.
Throw it in the backtester to make sure that it does what you want it to before going demo with it ;)

Have fun!
Radar =8^)
Check out my new, (well, old now), manual trade & automatic scale-in manager,
StackManV2
User avatar
keydcuk
Trader
Posts: 104
Joined: Tue Dec 04, 2012 8:01 pm

MQL Empty4 CODE FOR PROFIT CHECK BEFORE CLOSE

Post by keydcuk »

Thanks again.

I did try this and couldn't get it to work.

I think that I will take your advice in the PM you sent me and leave it with the experts that are working on this.

Cheers!

Daniel
User avatar
pascalx
Trader
Posts: 20
Joined: Mon Mar 28, 2016 2:40 pm

MQL Empty4 CODE FOR PROFIT CHECK BEFORE CLOSE

Post by pascalx »

Code: Select all

#define INVALID_TICKET_ID -1

bool GetRealOrderProfit(double& profit, int ticketId)
{
   if (ticketId != INVALID_TICKET_ID)
   {
      if (OrderSelect(ticketId, SELECT_BY_TICKET))
      {
         profit = OrderProfit() + OrderSwap() + OrderCommission();
         return true;
      }
   }
   return false;
}

void MyFunction()
{
   int myTicketId;
   // ...

   double myProfit;
   if (GetRealOrderProfit(myProfit, myTicketId) && myProfit > 0.0)
   {
       // my order is profitable, yay !!
   }
}
Something like this might do it. It might be missing spread, but you can easily correct the math if it is wrong. And you may need to work with MagicNumber to safely select the order.
Post Reply

Return to “Coders Hangout”