From MQL4 docs https://docs.mql4.com/indicators/imaonarray
Unlike iMA(...)
, the iMAOnArray()
function does not take data by
symbol name, timeframe, the applied price. The price data must be
previously prepared. The indicator is calculated from left to right.
To access to the array elements as to a series array (i.e., from right
to left), one has to use the ArraySetAsSeries()
function.
RSI3 is currently orientated right to left (0 is most recent time point, limit is furthest element).
Same issue with iStdDevOnArray()
Fix those issues and it should work as you want. Whether there is any value in drawing Bollinger bands on RSI is another matter
Update
The function ArraySetAsSeries()
can be used to swap the array between left-to-right and right-to-left
When you first initialise the RSI arrays ( in the OnInit()
) tell MetaTrader Terminal that they are timeseries.
ArraySetAsSeries(RSI1,True);
ArraySetAsSeries(RSI2,True);
ArraySetAsSeries(RSI3,True);
Then in main body, add ArraySetAsSeries(RSI3,False);
before your second for loop to swap the array orientation. Then ArraySetAsSeries(RSI3,True);
after the loop to restore the array orientation.
for(i=limit; i>=0; i--) {
RSI[i ] = iRSI(Symbol(),Period(),rsi_period,PRICE_CLOSE,i);
RSI2[i] = iRSI(Symbol(),Period(),rsi_period_2,PRICE_CLOSE,i);
RSI3[i] = iRSI(Symbol(),Period(),rsi_period_3,PRICE_CLOSE,i);
}
ArraySetAsSeries(RSI3,False);
for(i=limit; i>=0; i--) {
ma=iMAOnArray(RSI3,0,bb_period,0,0,i); // midle line
stdev=iStdDevOnArray(RSI3,0,bb_period,0,0,i); // dev
BBUP[i]=ma+bb_dev*stdev; // up line
BBDOWN[i]=ma-bb_dev*stdev; // down line
UP[i]=0;
DOWN[i]=0;
}
ArraySetAsSeries(RSI3,True);
if(limit<Bars-1) limit++;
for(i=limit; i>0; i--) {
if( RSI[i] <= BBDOWN[i] &&
RSI[i+1] > BBDOWN[i] &&
RSI2[i] <= BBDOWN[i] &&
RSI2[i+1] > BBDOWN[i] &&
RSI3[i] <= BBDOWN[i] &&
RSI3[i+1] > BBDOWN[i]) {
DOWN[i] = iLow(_Symbol, _Period, i);
}
if( RSI[i] >= BBUP[i] &&
RSI[i+1] < BBUP[i+1] &&
RSI2[i] >= BBUP[i] &&
RSI2[i+1] < BBUP[i+1] &&
RSI3[i] >= BBUP[i] &&
RSI3[i+1] < BBUP[i+1]) {
UP[i]= iHigh(_Symbol, _Period, i);
}
}
Basic indicator structure
You need to go through the MQL4 Documentation and learn the proper structure of an indicator. There needs to be an OnInit()
function where you initialise values. Then an OnCalculate()
function where you fill the indicator buffers.
//+-----------------------------------------------------------------+
//| Custom indicator initialization function |
//+-----------------------------------------------------------------+
int OnInit()
{
//--- indicator buffers mapping
ArraySetAsSeries(RSI3,True);
//---
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[])
{
// Do your calculations here
//--- return value of prev_calculated for next call
return(rates_total);
}
If you use iBandsOnArray()
to calculate Bollinger bands you won't need to swap the array direction after it is set in OnInit()
If the indicator is compiling but crashing, you will need to debug it. Simplest way is to look at the errors in the log and add PrintFormat() statements throughout your code so you can see what the indicator is doing at different points and see where it crashes.