Close 50% of an order

 

Hi,


I struggle to partially close an order to 50%, I would like some help please.


I've highlighted in yellow where I think the problem comes from but I can't think of anything else to get arount it.


I keep having this error 131 which is Invalid trade volumes but I can't tell why...


Hope that someone can help me, I saw some other topics but I still can't make it work, it would be brilliant a little bit of help...


Thank you very much.

//+------------------------------------------------------------------+
//|                                               Daily BreakOut.mq4 |
//|                        Copyright 2021, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict

datetime new_time=0;

extern int MagicNumber=123450;
extern string MoneyManagement = "====MONEY MANAGEMENT====";
extern bool FixedLot;
extern double LotSize=0.2;
extern bool AutoLot=false;
extern double Risk=0.5;
extern string STOPLOSS = "====STOPLOSS && TAKEPROFIT====";
extern int TP=10;
extern int SL=10;
extern string SLIS = "====SL IS ?====";
extern bool SLisSet=false;
extern bool BreakEven=false;
extern int TPMult=1;
extern bool SLisTrailingStop=false;



double P;
double D;
double Lot;



double TPBuy,TPSell,SLBuy,SLSell;
bool flagsell=true;
bool flagbuy=true;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---

//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {

   double EMA8=iMA(Symbol(),0,8,0,MODE_EMA,PRICE_CLOSE,0);
   double EMA21=iMA(Symbol(),0,21,0,MODE_EMA,PRICE_CLOSE,0);



   if(Digits == 5 || Digits ==3)
      P=Point*10;
   else
      P=1;

//===================================================================+
//                 STOP LOSS AND TAKE PROFIT MODES                   |
//===================================================================+




   if(SLisTrailingStop==true)
     {

      TPBuy=Ask+TP*P;
      SLBuy=Ask-SL*P;

      TPSell=Bid-TP*P;
      SLSell=Bid+SL*P;

      for(int b=OrdersTotal()-1; b>=0; b--)
        {

         if(OrderSelect(b,SELECT_BY_POS,MODE_TRADES))
           {
            if(OrderMagicNumber()==MagicNumber)
              {
               if(OrderSymbol()==Symbol())
                 {
                  if(OrderType()==OP_SELL)
                    {
                     if(OrderStopLoss() > Ask + SL *P)
                       {
                        if(OrderModify(OrderTicket(),OrderOpenPrice(), Ask+(SL*P),OrderTakeProfit(),0,clrAliceBlue)==true)
                          {
                           Print("Order modified Magic number :",MagicNumber);

                          }
                        else
                           Print("Error Trailing stop modify ",GetLastError());
                       }
                    }
                  else
                    {

                     if(OrderStopLoss() < Bid - SL *P)
                        if(OrderModify(OrderTicket(),OrderOpenPrice(), Bid-(SL*P),OrderTakeProfit(),0,clrAliceBlue)==true)
                          {
                           Print("Order modified Magic number :",MagicNumber);

                          }
                        else
                           Print("Error Trailing stop modify ",GetLastError(),"Magic number",MagicNumber);
                    }

                 }
              }
           }
        }
     }





   if(SLisSet==true)
     {
      TPBuy=Ask+TP*P;
      SLBuy=Ask-SL*P;

      TPSell=Bid-TP*P;
      SLSell=Bid+SL*P;
     }




   if(BreakEven==true)
     {
     
     
     
    
     double  HalfLot = MathFloor(((Lot/2)/0.01)*0.01); 
    
      for(int b=OrdersTotal()-1; b>=0; b--)
        {

         if(OrderSelect(b,SELECT_BY_POS,MODE_TRADES))
           {
            if(OrderMagicNumber()==MagicNumber)
              {
               if(OrderSymbol()==Symbol())
                 {
                  if(OrderType()==OP_BUY && flagbuy==false)
                    {



                     if(Bid > OrderOpenPrice()+(SL*P)*TPMult)
                       {
                       
                        if(OrderClose(OrderTicket(),HalfLot,Bid,0,clrGainsboro)==true)
                          {
                           flagbuy=true;
                           Print("Order partially closed, Magic number :",MagicNumber);
                          }
                        else
                           Print("Error partially closing order ",GetLastError(),"Magic number",MagicNumber);
                       }
                    }

                  else
                     if(OrderType()==OP_SELL  && flagsell==false)
                       {
                        if(Ask < OrderOpenPrice()-(SL*P)*TPMult)
                          {
                           if(OrderClose(OrderTicket(),HalfLot,Ask,0,clrGainsboro)==true)
                             {
                              flagsell=true;
                              Print("Order partially closed, Magic number :",MagicNumber);
                             }
                           else
                              Print("Error partially closing order ",GetLastError(),"Magic number",MagicNumber);

                          }
                       }

                 }
              }
           }
        }
     }


   if(AutoLot==true)
     {
      double  TickValue=MarketInfo(Symbol(), MODE_TICKVALUE);
      double minlot = MarketInfo(Symbol(), MODE_MINLOT);

      if(Digits == 5 || Digits ==3) // FOREX
        {
         D=10;
         Lot=((Risk/100)* AccountEquity()) / (TickValue*D)/ SL;
         
         if(Lot < minlot)
           {
            Lot = minlot;
           }
        }
      else  // SP500 / CAC40
        {
         D=1000;
         Lot= NormalizeDouble((((Risk/100)* AccountEquity()) / (TickValue*D)/ SL)*10,1);
         if(Lot < minlot)
           {
            Lot = minlot;
           }
        }
     }

   if(FixedLot==true)
     {
      Lot=LotSize;
     }




//===================================================================+
//                     BUY AND SELL CONDITIONS                       |
//===================================================================+


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
   if(new_time!=Time[0])
     {
      if(Ask>High[1])
        {


         if(EMA8>EMA21)
           {


            if(OrderSend(Symbol(),OP_BUY,Lot,Ask,0,SLBuy,TPBuy,NULL,MagicNumber,0,clrLimeGreen))
              {
               Print("Order buy", Symbol(), "Magic Number",MagicNumber);
               new_time=Time[0];
               flagbuy=false;
              }


            else
              {
               if(OrderSend(Symbol(),OP_BUY,Lot,Ask,0,SLBuy,TPBuy,NULL,MagicNumber,0,clrLimeGreen))
                 {
                  Print("Order buy", Symbol(), "Magic Number",MagicNumber);
                  new_time=Time[0];
                  flagbuy=false;
                 }
              }
           }

         else
           {

            if(OrderSend(Symbol(),OP_BUY,Lot,Ask,0,SLBuy,TPBuy,NULL,MagicNumber,0,clrLimeGreen))
              {
               Print("Order buy", Symbol(), "Magic Number",MagicNumber);
               new_time=Time[0];
               flagbuy=false;
              }

            else
              {
               if(OrderSend(Symbol(),OP_BUY,Lot,Ask,0,SLBuy,TPBuy,NULL,MagicNumber,0,clrLimeGreen))
                 {
                  Print("Order buy", Symbol(), "Magic Number",MagicNumber);
                  new_time=Time[0];
                  flagbuy=false;
                 }
              }
           }
        }



      if(Bid<Low[1])
        {


         if(EMA21>EMA8)
           {

            if(OrderSend(Symbol(),OP_SELL,Lot,Bid,0,SLSell,TPSell,NULL,MagicNumber,0,clrRed))
              {
               Print("Order sell", Symbol(), "Magic Number",MagicNumber);
               new_time=Time[0];
               flagsell=false;
              }


            else
              {
               if(OrderSend(Symbol(),OP_SELL,Lot,Bid,0,SLSell,TPSell,NULL,MagicNumber,0,clrRed))
                 {
                  Print("Order sell", Symbol(), "Magic Number",MagicNumber);
                  new_time=Time[0];
                  flagsell=false;
                 }
              }
           }

         else


            if(OrderSend(Symbol(),OP_SELL,Lot,Bid,0,SLSell,TPSell,NULL,MagicNumber,0,clrRed))
              {
               Print("Order sell", Symbol(), "Magic Number",MagicNumber);
               new_time=Time[0];
               flagsell=false;
              }



            else
              {
               if(OrderSend(Symbol(),OP_SELL,Lot,Bid,0,SLSell,TPSell,NULL,MagicNumber,0,clrRed))
                 {
                  Print("Order sell", Symbol(), "Magic Number",MagicNumber);
                  new_time=Time[0];
                  flagsell=false;
                 }
              }
        }
     }

  






//+------------------------------------------------------------------+





     {
      int i, iOrders = OrdersHistoryTotal() - 1;
      double OverallProfit= NormalizeDouble(0,2)  ;
      int TotalOfTrades=0;
      double MonthlyProfit=0;
      double WinningPosition=0;
      double  MaxDrawdown=0;
      double MaxProfit=0;
      double SuccesRate=0;

      for(i = iOrders; i >= 0; i--)
        {
         OrderSelect(i, SELECT_BY_POS, MODE_HISTORY);
         if(Symbol() == OrderSymbol())
           {
            if(OrderMagicNumber()== MagicNumber)
              {
               OverallProfit += OrderProfit()+OrderSwap()+OrderCommission();
               TotalOfTrades=TotalOfTrades+1;
               if(OrderProfit()>0)
                 {
                  WinningPosition+=1;
                 }
               if(TimeMonth(OrderCloseTime())==Month())
                 {
                  MonthlyProfit += OrderProfit()+OrderSwap()+OrderCommission();
                 }
               if(OverallProfit>MaxProfit)
                 {
                  MaxProfit=OverallProfit;
                 }
               double  Drawdown=OverallProfit-MaxProfit;

               if(Drawdown<MaxDrawdown)
                 {
                  MaxDrawdown=Drawdown;
                 }
               if(WinningPosition>0)
                 {
                  SuccesRate=(WinningPosition/TotalOfTrades)*100;
                 }
              }
           }

         color Color0=White;
         if(OverallProfit>0)
           {Color0=Green;}
         else
           {
            Color0=Red;
           }

         color Color1=White;
         if(MonthlyProfit>0)
           {Color1=Green;}
         else
           {
            Color1=Red;
           }


         //===================================================================+
         //                    SETTING VARIABLES ON CHART                     |
         //===================================================================+



         ObjectCreate("Rectangle",OBJ_RECTANGLE_LABEL,0,0,0);
         //--- set border type
         ObjectSet("Rectangle",OBJPROP_BORDER_TYPE,BORDER_RAISED);
         //--- set background color
         ObjectSet("Rectangle",OBJPROP_BGCOLOR,DarkBlue);
         //--- set label coordinates
         ObjectSet("Rectangle",OBJPROP_CORNER,0);
         ObjectSet("Rectangle",OBJPROP_XDISTANCE,5);
         ObjectSet("Rectangle",OBJPROP_YDISTANCE,20);
         //--- set label size
         ObjectSet("Rectangle",OBJPROP_CORNER,0);
         ObjectSet("Rectangle",OBJPROP_XSIZE,130);
         ObjectSet("Rectangle",OBJPROP_YSIZE,84);


         ObjectCreate("MaxDrawDown",OBJ_LABEL,0,0,0);
         ObjectCreate("MonthlyProfit",OBJ_LABEL,0,0,0);
         ObjectCreate("NumberOfTrades",OBJ_LABEL,0,0,0);
         ObjectCreate("OverallProfit",OBJ_LABEL,0,0,0);
         ObjectCreate("SuccesRate",OBJ_LABEL,0,0,0);

         ObjectSetText("OverallProfit","Overall profit :"+DoubleToStr(OverallProfit,2),10,"Arial",Color0);
         ObjectSetText("MonthlyProfit","Monthly profit :"+DoubleToStr(MonthlyProfit,2),10,"Arial",Color1);
         ObjectSetText("NumberOfTrades","Number of trades :"+DoubleToStr(TotalOfTrades,0),10,"Arial",White);
         ObjectSetText("MaxDrawDown","Max drawdown :"+DoubleToStr(MaxDrawdown,2),10,"Arial",White);
         ObjectSetText("SuccesRate","Succes rate :"+DoubleToStr(SuccesRate,2),10,"Arial",White);


         ObjectSet("OverallProfit",OBJPROP_CORNER,0);
         ObjectSet("OverallProfit",OBJPROP_XDISTANCE,10);
         ObjectSet("OverallProfit",OBJPROP_YDISTANCE,23);

         ObjectSet("MonthlyProfit",OBJPROP_CORNER,0);
         ObjectSet("MonthlyProfit",OBJPROP_XDISTANCE,10);
         ObjectSet("MonthlyProfit",OBJPROP_YDISTANCE,38);

         ObjectSet("NumberOfTrades",OBJPROP_CORNER,0);
         ObjectSet("NumberOfTrades",OBJPROP_XDISTANCE,10);
         ObjectSet("NumberOfTrades",OBJPROP_YDISTANCE,53);

         ObjectSet("MaxDrawDown",OBJPROP_CORNER,0);
         ObjectSet("MaxDrawDown",OBJPROP_XDISTANCE,10);
         ObjectSet("MaxDrawDown",OBJPROP_YDISTANCE,68);

         ObjectSet("SuccesRate",OBJPROP_CORNER,0);
         ObjectSet("SuccesRate",OBJPROP_XDISTANCE,10);
         ObjectSet("SuccesRate",OBJPROP_YDISTANCE,83);

        }





     }

  }
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
 
Macdrap: I struggle to partially close an order to 50%, I would like some help please.

I did not analyse all your code, but a quick look shows me that you are not checking for a minimum amount.

The calculation "MathFloor(((Lot/2)/0.01)*0.01)" could result in a value of "0", so you will not be able to close out a volume of "0".

Also, you should be verifying all volume against the brokers conditions of minimum volume, maximum volume and volume step. If you don't verify those metrics you will also get errors when the values are out of those limits.

So, also read the following thread post for an example of how to adjust the volume (lots) accordingly:

Forum on trading, automated trading systems and testing trading strategies

How to calculate lots using multiplier according to number of opened orders?

Fernando Carreiro, 2017.09.01 21:57

Don't use NormalizeDouble(). Here is some guidance (code is untested, just serves as example):

// Variables for Symbol Volume Conditions
double
   dblLotsMinimum = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_MIN  ),
   dblLotsMaximum = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_MAX  ),
   dblLotsStep    = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_STEP );
   
// Variables for Geometric Progression
double
   dblGeoRatio = 2.8,
   dblGeoInit  = dblLotsMinimum;
   
// Calculate Next Geometric Element
double
   dblGeoNext  = dblGeoInit * pow( dblGeoRatio, intOrderCount + 1 );
   
// Adjust Volume for allowable conditions
double
   dblLotsNext = fmin( dblLotsMaximum,                                     // Prevent too greater volume
                   fmax( dblLotsMinimum,                                   // Prevent too smaller volume
                     round( dblGeoNext / dblLotsStep ) * dblLotsStep ) );  // Align to Step value

 
Topics concerning MT4 and MQL4 have their own section.
In future please post in the correct section.
I have moved your topic to the MQL4 and Metatrader 4 section.
 

    Why did you post your MT4 question in the MT5 EA section instead of the MQL4 section, (bottom of the Root page)?
              General rules and best pratices of the Forum. - General - MQL5 programming forum?
    Next time post in the correct place. The moderators will likely move this thread there soon.

  1.      double  HalfLot = MathFloor(((Lot/2)/0.01)*0.01); 
    
    The amount you close must be a multiple of Lot Step. OK, except you shouldn't hard code numbers.
  2. The amount you close must be at least Min Lot. No check as Fernando stated.
  3. The amount remaining must also be at least Min Lot.
 
Fernando Carreiro:

I did not analyse all your code, but a quick look shows me that you are not checking for a minimum amount.

The calculation "MathFloor(((Lot/2)/0.01)*0.01)" could result in a value of "0", so you will not be able to close out a volume of "0".

Also, you should be verifying all volume against the brokers conditions of minimum volume, maximum volume and volume step. If you don't verify those metrics you will also get errors when the values are out of those limits.

So, also read the following thread post for an example of how to adjust the volume (lots) accordingly:


I change my code as below, but it still doesn't work, I've just saw the thread and I am not sure that I 100% understand it.


I am sorry I sound like I am an absolutely giant dodo (which I probably am) but I think I may need a bit more help...

   if(BreakEven==true)
     {
     
   double LotsMinimum = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_MIN  ),
   LotsMaximum = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_MAX  ),
   LotsStep    = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_STEP );
     double  HalfLot = MathFloor(((Lot/2)/LotsStep)*LotsStep);
     
     
      HalfLot = fmin( LotsMaximum,                                     
                   fmax( LotsMinimum,                                  
                     round( HalfLot / LotsStep ) * LotsStep ) );
     
    
      
    
      for(int b=OrdersTotal()-1; b>=0; b--)
        {

         if(OrderSelect(b,SELECT_BY_POS,MODE_TRADES))
           {
            if(OrderMagicNumber()==MagicNumber)
              {
               if(OrderSymbol()==Symbol())
                 {
                  if(OrderType()==OP_BUY && flagbuy==false)
                    {



                     if(Bid > OrderOpenPrice()+(SL*P)*TPMult)
                       {
                       
                        if(OrderClose(OrderTicket(),HalfLot,Bid,0,clrGainsboro)==true)
                          {
                           flagbuy=true;
                           Print("Order partially closed, Magic number :",MagicNumber);
                          }
                        else
                           Print("Error partially closing order ",GetLastError(),"Magic number",MagicNumber);
                       }
                    }

                  else
                     if(OrderType()==OP_SELL  && flagsell==false)
                       {
                        if(Ask < OrderOpenPrice()-(SL*P)*TPMult)
                          {
                           if(OrderClose(OrderTicket(),HalfLot,Ask,0,clrGainsboro)==true)
                             {
                              flagsell=true;
                              Print("Order partially closed, Magic number :",MagicNumber);
                             }
                           else
                              Print("Error partially closing order ",GetLastError(),"Magic number",MagicNumber);

                          }
                       }

                 }
              }
           }
        }
     }
William Roeder:

    Why did you post your MT4 question in the MT5 EA section instead of the MQL4 section, (bottom of the Root page)?
              General rules and best pratices of the Forum. - General - MQL5 programming forum?
    Next time post in the correct place. The moderators will likely move this thread there soon.

  1. The amount you close must be a multiple of Lot Step. OK, except you shouldn't hard code numbers.
  2. The amount you close must be at least Min Lot. No check as Fernando stated.
  3. The amount remaining must also be at least Min Lot.

Sorry about the wrong place for the post...

#1 I've swapped it for lotstep instead of numbers which makes absolutely sense..

#2 & #3 I still think that even after those checks I still would have those error 131 ... 


thanks for your help...

 

Macdrap: I change my code as below, but it still doesn't work, I've just saw the thread and I am not sure that I 100% understand it.

I am sorry I sound like I am an absolutely giant dodo (which I probably am) but I think I may need a bit more help...

Sorry about the wrong place for the post...

#1 I've swapped it for lotstep instead of numbers which makes absolutely sense..

#2 & #3 I still think that even after those checks I still would have those error 131 ... 

Like I said, I did not check all your code, only looking at it quickly!

However, in this new version, simplify your calculation, since "my code" is already doing the checking for you!

double
   LotsMinimum = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_MIN  ),
   LotsMaximum = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_MAX  ),
   LotsStep    = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_STEP );

double HalfLot = MathFloor( Lot / 2.0 );

       HalfLot = fmin( LotsMaximum,                                     
                   fmax( LotsMinimum,                                  
                     round( HalfLot / LotsStep ) * LotsStep ) );

I will check the rest of your code a little be later!

 

I have taken another look, but you are not assigning the trade's current volume to the variable "Lot". You are just assuming it has a volume of "Lot" based on your calculations.

Plus once the first half of the order is closed, it will not longer have what you think it has, so your calculations will no longer hold. You must first use the OrderLots() function to find out how much volume it has, and only then halve it!

So, once you have selected the order, first use the OrderLots() to get current volume of order, then halve it, and then close it partially.

EDIT: And please, please, use the code styler ([Ctrl+,] or Menu-Tools-Styler) on your code so that it is easier to read and remove all the extra white space that just makes it even more difficult to read.

OrderLots - Trade Functions - MQL4 Reference
OrderLots - Trade Functions - MQL4 Reference
  • docs.mql4.com
OrderLots - Trade Functions - MQL4 Reference
 
Fernando Carreiro:

I have taken another look, but you are not assigning the trade's current volume to the variable "Lot". You are just assuming it has a volume of "Lot" based on your calculations.

Plus once the first half of the order is closed, it will not longer have what you think it has, so your calculations will no longer hold. You must first use the OrderLots() function to find out how much volume it has, and only then halve it!

So, once you have selected the order, first use the OrderLots() to get current volume of order, then halve it, and then close it partially.

EDIT: And please, please, use the code styler ([Ctrl+,] or Menu-Tools-Styler) on your code so that it is easier to read and remove all the extra white space that just makes it even more difficult to read.

  if(BreakEven==true)
     {
      double
      LotsMinimum = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN),
      LotsMaximum = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX),
      LotsStep    = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);

      double HalfLot = MathFloor(OrderLots()/ 2.0);

      HalfLot = fmin(LotsMaximum,
                     fmax(LotsMinimum,
                          round(HalfLot / LotsStep) * LotsStep));


      for(int b=OrdersTotal()-1; b>=0; b--)
        {

         if(OrderSelect(b,SELECT_BY_POS,MODE_TRADES))
           {
            if(OrderMagicNumber()==MagicNumber)
              {
               if(OrderSymbol()==Symbol())
                 {



                  if(OrderType()==OP_BUY && flagbuy==false)
                    {



                     if(Bid > OrderOpenPrice()+(SL*P)*TPMult)
                       {

                        if(OrderClose(OrderTicket(),HalfLot,Bid,0,clrGainsboro)==true)
                          {
                           flagbuy=true;
                           Print("Order partially closed, Magic number :",MagicNumber);
                          }
                        else
                           Print("Error partially closing order ",GetLastError(),"Magic number",MagicNumber);
                       }
                    }

                  else
                     if(OrderType()==OP_SELL  && flagsell==false)
                       {
                        if(Ask < OrderOpenPrice()-(SL*P)*TPMult)
                          {
                           if(OrderClose(OrderTicket(),HalfLot,Ask,0,clrGainsboro)==true)
                             {
                              flagsell=true;
                              Print("Order partially closed, Magic number :",MagicNumber);
                             }
                           else
                              Print("Error partially closing order ",GetLastError(),"Magic number",MagicNumber);

                          }
                       }

                 }
              }
           }
        }
     }

I am sorry to be a pain ... But I don't think I still get it ... now my EA is basically partially closing only the minimum volume (0.01).


I replaced my Lot by the OrderLots() which I suppose is what you meant, I am so sorry but it just feels like the more I think about it the more I get confused about it....


Sorry about the (Ctr+ I normally do it..)


Thank for your time anyway

 
Macdrap: I am sorry to be a pain ... But I don't think I still get it ... now my EA is basically partially closing only the minimum volume (0.01). I replaced my Lot by the OrderLots() which I suppose is what you meant, I am so sorry but it just feels like the more I think about it the more I get confused about it.... 

NO! You can't use OrderLots() outside of a selected order. You did not follow the sequence I explained.

You have to do it for every single order, AFTER you select it and just before you do the partial close.

Here is just a sample summary code to help you understand (code is untested and not compiled, just written out here to show you the idea)...

// Function to do have Order Lots outside of OnTick
double OrderHalfLots()
{
   double
      LotsMinimum = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_MIN  ),
      LotsMaximum = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_MAX  ),
      LotsStep    = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_STEP );

   return( fmin( LotsMaximum, fmax( LotsMinimum,
      round( ( OrderLots() / 2.0 ) / LotsStep ) * LotsStep ) ) );
}

void OnTick()
{
   // ...
   if( OrderClose( OrderTicket(), OrderHalfLots(), Bid, 0, clrGainsboro ) )
   {
      // ...
   }
   // ...
}
EDIT: Please note that this is not the best way to do it, but it was a way to show you a possible way to do it!
 

Hi thanks for your great help Fernando,


the only problem with that is that it will even close half of half of the order ...

 
Macdrap: Hi thanks for your great help Fernando, the only problem with that is that it will even close half of half of the order ...

Then put in a condition to only apply partial closing to orders with a set or expected initial or minimum required volume!

You asked how to close 50%. It has been shown to you. Now take that knowledge and apply it according to the logic you wish to apply to your EAs.

Learning to code properly is not something you learn in a few days. It takes time, effort and dedication.

// Function to calculate Half the Volume
double HalfLots( double Lots )
{
   double
      LotsMinimum = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_MIN  ),
      LotsMaximum = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_MAX  ),
      LotsStep    = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_STEP );

   return( fmin( LotsMaximum, fmax( LotsMinimum,
      round( ( Lots * 0.5 ) / LotsStep ) * LotsStep ) ) );
}

void OnTick()
{
   // ...
   double CurrentLots = OrderLots();
   if( CurrentLots >= RequiredLots )
   {
      if( OrderClose( OrderTicket(), HalfLots( CurrentLots ), OrderClosePrice(), 0, clrGainsboro ) )
      {
         // ...
      }
   }
   // ...
}
Also, when closing an order, use OrderClosePrice() instead of Bid or Ask, as it will be the current Market price, valid for both Buy and Sell orders!
OrderClosePrice - Trade Functions - MQL4 Reference
OrderClosePrice - Trade Functions - MQL4 Reference
  • docs.mql4.com
OrderClosePrice - Trade Functions - MQL4 Reference
Reason: