MTF_Wilders_Trailing_Stop

Author: Copyright 2018, MetaQuotes Software Corp.
Price Data Components
Series array that contains open time of each barSeries array that contains close prices for each bar
Indicators Used
Indicator of the average true range
0 Views
0 Downloads
0 Favorites
MTF_Wilders_Trailing_Stop
ÿþ//+------------------------------------------------------------------+

//|                                    MTF_Wilders_Trailing_Stop.mq5 |

//|                        Copyright 2018, MetaQuotes Software Corp. |

//|                                                 https://mql5.com |

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

#property copyright "Copyright 2018, MetaQuotes Software Corp."

#property link      "https://mql5.com"

#property version   "1.00"

#property description "Multi Time Frame Wilders Trailing Stop indicator"

#property indicator_chart_window

#property indicator_buffers 6

#property indicator_plots   2

//--- plot UP

#property indicator_label1  "Bearish WTS"

#property indicator_type1   DRAW_LINE

#property indicator_color1  clrRed

#property indicator_style1  STYLE_SOLID

#property indicator_width1  2

//--- plot DN

#property indicator_label2  "Bullish WTS"

#property indicator_type2   DRAW_LINE

#property indicator_color2  clrGreen

#property indicator_style2  STYLE_SOLID

#property indicator_width2  2

//--- enums

enum ENUM_DRAW_MODE

  {

   DRAW_MODE_STEPS,  // Steps

   DRAW_MODE_SLOPE   // Slope

  };

//--- input parameters

input uint              InpPeriod      =  5;                // Period

input double            InpCoeff       =  3.5;              // ATR coefficient

input ENUM_TIMEFRAMES   InpTimeframe   =  PERIOD_CURRENT;   // WTS timeframe

//--- indicator buffers

double            BufferUP[];

double            BufferDN[];

double            BufferUPtmp[];

double            BufferDNtmp[];

double            BufferATR[];

double            BufferWTS[];

//--- global variables

ENUM_TIMEFRAMES   timeframe_wts;

double            coeff;

int               period;

int               handle_atr;

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

//| Custom indicator initialization function                         |

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

int OnInit()

  {

//--- timer

   EventSetTimer(90);

//--- set global variables

   timeframe_wts=(InpTimeframe>Period() ? InpTimeframe : Period());

//--- setting global variables

   period=int(InpPeriod<1 ? 1 : InpPeriod);

   coeff=InpCoeff;

//--- indicator buffers mapping

   SetIndexBuffer(0,BufferUP,INDICATOR_DATA);

   SetIndexBuffer(1,BufferDN,INDICATOR_DATA);

   SetIndexBuffer(2,BufferUPtmp,INDICATOR_CALCULATIONS);

   SetIndexBuffer(3,BufferDNtmp,INDICATOR_CALCULATIONS);

   SetIndexBuffer(4,BufferATR,INDICATOR_CALCULATIONS);

   SetIndexBuffer(5,BufferWTS,INDICATOR_CALCULATIONS);

//--- settings indicators parameters

   string label=TimeframeToString(timeframe_wts)+" Wilders Trailing Stop("+(string)period+","+DoubleToString(coeff,1)+")";

   IndicatorSetString(INDICATOR_SHORTNAME,label);

   IndicatorSetInteger(INDICATOR_DIGITS,Digits());

//--- setting plot buffer parameters

   PlotIndexSetString(0,PLOT_LABEL,TimeframeToString(timeframe_wts)+" Bearish WTS");

   PlotIndexSetString(1,PLOT_LABEL,TimeframeToString(timeframe_wts)+" Bullish WTS");

//--- setting buffer arrays as timeseries

   ArraySetAsSeries(BufferUP,true);

   ArraySetAsSeries(BufferDN,true);

   ArraySetAsSeries(BufferUPtmp,true);

   ArraySetAsSeries(BufferDNtmp,true);

   ArraySetAsSeries(BufferATR,true);

   ArraySetAsSeries(BufferWTS,true);

//--- create handle ATR

   ResetLastError();

   handle_atr=iATR(NULL,timeframe_wts,period);

   if(handle_atr==INVALID_HANDLE)

     {

      Print("The iATR(",TimeframeToString(timeframe_wts),",",(string)period,") object was not created: Error ",GetLastError());

      return INIT_FAILED;

     }

//--- get timeframe

   Time(NULL,timeframe_wts,1);

//---

   return(INIT_SUCCEEDED);

  }

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

//| Custom indicator iteration function                              |

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

int OnCalculate(const int rates_total,

                const int prev_calculated,

                const datetime &time[],

                const double &open[],

                const double &high[],

                const double &low[],

                const double &close[],

                const long &tick_volume[],

                const long &volume[],

                const int &spread[])

  {

//--- #AB0=>2:0 <0AA82>2 1CD5@>2 :0: B09<A5@89

   ArraySetAsSeries(close,true);

//--- @>25@:0 :>;8G5AB20 4>ABC?=KE 10@>2

   if(rates_total<4) return 0;

//--- @>25@:0 8 @0AGQB :>;8G5AB20 ?@>AG8BK205<KE 10@>2

   int limit=rates_total-prev_calculated;

   if(limit>1)

     {

      limit=rates_total-2;

      ArrayInitialize(BufferUP,EMPTY_VALUE);

      ArrayInitialize(BufferDN,EMPTY_VALUE);

      ArrayInitialize(BufferUPtmp,0);

      ArrayInitialize(BufferDNtmp,0);

      ArrayInitialize(BufferATR,0);

      ArrayInitialize(BufferWTS,0);

     }

//--- >43>B>2:0 40==KE

   if(Time(NULL,timeframe_wts,1)==0)

      return 0;

   int bars=(timeframe_wts==Period() ? rates_total : Bars(NULL,timeframe_wts));

   

   int count=(limit>1 ? fmin(bars,rates_total) : 1);

   int copied=CopyBuffer(handle_atr,0,0,count,BufferATR);

   if(copied!=count) return 0;

   

   for(int i=limit; i>=0; i--)

     {

      double loss=BufferATR[i]*coeff;

      double close0=Close(NULL,timeframe_wts,i);

      double close1=Close(NULL,timeframe_wts,i+1);

      if(close0==0 || close1==0)

         continue;

      if(close0>BufferWTS[i+1] && close1>BufferWTS[i+1])

        {

         BufferDNtmp[i]=BufferWTS[i]=fmax(BufferWTS[i+1],close0-loss);

         BufferUPtmp[i]=EMPTY_VALUE;

        }

      else

        {

         if(close0<BufferWTS[i+1] && close1<BufferWTS[i+1])

           {

            BufferUPtmp[i]=BufferWTS[i]=fmin(BufferWTS[i+1],close0+loss);

            BufferDNtmp[i]=EMPTY_VALUE;

           }

         else

           {

            if(close0>BufferWTS[i+1])

              {

               BufferDNtmp[i]=BufferWTS[i]=close0-loss;

               BufferUPtmp[i]=EMPTY_VALUE;

              }

            else

              {

               BufferUPtmp[i]=BufferWTS[i]=close0+loss;

               BufferDNtmp[i]=EMPTY_VALUE;

              }

           }

        }

     }



//---  0AGQB 8=48:0B>@0

   for(int i=limit; i>=0; i--)

     {

      DataConversion(rates_total,NULL,timeframe_wts,i,BufferUPtmp,BufferUP,0);

      DataConversion(rates_total,NULL,timeframe_wts,i,BufferDNtmp,BufferDN,0);

     }

   

//--- return value of prev_calculated for next call

   return(rates_total);

  }

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

//| Custom indicator timer function                                  |

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

void OnTimer()

  {

   Time(NULL,timeframe_wts,1);

  }  

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

//| Transfering data from the source timeframe to current timeframe  |

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

void DataConversion(const int rates_total,

                    const string symbol_name,

                    const ENUM_TIMEFRAMES timeframe_src,

                    const int shift,

                    const double &buffer_src[],

                    double &buffer_dest[],

                    ENUM_DRAW_MODE mode=DRAW_MODE_STEPS

                   )

  {

   double close=Close(symbol_name,timeframe_src,shift);

   if(close==0)

      return;

   if(timeframe_src==Period())

     {

      buffer_dest[shift]=buffer_src[shift];

      return;

     }

   int bar_curr=BarToCurrent(symbol_name,timeframe_src,shift);

   if(bar_curr>rates_total-1)

      return;

   int bar_prev=BarToCurrent(symbol_name,timeframe_src,shift+1);

   int bar_next=(shift>0 ? BarToCurrent(symbol_name,timeframe_src,shift-1) : 0);

   if(bar_prev==WRONG_VALUE || bar_curr==WRONG_VALUE || bar_next==WRONG_VALUE)

      return;

   buffer_dest[bar_curr]=buffer_src[shift];

   if(mode==DRAW_MODE_STEPS)

      for(int j=bar_curr; j>=bar_next; j--)

         buffer_dest[j]=buffer_dest[bar_curr];

   else

     {

      if(bar_prev>rates_total-1) return;

      for(int j=bar_prev; j>=bar_curr; j--)

         buffer_dest[j]=EquationDirect(bar_prev,buffer_dest[bar_prev],bar_curr,buffer_dest[bar_curr],j);

      if(shift==0)

         for(int j=bar_curr; j>=0; j--)

            buffer_dest[j]=buffer_dest[bar_curr];

     }

  }

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

//| >72@0I05B 10@ 7040==>3> B09<D@59<0 :0: 10@ B5:CI53> B09<D@59<0  |

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

int BarToCurrent(const string symbol_name,const ENUM_TIMEFRAMES timeframe_src,const int shift,bool exact=false)

  {

   datetime time=Time(symbol_name,timeframe_src,shift);

   return(time!=0 ? BarShift(symbol_name,Period(),time,exact) : WRONG_VALUE);

  }  

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

//| >72@0I05B A<5I5=85 10@0 ?> 2@5<5=8                              |

//| https://www.mql5.com/ru/forum/743/page11#comment_7010041         |

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

int BarShift(const string symbol_name,const ENUM_TIMEFRAMES timeframe,const datetime time,bool exact=false)

  {

   int res=Bars(symbol_name,timeframe,time+1,UINT_MAX);

   if(exact) if((timeframe!=PERIOD_MN1 || time>TimeCurrent()) && res==Bars(symbol_name,timeframe,time-PeriodSeconds(timeframe)+1,UINT_MAX)) return(WRONG_VALUE);

   return res;

  }

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

//| >72@0I05B Close                                                 |

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

double Close(const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int shift)

  {

   double array[];

   ArraySetAsSeries(array,true);

   return(CopyClose(symbol_name,timeframe,shift,1,array)==1 ? array[0] : 0);

  }

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

//| >72@0I05B Time                                                  |

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

datetime Time(const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int shift)

  {

   datetime array[];

   ArraySetAsSeries(array,true);

   return(CopyTime(symbol_name,timeframe,shift,1,array)==1 ? array[0] : 0);

  }

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

//| #@02=5=85 ?@O<>9                                                 |

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

double EquationDirect(const int left_bar,const double left_price,const int right_bar,const double right_price,const int bar_to_search) 

  {

   return(right_bar==left_bar ? left_price : (right_price-left_price)/(right_bar-left_bar)*(bar_to_search-left_bar)+left_price);

  }

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

//| Timeframe to string                                              |

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

string TimeframeToString(const ENUM_TIMEFRAMES timeframe)

  {

   return StringSubstr(EnumToString(timeframe),7);

  }

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

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