Position modifying and partial close

 

i have a take profit of "150" points but , I'd like to partially close a position if it get 50 points profits then modify the remaining position with a take profit (100 points) , here's my code

the problem is that the position closes fully at 50 points , i understand why but can't figure out how to fix it !!


    if(PositionsTotal() > 0 ) {
       
       for (int i = PositionsTotal() - 1; i >=0; i-- ) {
         
         ulong position_ticket =  PositionGetTicket(i);
         if (PositionSelectByTicket(position_ticket) ) {
         
         double position_sl = PositionGetDouble(POSITION_PRICE_OPEN);
         
         if ( (  (PositionGetDouble(POSITION_PROFIT) - PositionGetDouble(POSITION_SWAP) ) / PositionGetDouble(POSITION_VOLUME) )  > 50 ) {
 
               trade.PositionClosePartial(position_ticket,0.10,1);
               trade.PositionModify(position_ticket,position_sl ,Ask + 100 * _Point);
             
         }
         
        } // position select

       }//for loop
    } // total positions
    
    
    
 
  1. What is the size of your initial position? The partial close if of volume 0.1 lot.
  2. Does this code runs once, or at each tick? If the latter, then it eventually closes all position. Check also in the journal tab how many closes it has done. If so, you need to add a bool field condition, something like 
        //--- define in expert global part
        bool positions_modified=false;
    
        //--- as usual except the new condition check and set
        if(!positions_modified && PositionsTotal() > 0 ) {
           
           for (int i = PositionsTotal() - 1; i >=0; i-- ) {
             
             ulong position_ticket =  PositionGetTicket(i);
             if (PositionSelectByTicket(position_ticket) ) {
             
             double position_sl = PositionGetDouble(POSITION_PRICE_OPEN);
             
             if ( (  (PositionGetDouble(POSITION_PROFIT) - PositionGetDouble(POSITION_SWAP) ) / PositionGetDouble(POSITION_VOLUME) )  > 50 ) {
     
                   trade.PositionClosePartial(position_ticket,0.10,1);
                   trade.PositionModify(position_ticket,position_sl ,Ask + 100 * _Point);
                    positions_modified=true;
                 
             }
             
            } // position select
    
           }//for loop
        } // 


 
Amir Yacoby:
  1. What is the size of your initial position? The partial close if of volume 0.1 lot.
  2. Does this code runs once, or at each tick? If the latter, then it eventually closes all position. Check also in the journal tab how many closes it has done. If so, you need to add a bool field condition, something like 


1. it's 0.2 

2. it's inside onTick , that's why it closes all positions at the partial profit , and i tried adding this bool condition but it doesn't work !!  since after the first modifying the "positions_modified" will remain true 

How should i solve this ?!

 
andrw11:

1. it's 0.2 

2. it's inside onTick , that's why it closes all positions at the partial profit , and i tried adding this bool condition but it doesn't work !!  since after the first modifying the "positions_modified" will remain true 

How should i solve this ?!

This condition

if(!positions_modified && PositionsTotal() > 0 ) {

Is false (! means not which is equivalent to positions_modified=false) when positions_modified is true. So, how come it enters again? 

If positions_modified is defined at the global level, and not in OnTick then it remains true and if(!positions_modified) is false. This is how it should work.
So check what's wrong in the code.

 
Amir Yacoby:

This condition

Is false (! means not which is equivalent to positions_modified=false) when positions_modified is true. So, how come it enters again? 

If positions_modified is defined at the global level, and not in OnTick then it remains true and if(!positions_modified) is false. This is how it should work.
So check what's wrong in the code.

yes i know , but the problem is that after the first IF, the value of " positions_modified " will remain true as long as the expert works since the value won't reset to false again and won't modify any future positions !

 

There is only one solution: an array is declared in the "header" of the Expert Advisor, in which position identifiers will be stored.

In the loop, you do this: if you made a partial closure, enter the identifier   positions in the array. And before you carry out a partial closure, check whether this identifier is in the array.

 
Either what was suggested by Vladimir or select the order by the order ticket (which is supposed to be the same as position ticket) and check ORDER_INITIAL_VOLUME against the current volume of position(it is assumed that the position was opened by one order only, otherwise it wont work) Only modify when they are different. 
In the case you take the array way, dont forget to delete from array when a position is closed.
 
Vladimir Karputov :

There is only one solution: an array is declared in the "header" of the Expert Advisor, in which position identifiers will be stored.

In the loop, you do this: if you made a partial closure, enter the identifier   positions in the array. And before you carry out a partial closure, check whether this identifier is in the array.

Code example: Position Close Partial

 
Vladimir Karputov #:

Code example: Position Close Partial

Mr. Engineer
Vladimir Karputov
Hello dear friend, thank you for the explanation you gave above.
  Really, the internet platform can connect people's hearts together.

Can you please explain more about the idea you mentioned above?

Of course, I saw the code related to Position Close Partial and received the important points, but I don't know its philosophy!


I wish health and happiness for you dear kind

I also wish that you can be profitable in this chaotic market.

Be careful of your kindness.

Good internet friend!

thank you
Position Close Partial
Position Close Partial
  • www.mql5.com
Советник - утилита: производится частичное закрытие позиций по текущему символу
 
//+------------------------------------------------------------------+
//| Load Libraries                                                   |
//+------------------------------------------------------------------+
#include <Trade\PositionInfo.mqh>
#include <Trade\Trade.mqh>
#include <Trade\SymbolInfo.mqh>  
#include <Trade\AccountInfo.mqh>
#include <Trade\DealInfo.mqh>
#include <Trade\OrderInfo.mqh>
//+------------------------------------------------------------------+
//| Constants                                                        |
//+------------------------------------------------------------------+
input ulong ea_magic = 1071;//Expert Magic ID
                     

double ASK;
double BID;

CPositionInfo  m_position;                   // object of CPositionInfo class
CTrade         m_trade;                      // object of CTrade class
CSymbolInfo    m_symbol;                     // object of CSymbolInfo class
CAccountInfo   m_account;                    // object of CAccountInfo class
CDealInfo      m_deal;                       // object of CDealInfo class
COrderInfo     m_order;                      // object of COrderInfo class

enum isCheck 
{
   isCheck_1 =1,  // Yes
   isCheck_2 =2,  // No
};

input group "# Partial Close #";
input isCheck Partial_Type = isCheck_1;   // Use Partial Close?
input int MinReward_TP1 = 38;             // TP1 - Reward * %
input int Partial_Lot1 = 33;              // TP1 - Original Lot * %
input int MinReward_TP2 = 62;             // TP2 - Reward %
input int Partial_Lot2 = 33;              // TP2 - Orjinal Lot * % 

string Bars_PARTIAL; // Store Partial Close Time

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
   if(!RefreshRates())
   {
      return;
   }
   
   ASK = m_symbol.Ask();
   BID = m_symbol.Bid();

	if(Partial_Type ==1){
         for(int i=PositionsTotal()-1;i>=0;i--)
         {
            if(m_position.SelectByIndex(i)){
               if(m_position.Symbol()==Symbol() && m_position.Magic() ==ea_magic){
                  Check_PartialClose(m_position.Ticket(),m_position.Time(),m_position.PriceOpen(),m_position.TakeProfit(),m_position.Volume());
               }
            }
         }
      }

}
//+------------------------------------------------------------------+
//| Refresh Rates                                                    |
//+------------------------------------------------------------------+
bool RefreshRates(void)
{
   if(!m_symbol.RefreshRates())
   {
      Print("Error RefreshRates");
      return(false);
   }
   if(m_symbol.Ask()==0 || m_symbol.Bid()==0)
   {
      return(false);
   }
   return(true);
}
//+------------------------------------------------------------------+
//| Check Partial Close                                              |
//+------------------------------------------------------------------+
string TimeSeconds(){
   string TS;
   TS = TimeToString(TimeLocal(),TIME_DATE|TIME_SECONDS);
   return (TS);
}

void Check_PartialClose(ulong PosID, datetime StartTime, double PriceOpen, double Tp, double PosVolume){
   
   if (HistorySelect(StartTime, TimeCurrent()))
   {
      for (int i = HistoryDealsTotal() - 1; i >= 0; i--){
         if(m_deal.SelectByIndex(i)>0){
            if(m_deal.PositionId() == PosID){
               double   lot = m_deal.Volume();
               double   partialLot1;
               double   partialLot2;
               double   remainingLot;
               double   remainingLot2;
               double   target1;
               double   target2;
               double   target3;
               double   target4;
               partialLot1 = NormalizeDouble(lot*Partial_Lot1/100,2);
               partialLot2 = NormalizeDouble(lot*Partial_Lot2/100,2);
               remainingLot = NormalizeDouble(lot-partialLot1,2); 
               remainingLot2 = NormalizeDouble(remainingLot-partialLot2,2);
               
               if(Tp>PriceOpen){
                  if(m_deal.DealType() == DEAL_TYPE_BUY){
                     target1 = NormalizeDouble((PriceOpen+((Tp-PriceOpen)*MinReward_TP1/100)),_Digits);
                     target2 = NormalizeDouble((PriceOpen+((Tp-PriceOpen)*MinReward_TP2/100)),_Digits);
                     Comment("Son işlem BUY | Lot: ",lot," | Price Open: ",PriceOpen," | TP1: ",target1," | TP2: ",target2," | TP3: ",Tp);
                     
                     if(PosVolume == lot){
                        if(BID>=target1){
                           if(Bars_PARTIAL!=TimeSeconds()){
                              if(m_trade.PositionClosePartial(PosID,partialLot1)){
                                 Bars_PARTIAL=TimeSeconds();
                                    Print(PosID," Nolu Emir -> TP1 hits, Orjinal Lot: ",lot," | Kapatılan Lot: ",partialLot1," | Kalan Lot: ",remainingLot," | Fiyat: ",BID);
                              }
                           }           
                        }                           
                     }else if(PosVolume == remainingLot){
                        if(BID>=target2){
                           if(Bars_PARTIAL!=TimeSeconds()){
                              if(m_trade.PositionClosePartial(PosID,partialLot2)){
                                 Bars_PARTIAL=TimeSeconds();
                                 Print(PosID," Nolu Emir -> TP2 hits, Orjinal Lot: ",lot," | Kapatılan Lot: ",partialLot2," | Kalan Lot: ",remainingLot2," | Fiyat: ",BID);
                              }           
                           }                           
                        }
                     }
                     
                  }
               }
               if(Tp<PriceOpen){
                  if(m_deal.DealType() == DEAL_TYPE_SELL){
                     target3 = NormalizeDouble((PriceOpen-((PriceOpen-Tp)*MinReward_TP1/100)),_Digits);
                     target4 = NormalizeDouble((PriceOpen-((PriceOpen-Tp)*MinReward_TP2/100)),_Digits);
                     Comment("Son işlem SELL | Lot: ",lot," | Price Open: ",PriceOpen," | TP1: ",target3," | TP2: ",target4," | TP3: ",Tp);
                     if(PosVolume == lot){
                        if(ASK<=target3){
                           if(Bars_PARTIAL!=TimeSeconds()){
                              if(m_trade.PositionClosePartial(PosID,partialLot1)){
                                 Bars_PARTIAL=TimeSeconds();
                                    Print(PosID," Nolu Emir -> TP1 hits, Orjinal Lot: ",lot," | Kapatılan Lot: ",partialLot1," | Kalan Lot: ",remainingLot," | Fiyat: ",ASK);
                              }
                           }           
                        }                           
                     }else if(PosVolume == remainingLot){
                        if(ASK<=target4){
                           if(Bars_PARTIAL!=TimeSeconds()){
                              if(m_trade.PositionClosePartial(PosID,partialLot2)){
                                 Bars_PARTIAL=TimeSeconds();
                                 Print(PosID," Nolu Emir -> TP2 hits, Orjinal Lot: ",lot," | Kapatılan Lot: ",partialLot2," | Kalan Lot: ",remainingLot2," | Fiyat: ",ASK);
                              }         
                           }                           
                        }
                     }
                  }
               }
            }
         }
      }
   }
}
 

TP1 and TP2 is calculated from original TP. You can use something like this.

For example: Your TP is 300 pips. And your lot is 3.

input int MinReward_TP1 = 38;             // TP1 - Reward * %
input int Partial_Lot1 = 33;              // TP1 - Original Lot * %

TP1 REWARD is 300*38/100 = 114 pips. TP1 partial lot = 3*33/100 = 0,99 lot.

input int MinReward_TP2 = 62;             // TP2 - Reward %
input int Partial_Lot2 = 33;              // TP2 - Orjinal Lot * % 

TP2 Reward is 300*62/100 = 186 pips. TP2 Partial lot = 3*33/100 = 0,99 lot.