Indicators: Moving Average of RSI
Free code is much welcomed and other developers may find helpful. Thank you.
How to install the software in a trading platform and use it
When accuracy matters...
//+------------------------------------------------------------------+ //| MA_of_RSI.mq5 | //+------------------------------------------------------------------+ #property copyright "" #property link "" #property version "1.04" #property indicator_separate_window #property indicator_buffers 2 #property indicator_plots 2 #property indicator_label1 "MA of Custom RSI" #property indicator_type1 DRAW_LINE #property indicator_color1 clrLimeGreen #property indicator_style1 STYLE_SOLID #property indicator_width1 1 #property indicator_label2 "RSI Line" #property indicator_type2 DRAW_LINE #property indicator_color2 clrGray #property indicator_style2 STYLE_DOT #property indicator_width2 1 #property indicator_minimum 0 #property indicator_maximum 100 // Input parameters input int RSI1_Period = 14; // RSI1: Period input ENUM_APPLIED_PRICE RSI1_Applied_Price = PRICE_CLOSE; // RSI1: Applied Price input int MA_Period = 10; // MA Period enum ENUM_MA_METHOD_SUPPORTED { MA_SMA = MODE_SMA, // Simple MA MA_LWMA = MODE_LWMA // Linear-Weighted MA }; input ENUM_MA_METHOD_SUPPORTED MA_Method = MA_LWMA; // MA Method input double RSI1_Oversold = 30.0; // Oversold Level input double RSI1_Overbought = 70.0; // Overbought Level // Indicator buffers double maBuffer[]; double rsiBuffer[]; // Handles int rsi1Handle; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { if(RSI1_Period < 1) { Print("Invalid RSI1_Period: ", RSI1_Period); return INIT_PARAMETERS_INCORRECT; } if(MA_Period < 1) { Print("Invalid MA_Period: ", MA_Period); return INIT_PARAMETERS_INCORRECT; } if(RSI1_Oversold < 0.0 || RSI1_Oversold > 100.0 || RSI1_Overbought < 0.0 || RSI1_Overbought > 100.0) { Print("Oversold/Overbought must be within 0..100"); return INIT_PARAMETERS_INCORRECT; } if(RSI1_Oversold >= RSI1_Overbought) { Print("Oversold must be < Overbought"); return INIT_PARAMETERS_INCORRECT; } SetIndexBuffer(0, maBuffer, INDICATOR_DATA); SetIndexBuffer(1, rsiBuffer, INDICATOR_DATA); PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, RSI1_Period + MA_Period - 2); PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, RSI1_Period - 1); IndicatorSetString(INDICATOR_SHORTNAME, "MA of Custom RSI(" + string(RSI1_Period) + ") [" + DoubleToString(RSI1_Oversold, 1) + "/" + DoubleToString(RSI1_Overbought, 1) + "]"); IndicatorSetInteger(INDICATOR_DIGITS, 2); IndicatorSetInteger(INDICATOR_LEVELS, 2); IndicatorSetDouble(INDICATOR_LEVELVALUE, 0, RSI1_Oversold); IndicatorSetDouble(INDICATOR_LEVELVALUE, 1, RSI1_Overbought); IndicatorSetInteger(INDICATOR_LEVELSTYLE, STYLE_DOT); IndicatorSetInteger(INDICATOR_LEVELCOLOR, clrSilver); IndicatorSetInteger(INDICATOR_LEVELWIDTH, 1); IndicatorSetDouble(INDICATOR_MINIMUM, 0); IndicatorSetDouble(INDICATOR_MAXIMUM, 100); rsi1Handle = iCustom(_Symbol, _Period, "Examples\\RSI", RSI1_Period, RSI1_Applied_Price); if(rsi1Handle == INVALID_HANDLE) { Print("Error creating custom RSI handle: ", GetLastError()); return INIT_FAILED; } PlotIndexSetString(0, PLOT_LABEL, "MA of RSI(" + string(RSI1_Period) + ")"); PlotIndexSetString(1, PLOT_LABEL, "RSI(" + string(RSI1_Period) + ")"); return INIT_SUCCEEDED; } //+------------------------------------------------------------------+ //| Indicator deinitialization — release handle | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { if(rsi1Handle != INVALID_HANDLE) { IndicatorRelease(rsi1Handle); rsi1Handle = INVALID_HANDLE; } } //+------------------------------------------------------------------+ //| 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[]) { if(rates_total <= 0) return 0; ArraySetAsSeries(maBuffer, true); ArraySetAsSeries(rsiBuffer, true); double tempRSI[]; ArraySetAsSeries(tempRSI, true); int bars_ready = BarsCalculated(rsi1Handle); if(bars_ready <= 0) return prev_calculated; int copied = CopyBuffer(rsi1Handle, 0, 0, rates_total, tempRSI); if(copied <= 0) { Print("Error copying RSI buffer: ", GetLastError()); return prev_calculated; } if(prev_calculated == 0) { ArrayInitialize(maBuffer, EMPTY_VALUE); ArrayInitialize(rsiBuffer, EMPTY_VALUE); } int start; if(prev_calculated == 0) { start = copied - 1; } else { start = rates_total - prev_calculated; if(start < 1) start = 1; start += 1; if(start > copied - 1) start = copied - 1; } for(int i = start; i >= 0; --i) { if(i >= copied) { rsiBuffer[i] = EMPTY_VALUE; maBuffer[i] = EMPTY_VALUE; continue; } rsiBuffer[i] = tempRSI[i]; if(tempRSI[i] == EMPTY_VALUE) { rsiBuffer[i] = EMPTY_VALUE; maBuffer[i] = EMPTY_VALUE; continue; } if(i + MA_Period - 1 >= copied) { maBuffer[i] = EMPTY_VALUE; continue; } bool valid_window = true; for(int j = 0; j < MA_Period; ++j) { if(tempRSI[i + j] == EMPTY_VALUE) { valid_window = false; break; } } if(!valid_window) { maBuffer[i] = EMPTY_VALUE; continue; } maBuffer[i] = CalculateMA(tempRSI, i, MA_Period, MA_Method); } return rates_total; } //+------------------------------------------------------------------+ //| Helper function to calculate MA values | //+------------------------------------------------------------------+ double CalculateMA(double &data[], int index, int period, ENUM_MA_METHOD_SUPPORTED method) { if(period < 1) return EMPTY_VALUE; if(index < 0 || index + period - 1 >= ArraySize(data)) return EMPTY_VALUE; for(int k = 0; k < period; ++k) { if(data[index + k] == EMPTY_VALUE) return EMPTY_VALUE; } if(method == MA_SMA) { double sum = 0.0; for(int i = 0; i < period; i++) sum += data[index + i]; return sum / period; } else if(method == MA_LWMA) { double sum = 0.0; double weights = 0.0; for(int i = 0; i < period; i++) { double w = period - i; sum += data[index + i] * w; weights += w; } return sum / weights; } return EMPTY_VALUE; } //+------------------------------------------------------------------+
Moving Average of RSI:
This powerful tool filters the classic RSI through a moving average, providing a smoother, more reliable signal line for pinpointing entries, exits, and trend direction with unparalleled clarity.
Author: Tonny Obare