How to code Moving Average applied on Bollinger Bands

 

How do you apply an indicator on a multi-buffered indicator in MQL5 in general? For example, Moving Average applied on Bollinger Bands.

First, I create the variables:

int Bands_handle;
int MA_handle;
double MA[];

Then I create the indicator handles in the OnInit() function (note that Bands_handle is the last parameter in the iMA function):

Bands_handle = iBands(NULL, PERIOD_CURRENT, 20, 0, 2, PRICE_CLOSE);
MA_handle = iMA(NULL, PERIOD_CURRENT, 14, 0, MODE_SMA, Bands_handle);

then I copy the buffer in the OnCalculate() function:

CopyBuffer(MA_handle, 0, 0, rates_total, MA);

but where do you specify the upper or lower buffer for Bollinger Bands? (0 - BASE_LINE, 1 - UPPER_BAND, 2 - LOWER_BAND)

You can't put it in the CopyBuffer function, because that's for the Moving Average. I already tried to change buffer 0 to other number with no success:
CopyBuffer(MA_handle, UPPER_BAND, 0, rates_total, MA);
You can't specify the buffer in the iBands function either.

Documentation on MQL5: Timeseries and Indicators Access / CopyBuffer
Documentation on MQL5: Timeseries and Indicators Access / CopyBuffer
  • www.mql5.com
CopyBuffer - Timeseries and Indicators Access - MQL5 Reference - Reference on algorithmic/automated trading language for MetaTrader 5
 
michal32: How do you apply an indicator on a multi-buffered indicator in MQL5 in general? For example, Moving Average applied on Bollinger Bands. First, I create the variables: Then I create the indicator handles in the OnInit() function (note that Bands_handle is the last parameter in the iMA function): then I copy the buffer in the OnCalculate() function: but where do you specify the upper or lower buffer for Bollinger Bands? (0 - BASE_LINE, 1 - UPPER_BAND, 2 - LOWER_BAND). You can't put it in the CopyBuffer function, because that's for the Moving Average. I already tried to change buffer 0 to other number with no success: You can't specify the buffer in the iBands function either.

Unfortunately, when using one indicator's output to feed another via the use of their handle (applied price parameter), you cannot control the selection of the plot/buffer.

It is only feasible to use this functionality, when the source indicator has a single plot.

 
Fernando Carreiro #:

Unfortunately, when using one indicator's output to feed another via the use of their handle (applied price parameter), you cannot control the selection of the plot/buffer.

It is only feasible to use this functionality, when the source indicator has a single plot.

So what's the alternative solution? I know there are functions in "MovingAverages.mqh": SimpleMAOnBuffer, SmoothedMAOnBuffer, LinearWeightedMAOnBuffer, ... for each Moving Average which is an alternative to iMAOnArray() in MQL4.

But what if I want to use other indicator than Moving Average? In MQL4, there are functions iBandsOnArray, iRSIOnArray, ... which are missing in MQL5.

It becomes easier if I create a separate indicator that copies the buffer I need, e.g. one indicator that displays only the upper band of Bollinger Bands and another one that displays only the lower band. Then I can use the standard code for a single-buffered indicator. Otherwise, it becomes even more complex than MQL4 since I have to write the custom function "on array".

 
michal32 #: So what's the alternative solution? I know there are functions in "MovingAverages.mqh": SimpleMAOnBuffer, SmoothedMAOnBuffer, LinearWeightedMAOnBuffer, ... for each Moving Average which is an alternative to iMAOnArray() in MQL4. But what if I want to use other indicator than Moving Average? In MQL4, there are functions iBandsOnArray, iRSIOnArray, ... which are missing in MQL5. It becomes easier if I create a separate indicator that copies the buffer I need, e.g. one indicator that displays only the upper band of Bollinger Bands and another one that displays only the lower band. Then I can use the standard code for a single-buffered indicator. Otherwise, it becomes even more complex than MQL4 since I have to write the custom function "on array".

The alternative is to code your own calculations, be that in the form of a Custom Indicator, or applying calculations directly.

Also remember that knowing how Indicators work and how they are calculated can help simplify things.

For example, Bollinger bands are actually just a Moving Average and the Standard Deviation put together. In simple terms, Bollinger Bands is something like this ...

upper iBands = iMA + iStdDev * deviation
lower iBands = iMA - iStdDev * deviation

Every single one of the MQL's internal functions has a publicly know calculation or equation and it is provided in the documentation ...

So use that information to rebuild your new indicator calculations.
 
@Conor Mcnamara #: You didn't understand what I meant. You can perform as much math as you want on the output buffer values? You are thinking about this a strange way. He didn't mention anything about using other indicators, he just wants to make one indicator 

Please read the questions properly.

The OP is referring to a documented MQL5 method of passing one indicator's handle onto another via the applied price parameter (see documentation for iMA)

applied_price: [in]  The price used. Can be any of the price constants ENUM_APPLIED_PRICE or a handle of another indicator.

The OP is trying to use this method to try achieve the moving average of the non-primary buffer of the redirected indicator, but this is not possible via the applied price parameter method. So, I gave the OP and option.

Your answers however, are confusing the issue.

For reference from the OP's original post (notice the handle being used as the applied price parameter) ...

Then I create the indicator handles in the OnInit() function (note that Bands_handle is the last parameter in the iMA function):

Bands_handle = iBands(NULL, PERIOD_CURRENT, 20, 0, 2, PRICE_CLOSE);
MA_handle = iMA(NULL, PERIOD_CURRENT, 14, 0, MODE_SMA, Bands_handle);
 
michal32 #:

This code is doing the opposite thing - Bollinger Bands applied on Moving Average. I want Moving Average applied on Bollinger Bands which can't be solved this way.

Maybe in this particular case the result is the same, but generally applying an indicator to a moving average is not the same as applying a moving average to an indicator.

I have already given you the answer back on my post , but seems it has not been understood. I will try to elaborate using the lower band as an example ...

Given (using pseudo-code):

lower iBands = iMA - iStdDev * deviation

Then the moving average of the lower band can be calculated as (using pseudo-code) ...

iMA( [Lower iBand] ) = iMA ( [ iMA ] ) - iMA( [ iStdDev ] ) * deviation.

This is because of the following mathematical equivalence rule ...

if Z = X + Y, then the moving average of Z is the same as the moving average of X plus the moving average of Y

MA( Z ) = MA( X ) + MA( Y )
 
Fernando Carreiro #:

I have already given you the answer back on my post , but seems it has not been understood. I will try to elaborate using the lower band as an example ...

Given (using pseudo-code):

Then the moving average of the lower band can be calculated as (using pseudo-code) ...

This is because of the following mathematical equivalence rule ...

if Z = X + Y, then the moving average of Z is the same as the moving average of X plus the moving average of Y

I understood your answer. I'm now responding to other answers.

What if I want to use other indicator than Bollinger Bands where you don't have this formula?

In MQL4, this is solved in general by the function iMAOnArray. You copy the buffer of the first indicator into an array and then call iMAOnArray. This scheme works for all indicators.

In MQL5, it seems to be even more difficult than MQL4, because you have to include your own function iMAOnArray. Nobody has found a better solution than doing the same what's in MQL4 plus writing the function iMAOnArray that has been removed in MQL5.

 
michal32 #: In MQL4, this is solved in general by the function iMAOnArray. You copy the buffer of the first indicator into an array and then call iMAOnArray. This scheme works for all indicators. In MQL5, it seems to be even more difficult than MQL4, because you have to include your own function iMAOnArray. Nobody has found a better solution than doing the same what's in MQL4 plus writing the function iMAOnArray that has been removed in MQL5.

It is not more difficult. It is simply different. In MQL5 you can use the functions provided in "MovingAverages.mqh".

michal32 #: What if I want to use other indicator than Bollinger Bands where you don't have this formula?

Then you read the buffer values with CopyBuffer and apply logic and maths to it!

That is what programmers do. They solve the problem with logic and maths.

 

I have severely redacted a great number of posts from this thread, which diverted from the OP's original intended query.

Now, lets return to the original query, and will paraphrase to hopefully make it more clear ...

How to apply an indicator function (e.g. iMA) to the secondary plot output of another indicator (e.g. iBands), using the "applied price" handle method.

 
Fernando, it his he who must paraphrase what he is asking. Otherwise it is your own topic, and not his anymore.

 

To summarise the issue ...

Currently MQL5 does not offer a method to redirect secondary plots to the "applied price" parameter of an indicator function. It only works with the primary plot.

Possible work-arounds (can't be classified as solutions) ...

  • To collect the data from the secondary plots via the CopyBuffer function and then apply a moving average using the functions in in "MovingAverages.mqh" (for the moving average example).
  • To break-down the calculations of the original multi-plot indicator, and then use the "applied price" method on the elementary indicator functions.

Also, neither of the above two work-around are ideal, or efficient or even generic.

There may be other work-arounds that have not yet been proposed or discussed.

Reason: