RSI MTF ALERTS mq5

Please can soomeone help me to add alerts to this RSI MTF INDI ?

I am trying , but i have not so much knowledge about mql …

thankss

//±-----------------------------------------------------------------+
//| MTF_RSI_Smoothed.mq5 |
//| avoitenko |
//| https://login.mql5.com/en/users/avoitenko |
//±-----------------------------------------------------------------+
#property copyright “avoitenko”
#property link “https://login.mql5.com/en/users/avoitenko
#property version “1.00”
//—
#property indicator_separate_window
//—
#property indicator_buffers 3
#property indicator_plots 1
//— limits
#property indicator_minimum 0.0
#property indicator_maximum 100.0
//— levels
#property indicator_level1 30.0
#property indicator_level2 70.0
#property indicator_levelcolor clrSilver
#property indicator_levelstyle STYLE_DOT
#property indicator_levelwidth 1

//— line
#property indicator_type1 DRAW_LINE
#property indicator_color1 clrDodgerBlue
#property indicator_width1 1
//—
#include <MovingAverages.mqh>
//— input parameters
input ENUM_TIMEFRAMES InpTimeframe = PERIOD_H1; // Timeframe
input ushort InpPeriod = 14; // Period
input ushort InpSmoothing = 5; // Smoothing
input int overBought = 70;
input int overSold = 30;
input bool alertsOn = true;
input bool alertsMessage = true;
input bool alertsEmail = false;
//— buffers
double rsiBuffer[];
double maBuffer[];
double tfBuffer[];
datetime tfTime[];
double RSIBuffer[];
double Upper[];
double Lower[];

//— global variables
bool calculateValue;
string IndicatorFileName;
int rsi_handle;
int calc_handle;
ENUM_TIMEFRAMES iTimeframe;
ushort iPeriod;
ushort iSmoothing;
//±-----------------------------------------------------------------+
//| Custom indicator initialization function |
//±-----------------------------------------------------------------+
int OnInit()
{
//— normalize input parameters
iTimeframe=InpTimeframe;
if(iTimeframe>=0 && PeriodSeconds(iTimeframe)<PeriodSeconds(_Period)) iTimeframe=_Period;
//—
iPeriod=InpPeriod;
if(iPeriod<2)iPeriod=2;
//—
iSmoothing=InpSmoothing;
//— buffers
SetIndexBuffer(0,maBuffer,INDICATOR_DATA);
SetIndexBuffer(1,rsiBuffer,INDICATOR_CALCULATIONS);
SetIndexBuffer(2,tfBuffer,INDICATOR_CALCULATIONS);

//—
ArraySetAsSeries(maBuffer,true);
ArraySetAsSeries(rsiBuffer,true);
ArraySetAsSeries(tfBuffer,true);
//— recursive mode
calculateValue=(iTimeframe==-2);
if(calculateValue)
{
rsi_handle=iRSI(NULL,_Period,iPeriod,PRICE_CLOSE);
if(rsi_handle==INVALID_HANDLE){Print(“Error handle #0”);return(INIT_FAILED);}
return(INIT_SUCCEEDED);
}
//— normal mode
IndicatorFileName=MQLInfoString(MQL_PROGRAM_NAME);

calc_handle=iCustom(NULL,iTimeframe,IndicatorFileName,-2,iPeriod,iSmoothing);
if(calc_handle==INVALID_HANDLE){Print(“Error handle #2”);return(INIT_FAILED);}

rsi_handle=iRSI(NULL,iTimeframe,iPeriod,PRICE_CLOSE);
if(rsi_handle==INVALID_HANDLE){Print(“Error handle #3”);return(INIT_FAILED);}

string short_name=StringFormat(“RSI(%d,%d) %s”,iPeriod,iSmoothing,TimeframeToString(iTimeframe));
IndicatorSetString(INDICATOR_SHORTNAME,short_name);
IndicatorSetInteger(INDICATOR_DIGITS,2);
//—
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[])
{
ArraySetAsSeries(time,true);

int limit;
if(prev_calculated>rates_total || prev_calculated<=0)
{
ArrayInitialize(maBuffer,EMPTY_VALUE);
ArrayInitialize(rsiBuffer,0);
limit=rates_total-InpPeriod;
}
else limit=rates_total-prev_calculated;
//— for current tf
if(calculateValue || iTimeframe==PERIOD_CURRENT || iTimeframe==_Period)
{
if(iSmoothing<2)
{
if(CopyBuffer(rsi_handle,0,0,limit+1,maBuffer)!=limit+1) return(0);
}
else
{
if(CopyBuffer(rsi_handle,0,0,limit+1,rsiBuffer)!=limit+1) return(0);
SimpleMAOnBuffer(rates_total,prev_calculated,iPeriod,iSmoothing,rsiBuffer,maBuffer);
}
return(rates_total);
}
//— for mtf
int _bars=Bars(_Symbol,iTimeframe);
if(_bars<1) return(0);

datetime TimeBegining[];
if(CopyTime(_Symbol,iTimeframe,_bars-1,1,TimeBegining)!=1)
{
Print("Error #5 ",GetLastError());
return(0);
}
//—
int calc=BarsCalculated(calc_handle);
if(calc<0) return(0);
if(CopyBuffer(calc_handle,0,0,_bars,tfBuffer)!=_bars)
{
Print(“Error #6 “,GetLastError());
return(0);
}
//— first calc
int limits=MathMin(limit,calc);
//— regular
if(limits==0) limits=PeriodSeconds(iTimeframe)/PeriodSeconds(_Period);
if (alertsOn)
{
if (RSIBuffer[0]>overBought && RSIBuffer[1]<overBought)Alert(overBought+” OVERBOUGTH, _Symbol, TimeFrame, TimeCurrent “);
if (RSIBuffer[0]<overSold && RSIBuffer[1]>overSold) Alert(overBought+” OVERSOLD, _Symbol, TimeFrame, TimeCurrent”);
}
//—
for(int i=limits; i>=0; i–)
{
maBuffer[i]=EMPTY_VALUE;
if(time[i]>=TimeBegining[0])
{
int y=iBarShift(NULL,iTimeframe,time[i]);
if(y>=0) maBuffer[i] = tfBuffer[y];
}
}
return(rates_total);
}
//±-----------------------------------------------------------------+
//| iBarShift |
//±-----------------------------------------------------------------+
int iBarShift(string symbol,ENUM_TIMEFRAMES tf,datetime time)
{
datetime lastBar;
SeriesInfoInteger(symbol,tf,SERIES_LASTBAR_DATE,lastBar);
int res = Bars(symbol,tf,time,lastBar);
int mod = (int)fmod(time,PeriodSeconds(tf));
if(time>lastBar) res=0;
return((mod==0)?res-1:res);
}
//±-----------------------------------------------------------------+
//| TimeframeToString |
//±-----------------------------------------------------------------+
string TimeframeToString(ENUM_TIMEFRAMES _period=PERIOD_CURRENT)
{
if(_period==PERIOD_CURRENT)_period=_Period;
string str=EnumToString(_period);
if(StringLen(str)>7) return(StringSubstr(str,7));
return(“Unknown”);
}
//±-----------------------------------------------------------------+

what kind of alert are you looking for? and when do you want to be alerted?

hello i would like obten . symbol + timeframe+ price+ time EmailAlert over RSI levels 30,50,70

already have this new one and it is working well , but i would like obten this Alert format

Symbol: BTCUSD
Time Frame: 15 M
Price: 7.900
TimeAlert: 12:00 pm


RSI LEVEL is 30 (OVERSOLD)


//------------------------------------------------------------------
#property copyright “© mladen, 2016, MetaQuotes Software Corp.”
#property link “www.forex-tsd.com, www.mql5.com
//------------------------------------------------------------------
#property indicator_separate_window
#property indicator_buffers 8
#property indicator_plots 5

#property indicator_label1 “rsi OB/OS zone”
#property indicator_type1 DRAW_FILLING
#property indicator_color1 C’209,243,209’,C’255,230,183’
#property indicator_label2 “rsi up level”
#property indicator_type2 DRAW_LINE
#property indicator_color2 clrLimeGreen
#property indicator_style2 STYLE_DOT
#property indicator_label3 “rsi middle level”
#property indicator_type3 DRAW_LINE
#property indicator_color3 clrSilver
#property indicator_style3 STYLE_DOT
#property indicator_label4 “rsi down level”
#property indicator_type4 DRAW_LINE
#property indicator_color4 clrOrange
#property indicator_style4 STYLE_DOT
#property indicator_label5 “rsi”
#property indicator_type5 DRAW_COLOR_LINE
#property indicator_color5 clrSilver,clrLimeGreen,clrOrange
#property indicator_width5 2

//
//
//
//
//

enum enPrices
{
pr_close, // Close
pr_open, // Open
pr_high, // High
pr_low, // Low
pr_median, // Median
pr_typical, // Typical
pr_weighted, // Weighted
pr_average, // Average (high+low+open+close)/4
pr_medianb, // Average median body (open+close)/2
pr_tbiased, // Trend biased price
pr_tbiased2, // Trend biased (extreme) price
pr_haclose, // Heiken ashi close
pr_haopen , // Heiken ashi open
pr_hahigh, // Heiken ashi high
pr_halow, // Heiken ashi low
pr_hamedian, // Heiken ashi median
pr_hatypical, // Heiken ashi typical
pr_haweighted, // Heiken ashi weighted
pr_haaverage, // Heiken ashi average
pr_hamedianb, // Heiken ashi median body
pr_hatbiased, // Heiken ashi trend biased price
pr_hatbiased2 // Heiken ashi trend biased (extreme) price
};
enum enRsiTypes
{
rsi_cut, // Cuttler’s RSI
rsi_ehl, // Ehlers’ smoothed RSI
rsi_har, // Harris’ RSI
rsi_rap, // Rapid RSI
rsi_rsi, // RSI
rsi_rsx, // RSX
rsi_slo // Slow RSI
};
enum enColorOn
{
cc_onSlope, // Change color on slope change
cc_onMiddle, // Change color on middle line cross
cc_onLevels // Change color on outer levels cross
};
enum enMaTypes
{
ma_sma, // Simple moving average
ma_ema, // Exponential moving average
ma_smma, // Smoothed MA
ma_lwma // Linear weighted MA
};

input ENUM_TIMEFRAMES TimeFrame = PERIOD_CURRENT; // Time frame
input int RsiPeriod = 14; // Rsi period
input enPrices RsiPrice = pr_close; // Price to use
input enRsiTypes RsiMethod = rsi_rsi; // Rsi method
input int PriceSmoothing = 0; // Price smoothing (<= 1 for no smoothing)
input enMaTypes PriceSmoothingM = ma_ema; // Price smoothing method
input enColorOn ColorOn = cc_onLevels; // Color change :
input int MinMaxPeriod = 50; // Floating levels period (<= 1 for fixed levels)
input double LevelUp = 80.0; // Up level %
input double LevelDown = 20.0; // Down level %
input bool alertsOn = false; // Turn alerts on?
input bool alertsOnCurrent = true; // Alert on current bar?
input bool alertsMessage = true; // Display messageas on alerts?
input bool alertsSound = false; // Play sound on alerts?
input bool alertsEmail = false; // Send email on alerts?
input bool alertsNotify = false; // Send push notification on alerts?
input bool Interpolate = true; // Interpolate mtf data ?

double rsi[],rsic[],fill1[],fill2[],levelUp[],levelMi[],levelDn[],count[];
ENUM_TIMEFRAMES timeFrame;

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

int OnInit()
{
SetIndexBuffer(0,fill1 ,INDICATOR_DATA);
SetIndexBuffer(1,fill2 ,INDICATOR_DATA);
SetIndexBuffer(2,levelUp,INDICATOR_DATA);
SetIndexBuffer(3,levelMi,INDICATOR_DATA);
SetIndexBuffer(4,levelDn,INDICATOR_DATA);
SetIndexBuffer(5,rsi ,INDICATOR_DATA);
SetIndexBuffer(6,rsic ,INDICATOR_COLOR_INDEX);
SetIndexBuffer(7,count ,INDICATOR_CALCULATIONS);
for (int i=0; i<4; i++) PlotIndexSetInteger(i,PLOT_SHOW_DATA,false);
timeFrame = MathMax(_Period,TimeFrame);
IndicatorSetString(INDICATOR_SHORTNAME,timeFrameToString(timeFrame)+" “+getRsiName(RsiMethod)+”(oma) ("+(string)RsiPeriod+","+(string)PriceSmoothing+","+(string)MinMaxPeriod+")");
return(0);
}

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

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[])
{
if (Bars(_Symbol,_Period)<rates_total) return(-1);

  //
  //
  //
  //
  //
  
  if (timeFrame!=_Period)
  {
     double result[]; datetime currTime[],nextTime[]; 
     static int indHandle =-1;
            if (indHandle==-1) indHandle = iCustom(_Symbol,timeFrame,getIndicatorName(),PERIOD_CURRENT,RsiPeriod,RsiPrice,RsiMethod,PriceSmoothing,PriceSmoothingM,ColorOn,MinMaxPeriod,LevelUp,LevelDown,alertsOn,alertsOnCurrent,alertsMessage,alertsSound,alertsEmail,alertsNotify);
            if (indHandle==-1)                          return(0);
            if (CopyBuffer(indHandle,7,0,1,result)==-1) return(0); 
         
            //
            //
            //
            //
            //
          
            #define _processed EMPTY_VALUE-1
            int i,limit = rates_total-(int)MathMin(result[0]*PeriodSeconds(timeFrame)/PeriodSeconds(_Period),rates_total); 
            for (limit=MathMax(limit,0); limit>0 && !IsStopped(); limit--) if (count[limit]==_processed) break;
            for (i=MathMin(limit,MathMax(prev_calculated-1,0)); i<rates_total && !IsStopped(); i++    )
            {
               if (CopyBuffer(indHandle,0,time[i],1,result)==-1) break; fill1[i]   = result[0];
               if (CopyBuffer(indHandle,1,time[i],1,result)==-1) break; fill2[i]   = result[0];
               if (CopyBuffer(indHandle,2,time[i],1,result)==-1) break; levelUp[i] = result[0];
               if (CopyBuffer(indHandle,3,time[i],1,result)==-1) break; levelMi[i] = result[0];
               if (CopyBuffer(indHandle,4,time[i],1,result)==-1) break; levelDn[i] = result[0];
               if (CopyBuffer(indHandle,5,time[i],1,result)==-1) break; rsi[i]     = result[0];
               if (CopyBuffer(indHandle,6,time[i],1,result)==-1) break; rsic[i]    = result[0];
                                                                        count[i]   = _processed;
               
               //
               //
               //
               //
               //
               
               #define _interpolate(buff,i,k,n) buff[i-k] = buff[i]+(buff[i-n]-buff[i])*k/n
               if (!Interpolate) continue; CopyTime(_Symbol,TimeFrame,time[i  ],1,currTime); 
                  if (i<(rates_total-1)) { CopyTime(_Symbol,TimeFrame,time[i+1],1,nextTime); if (currTime[0]==nextTime[0]) continue; }
                  int n,k;
                     for(n=1; (i-n)> 0 && time[i-n] >= currTime[0]; n++) continue;	
                     for(k=1; (i-k)>=0 && k<n; k++)
                     {
                        _interpolate(fill1  ,i,k,n);
                        _interpolate(fill2  ,i,k,n);
                        _interpolate(levelUp,i,k,n);
                        _interpolate(levelDn,i,k,n);
                        _interpolate(levelMi,i,k,n);
                        _interpolate(rsi    ,i,k,n);
                     }                            
            }     
            if (i!=rates_total) return(0); return(rates_total);
  }

//
//
//
//
//

for (int i=(int)MathMax(prev_calculated-1,0); i<rates_total; i++)
{
rsi[i] = iRsi(RsiMethod,iCustomMa(PriceSmoothingM,getPrice(RsiPrice,open,close,high,low,i,rates_total),PriceSmoothing,i,rates_total),RsiPeriod,i,rates_total);
if (MinMaxPeriod<=1)
{
levelUp[i] = LevelUp;
levelDn[i] = LevelDown;
levelMi[i] = (levelUp[i]+levelDn[i])/2;
}
else
{
double min = rsi[i];
double max = rsi[i];
for (int k=1; k<MinMaxPeriod && i-k>=0; k++)
{
min = MathMin(rsi[i-k],min);
max = MathMax(rsi[i-k],max);
}
double range = max-min;
levelUp[i] = min+LevelUp range/100.0;
levelDn[i] = min+LevelDown
range/100.0;
levelMi[i] = min+0.5*range;
}
switch(ColorOn)
{
case cc_onLevels: rsic[i] = (rsi[i]>levelUp[i]) ? 1 : (rsi[i]<levelDn[i]) ? 2 : 0; break;
case cc_onMiddle: rsic[i] = (rsi[i]>levelMi[i]) ? 1 : (rsi[i]<levelMi[i]) ? 2 : 0; break;
default : rsic[i] = (i>0) ? (rsi[i]>rsi[i-1]) ? 1 : (rsi[i]<rsi[i-1]) ? 2 : 0 : 0;
}
fill1[i] = rsi[i];
fill2[i] = (rsi[i]>levelUp[i]) ? levelUp[i] : (rsi[i]<levelDn[i]) ? levelDn[i] : rsi[i];
}
count[rates_total-1] = MathMax(rates_total-prev_calculated+1,1);
manageAlerts(time,rsic,rates_total);
return(rates_total);
}

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

void manageAlerts(const datetime& time[], double& ttrend[], int bars)
{
if (!alertsOn) return;
int whichBar = bars-1; if (!alertsOnCurrent) whichBar = bars-2; datetime time1 = time[whichBar];
if (ttrend[whichBar] != ttrend[whichBar-1])
{
if (ttrend[whichBar] == 1) doAlert(time1," LEVEL OVERBOUGTH");
if (ttrend[whichBar] == 2) doAlert(time1," LEVEL OVERSOLD ");
}
}

//
//
//
//
//

void doAlert(datetime forTime, string doWhat)
{
static string previousAlert=“nothing”;
static datetime previousTime;

if (previousAlert != doWhat || previousTime != forTime)
{
previousAlert = doWhat;
previousTime = forTime;

  string message = timeFrameToString (+_Period)+ " getPrice( _Price)" "+_Symbol+" "at" "+TimeToString(TimeLocal(),TIME_SECONDS)"+ getRsiName( RsiMethod)+doWhat;
     if (alertsMessage) Alert(message);
     if (alertsEmail)   SendMail(_Symbol+" "+ getRsiName (RsiMethod),message);
     if (alertsNotify)  SendNotification(message);
     if (alertsSound)   PlaySound("alert2.wav");

}
}

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//
//

string getRsiName(int method)
{
switch (method)
{
case rsi_rsi: return(“RSI”);
case rsi_rsx: return(“RSX”);
case rsi_cut: return(“Cuttler’s RSI”);
case rsi_har: return(“Haris’ RSI”);
case rsi_rap: return(“Rapid RSI”);
case rsi_slo: return(“Slow RSI”);
case rsi_ehl: return(“Ehlers’ smoothed RSI”);
default: return("");
}
}

//
//
//
//
//

#define rsiInstances 1
double workRsi[][rsiInstances*13];
#define _price 0
#define _prices 3
#define _change 1
#define _changa 2
#define _rsival 1
#define _rsval 1
#define _smallRsiValue 0.0000000000000001

double iRsi(int rsiMode, double price, double period, int r, int bars, int instanceNo=0)
{
if (ArrayRange(workRsi,0)!=bars) ArrayResize(workRsi,bars);
int z = instanceNo*13;

//
//
//
//
//

workRsi[r][z+_price] = price;
switch (rsiMode)
{
case rsi_rsi:
{
double alpha = 1.0/MathMax(period,1);
if (r<period)
{
int k; double sum = 0; for (k=0; k<period && (r-k-1)>=0; k++) sum += MathAbs(workRsi[r-k][z+_price]-workRsi[r-k-1][z+_price]);
workRsi[r][z+_change] = (workRsi[r][z+_price]-workRsi[0][z+_price])/MathMax(k,1);
workRsi[r][z+_changa] = sum/MathMax(k,1);
}
else
{
double change = workRsi[r][z+_price]-workRsi[r-1][z+_price];
workRsi[r][z+_change] = workRsi[r-1][z+_change] + alpha*( change - workRsi[r-1][z+_change]);
workRsi[r][z+_changa] = workRsi[r-1][z+_changa] + alpha*(MathAbs(change) - workRsi[r-1][z+_changa]);
}
return(50.0*(workRsi[r][z+_change]/MathMax(workRsi[r][z+_changa],_smallRsiValue)+1));
}

  //
  //
  //
  //
  //
  
  case rsi_slo :
     {         
        double up = 0, dn = 0;
        for(int k=0; k<(int)period && (r-k-1)>=0; k++)
        {
           double diff = workRsi[r-k][z+_price]- workRsi[r-k-1][z+_price];
           if(diff>0)
                 up += diff;
           else  dn -= diff;
        }
        if (r<1)
              workRsi[r][z+_rsival] = 50;
        else               
               workRsi[r][z+_rsival] = workRsi[r-1][z+_rsival]+(1/MathMax(period,1))*(100*up/MathMax(up+dn,_smallRsiValue)-workRsi[r-1][z+_rsival]);
        return(workRsi[r][z+_rsival]);      
     }
  
  //
  //
  //
  //
  //

  case rsi_rap :
     {
        double up = 0, dn = 0;
        for(int k=0; k<(int)period && (r-k-1)>=0; k++)
        {
           double diff = workRsi[r-k][z+_price]- workRsi[r-k-1][z+_price];
           if(diff>0)
                 up += diff;
           else  dn -= diff;
        }
        return(100 * up /MathMax(up + dn,_smallRsiValue));      
     }            
     
  //
  //
  //
  //
  //
           
  case rsi_ehl :
     {
        double up = 0, dn = 0;
        workRsi[r][z+_prices] = (r>2) ? (workRsi[r][z+_price]+2.*workRsi[r-1][z+_price]+workRsi[r-2][z+_price])/4.0 : price;
        for(int k=0; k<(int)period && (r-k-1)>=0; k++)
        {
           double diff = workRsi[r-k][z+_prices]- workRsi[r-k-1][z+_prices];
           if(diff>0)
                 up += diff;
           else  dn -= diff;
        }
        return(50*(up-dn)/MathMax(up+dn,_smallRsiValue)+50);      
     }            

  //
  //
  //
  //
  //
  
  case rsi_cut :
     {
        double sump = 0;
        double sumn = 0;
        for (int k=0; k<(int)period && (r-k-1)>=0; k++)
        {
           double diff = workRsi[r-k][z+_price]-workRsi[r-k-1][z+_price];
              if (diff > 0) 
                    sump += diff;
              else  sumn -= diff;
        }
               workRsi[r][instanceNo+_rsival] = 100.0-100.0/(1.0+sump/MathMax(sumn,_smallRsiValue));
        return(workRsi[r][instanceNo+_rsival]);
     }            

  //
  //
  //
  //
  //

  case rsi_har :
     {
        double avgUp=0,avgDn=0,up=0,dn=0;
        for(int k=0; k<(int)period && (r-k-1)>=0; k++)
        {
           double diff = workRsi[r-k][instanceNo+_price]- workRsi[r-k-1][instanceNo+_price];
           if(diff>0)
                 { avgUp += diff; up++; }
           else  { avgDn -= diff; dn++; }
        }
        if (up!=0) avgUp /= up;
        if (dn!=0) avgDn /= dn;
                      workRsi[r][instanceNo+_rsival] = 100-100/(1.0+(avgUp/MathMax(avgDn,_smallRsiValue)));
               return(workRsi[r][instanceNo+_rsival]);
     }               

  //
  //
  //
  //
  //
  
  case rsi_rsx :  
     {   
        double Kg = (3.0)/(2.0+period), Hg = 1.0-Kg;
        if (r<period) { for (int k=1; k<13; k++) workRsi[r][k+z] = 0; return(50); }  

        //
        //
        //
        //
        //
  
        double mom = workRsi[r][_price+z]-workRsi[r-1][_price+z];
        double moa = MathAbs(mom);
        for (int k=0; k<3; k++)
        {
           int kk = k*2;
           workRsi[r][z+kk+1] = Kg*mom                + Hg*workRsi[r-1][z+kk+1];
           workRsi[r][z+kk+2] = Kg*workRsi[r][z+kk+1] + Hg*workRsi[r-1][z+kk+2]; mom = 1.5*workRsi[r][z+kk+1] - 0.5 * workRsi[r][z+kk+2];
           workRsi[r][z+kk+7] = Kg*moa                + Hg*workRsi[r-1][z+kk+7];
           workRsi[r][z+kk+8] = Kg*workRsi[r][z+kk+7] + Hg*workRsi[r-1][z+kk+8]; moa = 1.5*workRsi[r][z+kk+7] - 0.5 * workRsi[r][z+kk+8];
        }
        return(MathMax(MathMin((mom/MathMax(moa,_smallRsiValue)+1.0)*50.0,100.00),0.00)); 
     }            

}
return(0);
}

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//
//

#define priceInstances 1
double workHa[][priceInstances4];
double getPrice(int tprice, const double& open[], const double& close[], const double& high[], const double& low[], int i,int _bars, int instanceNo=0)
{
if (tprice>=pr_haclose)
{
if (ArrayRange(workHa,0)!= _bars) ArrayResize(workHa,_bars); instanceNo
=4;

     //
     //
     //
     //
     //
     
     double haOpen;
     if (i>0)
            haOpen  = (workHa[i-1][instanceNo+2] + workHa[i-1][instanceNo+3])/2.0;
     else   haOpen  = (open[i]+close[i])/2;
     double haClose = (open[i] + high[i] + low[i] + close[i]) / 4.0;
     double haHigh  = MathMax(high[i], MathMax(haOpen,haClose));
     double haLow   = MathMin(low[i] , MathMin(haOpen,haClose));

     if(haOpen  <haClose) { workHa[i][instanceNo+0] = haLow;  workHa[i][instanceNo+1] = haHigh; } 
     else                 { workHa[i][instanceNo+0] = haHigh; workHa[i][instanceNo+1] = haLow;  } 
                            workHa[i][instanceNo+2] = haOpen;
                            workHa[i][instanceNo+3] = haClose;
     //
     //
     //
     //
     //
     
     switch (tprice)
     {
        case pr_haclose:     return(haClose);
        case pr_haopen:      return(haOpen);
        case pr_hahigh:      return(haHigh);
        case pr_halow:       return(haLow);
        case pr_hamedian:    return((haHigh+haLow)/2.0);
        case pr_hamedianb:   return((haOpen+haClose)/2.0);
        case pr_hatypical:   return((haHigh+haLow+haClose)/3.0);
        case pr_haweighted:  return((haHigh+haLow+haClose+haClose)/4.0);
        case pr_haaverage:   return((haHigh+haLow+haClose+haOpen)/4.0);
        case pr_hatbiased:
           if (haClose>haOpen)
                 return((haHigh+haClose)/2.0);
           else  return((haLow+haClose)/2.0);        
        case pr_hatbiased2:
           if (haClose>haOpen)  return(haHigh);
           if (haClose<haOpen)  return(haLow);
                                return(haClose);        
     }

}

//
//
//
//
//

switch (tprice)
{
case pr_close: return(close[i]);
case pr_open: return(open[i]);
case pr_high: return(high[i]);
case pr_low: return(low[i]);
case pr_median: return((high[i]+low[i])/2.0);
case pr_medianb: return((open[i]+close[i])/2.0);
case pr_typical: return((high[i]+low[i]+close[i])/3.0);
case pr_weighted: return((high[i]+low[i]+close[i]+close[i])/4.0);
case pr_average: return((high[i]+low[i]+close[i]+open[i])/4.0);
case pr_tbiased:
if (close[i]>open[i])
return((high[i]+close[i])/2.0);
else return((low[i]+close[i])/2.0);
case pr_tbiased2:
if (close[i]>open[i]) return(high[i]);
if (close[i]<open[i]) return(low[i]);
return(close[i]);
}
return(0);
}

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

#define _maInstances 4
#define _maWorkBufferx1 1*_maInstances
#define _maWorkBufferx2 2*_maInstances

double iCustomMa(int mode, double price, double length, int r, int bars, int instanceNo=0)
{
switch (mode)
{
case ma_sma : return(iSma(price,(int)length,r,bars,instanceNo));
case ma_ema : return(iEma(price,length,r,bars,instanceNo));
case ma_smma : return(iSmma(price,(int)length,r,bars,instanceNo));
case ma_lwma : return(iLwma(price,(int)length,r,bars,instanceNo));
default : return(price);
}
}

//
//
//
//
//

double workSma[][_maWorkBufferx2];
double iSma(double price, int period, int r, int _bars, int instanceNo=0)
{
if (ArrayRange(workSma,0)!= _bars) ArrayResize(workSma,_bars); instanceNo *= 2; int k;

workSma[r][instanceNo+0] = price;
workSma[r][instanceNo+1] = price; for(k=1; k<period && (r-k)>=0; k++) workSma[r][instanceNo+1] += workSma[r-k][instanceNo+0];
workSma[r][instanceNo+1] /= 1.0*k;
return(workSma[r][instanceNo+1]);
}

//
//
//
//
//

double workEma[][_maWorkBufferx1];
double iEma(double price, double period, int r, int _bars, int instanceNo=0)
{
if (ArrayRange(workEma,0)!= _bars) ArrayResize(workEma,_bars);

workEma[r][instanceNo] = price;
if (r>0 && period>1)
workEma[r][instanceNo] = workEma[r-1][instanceNo]+(2.0/(1.0+period))*(price-workEma[r-1][instanceNo]);
return(workEma[r][instanceNo]);
}

//
//
//
//
//

double workSmma[][_maWorkBufferx1];
double iSmma(double price, double period, int r, int _bars, int instanceNo=0)
{
if (ArrayRange(workSmma,0)!= _bars) ArrayResize(workSmma,_bars);

workSmma[r][instanceNo] = price;
if (r>1 && period>1)
workSmma[r][instanceNo] = workSmma[r-1][instanceNo]+(price-workSmma[r-1][instanceNo])/period;
return(workSmma[r][instanceNo]);
}

//
//
//
//
//

double workLwma[][_maWorkBufferx1];
double iLwma(double price, double period, int r, int _bars, int instanceNo=0)
{
if (ArrayRange(workLwma,0)!= _bars) ArrayResize(workLwma,_bars);

workLwma[r][instanceNo] = price; if (period<=1) return(price);
double sumw = period;
double sum = period*price;

  for(int k=1; k<period && (r-k)>=0; k++)
  {
     double weight = period-k;
            sumw  += weight;
            sum   += weight*workLwma[r-k][instanceNo];  
  }             
  return(sum/sumw);

}

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

string getIndicatorName()
{
string path = MQL5InfoString(MQL5_PROGRAM_PATH);
string data = TerminalInfoString(TERMINAL_DATA_PATH)+"\MQL5\Indicators\";
string name = StringSubstr(path,StringLen(data));
return(name);
}

//
//
//
//
//

int _tfsPer[]={PERIOD_M1,PERIOD_M2,PERIOD_M3,PERIOD_M4,PERIOD_M5,PERIOD_M6,PERIOD_M10,PERIOD_M12,PERIOD_M15,PERIOD_M20,PERIOD_M30,PERIOD_H1,PERIOD_H2,PERIOD_H3,PERIOD_H4,PERIOD_H6,PERIOD_H8,PERIOD_H12,PERIOD_D1,PERIOD_W1,PERIOD_MN1};
string _tfsStr[]={“1 minute”,“2 minutes”,“3 minutes”,“4 minutes”,“5 minutes”,“6 minutes”,“10 minutes”,“12 minutes”,“15 minutes”,“20 minutes”,“30 minutes”,“1 hour”,“2 hours”,“3 hours”,“4 hours”,“6 hours”,“8 hours”,“12 hours”,“daily”,“weekly”,“monthly”};
string timeFrameToString(int period)
{
if (period==PERIOD_CURRENT)
period = _Period;
int i; for(i=ArraySize(_tfsPer)-1;i>=0;i–) if(period==_tfsPer[i]) break;
return(_tfsStr[i]);
}