Trailing Highest and Lowest position Net Price

Author: Copyright © 2021, Vladimir Karputov
Price Data Components
Series array that contains tick volumes of each bar
Miscellaneous
It issuies visual alerts to the screen
0 Views
0 Downloads
0 Favorites
Trailing Highest and Lowest position Net Price
ÿþ//+------------------------------------------------------------------+

//|               Trailing Highest and Lowest position Net Price.mq5 |

//|                              Copyright © 2021, Vladimir Karputov |

//|                      https://www.mql5.com/en/users/barabashkakvn |

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

#property copyright "Copyright © 2021, Vladimir Karputov"

#property link      "https://www.mql5.com/en/users/barabashkakvn"

#property version   "1.004"

#property description "'Allowed only BUY positions' - looking for the highest BUY and the lowest BUY"

#property description "'Allowed only SELL positions' - looking for the highest SELL and the lowest SELL"

#property description "Trailing - in Points (1.00055-1.00045=10 points)"

/*

   barabashkakvn Trading engine 4.005

*/

#include <Trade\PositionInfo.mqh>

#include <Trade\Trade.mqh>

#include <Trade\SymbolInfo.mqh>

#include <Trade\AccountInfo.mqh>

//---

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

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

//| Enum Trade Mode                                                  |

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

enum ENUM_TRADE_MODE

  {

   buy=0,      // Allowed only BUY positions

   sell=1,     // Allowed only SELL positions

  };

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

//| Enum Bar !urrent                                                 |

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

enum ENUM_BAR_CURRENT

  {

   bar_0=0,    // bar #0 (at every tick)

   bar_1=1,    // bar #1 (on a new bar)

  };

//--- input parameters

input group             "Trading settings"

input ENUM_TIMEFRAMES      InpWorkingPeriod        = PERIOD_CURRENT;          // Working timeframe

input ENUM_BAR_CURRENT     InpTrailingBarCurrent   = bar_1;                   // Trailing on ...

input uint                 InpTrailingStop         = 250;                     // Trailing Stop (min distance from price to Stop Loss)

input uint                 InpTrailingStep         = 50;                      // Trailing Step

input group             "Trade mode"

input ENUM_TRADE_MODE      InpTradeMode            = buy;                     // Trade mode:

input group             "Hline parameters"

//--- Hline Buy

input string               InpBuyName              = "Buy net price";         // Hline Buy: Name

input color                InpBuyColor             = clrBlue;                 // Hline Buy: Line color

input ENUM_LINE_STYLE      InpBuyStyle             = STYLE_DOT;               // Hline Buy: Line style

input int                  InpBuyWidth             = 1;                       // Hline Buy: Line width

//--- Hline Sell

input string               InpSellName             = "Sell net price";        // Hline Sell: Name

input color                InpSellColor            = clrRed;                  // Hline Sell: Line color

input ENUM_LINE_STYLE      InpSellStyle            = STYLE_DOT;               // Hline Sell: Line style

input int                  InpSellWidth            = 1;                       // Hline Sell: Line width

input group             "Additional features"

input bool                 InpPrintLog             = false;                   // Print log

input uchar                InpFreezeCoefficient    = 1;                       // Coefficient (if Freeze==0 Or StopsLevels==0)

input ulong                InpDeviation            = 10;                      // Deviation, in Points (1.00045-1.00055=10 points)

//---

double   m_trailing_stop            = 0.0;      // Trailing Stop              -> double

double   m_trailing_step            = 0.0;      // Trailing Step              -> double



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 a timer with a 1 second period

   EventSetTimer(12);

//--- forced initialization of variables

   m_trailing_stop            = 0.0;      // Trailing Stop              -> double

   m_trailing_step            = 0.0;      // Trailing Step              -> double

   m_prev_bars                = 0;        // "0" -> D'1970.01.01 00:00';

   m_init_error               = false;    // error on InInit

//---

   if(InpTrailingStop!=0 && InpTrailingStep==0)

     {

      string err_text=(TerminalInfoString(TERMINAL_LANGUAGE)=="Russian")?

                      ""@59;8=3 =52>7<>65=: ?0@0<5B@ \"Trailing Step\" @025= =C;N!":

                      "Trailing is not possible: parameter \"Trailing Step\" is zero!";

      if(MQLInfoInteger(MQL_TESTER)) // when testing, we will only output to the log about incorrect input parameters

         Print(__FILE__," ",__FUNCTION__,", ERROR: ",err_text);

      else // if the Expert Advisor is run on the chart, tell the user about the error

         Alert(__FILE__," ",__FUNCTION__,", ERROR: ",err_text);

      //---

      m_init_error=true;

      return(INIT_SUCCEEDED);

     }

//---

   ResetLastError();

   if(!m_symbol.Name(Symbol())) // sets symbol name

     {

      Print(__FILE__," ",__FUNCTION__,", ERROR: CSymbolInfo.Name");

      return(INIT_FAILED);

     }

   RefreshRates();

//---

   m_trade.SetMarginMode();

   m_trade.SetTypeFillingBySymbol(m_symbol.Name());

   m_trade.SetDeviationInPoints(InpDeviation);

//--- tuning for 3 or 5 digits

   int digits_adjust=1;

   if(m_symbol.Digits()==3 || m_symbol.Digits()==5)

      digits_adjust=10;

//---

   m_trailing_stop            = InpTrailingStop             * m_symbol.Point();

   m_trailing_step            = InpTrailingStep             * m_symbol.Point();

//---

   HLineCreate(ChartID(),InpBuyName,0,0,InpBuyColor,InpBuyStyle,InpBuyWidth);

   HLineCreate(ChartID(),InpSellName,0,0,InpSellColor,InpSellStyle,InpSellWidth);

//---

   /*bool res=false;

   while(!res)

      res=m_trade.Sell(0.01);

   Sleep(1000*3600*4);

   res=false;

   while(!res)

      res=m_trade.Sell(0.03);

   Sleep(1000*3600*4);

   res=false;

   while(!res)

      res=m_trade.Sell(0.05);

   Sleep(1000*3600*4);

   res=false;

   while(!res)

      res=m_trade.Buy(0.01);

   Sleep(1000*3600*4);

   res=false;

   while(!res)

      res=m_trade.Buy(0.03);

   Sleep(1000*3600*4);

   res=false;

   while(!res)

      res=m_trade.Buy(0.05);

   Sleep(1000*3600*4);*/

//---

   return(INIT_SUCCEEDED);

  }

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

//| Expert deinitialization function                                 |

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

void OnDeinit(const int reason)

  {

//--- destroy timer

   EventKillTimer();

//---

   HLineDelete(ChartID(),InpBuyName);

   HLineDelete(ChartID(),InpSellName);

  }

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

//| Expert tick function                                             |

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

void OnTick()

  {

   if(m_init_error)

      return;

//---

   if(InpTrailingBarCurrent==bar_0) // trailing at every tick

     {

      Trailing();

     }

//--- we work only at the time of the birth of new bar

   if(InpTrailingBarCurrent==bar_1)

     {

      datetime time_0=iTime(m_symbol.Name(),InpWorkingPeriod,0);

      if(time_0==m_prev_bars)

         return;

      m_prev_bars=time_0;

      //--- trailing only at the time of the birth of new bar

      Trailing();

     }

//---

  }

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

//| Timer function                                                   |

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

void OnTimer()

  {

//---

   if(ObjectFind(ChartID(),InpBuyName)<0)

      HLineCreate(ChartID(),InpBuyName,0,0,InpBuyColor,InpBuyStyle,InpBuyWidth);

   if(ObjectFind(ChartID(),InpSellName)<0)

      HLineCreate(ChartID(),InpSellName,0,0,InpSellColor,InpSellStyle,InpSellWidth);

  }

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

//| TradeTransaction function                                        |

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

void OnTradeTransaction(const MqlTradeTransaction &trans,

                        const MqlTradeRequest &request,

                        const MqlTradeResult &result)

  {

//---

  }

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

//| Refreshes the symbol quotes data                                 |

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

bool RefreshRates()

  {

//--- refresh rates

   if(!m_symbol.RefreshRates())

     {

      Print(__FILE__," ",__FUNCTION__,", ERROR: ","RefreshRates error");

      return(false);

     }

//--- protection against the return value of "zero"

   if(m_symbol.Ask()==0 || m_symbol.Bid()==0)

     {

      Print(__FILE__," ",__FUNCTION__,", ERROR: ","Ask == 0.0 OR Bid == 0.0");

      return(false);

     }

//---

   return(true);

  }

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

//| Check Freeze and Stops levels                                    |

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

void FreezeStopsLevels(double &freeze,double &stops)

  {

//--- check Freeze and Stops levels

   /*

   SYMBOL_TRADE_FREEZE_LEVEL shows the distance of freezing the trade operations

      for pending orders and open positions in points

   ------------------------|--------------------|--------------------------------------------

   Type of order/position  |  Activation price  |  Check

   ------------------------|--------------------|--------------------------------------------

   Buy Limit order         |  Ask               |  Ask-OpenPrice  >= SYMBOL_TRADE_FREEZE_LEVEL

   Buy Stop order          |  Ask               |  OpenPrice-Ask  >= SYMBOL_TRADE_FREEZE_LEVEL

   Sell Limit order        |  Bid               |  OpenPrice-Bid  >= SYMBOL_TRADE_FREEZE_LEVEL

   Sell Stop order         |  Bid               |  Bid-OpenPrice  >= SYMBOL_TRADE_FREEZE_LEVEL

   Buy position            |  Bid               |  TakeProfit-Bid >= SYMBOL_TRADE_FREEZE_LEVEL

                           |                    |  Bid-StopLoss   >= SYMBOL_TRADE_FREEZE_LEVEL

   Sell position           |  Ask               |  Ask-TakeProfit >= SYMBOL_TRADE_FREEZE_LEVEL

                           |                    |  StopLoss-Ask   >= SYMBOL_TRADE_FREEZE_LEVEL

   ------------------------------------------------------------------------------------------



   SYMBOL_TRADE_STOPS_LEVEL determines the number of points for minimum indentation of the

      StopLoss and TakeProfit levels from the current closing price of the open position

   ------------------------------------------------|------------------------------------------

   Buying is done at the Ask price                 |  Selling is done at the Bid price

   ------------------------------------------------|------------------------------------------

   TakeProfit        >= Bid                        |  TakeProfit        <= Ask

   StopLoss          <= Bid                        |  StopLoss          >= Ask

   TakeProfit - Bid  >= SYMBOL_TRADE_STOPS_LEVEL   |  Ask - TakeProfit  >= SYMBOL_TRADE_STOPS_LEVEL

   Bid - StopLoss    >= SYMBOL_TRADE_STOPS_LEVEL   |  StopLoss - Ask    >= SYMBOL_TRADE_STOPS_LEVEL

   ------------------------------------------------------------------------------------------

   */

   double coeff=(double)InpFreezeCoefficient;

   if(!RefreshRates() || !m_symbol.Refresh())

      return;

//--- FreezeLevel -> for pending order and modification

   double freeze_level=m_symbol.FreezeLevel()*m_symbol.Point();

   if(freeze_level==0.0)

     {

      if(InpFreezeCoefficient>0)

         freeze_level=(m_symbol.Ask()-m_symbol.Bid())*coeff;

     }

   else

      freeze_level*=coeff;

//--- StopsLevel -> for TakeProfit and StopLoss

   double stop_level=m_symbol.StopsLevel()*m_symbol.Point();

   if(stop_level==0.0)

     {

      if(InpFreezeCoefficient>0)

         stop_level=(m_symbol.Ask()-m_symbol.Bid())*coeff;

     }

   else

      stop_level*=coeff;

//---

   freeze=freeze_level;

   stops=stop_level;

//---

   return;

  }

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

//| Trailing                                                         |

//|   InpTrailingStop: min distance from price to Stop Loss          |

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

void Trailing()

  {

   if(InpTrailingStop==0)

      return;

   double freeze=0.0,stops=0.0;

   FreezeStopsLevels(freeze,stops);

   double max_levels=(freeze>stops)?freeze:stops;

   /*

   SYMBOL_TRADE_STOPS_LEVEL determines the number of points for minimum indentation of the

      StopLoss and TakeProfit levels from the current closing price of the open position

   ------------------------------------------------|------------------------------------------

   Buying is done at the Ask price                 |  Selling is done at the Bid price

   ------------------------------------------------|------------------------------------------

   TakeProfit        >= Bid                        |  TakeProfit        <= Ask

   StopLoss          <= Bid                        |  StopLoss          >= Ask

   TakeProfit - Bid  >= SYMBOL_TRADE_STOPS_LEVEL   |  Ask - TakeProfit  >= SYMBOL_TRADE_STOPS_LEVEL

   Bid - StopLoss    >= SYMBOL_TRADE_STOPS_LEVEL   |  StopLoss - Ask    >= SYMBOL_TRADE_STOPS_LEVEL

   ------------------------------------------------------------------------------------------



   SYMBOL_TRADE_FREEZE_LEVEL shows the distance of freezing the trade operations

      for pending orders and open positions in points

   ------------------------|--------------------|--------------------------------------------

   Type of order/position  |  Activation price  |  Check

   ------------------------|--------------------|--------------------------------------------

   Buy Limit order         |  Ask               |  Ask-OpenPrice  >= SYMBOL_TRADE_FREEZE_LEVEL

   Buy Stop order          |  Ask               |  OpenPrice-Ask  >= SYMBOL_TRADE_FREEZE_LEVEL

   Sell Limit order        |  Bid               |  OpenPrice-Bid  >= SYMBOL_TRADE_FREEZE_LEVEL

   Sell Stop order         |  Bid               |  Bid-OpenPrice  >= SYMBOL_TRADE_FREEZE_LEVEL

   Buy position            |  Bid               |  TakeProfit-Bid >= SYMBOL_TRADE_FREEZE_LEVEL

                           |                    |  Bid-StopLoss   >= SYMBOL_TRADE_FREEZE_LEVEL

   Sell position           |  Ask               |  Ask-TakeProfit >= SYMBOL_TRADE_FREEZE_LEVEL

                           |                    |  StopLoss-Ask   >= SYMBOL_TRADE_FREEZE_LEVEL

   ------------------------------------------------------------------------------------------

   */

   ulong  ticket_highest_buy  = 0,        ticket_lowest_buy    = 0;

   double price_highest_buy   = DBL_MIN,  price_lowest_buy     = DBL_MAX;

//---

   ulong  ticket_highest_sell = 0,        ticket_lowest_sell   = 0;

   double price_highest_sell  = DBL_MIN,  price_lowest_sell    = DBL_MAX;

//---

   for(int i=PositionsTotal()-1; i>=0; i--) // returns the number of open positions

      if(m_position.SelectByIndex(i))

         if(m_position.Symbol()==m_symbol.Name())

           {

            double price_open    = m_position.PriceOpen();

            ulong ticket         = m_position.Ticket();

            //---

            if(m_position.PositionType()==POSITION_TYPE_BUY)

              {

               if(price_open>price_highest_buy)

                 {

                  ticket_highest_buy   = ticket;

                  price_highest_buy    = price_open;

                 }

               if(price_open<price_lowest_buy)

                 {

                  ticket_lowest_buy    = ticket;

                  price_lowest_buy     = price_open;

                 }

              }

            if(m_position.PositionType()==POSITION_TYPE_SELL)

              {

               if(price_open>price_highest_sell)

                 {

                  ticket_highest_sell  = ticket;

                  price_highest_sell   = price_open;

                 }

               if(price_open<price_lowest_sell)

                 {

                  ticket_lowest_sell   = ticket;

                  price_lowest_sell    = price_open;

                 }

              }

           }

//--- check before calculating net price

   if(InpTradeMode==buy)

      if(ticket_highest_buy==0 || ticket_lowest_buy==0)

        {

         HLineMove(ChartID(),InpBuyName);

         HLineMove(ChartID(),InpSellName);

         return;

        }

   if(InpTradeMode==sell)

      if(ticket_highest_sell==0 || ticket_lowest_sell==0)

        {

         HLineMove(ChartID(),InpBuyName);

         HLineMove(ChartID(),InpSellName);

         return;

        }

//--- calculation net price

   double total_price_multiply_volume_buy    = 0.0;

   double total_volume_buy                   = 0.0;

   double net_price_buy                      = 0.0;

   double total_price_multiply_volume_sell   = 0.0;

   double total_volume_sell                  = 0.0;

   double net_price_sell                     = 0.0;

   int    count_buys                         = 0;

   int    count_sells                        = 0;

   double breakeven_price                    = 0.0;

   for(int i=PositionsTotal()-1; i>=0; i--) // returns the number of open positions

      if(m_position.SelectByIndex(i))

         if(m_position.Symbol()==m_symbol.Name())

           {

            ulong ticket         = m_position.Ticket();

            if(m_position.PositionType()==POSITION_TYPE_BUY)

              {

               if(InpTradeMode==buy && (ticket==ticket_highest_buy || ticket==ticket_lowest_buy))

                 {

                  total_price_multiply_volume_buy+=m_position.PriceOpen()*m_position.Volume();

                  total_volume_buy+=m_position.Volume();

                  count_buys++;

                 }

              }

            else

              {

               if(m_position.PositionType()==POSITION_TYPE_SELL)

                  if(InpTradeMode==sell && (ticket==ticket_highest_sell || ticket==ticket_lowest_sell))

                    {

                     total_price_multiply_volume_sell+=m_position.PriceOpen()*m_position.Volume();

                     total_volume_sell+=m_position.Volume();

                     count_sells++;

                    }

              }

           }

   if(InpTradeMode==buy)

     {

      if(total_price_multiply_volume_buy!=0 && total_volume_buy!=0)

        {

         net_price_buy=total_price_multiply_volume_buy/total_volume_buy;

         HLineMove(ChartID(),InpBuyName,net_price_buy);

        }

      else

         HLineMove(ChartID(),InpBuyName);

     }

   if(InpTradeMode==sell)

     {

      if(total_price_multiply_volume_sell!=0 && total_volume_sell!=0)

        {

         net_price_sell=total_price_multiply_volume_sell/total_volume_sell;

         HLineMove(ChartID(),InpSellName,net_price_sell);

        }

      else

         HLineMove(ChartID(),InpSellName);

     }

//--- check: can trailing be applied in two positions?

   double ask  = m_symbol.Ask();

   double bid  = m_symbol.Bid();

   if(InpTradeMode==buy && ticket_highest_buy>0 && ticket_lowest_buy>0 && ticket_highest_buy!=ticket_lowest_buy)

     {

      //--- highest buy

      if(!m_position.SelectByTicket(ticket_highest_buy))

         return;

      double price_current_highest_buy = m_position.PriceCurrent();

      double stop_loss_highest_buy     = m_position.StopLoss();

      double take_profit_highest_buy   = m_position.TakeProfit();

      long   magic_highest_buy         = m_position.Magic();

      if(!(price_current_highest_buy-net_price_buy>m_trailing_stop+m_trailing_step))

         return;

      if(!(stop_loss_highest_buy<price_current_highest_buy-(m_trailing_stop+m_trailing_step)))

         return;

      if(!(m_trailing_stop>=max_levels && (take_profit_highest_buy-bid>=max_levels || take_profit_highest_buy==0.0)))

         return;

      //--- lowest buy

      double price_current_lowest_buy  = m_position.PriceCurrent();

      double stop_loss_lowest_buy      = m_position.StopLoss();

      double take_profit_lowest_buy    = m_position.TakeProfit();

      long   magic_lowest_buy          = m_position.Magic();

      if(!m_position.SelectByTicket(ticket_lowest_buy))

         return;

      if(!(price_current_lowest_buy-net_price_buy>m_trailing_stop+m_trailing_step))

         return;

      if(!(stop_loss_lowest_buy<price_current_lowest_buy-(m_trailing_stop+m_trailing_step)))

         return;

      if(!(m_trailing_stop>=max_levels && (take_profit_lowest_buy-bid>=max_levels || take_profit_lowest_buy==0.0)))

         return;

      //--- modify

      if(!CompareDoubles(stop_loss_highest_buy,price_current_highest_buy-m_trailing_stop,m_symbol.Digits(),m_symbol.Point()))

        {

         m_trade.SetExpertMagicNumber(magic_highest_buy);

         if(!m_trade.PositionModify(ticket_highest_buy,m_symbol.NormalizePrice(price_current_highest_buy-m_trailing_stop),take_profit_highest_buy))

            if(InpPrintLog)

               Print(__FILE__," ",__FUNCTION__,", ERROR: ","Modify BUY ",ticket_highest_buy,

                     " Position -> false. Result Retcode: ",m_trade.ResultRetcode(),

                     ", description of result: ",m_trade.ResultRetcodeDescription());

        }

      if(!CompareDoubles(stop_loss_lowest_buy,price_current_lowest_buy-m_trailing_stop,m_symbol.Digits(),m_symbol.Point()))

        {

         m_trade.SetExpertMagicNumber(magic_lowest_buy);

         if(!m_trade.PositionModify(ticket_lowest_buy,m_symbol.NormalizePrice(price_current_lowest_buy-m_trailing_stop),take_profit_lowest_buy))

            if(InpPrintLog)

               Print(__FILE__," ",__FUNCTION__,", ERROR: ","Modify BUY ",ticket_lowest_buy,

                     " Position -> false. Result Retcode: ",m_trade.ResultRetcode(),

                     ", description of result: ",m_trade.ResultRetcodeDescription());

        }

     }

   if(InpTradeMode==sell && ticket_highest_sell>0 && ticket_lowest_sell>0 && ticket_highest_sell!=ticket_lowest_sell)

     {

      //--- highest sell

      if(!m_position.SelectByTicket(ticket_highest_sell))

         return;

      double price_current_highest_sell= m_position.PriceCurrent();

      double stop_loss_highest_sell    = m_position.StopLoss();

      double take_profit_highest_sell  = m_position.TakeProfit();

      long   magic_highest_sell        = m_position.Magic();

      if(!(net_price_sell-price_current_highest_sell>m_trailing_stop+m_trailing_step))

         return;

      if(!((stop_loss_highest_sell>(price_current_highest_sell+(m_trailing_stop+m_trailing_step))) || (stop_loss_highest_sell==0)))

         return;

      if(!(m_trailing_stop>=max_levels && ask-take_profit_highest_sell>=max_levels))

         return;

      //--- lowest sell

      if(!m_position.SelectByTicket(ticket_lowest_sell))

         return;

      double price_current_lowest_sell = m_position.PriceCurrent();

      double stop_loss_lowest_sell     = m_position.StopLoss();

      double take_profit_lowest_sell   = m_position.TakeProfit();

      long   magic_lowest_sell         = m_position.Magic();

      if(!(net_price_sell-price_current_lowest_sell>m_trailing_stop+m_trailing_step))

         return;

      if(!((stop_loss_lowest_sell>(price_current_lowest_sell+(m_trailing_stop+m_trailing_step))) || (stop_loss_lowest_sell==0)))

         return;

      if(!(m_trailing_stop>=max_levels && ask-take_profit_lowest_sell>=max_levels))

         return;

      //--- modify

      if(!CompareDoubles(stop_loss_highest_sell,price_current_lowest_sell+m_trailing_stop,m_symbol.Digits(),m_symbol.Point()))

        {

         m_trade.SetExpertMagicNumber(magic_highest_sell);

         if(!m_trade.PositionModify(ticket_highest_sell,m_symbol.NormalizePrice(price_current_lowest_sell+m_trailing_stop),take_profit_lowest_sell))

            if(InpPrintLog)

               Print(__FILE__," ",__FUNCTION__,", ERROR: ","Modify SELL ",ticket_highest_sell,

                     " Position -> false. Result Retcode: ",m_trade.ResultRetcode(),

                     ", description of result: ",m_trade.ResultRetcodeDescription());

        }

      if(!CompareDoubles(stop_loss_lowest_sell,price_current_lowest_sell+m_trailing_stop,m_symbol.Digits(),m_symbol.Point()))

        {

         m_trade.SetExpertMagicNumber(magic_lowest_sell);

         if(!m_trade.PositionModify(ticket_lowest_sell,m_symbol.NormalizePrice(price_current_lowest_sell+m_trailing_stop),take_profit_lowest_sell))

            if(InpPrintLog)

               Print(__FILE__," ",__FUNCTION__,", ERROR: ","Modify SELL ",ticket_lowest_sell,

                     " Position -> false. Result Retcode: ",m_trade.ResultRetcode(),

                     ", description of result: ",m_trade.ResultRetcodeDescription());

        }

     }

//--- if there is one position, there is a Stop Loss to be dropped

   if(InpTradeMode==buy)

     {

      if(ticket_highest_buy>0 && ticket_lowest_buy==0)

        {

         if(m_position.SelectByTicket(ticket_highest_buy))

           {

            if(m_position.StopLoss()>0.0)

              {

               double tp   = m_position.TakeProfit();

               long   magic= m_position.Magic();

               //--- modify

               m_trade.SetExpertMagicNumber(magic);

               if(!m_trade.PositionModify(ticket_highest_buy,0.0,tp))

                  if(InpPrintLog)

                     Print(__FILE__," ",__FUNCTION__,", ERROR: ","Modify BUY ",ticket_highest_buy,

                           " Position -> false. Result Retcode: ",m_trade.ResultRetcode(),

                           ", description of result: ",m_trade.ResultRetcodeDescription());

              }

           }

        }

      else

        {

         if(ticket_highest_buy==0 && ticket_lowest_buy>0)

           {

            if(m_position.SelectByTicket(ticket_lowest_buy))

              {

               if(m_position.StopLoss()>0.0)

                 {

                  double tp   = m_position.TakeProfit();

                  long   magic= m_position.Magic();

                  //--- modify

                  m_trade.SetExpertMagicNumber(magic);

                  if(!m_trade.PositionModify(ticket_lowest_buy,0.0,tp))

                     if(InpPrintLog)

                        Print(__FILE__," ",__FUNCTION__,", ERROR: ","Modify BUY ",ticket_lowest_buy,

                              " Position -> false. Result Retcode: ",m_trade.ResultRetcode(),

                              ", description of result: ",m_trade.ResultRetcodeDescription());

                 }

              }

           }

         else

           {

            if(ticket_highest_buy==ticket_lowest_buy)

              {

               if(m_position.SelectByTicket(ticket_highest_buy))

                 {

                  if(m_position.StopLoss()>0.0)

                    {

                     double tp   = m_position.TakeProfit();

                     long   magic= m_position.Magic();

                     //--- modify

                     m_trade.SetExpertMagicNumber(magic);

                     if(!m_trade.PositionModify(ticket_highest_buy,0.0,tp))

                        if(InpPrintLog)

                           Print(__FILE__," ",__FUNCTION__,", ERROR: ","Modify BUY ",ticket_highest_buy,

                                 " Position -> false. Result Retcode: ",m_trade.ResultRetcode(),

                                 ", description of result: ",m_trade.ResultRetcodeDescription());

                    }

                 }

              }

           }

        }

     }

   if(InpTradeMode==sell)

     {

      if(ticket_highest_sell>0 && ticket_lowest_sell==0)

        {

         if(m_position.SelectByTicket(ticket_highest_sell))

           {

            if(m_position.StopLoss()>0.0)

              {

               double tp   = m_position.TakeProfit();

               long   magic= m_position.Magic();

               //--- modify

               m_trade.SetExpertMagicNumber(magic);

               if(!m_trade.PositionModify(ticket_highest_sell,0.0,tp))

                  if(InpPrintLog)

                     Print(__FILE__," ",__FUNCTION__,", ERROR: ","Modify SELL ",ticket_highest_sell,

                           " Position -> false. Result Retcode: ",m_trade.ResultRetcode(),

                           ", description of result: ",m_trade.ResultRetcodeDescription());

              }

           }

        }

      else

        {

         if(ticket_highest_sell==0 && ticket_lowest_sell>0)

           {

            if(m_position.SelectByTicket(ticket_lowest_sell))

              {

               if(m_position.StopLoss()>0.0)

                 {

                  double tp   = m_position.TakeProfit();

                  long   magic= m_position.Magic();

                  //--- modify

                  m_trade.SetExpertMagicNumber(magic);

                  if(!m_trade.PositionModify(ticket_lowest_sell,0.0,tp))

                     if(InpPrintLog)

                        Print(__FILE__," ",__FUNCTION__,", ERROR: ","Modify SELL ",ticket_lowest_sell,

                              " Position -> false. Result Retcode: ",m_trade.ResultRetcode(),

                              ", description of result: ",m_trade.ResultRetcodeDescription());

                 }

              }

           }

         else

           {

            if(ticket_highest_sell==ticket_lowest_sell)

              {

               if(m_position.SelectByTicket(ticket_highest_sell))

                 {

                  if(m_position.StopLoss()>0.0)

                    {

                     double tp   = m_position.TakeProfit();

                     long   magic= m_position.Magic();

                     //--- modify

                     m_trade.SetExpertMagicNumber(magic);

                     if(!m_trade.PositionModify(ticket_highest_sell,0.0,tp))

                        if(InpPrintLog)

                           Print(__FILE__," ",__FUNCTION__,", ERROR: ","Modify SELL ",ticket_highest_sell,

                                 " Position -> false. Result Retcode: ",m_trade.ResultRetcode(),

                                 ", description of result: ",m_trade.ResultRetcodeDescription());

                    }

                 }

              }

           }

        }

     }

  }

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

//| Print CTrade result                                              |

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

void PrintResultModify(CTrade &trade,CSymbolInfo &symbol,CPositionInfo &position)

  {

   Print("File: ",__FILE__,", symbol: ",symbol.Name());

   Print("Code of request result: "+IntegerToString(trade.ResultRetcode()));

   Print("code of request result as a string: "+trade.ResultRetcodeDescription());

   Print("Deal ticket: "+IntegerToString(trade.ResultDeal()));

   Print("Order ticket: "+IntegerToString(trade.ResultOrder()));

   Print("Volume of deal or order: "+DoubleToString(trade.ResultVolume(),2));

   Print("Price, confirmed by broker: "+DoubleToString(trade.ResultPrice(),symbol.Digits()));

   Print("Current bid price: "+DoubleToString(symbol.Bid(),symbol.Digits())+" (the requote): "+DoubleToString(trade.ResultBid(),symbol.Digits()));

   Print("Current ask price: "+DoubleToString(symbol.Ask(),symbol.Digits())+" (the requote): "+DoubleToString(trade.ResultAsk(),symbol.Digits()));

   Print("Broker comment: "+trade.ResultComment());

   Print("Freeze Level: "+DoubleToString(symbol.FreezeLevel(),0),", Stops Level: "+DoubleToString(symbol.StopsLevel(),0));

   Print("Price of position opening: "+DoubleToString(position.PriceOpen(),symbol.Digits()));

   Print("Price of position's Stop Loss: "+DoubleToString(position.StopLoss(),symbol.Digits()));

   Print("Price of position's Take Profit: "+DoubleToString(position.TakeProfit(),symbol.Digits()));

   Print("Current price by position: "+DoubleToString(position.PriceCurrent(),symbol.Digits()));

  }

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

//| Create the horizontal line                                       |

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

bool HLineCreate(const long            chart_ID=0,        // chart's ID

                 const string          name="HLine",      // line name

                 const int             sub_window=0,      // subwindow index

                 double                price=0,           // line price

                 const color           clr=clrRed,        // line color

                 const ENUM_LINE_STYLE style=STYLE_SOLID, // line style

                 const int             width=1,           // line width

                 const bool            back=false,        // in the background

                 const bool            selection=false,   // highlight to move

                 const bool            hidden=true,       // hidden in the object list

                 const long            z_order=0)         // priority for mouse click

  {

//--- reset the error value

   ResetLastError();

//--- create a horizontal line

   if(!ObjectCreate(chart_ID,name,OBJ_HLINE,sub_window,0,price))

     {

      Print(__FUNCTION__,

            ": failed to create a horizontal line! Error code = ",GetLastError());

      return(false);

     }

//--- set line color

   ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr);

//--- set line display style

   ObjectSetInteger(chart_ID,name,OBJPROP_STYLE,style);

//--- set line width

   ObjectSetInteger(chart_ID,name,OBJPROP_WIDTH,width);

//--- display in the foreground (false) or background (true)

   ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back);

//--- enable (true) or disable (false) the mode of moving the line by mouse

//--- when creating a graphical object using ObjectCreate function, the object cannot be

//--- highlighted and moved by default. Inside this method, selection parameter

//--- is true by default making it possible to highlight and move the object

   ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection);

   ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection);

//--- hide (true) or display (false) graphical object name in the object list

   ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden);

//--- set the priority for receiving the event of a mouse click in the chart

   ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order);

//---

   ObjectSetString(chart_ID,name,OBJPROP_TEXT,name);

//--- successful execution

   return(true);

  }

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

//| Move horizontal line                                             |

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

bool HLineMove(const long   chart_ID=0,   // chart's ID

               const string name="HLine", // line name

               double       price=0)      // line price

  {

//--- reset the error value

   ResetLastError();

//--- move a horizontal line

   if(!ObjectMove(chart_ID,name,0,0,price))

     {

      Print(__FUNCTION__,

            ": failed to move the horizontal line! Error code = ",GetLastError());

      return(false);

     }

//--- successful execution

   return(true);

  }

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

//| Delete a horizontal line                                         |

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

bool HLineDelete(const long   chart_ID=0,   // chart's ID

                 const string name="HLine") // line name

  {

//--- reset the error value

   ResetLastError();

//--- delete a horizontal line

   if(!ObjectDelete(chart_ID,name))

     {

      Print(__FUNCTION__,

            ": failed to delete a horizontal line! Error code = ",GetLastError());

      return(false);

     }

//--- successful execution

   return(true);

  }

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

//| Compare doubles                                                  |

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

bool CompareDoubles(double number1,double number2,int digits,double points)

  {

   if(MathAbs(NormalizeDouble(number1-number2,digits))<=points)

      return(true);

   else

      return(false);

  }

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

Comments

Markdown supported. Formatting help

Markdown Formatting Guide

Element Markdown Syntax
Heading # H1
## H2
### H3
Bold **bold text**
Italic *italicized text*
Link [title](https://www.example.com)
Image ![alt text](image.jpg)
Code `code`
Code Block ```
code block
```
Quote > blockquote
Unordered List - Item 1
- Item 2
Ordered List 1. First item
2. Second item
Horizontal Rule ---