217 lines
7.1 KiB
MQL5
217 lines
7.1 KiB
MQL5
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| MA_of_RSI.mq5 |
|
||
|
|
//| |
|
||
|
|
//| |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
#property copyright "Copyright 2022, FxAutomated.com"
|
||
|
|
#property link "http://www.fxautomated.com"
|
||
|
|
#property version "1.00"
|
||
|
|
#property indicator_separate_window
|
||
|
|
#property indicator_buffers 4
|
||
|
|
#property indicator_plots 2
|
||
|
|
#property indicator_level1 15
|
||
|
|
#property indicator_level2 80
|
||
|
|
#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 = 1; // RSI1: Period
|
||
|
|
input ENUM_APPLIED_PRICE RSI1_Applied_Price = PRICE_CLOSE; // RSI1: Applied Price
|
||
|
|
input int MA_Period = 10; // MA Period
|
||
|
|
input ENUM_MA_METHOD MA_Method = MODE_LWMA; // MA Method
|
||
|
|
double RSI1_Oversold = 15; // Oversold Level
|
||
|
|
double RSI1_Overbought = 80; // Overbought Level
|
||
|
|
|
||
|
|
// Indicator buffers
|
||
|
|
double maBuffer[];
|
||
|
|
double rsiBuffer[];
|
||
|
|
double oversoldBuffer[];
|
||
|
|
double overboughtBuffer[];
|
||
|
|
|
||
|
|
// Handles
|
||
|
|
int rsi1Handle;
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Custom indicator initialization function |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
int OnInit()
|
||
|
|
{
|
||
|
|
// Set indicator buffers
|
||
|
|
SetIndexBuffer(0, maBuffer, INDICATOR_DATA);
|
||
|
|
SetIndexBuffer(1, rsiBuffer, INDICATOR_DATA);
|
||
|
|
SetIndexBuffer(2, oversoldBuffer, INDICATOR_CALCULATIONS);
|
||
|
|
SetIndexBuffer(3, overboughtBuffer, INDICATOR_CALCULATIONS);
|
||
|
|
|
||
|
|
// Set indicator properties
|
||
|
|
IndicatorSetString(INDICATOR_SHORTNAME, "MA of Custom RSI(" + string(RSI1_Period) + ")");
|
||
|
|
IndicatorSetInteger(INDICATOR_DIGITS, 2);
|
||
|
|
|
||
|
|
// Set levels for overbought and oversold
|
||
|
|
IndicatorSetDouble(INDICATOR_LEVELVALUE, 0, RSI1_Oversold);
|
||
|
|
IndicatorSetDouble(INDICATOR_LEVELVALUE, 1, RSI1_Overbought);
|
||
|
|
IndicatorSetInteger(INDICATOR_LEVELS, 2);
|
||
|
|
IndicatorSetInteger(INDICATOR_LEVELSTYLE, 0, STYLE_DOT);
|
||
|
|
IndicatorSetInteger(INDICATOR_LEVELSTYLE, 1, STYLE_DOT);
|
||
|
|
IndicatorSetInteger(INDICATOR_LEVELCOLOR, 0, clrSilver);
|
||
|
|
IndicatorSetInteger(INDICATOR_LEVELCOLOR, 1, clrSilver);
|
||
|
|
|
||
|
|
// Set indicator range
|
||
|
|
IndicatorSetDouble(INDICATOR_MINIMUM, 0);
|
||
|
|
IndicatorSetDouble(INDICATOR_MAXIMUM, 100);
|
||
|
|
|
||
|
|
// Get custom RSI handle :cite[1]:cite[9]
|
||
|
|
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;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Set index labels
|
||
|
|
PlotIndexSetString(0, PLOT_LABEL, "MA of RSI(" + string(RSI1_Period) + ")");
|
||
|
|
PlotIndexSetString(1, PLOT_LABEL, "RSI(" + string(RSI1_Period) + ")");
|
||
|
|
|
||
|
|
// Initialize level buffers
|
||
|
|
ArrayInitialize(oversoldBuffer, RSI1_Oversold);
|
||
|
|
ArrayInitialize(overboughtBuffer, RSI1_Overbought);
|
||
|
|
|
||
|
|
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[])
|
||
|
|
{
|
||
|
|
// Check if we have enough data
|
||
|
|
if(rates_total < MA_Period + RSI1_Period)
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
// Set arrays as series
|
||
|
|
ArraySetAsSeries(maBuffer, true);
|
||
|
|
ArraySetAsSeries(rsiBuffer, true);
|
||
|
|
ArraySetAsSeries(oversoldBuffer, true);
|
||
|
|
ArraySetAsSeries(overboughtBuffer, true);
|
||
|
|
ArraySetAsSeries(time, true);
|
||
|
|
|
||
|
|
// Calculate starting index
|
||
|
|
int start;
|
||
|
|
if(prev_calculated == 0)
|
||
|
|
{
|
||
|
|
start = rates_total - 1;
|
||
|
|
// Initialize buffers
|
||
|
|
ArrayInitialize(maBuffer, 0.0);
|
||
|
|
ArrayInitialize(rsiBuffer, 0.0);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
start = prev_calculated - 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get RSI values from custom indicator :cite[1]:cite[3]
|
||
|
|
double tempRSI[];
|
||
|
|
ArraySetAsSeries(tempRSI, true);
|
||
|
|
|
||
|
|
// Copy buffer 0 from custom RSI (main RSI line) :cite[1]:cite[9]
|
||
|
|
if(CopyBuffer(rsi1Handle, 0, 0, rates_total, tempRSI) <= 0)
|
||
|
|
{
|
||
|
|
Print("Error copying RSI buffer: ", GetLastError());
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Calculate MA of RSI for each bar
|
||
|
|
for(int i = start; i >= 0; i--)
|
||
|
|
{
|
||
|
|
// Store RSI value
|
||
|
|
rsiBuffer[i] = tempRSI[i];
|
||
|
|
|
||
|
|
// Check if we have enough data for MA calculation
|
||
|
|
if(i > rates_total - MA_Period)
|
||
|
|
{
|
||
|
|
maBuffer[i] = 0;
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Calculate MA of RSI :cite[6]
|
||
|
|
maBuffer[i] = CalculateMA(tempRSI, i, MA_Period, MA_Method);
|
||
|
|
|
||
|
|
// Set level values
|
||
|
|
oversoldBuffer[i] = RSI1_Oversold;
|
||
|
|
overboughtBuffer[i] = RSI1_Overbought;
|
||
|
|
}
|
||
|
|
|
||
|
|
return rates_total;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Helper function to calculate MA values |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
double CalculateMA(double &data[], int index, int period, ENUM_MA_METHOD method)
|
||
|
|
{
|
||
|
|
// For series arrays, index 0 is the current bar, higher indexes are older bars
|
||
|
|
if(index + period - 1 >= ArraySize(data))
|
||
|
|
return 0.0; // Not enough data
|
||
|
|
|
||
|
|
if(method == MODE_SMA)
|
||
|
|
{
|
||
|
|
double sum = 0;
|
||
|
|
for(int i = 0; i < period; i++)
|
||
|
|
sum += data[index + i]; // For series arrays, we sum from current to older
|
||
|
|
return sum / period;
|
||
|
|
}
|
||
|
|
else if(method == MODE_EMA)
|
||
|
|
{
|
||
|
|
// EMA calculation for series arrays
|
||
|
|
double ema = data[index + period - 1]; // Oldest value in the period
|
||
|
|
double k = 2.0 / (period + 1.0);
|
||
|
|
for(int i = period - 2; i >= 0; i--)
|
||
|
|
ema = data[index + i] * k + ema * (1 - k);
|
||
|
|
return ema;
|
||
|
|
}
|
||
|
|
else if(method == MODE_LWMA)
|
||
|
|
{
|
||
|
|
double sum = 0, weights = 0;
|
||
|
|
for(int i = 0; i < period; i++)
|
||
|
|
{
|
||
|
|
double w = period - i;
|
||
|
|
sum += data[index + i] * w;
|
||
|
|
weights += w;
|
||
|
|
}
|
||
|
|
return sum / weights;
|
||
|
|
}
|
||
|
|
else if(method == MODE_SMMA)
|
||
|
|
{
|
||
|
|
// SMMA calculation for series arrays
|
||
|
|
double smma = 0;
|
||
|
|
for(int i = 0; i < period; i++)
|
||
|
|
smma += data[index + i];
|
||
|
|
smma /= period;
|
||
|
|
|
||
|
|
for(int i = 1; i < period; i++)
|
||
|
|
smma = (smma * (period - 1) + data[index + i]) / period;
|
||
|
|
|
||
|
|
return smma;
|
||
|
|
}
|
||
|
|
return 0.0;
|
||
|
|
}
|
||
|
|
//+------------------------------------------------------------------+
|