Pending Trailing

Author: Copyright © 2020, Vladimir Karputov
Price Data Components
Series array that contains tick volumes of each bar
Orders Execution
Checks for the total of open ordersIt can change open orders parameters, due to possible stepping strategy
Miscellaneous
It issuies visual alerts to the screen
0 Views
0 Downloads
0 Favorites
Pending Trailing
ÿþ//+------------------------------------------------------------------+

//|                                             Pending Trailing.mq5 |

//|                              Copyright © 2020, Vladimir Karputov |

//|                     https://www.mql5.com/ru/market/product/43516 |

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

#property copyright "Copyright © 2020, Vladimir Karputov"

#property link      "https://www.mql5.com/ru/market/product/43516"

#property version   "1.000"

/*

   barabashkakvn Trading engine 3.111

*/

#include <Trade\Trade.mqh>

#include <Trade\SymbolInfo.mqh>

#include <Trade\AccountInfo.mqh>

#include <Trade\OrderInfo.mqh>

//---

CTrade         m_trade;                      // object of CTrade class

CSymbolInfo    m_symbol;                     // object of CSymbolInfo class

CAccountInfo   m_account;                    // object of CAccountInfo class

COrderInfo     m_order;                      // object of COrderInfo class

//--- input parameters

input ushort   InpTrailingFrequency = 10;          // Trailing, in seconds (< "10" -> only on a new bar)

input ushort   InpTrailingStop      = 25;          // Trailing Stop (min distance from price to Stop Loss, in pips

input ushort   InpTrailingStep      = 5;           // Trailing Step, in pips (1.00045-1.00055=1 pips)

//---

input bool     InpPrintLog          = false;       // Print log

input ulong    InpMagic             = 200;         // Magic number

//---

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

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



double   m_adjusted_point;                      // point value adjusted for 3 or 5 points

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

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

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

//| Expert initialization function                                   |

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

int OnInit()

  {

//---

   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!";

      //--- when testing, we will only output to the log about incorrect input parameters

      if(MQLInfoInteger(MQL_TESTER))

        {

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

         return(INIT_FAILED);

        }

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

        {

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

         return(INIT_PARAMETERS_INCORRECT);

        }

     }

//---

   return(INIT_SUCCEEDED);

  }

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

//| Expert deinitialization function                                 |

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

void OnDeinit(const int reason)

  {

//---



  }

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

//| Expert tick function                                             |

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

void OnTick()

  {

   if(InpTrailingFrequency>=10) // trailing no more than once every 10 seconds

     {

      datetime time_current=TimeCurrent();

      if(time_current-m_last_trailing>10)

        {

         Trailing();

         m_last_trailing=time_current;

        }

     }

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

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

   if(time_0==m_prev_bars)

      return;

   m_prev_bars=time_0;

   if(InpTrailingFrequency<10) // trailing only at the time of the birth of new bar

     {

      Trailing();

     }

//---

  }

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

//| 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())

     {

      if(InpPrintLog)

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

      return(false);

     }

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

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

     {

      if(InpPrintLog)

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

      return(false);

     }

//---

   return(true);

  }

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

//| Check Freeze and Stops levels                                    |

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

bool FreezeStopsLevels(double &level)

  {

//--- check Freeze and Stops levels

   /*

      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



      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

   */

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

      return(false);

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

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

   if(freeze_level==0.0)

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

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

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

   if(stop_level==0.0)

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



   if(freeze_level<=0.0 || stop_level<=0.0)

      return(false);



   level=(freeze_level>stop_level)?freeze_level:stop_level;



   double spread=m_symbol.Spread()*m_symbol.Point()*3.0;

   level=(level>spread)?level:spread;

//---

   return(true);

  }

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

//| Trailing                                                         |

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

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

void Trailing(void)

  {

   /*

      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

   */

   if(InpTrailingStop==0)

      return;

//---

   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(!SetInit(m_order.Symbol()))

            continue;

         double level;

         if(!FreezeStopsLevels(level))

            continue;

         double price_current = m_order.PriceCurrent();

         double price_open    = m_order.PriceOpen();

         if(price_current==0.0 || price_open==0.0)

            continue;

         double stop_loss     = m_order.StopLoss();

         double take_profit   = m_order.TakeProfit();

         double ask           = m_symbol.Ask();

         double bid           = m_symbol.Bid();

         //---

         if(m_order.OrderType()==ORDER_TYPE_BUY_LIMIT)

           {

            if(price_current-price_open>m_trailing_stop+m_trailing_step)

              {

               double new_price=m_symbol.NormalizePrice(price_current-m_trailing_stop);

               double new_sl=(stop_loss==0.0)?0.0:m_symbol.NormalizePrice(new_price-(price_open-stop_loss));

               double new_tp=(take_profit==0.0)?0.0:m_symbol.NormalizePrice(new_price+(take_profit-price_open));

               if(!m_trade.OrderModify(m_order.Ticket(),new_price,new_sl,new_tp,m_order.TypeTime(),m_order.TimeExpiration()))

                 {

                  if(InpPrintLog)

                     Print(__FILE__," ",__FUNCTION__,", ERROR: ","Modify BUY LIMIT ",m_order.Ticket(),

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

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

                 }

              }

            continue;

           }

         if(m_order.OrderType()==ORDER_TYPE_SELL_LIMIT)

           {

            if(price_open-price_current>m_trailing_stop+m_trailing_step)

              {

               double new_price=m_symbol.NormalizePrice(price_current+m_trailing_stop);

               double new_sl=(stop_loss==0.0)?0.0:m_symbol.NormalizePrice(new_price+(stop_loss-price_open));

               double new_tp=(take_profit==0.0)?0.0:m_symbol.NormalizePrice(new_price-(price_open-take_profit));

               if(!m_trade.OrderModify(m_order.Ticket(),new_price,new_sl,new_tp,m_order.TypeTime(),m_order.TimeExpiration()))

                 {

                  if(InpPrintLog)

                     Print(__FILE__," ",__FUNCTION__,", ERROR: ","Modify SELL LIMIT ",m_order.Ticket(),

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

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

                 }

              }

            continue;

           }

         if(m_order.OrderType()==ORDER_TYPE_BUY_STOP)

           {

            if(price_open-price_current>m_trailing_stop+m_trailing_step)

              {

               double new_price=m_symbol.NormalizePrice(price_current+m_trailing_stop);

               double new_sl=(stop_loss==0.0)?0.0:m_symbol.NormalizePrice(new_price-(price_open-stop_loss));

               double new_tp=(take_profit==0.0)?0.0:m_symbol.NormalizePrice(new_price+(take_profit-price_open));

               if(!m_trade.OrderModify(m_order.Ticket(),new_price,new_sl,new_tp,m_order.TypeTime(),m_order.TimeExpiration()))

                 {

                  if(InpPrintLog)

                     Print(__FILE__," ",__FUNCTION__,", ERROR: ","Modify BUY STOP ",m_order.Ticket(),

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

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

                 }

              }

            continue;

           }

         if(m_order.OrderType()==ORDER_TYPE_SELL_STOP)

           {

            if(price_current-price_open>m_trailing_stop+m_trailing_step)

              {

               double new_price=m_symbol.NormalizePrice(price_current-m_trailing_stop);

               double new_sl=(stop_loss==0.0)?0.0:m_symbol.NormalizePrice(new_price+(stop_loss-price_open));

               double new_tp=(take_profit==0.0)?0.0:m_symbol.NormalizePrice(new_price-(price_open-take_profit));

               if(!m_trade.OrderModify(m_order.Ticket(),new_price,new_sl,new_tp,m_order.TypeTime(),m_order.TimeExpiration()))

                 {

                  if(InpPrintLog)

                     Print(__FILE__," ",__FUNCTION__,", ERROR: ","Modify SELL STOP ",m_order.Ticket(),

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

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

                 }

              }

            continue;

           }

        }

  }

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

//| 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()));

  }

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

//| Set Init                                                         |

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

bool SetInit(const string symbol)

  {

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

     {

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

      return(false);

     }

   if(!RefreshRates())

      return(false);

//---

   m_trade.SetExpertMagicNumber(InpMagic);

   m_trade.SetMarginMode();

   m_trade.SetTypeFillingBySymbol(m_symbol.Name());

//--- 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;



   m_trailing_stop         = InpTrailingStop          * m_adjusted_point;

   m_trailing_step         = InpTrailingStep          * m_adjusted_point;

//---

   return(true);

  }

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

Comments