0

There are Bollinger Bands with three RSI running in the basement.

I want to do a check on the signal in such a way that when 3 RSI struck the zone of the upper Bbands, there was a signal down and vice versa:

int start(){
   double ma, stdev;
   int i, limit, count=IndicatorCounted();

   if(count<0) return(0);
   limit=Bars-count;  
   if(limit>1) limit=Bars-1;

    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);
        }

    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;
        }

    if(limit<Bars-1) limit++;

    for(i=limit; i>0; i--) {          
        if(RSI[i] <= BBDOWN[i] && RSI[i+1] > BBDOWN[i+1] && RSI2[i] <= BBDOWN[i] && RSI2[i+1] > BBDOWN[i+1] && RSI3[i] <= BBDOWN[i] && RSI3[i+1] > BBDOWN[i+1]){
           DOWN[i] = iLow(_Symbol, _Period, i);
           }
        if(RSI[i] >= BBUP[i] && RSI[i+1] < BBUP[i+1] &&W 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);
           }
    }

The whole problem is that I have very crooked signals.

Appear where they should not be, and there is no where to be.

  • 1
    Possible duplicate of [How to "tie" 3 RSI-indicators to one Bollinger Band, using IMAonArray()?](https://stackoverflow.com/questions/44102558/how-to-tie-3-rsi-indicators-to-one-bollinger-band-using-imaonarray) – rgunning May 23 '17 at 11:41
  • **Even more dup's** >>> "Есть 2 полосы бойлинджера BB1[] и BB2[] на графике + RSI[] и WPR[]. Хочу написать проверку так: Если РСИ пробила вверх ББ и ВПР выше верхнего уровня, то сигнал SELL должен быть только при разовом и одновременном соблюдением условий...." – user3666197 May 23 '17 at 14:30
  • 1
    What are you creating? Script? EA? Indicator? I'm assuming script from `int start()`. **Don't use `start`!! the correct function is `void OnStart()` [https://docs.mql4.com/basis/function/events](https://docs.mql4.com/basis/function/events)** code is incorrect and missing end '}' – rgunning May 24 '17 at 11:00
  • line 30 has a typo 'W' appearing after &&. – rgunning May 24 '17 at 11:12
  • Also other bugs/optimisations. This isn't really the place though to be fixing every line of your code. Especially when the premise of drawing bollinger bands on RSI is flawed in the first place as @user3666197 keeps pointing out – rgunning May 24 '17 at 11:16
  • create Indicator – user3711927 May 24 '17 at 12:50
  • see indicator example at bottom [https://docs.mql4.com/basis/function/events](https://docs.mql4.com/basis/function/events) you want an OnInit() and on OnCalculate() function. – rgunning May 24 '17 at 13:06

2 Answers2

2

THE BEST PRACTICE:


Step 0: Let's first agree in written WHAT is the actual TARGET:

If the TARGET is to compute & paint on GUI the Bollinger Bands on RSI3[] values, the best way to do this is to use:

UPPER[i] = iBandsOnArray( RSI3,                       // ArrayAsSeries[]
                          array_calculation_depth,    // reduce overheads
                          BB_MA_period,               // BBands period
                          BB_StDev_MUL,               // how many sigmas
                          BB_Zero_Shift,              // #DEFINE BB_Zero_Shift 0
                          MODE_UPPER,                 // BBands upper line
                          i                           // shifting operator[i]
                          );

This way one may efficiently produce each of the { MODE_UPPER | MODE_MAIN | MODE_LOWER } Bollinger Bands lines here, consistently generated over dimension-less RSI3[] data, thus protecting the sense of any additive operations in signal-composition(s) with other, dimension-less data, as in { RSI2[], RSI[] }.


Step 1: visually check the lines to validate any signal-conditions:

Given the GUI shows lines accordingly, one may try to compose signal-conditions. The "hot"-bar [0] is a live-bar, where novice may encounter tricking signalling situations, if not handled with due professional care.


Step 2: implement signal-conditions in code:

Only after Step 0) & 1) took place and both meet one's own prior expectations, any code starts to make sense to get built.

user3666197
  • 1
  • 6
  • 50
  • 92
1

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.

rgunning
  • 568
  • 2
  • 16
  • But it is possible to simulate this code, it's very difficult for me as a beginner to understand such subtleties ... thanks... – user3711927 May 23 '17 at 13:11
  • @user3711927 updated my answer to show basic idea of using ArraySetAsSeries to set indexing direction. code not tested – rgunning May 23 '17 at 13:46
  • You might have noticed already, the O/P has repeated the question, asking for a help without taking due care to review the provided warnings, that **any additive operation on** a mix of **aPriceDOMAIN** indicator **& dimension-less** indicator ( relative / percent ) yields to nonsense. You might be willing to re-align you answer so as to reflect this sure fact & not to "promise" an un-promisable to the O/P. **The problem is not within a syntax "repair", but in ( NOT ) ignoring the principal flaw in the said composition.** – user3666197 May 23 '17 at 13:49
  • @user3666197 yes I flagged it as a duplicate question. I'm answering purely to show the bug in the array indexing. I'm ignoring whether or not combining Bollinger bands and RSI has any value – rgunning May 23 '17 at 14:00
  • That's dangerous :o) – user3666197 May 23 '17 at 14:01
  • @user3666197 **fix 1 problem at a time**. Better to teach about time series array indexing now so they don't run into that particular error again in the future – rgunning May 23 '17 at 14:03
  • did not help! Compiles, but does not start – user3711927 May 24 '17 at 05:55
  • @user3711927 what errors are you getting? All I did was add a series of ArraySetAsSeries() calls to your code, my changes would not break anything unless added in wrong place. First 3 need to be in your OnInit() function . Other two in your onCalculate function before and after your loop as indicated. – rgunning May 24 '17 at 07:10
  • I have an int start () – user3711927 May 24 '17 at 10:37
  • 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); It not work!!! – user3711927 May 25 '17 at 11:10
  • missing a closing } but otherwise that line looks ok – rgunning May 25 '17 at 11:34
  • Cleaner way of writing that line would be if(MathMin(RSI[i],MathMin(RSI2[i],RSI3[i]))>=BBUP[i] && MathMax(RSI[i+1],MathMax(RSI2[i+1],RSI3[i+1])) – rgunning May 25 '17 at 11:38
  • if(MathMin(RSI[i],MathMin(RSI2[i],RSI3[i]))>=BBUP[i] - work, no problem! MathMax(RSI[i+1],MathMax(RSI2[i+1],RSI3[i+1])) – user3711927 May 26 '17 at 09:56