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
0 Views
0 Downloads
0 Favorites
MTF_TSI
ÿþ//+------------------------------------------------------------------+

//|                                                      MTF_TSI.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 "Multitimeframe True Strength Index oscillator"

#property indicator_separate_window

#property indicator_buffers 24

#property indicator_plots   3

//--- plot TSI1

#property indicator_label1  "TSI1"

#property indicator_type1   DRAW_LINE

#property indicator_color1  clrLimeGreen

#property indicator_style1  STYLE_SOLID

#property indicator_width1  1

//--- plot TSI2

#property indicator_label2  "TSI2"

#property indicator_type2   DRAW_LINE

#property indicator_color2  clrOrangeRed

#property indicator_style2  STYLE_SOLID

#property indicator_width2  1

//--- plot TSI3

#property indicator_label3  "TSI3"

#property indicator_type3   DRAW_LINE

#property indicator_color3  clrDodgerBlue

#property indicator_style3  STYLE_SOLID

#property indicator_width3  1

//--- enums

enum ENUM_DRAW_MODE

  {

   DRAW_MODE_STEPS,  // Steps

   DRAW_MODE_SLOPE   // Slope

  };

//--- input parameters

input uint              InpPeriodSm1   =  7;                // First smoothing period

input uint              InpPeriodSm2   =  14;               // Second smoothing period

input double            InpOverbought  =  25.0;             // Overbought

input double            InpOversold    = -25.0;             // Oversold

input ENUM_TIMEFRAMES   InpTimeframe1  =  PERIOD_H1;        // First TSI timeframe

input ENUM_TIMEFRAMES   InpTimeframe2  =  PERIOD_H4;        // Second TSI timeframe

input ENUM_TIMEFRAMES   InpTimeframe3  =  PERIOD_D1;        // Third TSI timeframe

input ENUM_DRAW_MODE    InpDrawMode    =  DRAW_MODE_STEPS;  // Drawing mode

//--- indicator buffers

double         BufferTSI1[];

double         BufferTSI2[];

double         BufferTSI3[];

double         BufferTSI1tmp[];

double         BufferTSI2tmp[];

double         BufferTSI3tmp[];

//---

double         BufferUDM1[];

double         BufferADM1[];

double         BufferUDM11[];

double         BufferUDM21[];

double         BufferADM11[];

double         BufferADM21[];

//---

double         BufferUDM2[];

double         BufferADM2[];

double         BufferUDM12[];

double         BufferUDM22[];

double         BufferADM12[];

double         BufferADM22[];

//---

double         BufferUDM3[];

double         BufferADM3[];

double         BufferUDM13[];

double         BufferUDM23[];

double         BufferADM13[];

double         BufferADM23[];

//--- global variables

ENUM_TIMEFRAMES   timeframe1;

ENUM_TIMEFRAMES   timeframe2;

ENUM_TIMEFRAMES   timeframe3;

double            overbought;

double            oversold;

int               period_sm1;

int               period_sm2;

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

//| Custom indicator initialization function                         |

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

int OnInit()

  {

//--- timer

   EventSetTimer(90);

//--- set global variables

   period_sm1=int(InpPeriodSm1<2 ? 2 : InpPeriodSm1);

   period_sm2=int(InpPeriodSm2<2 ? 2 : InpPeriodSm2);

   overbought=(fabs(InpOverbought)<0.1 ? 0.1 : InpOverbought>100.0 ? 100.0 : fabs(InpOverbought));

   oversold=(-fabs(InpOversold)>-0.1 ? -0.1 : -fabs(InpOversold)<-100.0 ? -100.0 : -fabs(InpOversold));

   timeframe1=(InpTimeframe1>Period() ? InpTimeframe1 : Period());

   timeframe2=(InpTimeframe2>Period() ? InpTimeframe2 : Period());

   timeframe3=(InpTimeframe3>Period() ? InpTimeframe3 : Period());

//--- indicator buffers mapping

   SetIndexBuffer(0,BufferTSI1,INDICATOR_DATA);

   SetIndexBuffer(1,BufferTSI2,INDICATOR_DATA);

   SetIndexBuffer(2,BufferTSI3,INDICATOR_DATA);

   SetIndexBuffer(3,BufferTSI1tmp,INDICATOR_CALCULATIONS);

   SetIndexBuffer(4,BufferTSI2tmp,INDICATOR_CALCULATIONS);

   SetIndexBuffer(5,BufferTSI3tmp,INDICATOR_CALCULATIONS);

   SetIndexBuffer(6,BufferUDM1,INDICATOR_CALCULATIONS);

   SetIndexBuffer(7,BufferUDM11,INDICATOR_CALCULATIONS);

   SetIndexBuffer(8,BufferUDM21,INDICATOR_CALCULATIONS);

   SetIndexBuffer(9,BufferADM1,INDICATOR_CALCULATIONS);

   SetIndexBuffer(10,BufferADM11,INDICATOR_CALCULATIONS);

   SetIndexBuffer(11,BufferADM21,INDICATOR_CALCULATIONS);

   SetIndexBuffer(12,BufferUDM2,INDICATOR_CALCULATIONS);

   SetIndexBuffer(13,BufferUDM12,INDICATOR_CALCULATIONS);

   SetIndexBuffer(14,BufferUDM22,INDICATOR_CALCULATIONS);

   SetIndexBuffer(15,BufferADM2,INDICATOR_CALCULATIONS);

   SetIndexBuffer(16,BufferADM12,INDICATOR_CALCULATIONS);

   SetIndexBuffer(17,BufferADM22,INDICATOR_CALCULATIONS);

   SetIndexBuffer(18,BufferUDM3,INDICATOR_CALCULATIONS);

   SetIndexBuffer(19,BufferUDM13,INDICATOR_CALCULATIONS);

   SetIndexBuffer(20,BufferUDM23,INDICATOR_CALCULATIONS);

   SetIndexBuffer(21,BufferADM3,INDICATOR_CALCULATIONS);

   SetIndexBuffer(22,BufferADM13,INDICATOR_CALCULATIONS);

   SetIndexBuffer(23,BufferADM23,INDICATOR_CALCULATIONS);

//--- setting indicator parameters

   string label=TimeframeToString(timeframe1)+","+TimeframeToString(timeframe2)+","+TimeframeToString(timeframe3)+" True Strength Index ("+(string)period_sm1+","+(string)period_sm2+")";

   IndicatorSetString(INDICATOR_SHORTNAME,label);

   IndicatorSetInteger(INDICATOR_DIGITS,Digits());

   IndicatorSetInteger(INDICATOR_LEVELS,2);

   IndicatorSetDouble(INDICATOR_LEVELVALUE,0,overbought);

   IndicatorSetDouble(INDICATOR_LEVELVALUE,1,oversold);

   IndicatorSetString(INDICATOR_LEVELTEXT,0,"Overbought");

   IndicatorSetString(INDICATOR_LEVELTEXT,1,"Oversold");

//--- setting plot buffer parameters

   PlotIndexSetString(0,PLOT_LABEL,TimeframeToString(timeframe1)+" TSI ("+(string)period_sm1+","+(string)period_sm2+")");

   PlotIndexSetString(1,PLOT_LABEL,TimeframeToString(timeframe2)+" TSI ("+(string)period_sm1+","+(string)period_sm2+")");

   PlotIndexSetString(2,PLOT_LABEL,TimeframeToString(timeframe3)+" TSI ("+(string)period_sm1+","+(string)period_sm2+")");

//--- setting buffer arrays as timeseries

   ArraySetAsSeries(BufferTSI1,true);

   ArraySetAsSeries(BufferTSI2,true);

   ArraySetAsSeries(BufferTSI3,true);

   ArraySetAsSeries(BufferTSI1tmp,true);

   ArraySetAsSeries(BufferTSI2tmp,true);

   ArraySetAsSeries(BufferTSI3tmp,true);

   ArraySetAsSeries(BufferUDM1,true);

   ArraySetAsSeries(BufferUDM11,true);

   ArraySetAsSeries(BufferUDM21,true);

   ArraySetAsSeries(BufferADM1,true);

   ArraySetAsSeries(BufferADM11,true);

   ArraySetAsSeries(BufferADM21,true);

   ArraySetAsSeries(BufferUDM2,true);

   ArraySetAsSeries(BufferUDM12,true);

   ArraySetAsSeries(BufferUDM22,true);

   ArraySetAsSeries(BufferADM2,true);

   ArraySetAsSeries(BufferADM12,true);

   ArraySetAsSeries(BufferADM22,true);

   ArraySetAsSeries(BufferUDM3,true);

   ArraySetAsSeries(BufferUDM13,true);

   ArraySetAsSeries(BufferUDM23,true);

   ArraySetAsSeries(BufferADM3,true);

   ArraySetAsSeries(BufferADM13,true);

   ArraySetAsSeries(BufferADM23,true);

//--- get timeframe

   Time(NULL,timeframe1,1);

   Time(NULL,timeframe2,1);

   Time(NULL,timeframe3,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[])

  {

//--- @>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(BufferTSI1,EMPTY_VALUE);

      ArrayInitialize(BufferTSI2,EMPTY_VALUE);

      ArrayInitialize(BufferTSI3,EMPTY_VALUE);

      ArrayInitialize(BufferTSI1tmp,0);

      ArrayInitialize(BufferTSI2tmp,0);

      ArrayInitialize(BufferTSI3tmp,0);

      ArrayInitialize(BufferUDM1,0);

      ArrayInitialize(BufferUDM11,0);

      ArrayInitialize(BufferUDM21,0);

      ArrayInitialize(BufferADM1,0);

      ArrayInitialize(BufferADM11,0);

      ArrayInitialize(BufferADM21,0);

      ArrayInitialize(BufferUDM2,0);

      ArrayInitialize(BufferUDM12,0);

      ArrayInitialize(BufferUDM22,0);

      ArrayInitialize(BufferADM2,0);

      ArrayInitialize(BufferADM12,0);

      ArrayInitialize(BufferADM22,0);

      ArrayInitialize(BufferUDM3,0);

      ArrayInitialize(BufferUDM13,0);

      ArrayInitialize(BufferUDM23,0);

      ArrayInitialize(BufferADM3,0);

      ArrayInitialize(BufferADM13,0);

      ArrayInitialize(BufferADM23,0);

     }

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

   if(Time(NULL,timeframe1,1)==0 || Time(NULL,timeframe2,1)==0 || Time(NULL,timeframe3,1)==0)

      return 0;

   int bars1=(timeframe1==Period() ? rates_total : Bars(NULL,timeframe1));

   int bars2=(timeframe2==Period() ? rates_total : Bars(NULL,timeframe2));

   int bars3=(timeframe3==Period() ? rates_total : Bars(NULL,timeframe3));

   

   for(int i=limit; i>=0 && !IsStopped(); i--)

     {

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

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

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

         continue;

      BufferUDM1[i]=close0-close1;

      BufferADM1[i]=fabs(BufferUDM1[i]);

      //---

      close0=Close(NULL,timeframe2,i);

      close1=Close(NULL,timeframe2,i+1);

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

         continue;

      BufferUDM2[i]=close0-close1;

      BufferADM2[i]=fabs(BufferUDM2[i]);

      //---

      close0=Close(NULL,timeframe3,i);

      close1=Close(NULL,timeframe3,i+1);

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

         continue;

      BufferUDM3[i]=close0-close1;

      BufferADM3[i]=fabs(BufferUDM3[i]);

     }

   for(int i=limit; i>=0 && !IsStopped(); i--)

     {

      BufferUDM11[i]=EMA(fmin(bars1,rates_total),BufferUDM1[i],BufferUDM11[i+1],period_sm1,i);

      BufferADM11[i]=EMA(fmin(bars1,rates_total),BufferADM1[i],BufferADM11[i+1],period_sm1,i);

      //---

      BufferUDM12[i]=EMA(fmin(bars2,rates_total),BufferUDM2[i],BufferUDM12[i+1],period_sm1,i);

      BufferADM12[i]=EMA(fmin(bars2,rates_total),BufferADM2[i],BufferADM12[i+1],period_sm1,i);

      //---

      BufferUDM13[i]=EMA(fmin(bars3,rates_total),BufferUDM3[i],BufferUDM13[i+1],period_sm1,i);

      BufferADM13[i]=EMA(fmin(bars3,rates_total),BufferADM3[i],BufferADM13[i+1],period_sm1,i);

     }

   for(int i=limit; i>=0 && !IsStopped(); i--)

     {

      BufferUDM21[i]=EMA(fmin(bars1,rates_total),BufferUDM11[i],BufferUDM21[i+1],period_sm2,i);

      BufferADM21[i]=EMA(fmin(bars1,rates_total),BufferADM11[i],BufferADM21[i+1],period_sm2,i);

      //---

      BufferUDM22[i]=EMA(fmin(bars2,rates_total),BufferUDM12[i],BufferUDM22[i+1],period_sm2,i);

      BufferADM22[i]=EMA(fmin(bars2,rates_total),BufferADM12[i],BufferADM22[i+1],period_sm2,i);

      //---

      BufferUDM23[i]=EMA(fmin(bars3,rates_total),BufferUDM13[i],BufferUDM23[i+1],period_sm2,i);

      BufferADM23[i]=EMA(fmin(bars3,rates_total),BufferADM13[i],BufferADM23[i+1],period_sm2,i);

     }

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

     {

      BufferTSI1tmp[i]=(BufferADM21[i]!=0 ? 100.0*BufferUDM21[i]/BufferADM21[i] : 0);

      BufferTSI2tmp[i]=(BufferADM22[i]!=0 ? 100.0*BufferUDM22[i]/BufferADM22[i] : 0);

      BufferTSI3tmp[i]=(BufferADM23[i]!=0 ? 100.0*BufferUDM23[i]/BufferADM23[i] : 0);

     }



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

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

     {

      DataConversion(rates_total,NULL,timeframe1,i,BufferTSI1tmp,BufferTSI1,InpDrawMode);

      DataConversion(rates_total,NULL,timeframe2,i,BufferTSI2tmp,BufferTSI2,InpDrawMode);

      DataConversion(rates_total,NULL,timeframe3,i,BufferTSI3tmp,BufferTSI3,InpDrawMode);

     }

   

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

   return(rates_total);

  }

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

//| Custom indicator timer function                                  |

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

void OnTimer()

  {

   Time(NULL,timeframe1,1);

   Time(NULL,timeframe2,1);

   Time(NULL,timeframe3,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

                   )

  {

   if(Time(symbol_name,timeframe_src,shift)==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);

  }

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

//| Exponential Moving Average                                       |

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

double EMA(const int rates_total,const double price,const double prev,const int period,const int shift)

  {

   return(shift>=rates_total-2 || period<1 ? price : prev+2.0/(1+period)*(price-prev));

  }

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

Comments