How to start with MQL5 - page 29

 
The full version of the indicator is available at: Difference Two iMA
 

Close only profitable positions

Code: Close Profitable Position.mq5

Forum on trading, automated trading systems and testing trading strategies

(MQL5) Close when position reaches a specified profit

Vladimir Karputov, 2020.11.08 06:17

***The EA checks the positions for all symbols and for all Magic Numbers.

//+------------------------------------------------------------------+
//|                                    Close Profitable Position.mq5 |
//|                              Copyright © 2020, Vladimir Karputov |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2020, Vladimir Karputov"
#property version   "1.000"
/*
   barabashkakvn Trading engine 3.143
*/
#include <Trade\PositionInfo.mqh>
#include <Trade\Trade.mqh>
//---
CPositionInfo  m_position;             // object of CPositionInfo class
CTrade         m_trade;                // object of CTrade class
//--- input parameters
input double   InpProfitInMoney  = 9;  // Profit in money
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   for(int i=PositionsTotal()-1; i>=0; i--) // returns the number of current positions
      if(m_position.SelectByIndex(i)) // selects the position by index for further access to its properties
        {
         double profit=m_position.Commission()+m_position.Swap()+m_position.Profit();
         if(profit>=InpProfitInMoney)
            m_trade.PositionClose(m_position.Ticket());
        }
  }
//+------------------------------------------------------------------+

 

Custom Moving Average as a resource

Code: Custom Moving Average as a resource.mq5

It is often asked: "If an Expert Advisor uses a custom indicator, how should you write the Expert Advisor code correctly to make the Expert Advisor work on the MQL5 VPS"?

The answer is this: the indicator must be created as a resource. See example below:

Please note: I moved the 'Custom Moving Average' indicator to the root folder 'Indicators'

//+------------------------------------------------------------------+
//|                          Custom Moving Average as a resource.mq5 |
//|                              Copyright © 2021, Vladimir Karputov |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2021, Vladimir Karputov"
#property version   "1.000"
#property description "An example of using the MQL5 VPS: the Expert Advisor uses the 'Custom Moving Average' indicator as a resource"
#resource "\\Indicators\\Custom Moving Average.ex5"
//--- input parameters
input int            InpMAPeriod = 13;          // Period
input int            InpMAShift  = 0;           // Shift
input ENUM_MA_METHOD InpMAMethod = MODE_SMMA;   // Method
input bool           InpPrintLog = true;        // Print log
//---
int      handle_iCustom;                        // variable for storing the handle of the iCustom indicator
datetime m_prev_bars             = 0;           // "0" -> D'1970.01.01 00:00';
bool     m_init_error            = false;       // error on InInit
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- create timer
   EventSetTimer(60);
//--- create handle of the indicator iCustom
   handle_iCustom=iCustom(Symbol(),Period(),"::Indicators\\Custom Moving Average.ex5");
//--- if the handle is not created
   if(handle_iCustom==INVALID_HANDLE)
     {
      //--- tell about the failure and output the error code
      PrintFormat("Failed to create handle of the iCustom indicator for the symbol %s/%s, error code %d",
                  Symbol(),
                  EnumToString(Period()),
                  GetLastError());
      //--- the indicator is stopped early
      m_init_error=true;
      return(INIT_SUCCEEDED);
     }
   Print(__FUNCTION__);
//---
   double array_ma[];
   ArraySetAsSeries(array_ma,true);
   int start_pos=0,count=3;
   if(iGetArray(handle_iCustom,0,start_pos,count,array_ma))
     {
      Print("---");
      Print(TimeToString(m_prev_bars,TIME_DATE|TIME_MINUTES));
      string text="";
      for(int i=0; i<count; i++)
         text=text+IntegerToString(i)+": "+DoubleToString(array_ma[i],Digits()+1)+"\n";
      //---
      Print(text);
     }
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- destroy timer
   EventKillTimer();
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
  }
//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
//---
   if(m_init_error)
      return;
//--- we work only at the time of the birth of new bar
   datetime time_0=iTime(Symbol(),Period(),0);
   if(time_0==m_prev_bars)
      return;
   m_prev_bars=time_0;
//---
   double array_ma[];
   ArraySetAsSeries(array_ma,true);
   int start_pos=0,count=3;
   if(!iGetArray(handle_iCustom,0,start_pos,count,array_ma))
     {
      m_prev_bars=0;
      return;
     }
   Print("---");
   Print(__FUNCTION__);
   Print(TimeToString(m_prev_bars,TIME_DATE|TIME_MINUTES));
   string text="";
   for(int i=0; i<count; i++)
      text=text+IntegerToString(i)+": "+DoubleToString(array_ma[i],Digits()+1)+"\n";
   Print(text);
//---
  }
//+------------------------------------------------------------------+
//| Get value of buffers                                             |
//+------------------------------------------------------------------+
bool iGetArray(const int handle,const int buffer,const int start_pos,
               const int count,double &arr_buffer[])
  {
   bool result=true;
   if(!ArrayIsDynamic(arr_buffer))
     {
      if(InpPrintLog)
         PrintFormat("ERROR! EA: %s, FUNCTION: %s, this a no dynamic array!",__FILE__,__FUNCTION__);
      return(false);
     }
   ArrayFree(arr_buffer);
//--- reset error code
   ResetLastError();
//--- fill a part of the iBands array with values from the indicator buffer
   int copied=CopyBuffer(handle,buffer,start_pos,count,arr_buffer);
   if(copied!=count)
     {
      //--- if the copying fails, tell the error code
      if(InpPrintLog)
         PrintFormat("ERROR! EA: %s, FUNCTION: %s, amount to copy: %d, copied: %d, error code %d",
                     __FILE__,__FUNCTION__,count,copied,GetLastError());
      //--- quit with zero result - it means that the indicator is considered as not calculated
      return(false);
     }
   return(result);
  }
//+------------------------------------------------------------------+


I have compiled an indicator and an advisor. The EA attached it to the chart and carried out the migration. The result of working at the MQL5 VPS:

Custom Moving Average as a resource

As you can see, everything works great!

 

Adding the 'iSAR' indicator to the chart

Code: iSAR ChartIndicatorAdd.mq5

//+------------------------------------------------------------------+
//|                                       iSAR ChartIndicatorAdd.mq5 |
//|                              Copyright © 2021, Vladimir Karputov |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2021, Vladimir Karputov"
#property version   "1.00"
//--- input parameters
input group             "SAR"
input double               Inp_SAR_step         = 0.02;     // SAR: price increment step - acceleration factor
input double               Inp_SAR_maximum      = 0.2;      // SAR: maximum value of step
//---
int      handle_iSAR;               // variable for storing the handle of the iSAR indicator
bool     m_init_error   = false;    // error on InInit
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- create handle of the indicator iSAR
   handle_iSAR=iSAR(Symbol(),Period(),Inp_SAR_step,Inp_SAR_maximum);
//--- if the handle is not created
   if(handle_iSAR==INVALID_HANDLE)
     {
      //--- tell about the failure and output the error code
      PrintFormat("Failed to create handle of the iSAR indicator for the symbol %s/%s, error code %d",
                  Symbol(),
                  EnumToString(Period()),
                  GetLastError());
      //--- the indicator is stopped early
      m_init_error=true;
      return(INIT_SUCCEEDED);
     }
//---
   int debug         = MQLInfoInteger(MQL_DEBUG);
   int profiler      = MQLInfoInteger(MQL_PROFILER);
   int tester        = MQLInfoInteger(MQL_TESTER);
   int forward       = MQLInfoInteger(MQL_FORWARD);
   int optimization  = MQLInfoInteger(MQL_OPTIMIZATION);
   int visual_mode   = MQLInfoInteger(MQL_VISUAL_MODE);
   /*
      Print("MQL_DEBUG: ",debug,", ",
            "MQL_PROFILER: ",profiler,", ",
            "MQL_TESTER: ",tester,", ",
            "MQL_FORWARD: ",forward,", ",
            "MQL_OPTIMIZATION: ",optimization,", ",
            "MQL_VISUAL_MODE: ",visual_mode);
   */
   /*
      F5          -> MQL_DEBUG: 1, MQL_PROFILER: 0, MQL_TESTER: 0, MQL_FORWARD: 0, MQL_OPTIMIZATION: 0, MQL_VISUAL_MODE: 0
      Ctrl + F5   -> MQL_DEBUG: 1, MQL_PROFILER: 0, MQL_TESTER: 1, MQL_FORWARD: 0, MQL_OPTIMIZATION: 0, MQL_VISUAL_MODE: 1
      Online      -> MQL_DEBUG: 0, MQL_PROFILER: 0, MQL_TESTER: 0, MQL_FORWARD: 0, MQL_OPTIMIZATION: 0, MQL_VISUAL_MODE: 0
   */
//---
   if((debug==1 && tester==0) || (debug==0 && tester==0)) // F5 OR Online
     {
      int windows_total=(int)ChartGetInteger(0,CHART_WINDOWS_TOTAL);
      for(int i=windows_total-1; i>=0; i--)
        {
         for(int j=ChartIndicatorsTotal(0,i)-1; j>=0; j--)
           {
            string name=ChartIndicatorName(0,i,j);
            Print(__FUNCSIG__,", windows ",i,", indicator# ",j,", indicator name ",name);
            if(name=="SAR("+DoubleToString(Inp_SAR_step,2)+","+DoubleToString(Inp_SAR_maximum,2)+")")
               ChartIndicatorDelete(0,i,name);
           }
        }
      //---
      bool add=ChartIndicatorAdd(ChartID(),0,handle_iSAR);
      Print("Result Chart Indicator Add 'SAR': ",((add)?"true":"false"));
     }
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   if(handle_iSAR!=INVALID_HANDLE)
      IndicatorRelease(handle_iSAR);
   int debug         = MQLInfoInteger(MQL_DEBUG);
   int profiler      = MQLInfoInteger(MQL_PROFILER);
   int tester        = MQLInfoInteger(MQL_TESTER);
   int forward       = MQLInfoInteger(MQL_FORWARD);
   int optimization  = MQLInfoInteger(MQL_OPTIMIZATION);
   int visual_mode   = MQLInfoInteger(MQL_VISUAL_MODE);
   /*
      Print("MQL_DEBUG: ",debug,", ",
            "MQL_PROFILER: ",profiler,", ",
            "MQL_TESTER: ",tester,", ",
            "MQL_FORWARD: ",forward,", ",
            "MQL_OPTIMIZATION: ",optimization,", ",
            "MQL_VISUAL_MODE: ",visual_mode);
   */
   /*
      F5          -> MQL_DEBUG: 1, MQL_PROFILER: 0, MQL_TESTER: 0, MQL_FORWARD: 0, MQL_OPTIMIZATION: 0, MQL_VISUAL_MODE: 0
      Ctrl + F5   -> MQL_DEBUG: 1, MQL_PROFILER: 0, MQL_TESTER: 1, MQL_FORWARD: 0, MQL_OPTIMIZATION: 0, MQL_VISUAL_MODE: 1
      Online      -> MQL_DEBUG: 0, MQL_PROFILER: 0, MQL_TESTER: 0, MQL_FORWARD: 0, MQL_OPTIMIZATION: 0, MQL_VISUAL_MODE: 0
   */
//---
   if((debug==1 && tester==0) || (debug==0 && tester==0)) // F5 OR Online
     {
      int windows_total=(int)ChartGetInteger(0,CHART_WINDOWS_TOTAL);
      for(int i=windows_total-1; i>=0; i--)
        {
         for(int j=ChartIndicatorsTotal(0,i)-1; j>=0; j--)
           {
            string name=ChartIndicatorName(0,i,j);
            Print(__FUNCTION__,", windows ",i,", indicator# ",j,", indicator name ",name);
            if(name=="SAR("+DoubleToString(Inp_SAR_step,2)+","+DoubleToString(Inp_SAR_maximum,2)+")")
               ChartIndicatorDelete(0,i,name);
           }
        }
     }
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   if(m_init_error)
      return;
  }
//+------------------------------------------------------------------+


Result:

We have a chart with two indicators: iMA in the main window and iMACD in the subwindow.

iSAR ChartIndicatorAdd


We launch our advisor:

iSAR ChartIndicatorAdd

and tab 'Experts':

iSAR ChartIndicatorAdd (GBPUSD,M20)     int OnInit(), windows 1, indicator# 0, indicator name MACD(12,26,9)
iSAR ChartIndicatorAdd (GBPUSD,M20)     int OnInit(), windows 0, indicator# 0, indicator name MA(13)
iSAR ChartIndicatorAdd (GBPUSD,M20)     Result Chart Indicator Add 'SAR': true


If you switch the timeframe:

iSAR ChartIndicatorAdd

check: looks at all indicators

iSAR ChartIndicatorAdd

and tab 'Experts':

iSAR ChartIndicatorAdd (GBPUSD,M20)     OnDeinit, windows 1, indicator# 0, indicator name MACD(12,26,9)
iSAR ChartIndicatorAdd (GBPUSD,M20)     OnDeinit, windows 0, indicator# 1, indicator name SAR(0.02,0.20)
iSAR ChartIndicatorAdd (GBPUSD,M20)     OnDeinit, windows 0, indicator# 0, indicator name MA(13)
iSAR ChartIndicatorAdd (GBPUSD,H4)      int OnInit(), windows 1, indicator# 0, indicator name MACD(12,26,9)
iSAR ChartIndicatorAdd (GBPUSD,H4)      int OnInit(), windows 0, indicator# 0, indicator name MA(13)
iSAR ChartIndicatorAdd (GBPUSD,H4)      Result Chart Indicator Add 'SAR': true


 

Why does a window, when hidden, return different parameters than when it is active?

The answer is simple - it's all about the Windows operating system. A window can have several states: the window is fully maximized, minimized, and minimized. When the window is inactive, it is in the minimized state (if you have not minimized it before). Let's check it out. We use the Bar number indicator - it numbers the bars and the service indicator 'CHART_FIRST_VISIBLE_BAR.mq5' - the indicator displays the value

CHART_FIRST_VISIBLE_BAR

The number of the first visible bar on the chart. Bar indexing matches   timeseries .

int r / o


Here's what happens: first, the window is fully maximized, then the window is minimized, and after that we switch to another chart (which we fully maximize)

CHART_FIRST_VISIBLE_BAR



Bar number
Bar number
  • www.mql5.com
Нумерация баров при помощи графических объектов OBJ_TEXT
 

Hello Vladimir,

Thanks so much for your efforts with numerous codes and EA that have assisted several beginners in MQL5 programming like me understand the rudiments of coding MQL5 language.   

Please I have this EA, copied and modified from some of your codes to suit my strategy, which is supposed to ensure that not more than 2 positions share similar lot sizes.

For instance, only One Sell and One Buy position can have same lot size i.e. for any particular lot size, only One Buy and One Sell position can be opened.

Furthermore, when last opened Buy position is in losses, it ought to Open a Sell with similar Lot size and vice versa.

The challenge encountered is that the EA hardly opens a Sell position even when last Buy position is in losses.

   if(count_positions>0)
     {
      double Ask=NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
      double Bid=NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
      double max_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX);
      if(last_position_type==POSITION_TYPE_BUY && m_symbol.Ask()-(TP * _Point) >last_position_price_open)
         m_trade.Buy(last_position_volume*2,m_symbol.Name(),Ask,0,(Ask+TP*_Point),NULL);
      if(last_position_type==POSITION_TYPE_BUY && last_position_price_open > m_symbol.Ask() + (TP * _Point))
         if(count_max_volume==1 && last_position_volume==max_volume)
            m_trade.Sell(last_position_volume*1,m_symbol.Name(),Bid,0,(Bid-TP*_Point),NULL);
      if(last_position_type==POSITION_TYPE_SELL && m_symbol.Bid()+(TP * _Point) <last_position_price_open)
         m_trade.Sell(last_position_volume*2,m_symbol.Name(),Bid,0,(Bid-TP*_Point),NULL);
      if(last_position_type==POSITION_TYPE_SELL && last_position_price_open < m_symbol.Bid() - (TP * _Point))
         if(count_max_volume==1 && last_position_volume==max_volume)
            m_trade.Buy(last_position_volume*1,m_symbol.Name(),Ask,0,(Ask+TP*_Point),NULL);
     }
   if(count_positions==0 && count_pending_orders==0)
     {
      double Ask=NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
      double Bid=NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
      m_trade.Sell(InpLot,m_symbol.Name(),Bid,0,(Bid-TP*_Point),NULL);
      m_trade.Buy(InpLot,m_symbol.Name(),Ask,0,(Ask+TP*_Point),NULL);
      return;
     }

 

 

 

 
CodeFx # :


Try this code:

   if(count_positions>0)
     {
      string Name       = m_symbol.Name();
      double Ask        = m_symbol.Ask();
      double Bid        = m_symbol.Bid();
      double LotsMax    = m_symbol.LotsMax();
      if(last_position_type==POSITION_TYPE_BUY && (Ask-m_take_profit>last_position_price_open))
        {
         m_trade.Buy(last_position_volume*2.0,Name,Ask,0.0,m_symbol.NormalizePrice(Ask+m_take_profit)));
         return;
        }
      if(last_position_type==POSITION_TYPE_BUY && (last_position_price_open>Ask+m_take_profit))
        {
         if(count_max_volume==1 && last_position_volume==LotsMax)
           {
            m_trade.Sell(last_position_volume*1.0,Name,Bid,0.0,m_symbol.NormalizePrice(Bid-m_take_profit));
            return;
           }
        }
      if(last_position_type==POSITION_TYPE_SELL && (Bid+m_take_profit<last_position_price_open))
        {
         m_trade.Sell(last_position_volume*2.0,Name,Bid,0.0,m_symbol.NormalizePrice(Bid-m_take_profit));
         return;
        }
      if(last_position_type==POSITION_TYPE_SELL && (last_position_price_open<Bid-m_take_profit))
        {
         if(count_max_volume==1 && last_position_volume==LotsMax)
           {
            m_trade.Buy(last_position_volume*1.0,Name,Ask,0,m_symbol.NormalizePrice(Ask+m_take_profit));
            return;
           }
        }
     }
   if(count_positions==0 && count_pending_orders==0)
     {
      m_trade.Sell(InpLot,Name,Bid,0.0,m_symbol.NormalizePrice(Bid-m_take_profit));
      m_trade.Buy(InpLot,Name,Ask,0.0,m_symbol.NormalizePrice(Ask+m_take_profit));
      return;
     }
 
Vladimir Karputov #:

Try this code:

Thanks so much for your assistance. I tried the code as advised however I discovered that a maximum of 7 positions were opened within a year when backtested while for some other years only 2 positions opened. Kindly see the complete code below:

***

 
CodeFx # :

Thanks so much for your assistance. I tried the code as advised however I discovered that a maximum of 7 positions were opened within a year when backtested while for some other years only 2 positions opened. Kindly see the complete code below:

***

Please never insert the code as a sheet of text.

You need to do this: insert text using the button Codeand add the code using the button Attach file...

 
Vladimir Karputov #:

Please never insert the code as a sheet of text.

You need to do this: insert text using the button and add the code using the button ...

Many thanks for the correction and apologies for that error. Kindly see the complete code, based on your advice, which opened a maximum of 7 positions within a year when backtested while for some other years only 2 positions were opened: 

//+------------------------------------------------------------------+
//|                                                 New edition).mq5 |
//|                                              Copyright © 2021,   |
//|                                          |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2021"
#property link      "CodeFx"
#property version   "1.000"
//---
#include <Trade\PositionInfo.mqh>
#include <Trade\Trade.mqh>
#include <Trade\SymbolInfo.mqh>  
#include <Trade\OrderInfo.mqh>

CPositionInfo  m_position;                   // trade position object
CTrade         m_trade;                      // trading object
CSymbolInfo    m_symbol;                     // symbol info object
COrderInfo     m_order;                      // pending orders object
//--- input parameters
input ushort   InpStep           = 10;
input double   InpLot            = 0.01;
ulong          m_magic           = 12345;    // magic number
ulong          m_slippage=30;                // slippage
//---
double         ExtStep=0.0;
double         m_adjusted_point;             // point value adjusted for 3 or 5 points
input int      PF                = 10;       // Incremental Profit To Close All Trades
input int      DEP               = 1000;     // Deposit or Start Balance 
double         Previous_balance  = AccountInfoDouble (ACCOUNT_BALANCE); // Balance at start of each algorithm  
double         m_take_profit     = 250;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
 
   Comment("????? ????????? ",TimeToString(TimeCurrent(),TIME_DATE|TIME_MINUTES|TIME_SECONDS));
//---
   if(!m_symbol.Name(Symbol())) // sets symbol name
      return(INIT_FAILED);
   RefreshRates();

   string err_text="";
   if(!CheckVolumeValue(InpLot,err_text))
     {
      Print(err_text);
      return(INIT_PARAMETERS_INCORRECT);
     }
//---
   m_trade.SetExpertMagicNumber(m_magic);
//---
   if(IsFillingTypeAllowed(m_symbol.Name(),SYMBOL_FILLING_FOK))
      m_trade.SetTypeFilling(ORDER_FILLING_FOK);
   else if(IsFillingTypeAllowed(m_symbol.Name(),SYMBOL_FILLING_IOC))
      m_trade.SetTypeFilling(ORDER_FILLING_IOC);
   else
      m_trade.SetTypeFilling(ORDER_FILLING_RETURN);
//---
   m_trade.SetDeviationInPoints(m_slippage);
//--- tuning for 3 or 5 digits
   int digits_adjust=1;
   if(m_symbol.Digits()==3 || m_symbol.Digits()==5)
      digits_adjust=10;
   m_adjusted_point=m_symbol.Point()*digits_adjust;

   ExtStep=InpStep*m_adjusted_point;
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
 {
   datetime             last_position_time         = 0;
   double               last_position_price_open   = 0.0;
   double               last_position_volume       = 0.0;
   ENUM_POSITION_TYPE   last_position_type         = -1;
   int                  count_positions            = 0;    
   int                  count_max_volume           = 0;
   double               total_profit               = 0;

   for(int i=PositionsTotal()-1;i>=0;i--)
      if(m_position.SelectByIndex(i)) // selects the position by index for further access to its properties
         if(m_position.Symbol()==m_symbol.Name() && m_position.Magic()==m_magic)
           {
            if(m_position.Time()>last_position_time)
              {
               last_position_time         = m_position.Time();
               last_position_price_open   = m_position.PriceOpen();
               last_position_volume       = m_position.Volume();
               last_position_type         = m_position.PositionType();               
              }
            count_positions++;
            count_max_volume++;           
            total_profit=total_profit+m_position.Commission()+m_position.Swap()+m_position.Profit();
           }
           
   int count_pending_orders=0;
   for(int i=OrdersTotal()-1;i>=0;i--) // returns the number of current orders
      if(m_order.SelectByIndex(i)) // selects the pending order by index for further access to its properties
         if(m_order.Symbol()==m_symbol.Name() && m_order.Magic()==m_magic)
            count_pending_orders++;

if (PositionsTotal()==0)
{Previous_balance = AccountInfoDouble (ACCOUNT_BALANCE);} 

double equity    = AccountInfoDouble (ACCOUNT_EQUITY);
if(equity > Previous_balance + PF) 
     {
      Print("Closing on profit");
      CloseAllPositions();
      return;
     } 

   if(!RefreshRates())
      return;

if(count_positions>0)
     {
      string Name       = m_symbol.Name();
      double Ask        = m_symbol.Ask();
      double Bid        = m_symbol.Bid();
      double LotsMax    = m_symbol.LotsMax();
      
      if(last_position_type==POSITION_TYPE_BUY && (Ask-m_take_profit>last_position_price_open))
        {
         m_trade.Buy(last_position_volume*2.0,Name,Ask,0.0,m_symbol.NormalizePrice(Ask+m_take_profit));
         return;
        }
        
      if(last_position_type==POSITION_TYPE_BUY && (last_position_price_open>Ask+m_take_profit))
        {
         if(count_max_volume==1 && last_position_volume==LotsMax)
           {
            m_trade.Sell(last_position_volume*1.0,Name,Bid,0.0,m_symbol.NormalizePrice(Bid-m_take_profit));
            return;
           }
        }
        
      if(last_position_type==POSITION_TYPE_SELL && (Bid+m_take_profit<last_position_price_open))
        {
         m_trade.Sell(last_position_volume*2.0,Name,Bid,0.0,m_symbol.NormalizePrice(Bid-m_take_profit));
         return;
        }
        
      if(last_position_type==POSITION_TYPE_SELL && (last_position_price_open<Bid-m_take_profit))
        {
         if(count_max_volume==1 && last_position_volume==LotsMax)
           {
            m_trade.Buy(last_position_volume*1.0,Name,Ask,0,m_symbol.NormalizePrice(Ask+m_take_profit));
            return;
           }
        }
     }
     
   if(count_positions==0 && count_pending_orders==0)
     {
      string Name       = m_symbol.Name();
      double Ask        = m_symbol.Ask();
      double Bid        = m_symbol.Bid();
      m_trade.Sell(InpLot,Name,Bid,0.0,m_symbol.NormalizePrice(Bid-m_take_profit));
      m_trade.Buy(InpLot,Name,Ask,0.0,m_symbol.NormalizePrice(Ask+m_take_profit));
      return;
     }


   if(count_positions>0 && count_pending_orders>0)
      DeleteAllOrders();
//---
   return;
  }
//+------------------------------------------------------------------+
//| Refreshes the symbol quotes data                                 |
//+------------------------------------------------------------------+
bool RefreshRates()
  {
//--- refresh rates
   if(!m_symbol.RefreshRates())
      return(false);
//--- protection against the return value of "zero"
   if(m_symbol.Ask()==0 || m_symbol.Bid()==0)
      return(false);
//---
   return(true);
  }
  
//+------------------------------------------------------------------+
//| Check the correctness of the order volume                        |
//+------------------------------------------------------------------+
bool CheckVolumeValue(double volume,string &error_description)
  {
//--- minimal allowed volume for trade operations
// double min_volume=m_symbol.LotsMin();
   double min_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MIN);
   if(volume<min_volume)
     {
      error_description=StringFormat("Volume is less than the minimal allowed SYMBOL_VOLUME_MIN=%.2f",min_volume);
      return(false);
     }

//--- maximal allowed volume of trade operations
// double max_volume=m_symbol.LotsMax();
   double max_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX);
   if(volume>max_volume)
     {
      error_description=StringFormat("Volume is greater than the maximal allowed SYMBOL_VOLUME_MAX=%.2f",max_volume);
      return(false);
     }

//--- get minimal step of volume changing
// double volume_step=m_symbol.LotsStep();
   double volume_step=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_STEP);

   int ratio=(int)MathRound(volume/volume_step);
   if(MathAbs(ratio*volume_step-volume)>0.0000001)
     {
      error_description=StringFormat("Volume is not a multiple of the minimal step SYMBOL_VOLUME_STEP=%.2f, the closest correct volume is %.2f",
                                     volume_step,ratio*volume_step);
      return(false);
     }
   error_description="Correct volume value";
   return(true);
  }
//+------------------------------------------------------------------+ 
//| Checks if the specified filling mode is allowed        .          | 
//+------------------------------------------------------------------+ 
bool IsFillingTypeAllowed(string symbol,int fill_type)
  {
//--- Obtain the value of the property that describes allowed filling modes 
   int filling=(int)SymbolInfoInteger(symbol,SYMBOL_FILLING_MODE);
//--- Return true, if mode fill_type is allowed 
   return((filling & fill_type)==fill_type);
  }
//+------------------------------------------------------------------+
//| Close all positions                                              |
//+------------------------------------------------------------------+
void CloseAllPositions()
  { 
   for(int i=PositionsTotal()-1;i>=0;i--) // returns the number of current positions
      if(m_position.SelectByIndex(i))     // selects the position by index for further access to its properties
         if(m_position.Symbol()==m_symbol.Name() && m_position.Magic()==m_magic)
            m_trade.PositionClose(m_position.Ticket()); // close a position by the specified symbol
  }
//+------------------------------------------------------------------+
//| Delete all pendingA rders                                         |
//+------------------------------------------------------------------+
void DeleteAllOrders()
  {
   for(int i=OrdersTotal()-1;i>=0;i--) // returns the number of current orders
      if(m_order.SelectByIndex(i))     // selects the pending order by index for further access to its properties
         if(m_order.Symbol()==m_symbol.Name() && m_order.Magic()==m_magic)
            m_trade.OrderDelete(m_order.Ticket());
  }
//+------------------------------------------------------------------+


However, my initial code opened several positions yearly as expected but its problem was just that when the last opened Buy position is in losses it fails to open a sell position as intended. Kindly have a look at the code:

//+------------------------------------------------------------------+
//|                                                 New edition).mq5 |
//|                                              Copyright © 2021,   |
//|                                          |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2021"
#property link      "CodeFx"
#property version   "1.000"
//---
#include <Trade\PositionInfo.mqh>
#include <Trade\Trade.mqh>
#include <Trade\SymbolInfo.mqh>  
#include <Trade\OrderInfo.mqh>

CPositionInfo  m_position;                   // trade position object
CTrade         m_trade;                      // trading object
CSymbolInfo    m_symbol;                     // symbol info object
COrderInfo     m_order;                      // pending orders object
//--- input parameters
input ushort   InpStep           = 10;
input double   InpLot            = 0.01;
ulong          m_magic           = 12345;    // magic number
ulong          m_slippage        = 30;       // slippage
//---
double         ExtStep           = 0.0;
double         m_adjusted_point;             // point value adjusted for 3 or 5 points
input int      PF                = 10;       // Incremental Profit To Close All Trades
input int      DEP               = 1000;     // Deposit or Start Balance 
input int      TP                = 250;      // TakeProfit
double         Previous_balance  = AccountInfoDouble (ACCOUNT_BALANCE); // Balance at start of each algorithm  

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
 
   Comment("????? ????????? ",TimeToString(TimeCurrent(),TIME_DATE|TIME_MINUTES|TIME_SECONDS));
//---
   if(!m_symbol.Name(Symbol())) // sets symbol name
      return(INIT_FAILED);
   RefreshRates();

   string err_text="";
   if(!CheckVolumeValue(InpLot,err_text))
     {
      Print(err_text);
      return(INIT_PARAMETERS_INCORRECT);
     }
//---
   m_trade.SetExpertMagicNumber(m_magic);
//---
   if(IsFillingTypeAllowed(m_symbol.Name(),SYMBOL_FILLING_FOK))
      m_trade.SetTypeFilling(ORDER_FILLING_FOK);
   else if(IsFillingTypeAllowed(m_symbol.Name(),SYMBOL_FILLING_IOC))
      m_trade.SetTypeFilling(ORDER_FILLING_IOC);
   else
      m_trade.SetTypeFilling(ORDER_FILLING_RETURN);
//---
   m_trade.SetDeviationInPoints(m_slippage);
//--- tuning for 3 or 5 digits
   int digits_adjust=1;
   if(m_symbol.Digits()==3 || m_symbol.Digits()==5)
      digits_adjust=10;
   m_adjusted_point=m_symbol.Point()*digits_adjust;

   ExtStep=InpStep*m_adjusted_point;
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   datetime             last_position_time         = 0;
   double               last_position_price_open   = 0.0;
   double               last_position_volume       = 0.0;
   ENUM_POSITION_TYPE   last_position_type         = -1;
   int                  count_positions            = 0;    
   int                  count_max_volume           = 0;
   double               total_profit               = 0;

   for(int i=PositionsTotal()-1;i>=0;i--)
      if(m_position.SelectByIndex(i)) // selects the position by index for further access to its properties
         if(m_position.Symbol()==m_symbol.Name() && m_position.Magic()==m_magic)
           {
            if(m_position.Time()>last_position_time)
              {
               last_position_time         = m_position.Time();
               last_position_price_open   = m_position.PriceOpen();
               last_position_volume       = m_position.Volume();
               last_position_type         = m_position.PositionType();               
              }
            count_positions++;
            count_max_volume++;           
            total_profit=total_profit+m_position.Commission()+m_position.Swap()+m_position.Profit();
           }
   int count_pending_orders=0;
   for(int i=OrdersTotal()-1;i>=0;i--) // returns the number of current orders
      if(m_order.SelectByIndex(i)) // selects the pending order by index for further access to its properties
         if(m_order.Symbol()==m_symbol.Name() && m_order.Magic()==m_magic)
            count_pending_orders++;

if (PositionsTotal()==0)
{Previous_balance = AccountInfoDouble (ACCOUNT_BALANCE);} 

double equity    = AccountInfoDouble (ACCOUNT_EQUITY);
if(equity > Previous_balance + PF) 
     {
      Print("Closing on profit");
      CloseAllPositions();
      return;
     } 

   if(!RefreshRates())
      return;

   if(count_positions>0)
     {
       double Ask=NormalizeDouble (SymbolInfoDouble (_Symbol,SYMBOL_ASK),_Digits);
       double Bid=NormalizeDouble (SymbolInfoDouble (_Symbol,SYMBOL_BID),_Digits); 
       double max_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX);
       
       if(last_position_type==POSITION_TYPE_BUY && m_symbol.Ask()-(TP * _Point) >last_position_price_open )                  
         m_trade.Buy(last_position_volume*2,m_symbol.Name(),Ask,0,(Ask+TP*_Point),NULL);
                                     
       if(last_position_type==POSITION_TYPE_BUY && last_position_price_open > m_position.PriceCurrent() + (TP * _Point) )                                 
       if(count_max_volume==1 && last_position_volume==max_volume) 
           m_trade.Sell(last_position_volume*1,m_symbol.Name(),Bid,0,(Bid-TP*_Point),NULL); 
                              
       if(last_position_type==POSITION_TYPE_SELL && m_symbol.Bid()+(TP * _Point) <last_position_price_open )       
         m_trade.Sell(last_position_volume*2,m_symbol.Name(),Bid,0,(Bid-TP*_Point),NULL);  
        
       if(last_position_type==POSITION_TYPE_SELL && last_position_price_open < m_position.PriceCurrent() - (TP * _Point) )                                                  
       if(count_max_volume==1 && last_position_volume==max_volume) 
           m_trade.Buy(last_position_volume*1,m_symbol.Name(),Ask,0,(Ask+TP*_Point),NULL);                                                                                                                   
               }

   if(count_positions==0 && count_pending_orders==0)
     {
      double Ask=NormalizeDouble (SymbolInfoDouble (_Symbol,SYMBOL_ASK),_Digits);
      double Bid=NormalizeDouble (SymbolInfoDouble (_Symbol,SYMBOL_BID),_Digits);     
      m_trade.Sell(InpLot,m_symbol.Name(),Bid,0,(Bid-TP*_Point),NULL);                 
      m_trade.Buy(InpLot,m_symbol.Name(),Ask,0,(Ask+TP*_Point),NULL);      
      return;
     }

   if(count_positions>0 && count_pending_orders>0)
      DeleteAllOrders();
//---
   return;
  }
//+------------------------------------------------------------------+
//| Refreshes the symbol quotes data                                 |
//+------------------------------------------------------------------+
bool RefreshRates()
  {
//--- refresh rates
   if(!m_symbol.RefreshRates())
      return(false);
//--- protection against the return value of "zero"
   if(m_symbol.Ask()==0 || m_symbol.Bid()==0)
      return(false);
//---
   return(true);
  }
  
//+------------------------------------------------------------------+
//| Check the correctness of the order volume                        |
//+------------------------------------------------------------------+
bool CheckVolumeValue(double volume,string &error_description)
  {
//--- minimal allowed volume for trade operations
// double min_volume=m_symbol.LotsMin();
   double min_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MIN);
   if(volume<min_volume)
     {
      error_description=StringFormat("Volume is less than the minimal allowed SYMBOL_VOLUME_MIN=%.2f",min_volume);
      return(false);
     }

//--- maximal allowed volume of trade operations
// double max_volume=m_symbol.LotsMax();
   double max_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX);
   if(volume>max_volume)
     {
      error_description=StringFormat("Volume is greater than the maximal allowed SYMBOL_VOLUME_MAX=%.2f",max_volume);
      return(false);
     }

//--- get minimal step of volume changing
// double volume_step=m_symbol.LotsStep();
   double volume_step=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_STEP);

   int ratio=(int)MathRound(volume/volume_step);
   if(MathAbs(ratio*volume_step-volume)>0.0000001)
     {
      error_description=StringFormat("Volume is not a multiple of the minimal step SYMBOL_VOLUME_STEP=%.2f, the closest correct volume is %.2f",
                                     volume_step,ratio*volume_step);
      return(false);
     }
   error_description="Correct volume value";
   return(true);
  }
//+------------------------------------------------------------------+ 
//| Checks if the specified filling mode is allowed        .          | 
//+------------------------------------------------------------------+ 
bool IsFillingTypeAllowed(string symbol,int fill_type)
  {
//--- Obtain the value of the property that describes allowed filling modes 
   int filling=(int)SymbolInfoInteger(symbol,SYMBOL_FILLING_MODE);
//--- Return true, if mode fill_type is allowed 
   return((filling & fill_type)==fill_type);
  }
//+------------------------------------------------------------------+
//| Close all positions                                              |
//+------------------------------------------------------------------+
void CloseAllPositions()
  { 
   for(int i=PositionsTotal()-1;i>=0;i--) // returns the number of current positions
      if(m_position.SelectByIndex(i))     // selects the position by index for further access to its properties
         if(m_position.Symbol()==m_symbol.Name() && m_position.Magic()==m_magic)
            m_trade.PositionClose(m_position.Ticket()); // close a position by the specified symbol
  }
//+------------------------------------------------------------------+
//| Delete all pendingA rders                                         |
//+------------------------------------------------------------------+
void DeleteAllOrders()
  {
   for(int i=OrdersTotal()-1;i>=0;i--) // returns the number of current orders
      if(m_order.SelectByIndex(i))     // selects the pending order by index for further access to its properties
         if(m_order.Symbol()==m_symbol.Name() && m_order.Magic()==m_magic)
            m_trade.OrderDelete(m_order.Ticket());
  }
//+------------------------------------------------------------------+


Kindly assist, thanks. 
  

Reason: