RSI_MTF is a technical indicator based on the Relative Strength Index (RSI) designed to display RSI signals from multiple timeframes simultaneously within a single MetaTrader 5 chart window. This indicator is highly useful for traders who want to perform efficient multi-timeframe analysis.
Main Features
- Displays RSI signals from up to 21 different timeframes (M1 to MN1).
- Visualizes RSI direction signals using colored arrows (up, down, neutral).
- Interactive panel to switch timeframes directly from the chart.
- Signal notifications via pop-up, email, and push notifications.
- Flexible settings for colors, fonts, and panel positioning.
Technical Overview: How the Indicator Works
In this section of this article discusses the technical details and implementation of the RSI_MTF indicator on the MetaTrader 5 platform.
This section explains how key functions such as: RSI_MTF_Config(void) Function
virtual void RSI_MTF_Config(void)
{
//--
ENUM_TIMEFRAMES TFIx[]= {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};
tfxar=ArraySize(TFIx);
ArrayResize(TFId,tfxar,tfxar);
ArrayResize(Arwcolor,tfxar,tfxar);
ArrayCopy(TFId,TFIx,0,0,WHOLE_ARRAY);
//--
string TFxc[]= {"M1","M2","M3","M4","M5","M6","M10","M12","M15","M20","M30","H1",
"H2","H3","H4","H6","H8","H12","D1","W1","MN1"}; // 21 Timeframes
//--
ArrayResize(hRSI,tfxar,tfxar);
ArrayResize(TFSc,tfxar,tfxar);
ArrayCopy(TFSc,TFxc,0,0,WHOLE_ARRAY);
//--
if(BarCalc<1)
{
RSI_period=14;
PrintFormat("Incorrect value for input variable BarCalc = %d. Indicator will use value %d for calculations.",
BarCalc,RSI_period);
}
else
RSI_period=BarCalc;
//--
ttlbars=BarCalc*3+3;
//--
for(int x=0; x<tfxar; x++)
hRSI[x]=iRSI(Symbol(),TFId[x],RSI_period,PRICE_CLOSE); // Handle of iRSI Indicator on each timeframe
//--
DeletedRSIObject();
RSIMovementCalculation(25);
PositionCore();
//--
if(display)
DrawRSIObject();
//---
}
//---
RSIDirectionScan() Function
//---
int RSIDirectionScan(const ENUM_TIMEFRAMES stf,int shift) // Scan OBV Direction
{
//--
int ret=0;
int rise=1,
down=-1;
//--
int br=shift+2;
double res=0.0;
UpdatePrice(stf);
//--
double RSI[];
ArrayResize(RSI,br,br);
ArraySetAsSeries(RSI,true);
//--
int xx=TFIndexArray(stf);
CopyBuffer(hRSI[xx],0,0,br,RSI);
//--
if(RSI[shift]>RSI[shift+1]) ret=rise;
if(RSI[shift]<RSI[shift+1]) ret=down;
//--
return(ret);
//---
} //-end RSIDirectionScan()
//---
RSIMovementCalculation() Function work synergistically to produce accurate and easy-to-understand multi-timeframe RSI signals.
//---
void RSIMovementCalculation(int barCnt) // Scan the direction of iRSI on each timeframe
{
//--
ArrayResize(PowerMove,barCnt,barCnt);
ArraySetAsSeries(PowerMove,true);
//--
for(int i=barCnt-1; i>=0; i--)
{
up=0;
dw=0;
//--
for(int x=0; x<tfxar; x++)
{
Arwcolor[x]=NTArrow;
PowerMove[i]=0.0;
int PPM=RSIDirectionScan(TFId[x],0);
if(PPM>0)
{
up++;
Arwcolor[x]=ArrowUp;
}
if(PPM<0)
{
dw++;
Arwcolor[x]=ArrowDn;
}
if(x==tfxar-1)
{
if(up>dw+1)
{
PowerMove[i]=1.0;
TColor=ArrowUp;
curAlert=1;
}
if(dw>up+1)
{
PowerMove[i]=-1.0;
TColor=ArrowDn;
curAlert=-1;
}
}
}
}
//--
return;
//---
} //-end RSIMovementCalculation()
//---
The RSI_MTF_Config() function is responsible for retrieving RSI values from various user-defined timeframes. These values are then analyzed by RSIDirectionScan() to determine the RSI movement direction on each timeframe—whether it is rising, falling, or neutral.
Subsequently, RSIMovementCalculation() calculates the number of upward and downward signals from all monitored timeframes. If upward signals dominate by a certain margin, the indicator displays a green arrow indicating an uptrend. Conversely, if downward signals dominate, a red arrow appears. If signals are neutral or no dominance exists, a gray arrow is shown.
This section also explains how the interactive panel on the chart allows users to easily switch the monitored timeframe by clicking available buttons. The panel can be positioned at the top or bottom of the chart according to user preference.
With a deep understanding from this section, users can optimize the use of the RSI_MTF indicator for more effective and efficient multi-timeframe analysis in trading decisions.
Visualization and Interactive Panel
The DrawRSIObject() function is responsible for displaying arrows and interactive buttons on the chart. Traders can click timeframe buttons to instantly switch the chart view to that timeframe. The panel can be positioned at the top or bottom of the chart based on user preference.
//---
void DrawRSIObject(void)
{
//--
CreateButtonTemplate(CI,ObjName+"Template",397,66,STYLE_SOLID,9,BORDER_RAISED,clrMistyRose,clrLavenderBlush,clrWhite,bcor,corx,cory,true);
for(int x=0; x<tfhalf; x++)
{
CreateArrowLabel(CI,ObjName+"_win_arrow_"+string(x),CharToString((uchar)windchar),"Wingdings",windsize,Arwcolor[x],bcor,
txttf+horizL1+(x*scaleX)+offsetX+x,vertiL1,true,"Arrow_"+TFSc[x]);
CreateButtonClick(CI,TFSc[x],27,15,font_mode,fontSize,BORDER_FLAT,TFSc[x],clrBurlyWood,clrSilver,clrBlue,
bcor,txttf+horizL2+(x*scaleA)+offsetX,vertiL2,true,
"Change Timeframe to : "+TFSc[x]);
}
for(int x=tfhalf, x2=0; x<tfxar; x++, x2++)
{
CreateArrowLabel(CI,ObjName+"_win_arrow_"+string(x),CharToString((uchar)windchar),"Wingdings",windsize,Arwcolor[x],bcor,
txttf+horizL3+(x2*scaleX)+offsetX+x2,vertiL3,true,"Arrow_"+TFSc[x]);
CreateButtonClick(CI,TFSc[x],27,15,font_mode,fontSize,BORDER_FLAT,TFSc[x],clrBurlyWood,clrSilver,clrBlue,
bcor,txttf+horizL4+(x2*scaleA)+offsetX,vertiL4,true,
"Change Timeframe to : "+TFSc[x]);
//--
if(x==20)
{
int arrowChar=TColor==ArrowUp ? 200 : TColor==ArrowDn ? 202 : windchar;
CreateArrowLabel(CI,ObjName+"_tfx_arrow_"+string(x+1),"Move",font_mode,fontSize,clrBlue,bcor,
519+horizL5,vertiL5,true,"Move");
CreateArrowLabel(CI,ObjName+"_win_arrow_"+string(x+1),CharToString((uchar)arrowChar),"Wingdings",15,TColor,bcor,
522+horizL6,vertiL6,true,"Arrow Indicator Movement");
}
}
DisplayButtonClick("X");
CreateButtonTemplate(CI,ObjName+"TemplateName1",17,15,STYLE_SOLID,1,BORDER_FLAT,clrMistyRose,clrLavenderBlush,clrWhite,bcor,TNamex,TNamey1,true);
CreateButtonTemplate(CI,ObjName+"TemplateName2",17,15,STYLE_SOLID,1,BORDER_FLAT,clrMistyRose,clrLavenderBlush,clrWhite,bcor,TNamex,TNamey2,true);
CreateButtonTemplate(CI,ObjName+"TemplateName3",17,15,STYLE_SOLID,1,BORDER_FLAT,clrMistyRose,clrLavenderBlush,clrWhite,bcor,TNamex,TNamey3,true);
CreateArrowLabel(CI,ObjName+"_name1",hName1,font_mode,fontSize+1,clrBlue,bcor,TNamexn,TNamey1n,true,hName1);
CreateArrowLabel(CI,ObjName+"_name2",hName2,font_mode,fontSize+1,clrBlue,bcor,TNamexn,TNamey2n,true,hName2);
CreateArrowLabel(CI,ObjName+"_name3",hName3,font_mode,fontSize+1,clrBlue,bcor,TNamexn,TNamey3n,true,hName3);
//--
if(corpos==postop)
{
DisplayButtonClick("cstar");
DisplayButtonClick("arbot");
}
if(corpos==posbot)
{
DisplayButtonClick("cstar");
DisplayButtonClick("artop");
}
//--
return;
//---
} //-end DrawRSIObject()
//---
Supporting Functions and Code Explanation
In this section, we provide detailed explanations of specific key functions used in the RSI_MTF indicator to help you understand their roles and how they contribute to the overall functionality.
1. The DrawRSIObject() function is designed to create and display a graphical user interface (GUI) for an RSI (Relative Strength Index) indicator in a trading platform, likely MetaTrader (MQL4 or MQL5). It builds a panel with buttons and arrow labels that allow the user to interact with different timeframes and visual elements.
//---
void DrawRSIObject(void)
{
//--
CreateButtonTemplate(CI,ObjName+"Template",397,66,STYLE_SOLID,9,BORDER_RAISED,clrMistyRose,clrLavenderBlush,clrWhite,bcor,corx,cory,true);
for(int x=0; x<tfhalf; x++)
{
CreateArrowLabel(CI,ObjName+"_win_arrow_"+string(x),CharToString((uchar)windchar),"Wingdings",windsize,Arwcolor[x],bcor,
txttf+horizL1+(x*scaleX)+offsetX+x,vertiL1,true,"Arrow_"+TFSc[x]);
CreateButtonClick(CI,TFSc[x],27,15,font_mode,fontSize,BORDER_FLAT,TFSc[x],clrBurlyWood,clrSilver,clrBlue,
bcor,txttf+horizL2+(x*scaleA)+offsetX,vertiL2,true,
"Change Timeframe to : "+TFSc[x]);
}
for(int x=tfhalf, x2=0; x<tfxar; x++, x2++)
{
CreateArrowLabel(CI,ObjName+"_win_arrow_"+string(x),CharToString((uchar)windchar),"Wingdings",windsize,Arwcolor[x],bcor,
txttf+horizL3+(x2*scaleX)+offsetX+x2,vertiL3,true,"Arrow_"+TFSc[x]);
CreateButtonClick(CI,TFSc[x],27,15,font_mode,fontSize,BORDER_FLAT,TFSc[x],clrBurlyWood,clrSilver,clrBlue,
bcor,txttf+horizL4+(x2*scaleA)+offsetX,vertiL4,true,
"Change Timeframe to : "+TFSc[x]);
//--
if(x==20)
{
int arrowChar=TColor==ArrowUp ? 200 : TColor==ArrowDn ? 202 : windchar;
CreateArrowLabel(CI,ObjName+"_tfx_arrow_"+string(x+1),"Move",font_mode,fontSize,clrBlue,bcor,
519+horizL5,vertiL5,true,"Move");
CreateArrowLabel(CI,ObjName+"_win_arrow_"+string(x+1),CharToString((uchar)arrowChar),"Wingdings",15,TColor,bcor,
522+horizL6,vertiL6,true,"Arrow Indicator Movement");
}
}
DisplayButtonClick("X");
CreateButtonTemplate(CI,ObjName+"TemplateName1",17,15,STYLE_SOLID,1,BORDER_FLAT,clrMistyRose,clrLavenderBlush,clrWhite,bcor,TNamex,TNamey1,true);
CreateButtonTemplate(CI,ObjName+"TemplateName2",17,15,STYLE_SOLID,1,BORDER_FLAT,clrMistyRose,clrLavenderBlush,clrWhite,bcor,TNamex,TNamey2,true);
CreateButtonTemplate(CI,ObjName+"TemplateName3",17,15,STYLE_SOLID,1,BORDER_FLAT,clrMistyRose,clrLavenderBlush,clrWhite,bcor,TNamex,TNamey3,true);
CreateArrowLabel(CI,ObjName+"_name1",hName1,font_mode,fontSize+1,clrBlue,bcor,TNamexn,TNamey1n,true,hName1);
CreateArrowLabel(CI,ObjName+"_name2",hName2,font_mode,fontSize+1,clrBlue,bcor,TNamexn,TNamey2n,true,hName2);
CreateArrowLabel(CI,ObjName+"_name3",hName3,font_mode,fontSize+1,clrBlue,bcor,TNamexn,TNamey3n,true,hName3);
//--
if(corpos==postop)
{
DisplayButtonClick("cstar");
DisplayButtonClick("arbot");
}
if(corpos==posbot)
{
DisplayButtonClick("cstar");
DisplayButtonClick("artop");
}
//--
return;
//---
} //-end DrawRSIObject()
//---
This function builds a user interface for an RSI indicator, complete with buttons for changing timeframes, visual arrow indicators, and labels. It adapts the layout based on the number of timeframes and the current position setting PositionCore(void) function, and includes interactive elements for user control.
2. The ChangeChartSymbol() function is used to update the chart's timeframe and refresh the RSI (Relative Strength Index) panel accordingly. It's part of a graphical user interface system for a trading platform, likely MetaTrader.
//---
void ChangeChartSymbol(string tf_name,ENUM_TIMEFRAMES stf)
{
//---
//--- unpress the button
ObjectSetInteger(CI,tf_name,OBJPROP_STATE,false);
ObjectSetInteger(CI,tf_name,OBJPROP_ZORDER,0);
//--
DeletedRSIObject();
PanelPosChange(corpos);
ChartSetSymbolPeriod(CI,Symbol(),stf);
if(display)
DrawRSIObject();
//--
ChartRedraw(CI);
//--
return;
//---
} //-end ChangeChartSymbol()
//---
This function handles the logic for switching timeframes in a trading chart. It ensures the interface updates correctly by resetting the button state, removing and redrawing the RSI panel, and refreshing the chart display.
3. The DisplayButtonClick() function dynamically creates and displays specific buttons on a trading chart interface based on a given action request. It’s part of a graphical user interface (GUI) system, likely for a MetaTrader platform.
//---
void DisplayButtonClick(string actreq)
{
//--
if(actreq=="cstar")
CreateButtonClick(CI,cstar,20,20,"Wingdings",13,BORDER_FLAT,cstar,clrWhite,clrWhite,TColor,CORNER_RIGHT_UPPER,25,40,true,"Open Panel Indicator");
if(actreq=="artop")
CreateButtonClick(CI,artop,18,18,"Wingdings",11,BORDER_FLAT,artop,clrWhite,clrWhite,clrGreen,CORNER_RIGHT_UPPER,24,20,true,"Change Panel to Top");
if(actreq=="arbot")
CreateButtonClick(CI,arbot,18,18,"Wingdings",11,BORDER_FLAT,arbot,clrWhite,clrWhite,clrGreen,CORNER_RIGHT_UPPER,24,62,true,"Change Panel to Bottom");
if(actreq=="X")
CreateButtonClick(CI,"X",17,15,"Arial Black",fontSize,BORDER_FLAT,"X",clrWhite,clrWhite,clrRed,bcor,txttf-7+(11*scaleA)+offsetX,cory,true,"Close Panel");
//--
ChartRedraw(CI);
//--
return;
//---
} //-end DisplayButtonClick()
//---
This function acts like a button dispatcher. Based on the input string (), it creates and displays a specific button on the chart interface. Each button has a unique purpose—like opening the panel, moving it, or closing it—and is styled and positioned accordingly.
4. The CreateArrowLabel() function creates a custom text label—typically used to display an arrow or symbol—on a trading chart. This label is styled and positioned according to the parameters passed in, and it can include a tooltip for user interaction.
//---
bool CreateArrowLabel(long chart_id,
string lable_name,
string label_text,
string font_model,
int font_size,
color label_color,
int chart_corner,
int x_cor,
int y_cor,
bool price_hidden,
string tooltip)
{
//--
ObjectDelete(chart_id,lable_name);
//--
if(!ObjectCreate(chart_id,lable_name,OBJ_LABEL,0,0,0,0,0)) // create Label
{
Print(__FUNCTION__, ": failed to create \"Arrow Label\" sign! Error code = ",GetLastError());
return(false);
}
//--
ObjectSetString(chart_id,lable_name,OBJPROP_TEXT,label_text);
ObjectSetString(chart_id,lable_name,OBJPROP_FONT,font_model);
ObjectSetInteger(chart_id,lable_name,OBJPROP_FONTSIZE,WS(font_size));
ObjectSetInteger(chart_id,lable_name,OBJPROP_COLOR,label_color);
ObjectSetInteger(chart_id,lable_name,OBJPROP_CORNER,chart_corner);
ObjectSetInteger(chart_id,lable_name,OBJPROP_ANCHOR,ancp);
ObjectSetInteger(chart_id,lable_name,OBJPROP_XDISTANCE,WS(x_cor));
ObjectSetInteger(chart_id,lable_name,OBJPROP_YDISTANCE,WS(y_cor));
ObjectSetInteger(chart_id,lable_name,OBJPROP_HIDDEN,price_hidden);
ObjectSetString(chart_id,lable_name,OBJPROP_TOOLTIP,tooltip);
//-- successful execution
return(true);
//---
} //-end CreateArrowLabel()
//---
This function creates a styled label (often used for arrows or icons) on a chart, deletes any existing label with the same name, and configures its appearance and position. It’s a reusable utility for building GUI elements in a trading interface.
5. The CreateButtonTemplate() function creates a rectangular label on a trading chart (likely in MetaTrader) that acts as a visual button. It sets the button’s size, style, colors, position, and visibility.
//---
void CreateButtonTemplate(long chartid,
string obj_name,
int x_size,
int y_size,
int style,
int width,
int border,
color bordcolor,
color bgcolor,
color objcolor,
int corner,
int x_dist,
int y_dist,
bool hidden)
{
//--
ObjectCreate(chartid,obj_name,OBJ_RECTANGLE_LABEL,0,0,0); // create Rectangle Label
ObjectSetInteger(chartid,obj_name,OBJPROP_XSIZE,WS(x_size));
ObjectSetInteger(chartid,obj_name,OBJPROP_YSIZE,WS(y_size));
ObjectSetInteger(chartid,obj_name,OBJPROP_STYLE,style);
ObjectSetInteger(chartid,obj_name,OBJPROP_WIDTH,WS(width));
ObjectSetInteger(chartid,obj_name,OBJPROP_BORDER_TYPE,WS(border));
ObjectSetInteger(chartid,obj_name,OBJPROP_BORDER_COLOR,bordcolor);
ObjectSetInteger(chartid,obj_name,OBJPROP_BGCOLOR,bgcolor);
ObjectSetInteger(chartid,obj_name,OBJPROP_COLOR,objcolor);
ObjectSetInteger(chartid,obj_name,OBJPROP_CORNER,corner);
ObjectSetInteger(chartid,obj_name,OBJPROP_XDISTANCE,WS(x_dist));
ObjectSetInteger(chartid,obj_name,OBJPROP_YDISTANCE,WS(y_dist));
ObjectSetInteger(chartid,obj_name,OBJPROP_HIDDEN,hidden);
ChartRedraw(chartid);
//--
return;
//---
} //-end CreateButtonTemplate()
//---
This function is a reusable utility for drawing styled rectangular buttons on a chart. It abstracts away the complexity of setting multiple visual and positional properties, making it easier to maintain consistent UI elements across the trading interface.
6. The OnChartEvent() function handles user interactions with chart objects—specifically mouse clicks on GUI elements like buttons. It’s part of an interactive RSI panel system in MetaTrader, allowing users to control the panel’s visibility, position, and chart timeframe.
//+------------------------------------------------------------------+
//| ChartEvent function |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
const long &lparam,
const double &dparam,
const string &sparam)
{
//---
//--- handling CHARTEVENT_CLICK event ("Clicking the chart")
ResetLastError();
//--
if(id==CHARTEVENT_OBJECT_CLICK)
{
//--- if "X" button is click
if(sparam=="X")
{
mi.DeletedRSIObject();
//--- unpress the button
ObjectSetInteger(mi.CI,"X",OBJPROP_STATE,false);
ObjectSetInteger(mi.CI,"X",OBJPROP_ZORDER,0);
//--
mi.display=false;
ObjectDelete(mi.CI,"X");
mi.DisplayPanelButton();
}
//--- if "cstar" button is click
if(sparam==mi.cstar)
{
mi.DeletedRSIObject();
mi.DisplayPanelButton();
//--- unpress the button
ObjectSetInteger(mi.CI,mi.cstar,OBJPROP_STATE,false);
ObjectSetInteger(mi.CI,mi.cstar,OBJPROP_ZORDER,0);
if(!mi.display)
mi.display=true;
if(mi.corpos==mi.posbot) ObjectDelete(mi.CI,mi.arbot);
if(mi.corpos==mi.postop) ObjectDelete(mi.CI,mi.artop);
mi.DrawRSIObject();
//--
ChartRedraw(mi.CI);
}
//--- if "artop" button is click
if(sparam==mi.artop)
{
mi.DeletedRSIObject();
mi.DisplayPanelButton();
//--- unpress the button
ObjectSetInteger(mi.CI,mi.artop,OBJPROP_STATE,false);
ObjectSetInteger(mi.CI,mi.artop,OBJPROP_ZORDER,0);
if(!mi.display)
mi.display=true;
ObjectDelete(mi.CI,mi.artop);
mi.PanelPosChange(mi.postop);
//--
ObjectDelete(mi.CI,"X");
mi.DisplayButtonClick("arbot");
mi.DrawRSIObject();
//--
ChartRedraw(mi.CI);
}
//--- if "arbot" button is click
if(sparam==mi.arbot)
{
mi.DeletedRSIObject();
mi.DisplayPanelButton();
//--- unpress the button
ObjectSetInteger(mi.CI,mi.arbot,OBJPROP_STATE,false);
ObjectSetInteger(mi.CI,mi.arbot,OBJPROP_ZORDER,0);
if(!mi.display)
mi.display=true;
ObjectDelete(mi.CI,mi.arbot);
mi.PanelPosChange(mi.posbot);
//--
ObjectDelete(mi.CI,"X");
mi.DisplayButtonClick("artop");
mi.DrawRSIObject();
//--
ChartRedraw(mi.CI);
}
//--- if TF button is click
//--
if(sparam==mi.TFSc[0])
{
mi.ChangeChartSymbol(mi.TFSc[0],mi.TFId[0]);
}
//--
if(sparam==mi.TFSc[1])
{
mi.ChangeChartSymbol(mi.TFSc[1],mi.TFId[1]);
}
//--
if(sparam==mi.TFSc[2])
{
mi.ChangeChartSymbol(mi.TFSc[2],mi.TFId[2]);
}
//--
if(sparam==mi.TFSc[3])
{
mi.ChangeChartSymbol(mi.TFSc[3],mi.TFId[3]);
}
//--
if(sparam==mi.TFSc[4])
{
mi.ChangeChartSymbol(mi.TFSc[4],mi.TFId[4]);
}
//--
if(sparam==mi.TFSc[5])
{
mi.ChangeChartSymbol(mi.TFSc[5],mi.TFId[5]);
}
//--
if(sparam==mi.TFSc[6])
{
mi.ChangeChartSymbol(mi.TFSc[6],mi.TFId[6]);
}
//--
if(sparam==mi.TFSc[7])
{
mi.ChangeChartSymbol(mi.TFSc[7],mi.TFId[7]);
}
//--
if(sparam==mi.TFSc[8])
{
mi.ChangeChartSymbol(mi.TFSc[8],mi.TFId[8]);
}
//--
if(sparam==mi.TFSc[9])
{
mi.ChangeChartSymbol(mi.TFSc[9],mi.TFId[9]);
}
//--
if(sparam==mi.TFSc[10])
{
mi.ChangeChartSymbol(mi.TFSc[10],mi.TFId[10]);
}
//--
if(sparam==mi.TFSc[11])
{
mi.ChangeChartSymbol(mi.TFSc[11],mi.TFId[11]);
}
//--
if(sparam==mi.TFSc[12])
{
mi.ChangeChartSymbol(mi.TFSc[12],mi.TFId[12]);
}
//--
if(sparam==mi.TFSc[13])
{
mi.ChangeChartSymbol(mi.TFSc[13],mi.TFId[13]);
}
//--
if(sparam==mi.TFSc[14])
{
mi.ChangeChartSymbol(mi.TFSc[14],mi.TFId[14]);
}
//--
if(sparam==mi.TFSc[15])
{
mi.ChangeChartSymbol(mi.TFSc[15],mi.TFId[15]);
}
//--
if(sparam==mi.TFSc[16])
{
mi.ChangeChartSymbol(mi.TFSc[16],mi.TFId[16]);
}
//--
if(sparam==mi.TFSc[17])
{
mi.ChangeChartSymbol(mi.TFSc[17],mi.TFId[17]);
}
//--
if(sparam==mi.TFSc[18])
{
mi.ChangeChartSymbol(mi.TFSc[18],mi.TFId[18]);
}
//--
if(sparam==mi.TFSc[19])
{
mi.ChangeChartSymbol(mi.TFSc[19],mi.TFId[19]);
}
//--
if(sparam==mi.TFSc[20])
{
mi.ChangeChartSymbol(mi.TFSc[20],mi.TFId[20]);
}
//--
}
//---
} //-end OnChartEvent()
//---------//
This function is the central event handler for all GUI interactions in the RSI panel. It manages:
- Showing/hiding the panel.
- Moving the panel between top and bottom positions.
- Switching chart timeframes via button clicks.
It ensures the interface remains responsive and visually consistent after each user action.
Conclusion
The Relative Strength Index Multi-Timeframe Indicator for MT5 offers a complete solution for traders who want to understand trend strength across all timeframes simultaneously. Using a unique formula that scans and weighs up/down movement across 21 timeframes, it delivers a summary arrow signal that simplifies complex data into an actionable visual.
With features like dynamic chart interaction, visual arrows, alerts, and a lightweight design, this tool is ideal for discretionary and algorithmic traders alike.
We hope that this article and the RSI_MTF or Relative Strength Index Multi-Timeframe Indicator for MT5 program will be useful for traders in learning and generating new ideas for trading, who can ultimately make money from home by trading forex.
Please download the RSI_MTF indicator from My Google Drive: Relative Strength Index Multi-Timeframe Indicator for MT5
Vital Records
If you would like to receive a source program for this article, please send a request via Contact Us form page, and I will send it to your email, source code: Relative Strength Index Multi-Timeframe Indicator for MT5
If you think the Relative Strength Index Multi-Timeframe Indicator for MT5 is worthy of being used for automated trading as an Expert Advisor, please leave a comment below this article.
If at least 25 people agree that this indicator is worthy of being used as an Expert Advisor, I will create an Expert Advisor based on its signals and share it on this blog.
Thanks for reading this article.
Maybe this Ads is interesting for you - Read more..
//+------------------------------------------------------------------+
//| RSI_MTF.mq5 |
//| Copyright 2025, Roberto Jacobs (3rjfx) |
//| https://www.mql5.com/en/users/3rjfx |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, Roberto Jacobs (3rjfx) ~ Date: 2025-01-13"
#property link "https://www.mql5.com/en/users/3rjfx"
#property version "1.00"
#property description "RSI_MTF is the Relative Strength Index Indicator in Multi Timeframe"
#property description "for MT5 which is calculated and scan RSI on each timeframe."
//---
#property indicator_chart_window
#property indicator_plots 1
#property indicator_buffers 1
//---
//--
enum YN
{
No,
Yes
};
//--
enum fonts
{
Verdana,
Bodoni_MT_Black
};
//--
//---
input group "==== Indicator Period Calculation ===="
input int BarCalc = 14; // Input Indicator Period
input group "==== Indicator Color and Font ===="
input color ArrowUp = clrMediumSeaGreen; // Arrow Up Color
input color ArrowDn = clrDeepPink; // Arrow Down Color
input color NTArrow = clrGold; // Arrow No Signal
input fonts f_model = Bodoni_MT_Black; // Select Font Model
input group "==== Input parameters for alerts ===="
input YN alerts = Yes; // Display Alerts Pop-up on Chart (Yes) or (No)
input YN UseEmailAlert = No; // Email Alert (Yes) or (No)
input YN UseSendnotify = No; // Send Notification (Yes) or (No)
//---
//---------//
//+------------------------------------------------------------------+
//| class for MTF indicator |
//+------------------------------------------------------------------+
class MTF_Indi
{
//---
public:
//--
int fbar;
int star,
tstar,
bstar;
int hRSI[];
int TNamex,
TNamexn,
TNamey1,
TNamey2,
TNamey3,
TNamey1n,
TNamey2n,
TNamey3n;
int tfxar;
int up,dw;
int tfhalf;
int maxbar;
int ttlbars;
int scaleX,
scaleA,
scaleY,
horizL1,
horizL2,
horizL3,
horizL4,
horizL5,
horizL6,
vertiL1,
vertiL2,
vertiL3,
vertiL4,
vertiL5,
vertiL6,
offsetX,
offsetY,
fontSize,
windchar,
windsize;
int corx,
cory,
txttf;
int curmin,
prvmin;
int corpos;
int pospos,
postop,
posbot;
int curAlert;
int prvAlert;
int RSI_period;
//--
long CI;
string posisi,
sigpos,
indname,
msgText,
ObjName;
string cstar,
artop,
arbot;
string hName1,
hName2,
hName3;
string font_mode;
bool display;
double OPEN[],
HIGH[],
LOW[],
CLOSE[];
long VOLUME[];
datetime TIME[];
datetime cbartime;
//--
int year, // Year
mon, // Month
day, // Day
hour, // Hour
min, // Minutes
sec, // Seconds
dow, // Day of week (0-Sunday, 1-Monday, ... ,6-Saturday)
doy; // Day number of the year (January 1st is assigned the number value of zero)
//---- buffers
double PowerMove[];
string TFSc[];
color Arwcolor[];
color TColor;
ENUM_TIMEFRAMES TFId[];
ENUM_BASE_CORNER bcor;
ENUM_ANCHOR_POINT ancp;
//---
//---
//- Constructor
MTF_Indi(void):
year(0),
mon(1),
day(2),
hour(3),
min(4),
sec(5),
dow(6),
doy(7),
fbar(25),
star(181),
maxbar(3),
pospos(0),
postop(0),
posbot(1),
tstar(217),
bstar(218),
tfhalf(11),
scaleX(35),
scaleA(36),
scaleY(50),
offsetY(18),
offsetX(120),
fontSize(7),
cbartime(0),
posisi(""),
sigpos(""),
msgText(""),
curAlert(0),
prvAlert(0),
windsize(12),
windchar(108),
CI(ChartID()),
display(false),
ObjName("RSI_"),
font_mode(FontsModel(f_model)),
cstar(CharToString((uchar)star)),
artop(CharToString((uchar)tstar)),
arbot(CharToString((uchar)bstar)),
indname(MQLInfoString(MQL_PROGRAM_NAME))
{
}
//---
//- Destructor
~MTF_Indi(void)
{
}
//---
//---
virtual void RSI_MTF_Config(void)
{
//--
ENUM_TIMEFRAMES TFIx[]= {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};
tfxar=ArraySize(TFIx);
ArrayResize(TFId,tfxar,tfxar);
ArrayResize(Arwcolor,tfxar,tfxar);
ArrayCopy(TFId,TFIx,0,0,WHOLE_ARRAY);
//--
string TFxc[]= {"M1","M2","M3","M4","M5","M6","M10","M12","M15","M20","M30","H1",
"H2","H3","H4","H6","H8","H12","D1","W1","MN1"}; // 21 Timeframes
//--
ArrayResize(hRSI,tfxar,tfxar);
ArrayResize(TFSc,tfxar,tfxar);
ArrayCopy(TFSc,TFxc,0,0,WHOLE_ARRAY);
//--
if(BarCalc<1)
{
RSI_period=14;
PrintFormat("Incorrect value for input variable BarCalc = %d. Indicator will use value %d for calculations.",
BarCalc,RSI_period);
}
else
RSI_period=BarCalc;
//--
ttlbars=BarCalc*3+3;
//--
for(int x=0; x<tfxar; x++)
hRSI[x]=iRSI(Symbol(),TFId[x],RSI_period,PRICE_CLOSE); // Handle of iRSI Indicator on each timeframe
//--
DeletedRSIObject();
RSIMovementCalculation(25);
PositionCore();
//--
if(display)
DrawRSIObject();
//---
}
//---
//---
void PositionCore(void)
{
corpos=pospos;
if(corpos>-1)
{
if(corpos==postop)
{
bcor=CORNER_LEFT_UPPER;
ancp=ANCHOR_CENTER;
corx=155;
cory=13;
txttf=45;
horizL1=8;
horizL2=-5;
horizL3=8;
horizL4=-5;
horizL5=11;
horizL6=10;
vertiL1=39;
vertiL2=18;
vertiL3=69;
vertiL4=48;
vertiL5=52;
vertiL6=67;
TNamex=554;
TNamexn=562;
TNamey1=30;
TNamey2=46;
TNamey3=62;
TNamey1n=38;
TNamey2n=54;
TNamey3n=70;
hName1="R";
hName2="S";
hName3="I";
//--
DisplayButtonClick("cstar");
DisplayButtonClick("arbot");
//--
}
if(corpos==posbot)
{
bcor=CORNER_LEFT_LOWER;
ancp=ANCHOR_CENTER;
corx=155;
cory=74;
txttf=45;
horizL1=8;
horizL2=-5;
horizL3=8;
horizL4=-5;
horizL5=11;
horizL6=10;
vertiL1=34;
vertiL2=29;
vertiL3=65;
vertiL4=59;
vertiL5=49;
vertiL6=61;
TNamex=554;
TNamexn=562;
TNamey1=13;
TNamey2=46;
TNamey3=62;
TNamey1n=18;
TNamey2n=33;
TNamey3n=49;
hName1="I";
hName2="S";
hName3="R";
//--
DisplayButtonClick("cstar");
DisplayButtonClick("artop");
//--
}
display=true;
}
}
//---
//---
void DrawRSIObject(void)
{
//--
CreateButtonTemplate(CI,ObjName+"Template",397,66,STYLE_SOLID,9,BORDER_RAISED,clrMistyRose,clrLavenderBlush,clrWhite,bcor,corx,cory,true);
for(int x=0; x<tfhalf; x++)
{
CreateArrowLabel(CI,ObjName+"_win_arrow_"+string(x),CharToString((uchar)windchar),"Wingdings",windsize,Arwcolor[x],bcor,
txttf+horizL1+(x*scaleX)+offsetX+x,vertiL1,true,"Arrow_"+TFSc[x]);
CreateButtonClick(CI,TFSc[x],27,15,font_mode,fontSize,BORDER_FLAT,TFSc[x],clrBurlyWood,clrSilver,clrBlue,
bcor,txttf+horizL2+(x*scaleA)+offsetX,vertiL2,true,
"Change Timeframe to : "+TFSc[x]);
}
for(int x=tfhalf, x2=0; x<tfxar; x++, x2++)
{
CreateArrowLabel(CI,ObjName+"_win_arrow_"+string(x),CharToString((uchar)windchar),"Wingdings",windsize,Arwcolor[x],bcor,
txttf+horizL3+(x2*scaleX)+offsetX+x2,vertiL3,true,"Arrow_"+TFSc[x]);
CreateButtonClick(CI,TFSc[x],27,15,font_mode,fontSize,BORDER_FLAT,TFSc[x],clrBurlyWood,clrSilver,clrBlue,
bcor,txttf+horizL4+(x2*scaleA)+offsetX,vertiL4,true,
"Change Timeframe to : "+TFSc[x]);
//--
if(x==20)
{
int arrowChar=TColor==ArrowUp ? 200 : TColor==ArrowDn ? 202 : windchar;
CreateArrowLabel(CI,ObjName+"_tfx_arrow_"+string(x+1),"Move",font_mode,fontSize,clrBlue,bcor,
519+horizL5,vertiL5,true,"Move");
CreateArrowLabel(CI,ObjName+"_win_arrow_"+string(x+1),CharToString((uchar)arrowChar),"Wingdings",15,TColor,bcor,
522+horizL6,vertiL6,true,"Arrow Indicator Movement");
}
}
DisplayButtonClick("X");
CreateButtonTemplate(CI,ObjName+"TemplateName1",17,15,STYLE_SOLID,1,BORDER_FLAT,clrMistyRose,clrLavenderBlush,clrWhite,bcor,TNamex,TNamey1,true);
CreateButtonTemplate(CI,ObjName+"TemplateName2",17,15,STYLE_SOLID,1,BORDER_FLAT,clrMistyRose,clrLavenderBlush,clrWhite,bcor,TNamex,TNamey2,true);
CreateButtonTemplate(CI,ObjName+"TemplateName3",17,15,STYLE_SOLID,1,BORDER_FLAT,clrMistyRose,clrLavenderBlush,clrWhite,bcor,TNamex,TNamey3,true);
CreateArrowLabel(CI,ObjName+"_name1",hName1,font_mode,fontSize+1,clrBlue,bcor,TNamexn,TNamey1n,true,hName1);
CreateArrowLabel(CI,ObjName+"_name2",hName2,font_mode,fontSize+1,clrBlue,bcor,TNamexn,TNamey2n,true,hName2);
CreateArrowLabel(CI,ObjName+"_name3",hName3,font_mode,fontSize+1,clrBlue,bcor,TNamexn,TNamey3n,true,hName3);
//--
if(corpos==postop)
{
DisplayButtonClick("cstar");
DisplayButtonClick("arbot");
}
if(corpos==posbot)
{
DisplayButtonClick("cstar");
DisplayButtonClick("artop");
}
//--
return;
//---
} //-end DrawRSIObject()
//---
//---
void PanelPosChange(int inpos)
{
corpos=inpos;
//--
if(inpos>=0)
{
if(inpos==postop)
{
bcor=CORNER_LEFT_UPPER;
ancp=ANCHOR_CENTER;
corx=155;
cory=13;
txttf=45;
horizL1=8;
horizL2=-5;
horizL3=8;
horizL4=-5;
horizL5=11;
horizL6=10;
vertiL1=39;
vertiL2=18;
vertiL3=69;
vertiL4=48;
vertiL5=52;
vertiL6=67;
TNamex=554;
TNamexn=562;
TNamey1=30;
TNamey2=46;
TNamey3=62;
TNamey1n=38;
TNamey2n=54;
TNamey3n=70;
hName1="R";
hName2="S";
hName3="I";
//--
DisplayButtonClick("cstar");
DisplayButtonClick("arbot");
//--
}
if(inpos==posbot)
{
bcor=CORNER_LEFT_LOWER;
ancp=ANCHOR_CENTER;
corx=155;
cory=74;
txttf=45;
horizL1=8;
horizL2=-5;
horizL3=8;
horizL4=-5;
horizL5=11;
horizL6=10;
vertiL1=34;
vertiL2=29;
vertiL3=65;
vertiL4=59;
vertiL5=49;
vertiL6=61;
TNamex=554;
TNamexn=562;
TNamey1=25;
TNamey2=41;
TNamey3=57;
TNamey1n=18;
TNamey2n=33;
TNamey3n=49;
hName1="I";
hName2="S";
hName3="R";
//--
DisplayButtonClick("cstar");
DisplayButtonClick("artop");
//--
}
display=true;
}
//---
}
//---
//---
void UpdatePrice(ENUM_TIMEFRAMES xtf)
{
maxbar=fbar;
//--
ArrayFree(OPEN);
ArrayFree(HIGH);
ArrayFree(LOW);
ArrayFree(CLOSE);
ArrayFree(TIME);
ArrayFree(VOLUME);
//--
ArrayResize(OPEN,maxbar,maxbar);
ArrayResize(HIGH,maxbar,maxbar);
ArrayResize(LOW,maxbar,maxbar);
ArrayResize(CLOSE,maxbar,maxbar);
ArrayResize(TIME,maxbar,maxbar);
ArrayResize(VOLUME,maxbar,maxbar);
//--
ArraySetAsSeries(OPEN,true);
ArraySetAsSeries(HIGH,true);
ArraySetAsSeries(LOW,true);
ArraySetAsSeries(CLOSE,true);
ArraySetAsSeries(TIME,true);
ArraySetAsSeries(VOLUME,true);
//--
ArrayInitialize(OPEN,0.0);
ArrayInitialize(HIGH,0.0);
ArrayInitialize(LOW,0.0);
ArrayInitialize(CLOSE,0.0);
ArrayInitialize(TIME,0);
ArrayInitialize(VOLUME,0);
//--
int barx=PeriodSeconds(xtf)/60*maxbar;
RefreshPrice(PERIOD_M1,maxbar);
RefreshPrice(xtf,barx);
//--
int co=CopyOpen(Symbol(),xtf,0,maxbar,OPEN);
int ch=CopyHigh(Symbol(),xtf,0,maxbar,HIGH);
int cl=CopyLow(Symbol(),xtf,0,maxbar,LOW);
int cc=CopyClose(Symbol(),xtf,0,maxbar,CLOSE);
int ct=CopyTime(Symbol(),xtf,0,maxbar,TIME);
int cv=CopyTickVolume(Symbol(),xtf,0,maxbar,VOLUME);
//--
return;
//---
} //-end UpdatePrice()
//---
//---
void RefreshPrice(ENUM_TIMEFRAMES xtf,int bars)
{
//--
MqlRates parray[];
ArraySetAsSeries(parray,true);
int copied=CopyRates(Symbol(),xtf,0,bars,parray);
//--
return;
//---
} //-end RefreshPrice()
//---
//---
int RSIDirectionScan(const ENUM_TIMEFRAMES stf,int shift) // Scan OBV Direction
{
//--
int ret=0;
int rise=1,
down=-1;
//--
int br=shift+2;
double res=0.0;
UpdatePrice(stf);
//--
double RSI[];
ArrayResize(RSI,br,br);
ArraySetAsSeries(RSI,true);
//--
int xx=TFIndexArray(stf);
CopyBuffer(hRSI[xx],0,0,br,RSI);
//--
if(RSI[shift]>RSI[shift+1]) ret=rise;
if(RSI[shift]<RSI[shift+1]) ret=down;
//--
return(ret);
//---
} //-end RSIDirectionScan()
//---
//---
void RSIMovementCalculation(int barCnt) // Scan the direction of iRSI on each timeframe
{
//--
ArrayResize(PowerMove,barCnt,barCnt);
ArraySetAsSeries(PowerMove,true);
//--
for(int i=barCnt-1; i>=0; i--)
{
up=0;
dw=0;
//--
for(int x=0; x<tfxar; x++)
{
Arwcolor[x]=NTArrow;
PowerMove[i]=0.0;
int PPM=RSIDirectionScan(TFId[x],0);
if(PPM>0)
{
up++;
Arwcolor[x]=ArrowUp;
}
if(PPM<0)
{
dw++;
Arwcolor[x]=ArrowDn;
}
if(x==tfxar-1)
{
if(up>dw+1)
{
PowerMove[i]=1.0;
TColor=ArrowUp;
curAlert=1;
}
if(dw>up+1)
{
PowerMove[i]=-1.0;
TColor=ArrowDn;
curAlert=-1;
}
}
}
}
//--
return;
//---
} //-end RSIMovementCalculation()
//---
//---
double NonZeroDiv(double val1,double val2)
{
//--
double resval=0;
if(val1==0.0 || val2==0.0) resval=0.00;
else
resval=val1/val2;
//--
return(resval);
//---
} //-end NonZeroDiv()
//---
//---
int TFIndexArray(ENUM_TIMEFRAMES TF)
{
//--
int res=-1;
//--
for(int x=0; x<tfxar; x++)
{
if(TF==TFId[x])
{
res=x;
break;
}
}
//--
return(res);
//---
} //-end TFIndexArray()
//---
//---
int ThisTime(const int reqmode)
{
//--
MqlDateTime tm;
TimeCurrent(tm);
int valtm=0;
//--
switch(reqmode)
{
case 0:
valtm=tm.year;
break; // Return Year
case 1:
valtm=tm.mon;
break; // Return Month
case 2:
valtm=tm.day;
break; // Return Day
case 3:
valtm=tm.hour;
break; // Return Hour
case 4:
valtm=tm.min;
break; // Return Minutes
case 5:
valtm=tm.sec;
break; // Return Seconds
case 6:
valtm=tm.day_of_week;
break; // Return Day of week (0-Sunday, 1-Monday, ... ,6-Saturday)
case 7:
valtm=tm.day_of_year;
break; // Return Day number of the year (January 1st is assigned the number value of zero)
}
//--
return(valtm);
//---
} //-end ThisTime()
//---
//---
void Do_Alerts(string msg)
{
//--
Print("--- "+Symbol()+","+strTF(Period())+": "+msg+
"\n--- at: ",TimeToString(TimeCurrent(),TIME_DATE|TIME_MINUTES));
//--
if(alerts==Yes)
{
Alert("--- "+Symbol()+","+strTF(Period())+": "+msg+
"--- at: ",TimeToString(TimeCurrent(),TIME_DATE|TIME_MINUTES));
}
//--
if(UseEmailAlert==Yes)
SendMail(indname,"--- "+Symbol()+" "+strTF(Period())+": "+msg+
"\n--- at: "+TimeToString(TimeCurrent(),TIME_DATE|TIME_MINUTES));
//--
if(UseSendnotify==Yes)
SendNotification(Symbol()+"--- "+Symbol()+" "+strTF(Period())+": "+msg+
"\n--- at: "+TimeToString(iTime(Symbol(),0,0),TIME_DATE|TIME_MINUTES));
//--
return;
//---
} //-end Do_Alerts()
//---
//---
string FontsModel(int mode)
{
string str_font;
switch(mode)
{
case 0:
str_font="Verdana";
break;
case 1:
str_font="Bodoni MT Black";
break;
}
//--
return(str_font);
//---
} //-end FontsModel()
//---
//---
void ChangeChartSymbol(string tf_name,ENUM_TIMEFRAMES stf)
{
//---
//--- unpress the button
ObjectSetInteger(CI,tf_name,OBJPROP_STATE,false);
ObjectSetInteger(CI,tf_name,OBJPROP_ZORDER,0);
//--
DeletedRSIObject();
PanelPosChange(corpos);
ChartSetSymbolPeriod(CI,Symbol(),stf);
if(display)
DrawRSIObject();
//--
ChartRedraw(CI);
//--
return;
//---
} //-end ChangeChartSymbol()
//---
//---
void DisplayPanelButton(void)
{
//--
ObjectDelete(CI,cstar);
ObjectDelete(CI,artop);
ObjectDelete(CI,arbot);
//--
CreateButtonClick(CI,cstar,20,20,"Wingdings",13,BORDER_FLAT,cstar,clrWhite,clrWhite,TColor,CORNER_RIGHT_UPPER,25,40,true,"Open Panel Indicator");
CreateButtonClick(CI,artop,18,18,"Wingdings",11,BORDER_FLAT,artop,clrWhite,clrWhite,clrGreen,CORNER_RIGHT_UPPER,24,20,true,"Change Panel to Top");
CreateButtonClick(CI,arbot,18,18,"Wingdings",11,BORDER_FLAT,arbot,clrWhite,clrWhite,clrGreen,CORNER_RIGHT_UPPER,24,62,true,"Change Panel to Bottom");
//--
ChartRedraw(CI);
//--
return;
//---
} //-end DisplayPanelButton()
//---
//---
void DisplayButtonClick(string actreq)
{
//--
if(actreq=="cstar")
CreateButtonClick(CI,cstar,20,20,"Wingdings",13,BORDER_FLAT,cstar,clrWhite,clrWhite,TColor,CORNER_RIGHT_UPPER,25,40,true,"Open Panel Indicator");
if(actreq=="artop")
CreateButtonClick(CI,artop,18,18,"Wingdings",11,BORDER_FLAT,artop,clrWhite,clrWhite,clrGreen,CORNER_RIGHT_UPPER,24,20,true,"Change Panel to Top");
if(actreq=="arbot")
CreateButtonClick(CI,arbot,18,18,"Wingdings",11,BORDER_FLAT,arbot,clrWhite,clrWhite,clrGreen,CORNER_RIGHT_UPPER,24,62,true,"Change Panel to Bottom");
if(actreq=="X")
CreateButtonClick(CI,"X",17,15,"Arial Black",fontSize,BORDER_FLAT,"X",clrWhite,clrWhite,clrRed,bcor,txttf-7+(11*scaleA)+offsetX,cory,true,"Close Panel");
//--
ChartRedraw(CI);
//--
return;
//---
} //-end DisplayButtonClick()
//---
//---
void DeletedRSIObject(void)
{
//--
string name;
for(int i=ObjectsTotal(CI,-1,-1)-1; i>=0; i--)
{
name=ObjectName(CI,i,-1,-1);
if(StringFind(name,ObjName,0)>-1)
ObjectDelete(CI,name);
for(int x=0; x<tfxar; x++)
{
if(StringFind(name,TFSc[x],0)>-1)
ObjectDelete(CI,name);
}
//--
ObjectDelete(CI,"X");
ObjectDelete(CI,cstar);
ObjectDelete(CI,artop);
ObjectDelete(CI,arbot);
}
//--
return;
//---
} //-end DeletedRSIObject()
//---
//---
string strTF(ENUM_TIMEFRAMES period)
{
string intf="";
//--
switch(period)
{
//--
case PERIOD_M1:
{intf="M1"; break;}
case PERIOD_M2:
{intf="M2"; break;}
case PERIOD_M3:
{intf="M3"; break;}
case PERIOD_M4:
{intf="M4"; break;}
case PERIOD_M5:
{intf="M5"; break;}
case PERIOD_M6:
{intf="M6"; break;}
case PERIOD_M10:
{intf="M10"; break;}
case PERIOD_M12:
{intf="M12"; break;}
case PERIOD_M15:
{intf="M15"; break;}
case PERIOD_M20:
{intf="M20"; break;}
case PERIOD_M30:
{intf="M30"; break;}
case PERIOD_H1:
{intf="H1"; break;}
case PERIOD_H2:
{intf="H2"; break;}
case PERIOD_H3:
{intf="H3"; break;}
case PERIOD_H4:
{intf="H4"; break;}
case PERIOD_H6:
{intf="H6"; break;}
case PERIOD_H8:
{intf="H8"; break;}
case PERIOD_H12:
{intf="H12"; break;}
case PERIOD_D1:
{intf="D1"; break;}
case PERIOD_W1:
{intf="W1"; break;}
case PERIOD_MN1:
{intf="MN1"; break;}
//--
}
return(intf);
//---
} //-end strTF()
//---
//---
string getUninitReasonText(int reasonCode)
{
//--
string text="";
//--
switch(reasonCode)
{
case REASON_PROGRAM:
text="The EA has stopped working calling by remove function.";
break;
case REASON_REMOVE:
text="Program "+__FILE__+" was removed from chart";
break;
case REASON_RECOMPILE:
text="Program recompiled.";
break;
case REASON_CHARTCHANGE:
text="Symbol or timeframe was changed";
break;
case REASON_CHARTCLOSE:
text="Chart was closed";
break;
case REASON_PARAMETERS:
text="Input-parameter was changed";
break;
case REASON_ACCOUNT:
text="Account was changed";
break;
case REASON_TEMPLATE:
text="New template was applied to chart";
break;
case REASON_INITFAILED:
text="The OnInit() handler returned a non-zero value.";
break;
case REASON_CLOSE:
text="Terminal closed.";
break;
default:
text="Another reason";
break;
}
//--
return text;
//---
} //-end getUninitReasonText()
//---
//---
int WS(int width) // Width Scaling factor wide button
{
//--
int res=0;
int reswidth=0;
//-- Calculating the scaling factor wide button on a screen
int scale_factor=(TerminalInfoInteger(TERMINAL_SCREEN_DPI));
// The basic width in the screen points for standard monitors with DPI=96
//-- Use of the scaling factor
reswidth=(width * scale_factor) / 96;
res=(int)NormalizeDouble(reswidth*1.25,0);
//--
return(res);
//---
} //-end WS()
//---
//---
void CreateButtonClick(long chartid,
string button_name,
int button_x_size,
int button_y_size,
string button_font_model,
int button_font_size,
int button_border,
string button_name_text,
color button_bord_color,
color button_bg_color,
color button_color,
int button_corner,
int button_xdist,
int button_ydist,
bool button_hidden,
string tooltip)
{
//--
ObjectCreate(chartid,button_name,OBJ_BUTTON,0,0,0); // create button
ObjectSetInteger(chartid,button_name,OBJPROP_XSIZE,WS(button_x_size));
ObjectSetInteger(chartid,button_name,OBJPROP_YSIZE,WS(button_y_size));
ObjectSetString(chartid,button_name,OBJPROP_TEXT,button_name_text);
ObjectSetString(chartid,button_name,OBJPROP_FONT,button_font_model);
ObjectSetInteger(chartid,button_name,OBJPROP_FONTSIZE,WS(button_font_size));
ObjectSetInteger(chartid,button_name,OBJPROP_BORDER_TYPE,WS(button_border));
ObjectSetInteger(chartid,button_name,OBJPROP_BORDER_COLOR,button_bord_color);
ObjectSetInteger(chartid,button_name,OBJPROP_BGCOLOR,button_bg_color);
ObjectSetInteger(chartid,button_name,OBJPROP_COLOR,button_color);
ObjectSetInteger(chartid,button_name,OBJPROP_ANCHOR,ancp);
ObjectSetInteger(chartid,button_name,OBJPROP_CORNER,button_corner);
ObjectSetInteger(chartid,button_name,OBJPROP_XDISTANCE,WS(button_xdist));
ObjectSetInteger(chartid,button_name,OBJPROP_YDISTANCE,WS(button_ydist));
ObjectSetInteger(chartid,button_name,OBJPROP_HIDDEN,button_hidden);
ObjectSetString(chartid,button_name,OBJPROP_TOOLTIP,tooltip);
ChartRedraw(chartid);
//--
return;
//---
} //-end CreateButtonClick()
//---
//---
bool CreateArrowLabel(long chart_id,
string lable_name,
string label_text,
string font_model,
int font_size,
color label_color,
int chart_corner,
int x_cor,
int y_cor,
bool price_hidden,
string tooltip)
{
//--
ObjectDelete(chart_id,lable_name);
//--
if(!ObjectCreate(chart_id,lable_name,OBJ_LABEL,0,0,0,0,0)) // create Label
{
Print(__FUNCTION__, ": failed to create \"Arrow Label\" sign! Error code = ",GetLastError());
return(false);
}
//--
ObjectSetString(chart_id,lable_name,OBJPROP_TEXT,label_text);
ObjectSetString(chart_id,lable_name,OBJPROP_FONT,font_model);
ObjectSetInteger(chart_id,lable_name,OBJPROP_FONTSIZE,WS(font_size));
ObjectSetInteger(chart_id,lable_name,OBJPROP_COLOR,label_color);
ObjectSetInteger(chart_id,lable_name,OBJPROP_CORNER,chart_corner);
ObjectSetInteger(chart_id,lable_name,OBJPROP_ANCHOR,ancp);
ObjectSetInteger(chart_id,lable_name,OBJPROP_XDISTANCE,WS(x_cor));
ObjectSetInteger(chart_id,lable_name,OBJPROP_YDISTANCE,WS(y_cor));
ObjectSetInteger(chart_id,lable_name,OBJPROP_HIDDEN,price_hidden);
ObjectSetString(chart_id,lable_name,OBJPROP_TOOLTIP,tooltip);
//-- successful execution
return(true);
//---
} //-end CreateArrowLabel()
//---
//---
void CreateButtonTemplate(long chartid,
string obj_name,
int x_size,
int y_size,
int style,
int width,
int border,
color bordcolor,
color bgcolor,
color objcolor,
int corner,
int x_dist,
int y_dist,
bool hidden)
{
//--
ObjectCreate(chartid,obj_name,OBJ_RECTANGLE_LABEL,0,0,0); // create Rectangle Label
ObjectSetInteger(chartid,obj_name,OBJPROP_XSIZE,WS(x_size));
ObjectSetInteger(chartid,obj_name,OBJPROP_YSIZE,WS(y_size));
ObjectSetInteger(chartid,obj_name,OBJPROP_STYLE,style);
ObjectSetInteger(chartid,obj_name,OBJPROP_WIDTH,WS(width));
ObjectSetInteger(chartid,obj_name,OBJPROP_BORDER_TYPE,WS(border));
ObjectSetInteger(chartid,obj_name,OBJPROP_BORDER_COLOR,bordcolor);
ObjectSetInteger(chartid,obj_name,OBJPROP_BGCOLOR,bgcolor);
ObjectSetInteger(chartid,obj_name,OBJPROP_COLOR,objcolor);
ObjectSetInteger(chartid,obj_name,OBJPROP_CORNER,corner);
ObjectSetInteger(chartid,obj_name,OBJPROP_XDISTANCE,WS(x_dist));
ObjectSetInteger(chartid,obj_name,OBJPROP_YDISTANCE,WS(y_dist));
ObjectSetInteger(chartid,obj_name,OBJPROP_HIDDEN,hidden);
ChartRedraw(chartid);
//--
return;
//---
} //-end CreateButtonTemplate()
//---
//---
}; //-end class MTF_Indi()
//---------//
MTF_Indi mi;
//---------//
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- indicator buffers mapping
mi.RSI_MTF_Config();
//--
SetIndexBuffer(0,mi.PowerMove,INDICATOR_DATA);
PlotIndexSetString(0,PLOT_LABEL,"Move");
//--
IndicatorSetString(INDICATOR_SHORTNAME,mi.indname);
IndicatorSetInteger(INDICATOR_DIGITS,2);
//---
return(INIT_SUCCEEDED);
}
//---------//
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
Comment("");
Print(mi.getUninitReasonText(reason));
//-- Release all handle indicators for all symbols
for(int x=0; x<mi.tfxar; x++)
IndicatorRelease(mi.hRSI[x]);
//--
mi.DeletedRSIObject();
//--
ChartRedraw(mi.CI);
//---
return;
//---
} //-end OnDeinit()
//-------//
//+------------------------------------------------------------------+
//| 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[])
{
//---
ResetLastError();
//--
int limit;
limit=rates_total-prev_calculated;
if(prev_calculated>0)
limit++;
if(limit>mi.ttlbars)
limit=mi.ttlbars;
if(limit-3<=1)
limit=3;
//--
mi.RSIMovementCalculation(limit);
//--
if(alerts==Yes||UseEmailAlert==Yes||UseSendnotify==Yes)
{
mi.curmin=mi.ThisTime(mi.min);
if(mi.curmin!=mi.prvmin && mi.curAlert==1 && mi.curAlert!=mi.prvAlert)
{
string AlertTxt="The strength of the RSI movement appears to be Rise.";
mi.Do_Alerts(AlertTxt);
mi.prvAlert=mi.curAlert;
mi.prvmin=mi.curmin;
}
if(mi.curmin!=mi.prvmin && mi.curAlert==-1 && mi.curAlert!=mi.prvAlert)
{
string AlertTxt="The strength of the RSI movement appears to be Down.";
mi.Do_Alerts(AlertTxt);
mi.prvAlert=mi.curAlert;
mi.prvmin=mi.curmin;
}
}
//--
if(mi.display)
mi.DrawRSIObject();
//---
//--- return value of prev_calculated for next call
return(rates_total);
}
//---------//
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| ChartEvent function |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
const long &lparam,
const double &dparam,
const string &sparam)
{
//---
//--- handling CHARTEVENT_CLICK event ("Clicking the chart")
ResetLastError();
//--
if(id==CHARTEVENT_OBJECT_CLICK)
{
//--- if "X" button is click
if(sparam=="X")
{
mi.DeletedRSIObject();
//--- unpress the button
ObjectSetInteger(mi.CI,"X",OBJPROP_STATE,false);
ObjectSetInteger(mi.CI,"X",OBJPROP_ZORDER,0);
//--
mi.display=false;
ObjectDelete(mi.CI,"X");
mi.DisplayPanelButton();
}
//--- if "cstar" button is click
if(sparam==mi.cstar)
{
mi.DeletedRSIObject();
mi.DisplayPanelButton();
//--- unpress the button
ObjectSetInteger(mi.CI,mi.cstar,OBJPROP_STATE,false);
ObjectSetInteger(mi.CI,mi.cstar,OBJPROP_ZORDER,0);
if(!mi.display)
mi.display=true;
if(mi.corpos==mi.posbot) ObjectDelete(mi.CI,mi.arbot);
if(mi.corpos==mi.postop) ObjectDelete(mi.CI,mi.artop);
mi.DrawRSIObject();
//--
ChartRedraw(mi.CI);
}
//--- if "artop" button is click
if(sparam==mi.artop)
{
mi.DeletedRSIObject();
mi.DisplayPanelButton();
//--- unpress the button
ObjectSetInteger(mi.CI,mi.artop,OBJPROP_STATE,false);
ObjectSetInteger(mi.CI,mi.artop,OBJPROP_ZORDER,0);
if(!mi.display)
mi.display=true;
ObjectDelete(mi.CI,mi.artop);
mi.PanelPosChange(mi.postop);
//--
ObjectDelete(mi.CI,"X");
mi.DisplayButtonClick("arbot");
mi.DrawRSIObject();
//--
ChartRedraw(mi.CI);
}
//--- if "arbot" button is click
if(sparam==mi.arbot)
{
mi.DeletedRSIObject();
mi.DisplayPanelButton();
//--- unpress the button
ObjectSetInteger(mi.CI,mi.arbot,OBJPROP_STATE,false);
ObjectSetInteger(mi.CI,mi.arbot,OBJPROP_ZORDER,0);
if(!mi.display)
mi.display=true;
ObjectDelete(mi.CI,mi.arbot);
mi.PanelPosChange(mi.posbot);
//--
ObjectDelete(mi.CI,"X");
mi.DisplayButtonClick("artop");
mi.DrawRSIObject();
//--
ChartRedraw(mi.CI);
}
//--- if TF button is click
//--
if(sparam==mi.TFSc[0])
{
mi.ChangeChartSymbol(mi.TFSc[0],mi.TFId[0]);
}
//--
if(sparam==mi.TFSc[1])
{
mi.ChangeChartSymbol(mi.TFSc[1],mi.TFId[1]);
}
//--
if(sparam==mi.TFSc[2])
{
mi.ChangeChartSymbol(mi.TFSc[2],mi.TFId[2]);
}
//--
if(sparam==mi.TFSc[3])
{
mi.ChangeChartSymbol(mi.TFSc[3],mi.TFId[3]);
}
//--
if(sparam==mi.TFSc[4])
{
mi.ChangeChartSymbol(mi.TFSc[4],mi.TFId[4]);
}
//--
if(sparam==mi.TFSc[5])
{
mi.ChangeChartSymbol(mi.TFSc[5],mi.TFId[5]);
}
//--
if(sparam==mi.TFSc[6])
{
mi.ChangeChartSymbol(mi.TFSc[6],mi.TFId[6]);
}
//--
if(sparam==mi.TFSc[7])
{
mi.ChangeChartSymbol(mi.TFSc[7],mi.TFId[7]);
}
//--
if(sparam==mi.TFSc[8])
{
mi.ChangeChartSymbol(mi.TFSc[8],mi.TFId[8]);
}
//--
if(sparam==mi.TFSc[9])
{
mi.ChangeChartSymbol(mi.TFSc[9],mi.TFId[9]);
}
//--
if(sparam==mi.TFSc[10])
{
mi.ChangeChartSymbol(mi.TFSc[10],mi.TFId[10]);
}
//--
if(sparam==mi.TFSc[11])
{
mi.ChangeChartSymbol(mi.TFSc[11],mi.TFId[11]);
}
//--
if(sparam==mi.TFSc[12])
{
mi.ChangeChartSymbol(mi.TFSc[12],mi.TFId[12]);
}
//--
if(sparam==mi.TFSc[13])
{
mi.ChangeChartSymbol(mi.TFSc[13],mi.TFId[13]);
}
//--
if(sparam==mi.TFSc[14])
{
mi.ChangeChartSymbol(mi.TFSc[14],mi.TFId[14]);
}
//--
if(sparam==mi.TFSc[15])
{
mi.ChangeChartSymbol(mi.TFSc[15],mi.TFId[15]);
}
//--
if(sparam==mi.TFSc[16])
{
mi.ChangeChartSymbol(mi.TFSc[16],mi.TFId[16]);
}
//--
if(sparam==mi.TFSc[17])
{
mi.ChangeChartSymbol(mi.TFSc[17],mi.TFId[17]);
}
//--
if(sparam==mi.TFSc[18])
{
mi.ChangeChartSymbol(mi.TFSc[18],mi.TFId[18]);
}
//--
if(sparam==mi.TFSc[19])
{
mi.ChangeChartSymbol(mi.TFSc[19],mi.TFId[19]);
}
//--
if(sparam==mi.TFSc[20])
{
mi.ChangeChartSymbol(mi.TFSc[20],mi.TFId[20]);
}
//--
}
//---
} //-end OnChartEvent()
//---------//




