It cannot be created using the MQL5 Wizard - you are cunning :).
Let's take one step at a time: tell me which constructions you need (lines or Arrow) and I will guide you through the steps of the MQL5 Wizard.
It cannot be created using the MQL5 Wizard - you are cunning :).
Let's take one step at a time: tell me which constructions you need (lines or Arrow) and I will guide you through the steps of the MQL5 Wizard.
Thanks.
I'd like to calculate the difference between two moving averages, so in the OnCalculate function I'd write something like this:
SimpleMAOnBuffer(rates_total, 0, 1, ShortInterval, open, ShortBuffer); SimpleMAOnBuffer(rates_total, 0, 1, LongInterval, open, LongBuffer); for (int i = 1; i < rates_total; i++) { WAvgBuffer[i] = ShortBuffer[i] - LongBuffer[i]; }
I want to obtain a line in a separate window, and the line is defined by values in WAvgBuffer.
WAvgBuffer is the buffer that I've created with INDICATOR_DATA, and it works (if I assign a constant value to every element of WAvgBuffer array, I can see the line in the chart). I've seen in the article linked in my first post that it's possible to use many indicator buffers, and it's for MQL5, so even if It should be possible to obtain the same result in other ways (for example with dynamic arrays defined inside the OnCalculate function), I'd like to know why it's not working my example, and where the warning come from (I've searched the indicator_buffers in all the project with a text search but without success, mine is the only definition of that property).
How to create an indicator - the difference between two iMAs (Moving Average).
Step 1. Right click on the folder and select 'New File'
Step 2. Indicator name (string 'Namde'), one input parameter ('Parameters')
Step 3. Selecting the full version of OnCalculate
Step 4. 'Indicator in separate windows'c, add one line' Diff_Two_iMA '
We get the workpiece:
//+------------------------------------------------------------------+ //| Difference Two iMA.mq5 | //| Copyright © 2021, Vladimir Karputov | //+------------------------------------------------------------------+ #property copyright "Copyright © 2021, Vladimir Karputov" #property version "1.00" #property indicator_separate_window #property indicator_buffers 1 #property indicator_plots 1 //--- plot Diff_Two_iMA #property indicator_label1 "Diff_Two_iMA" #property indicator_type1 DRAW_LINE #property indicator_color1 clrYellowGreen #property indicator_style1 STYLE_SOLID #property indicator_width1 1 //--- input parameters input int Input1=9; //--- indicator buffers double Diff_Two_iMABuffer[]; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- indicator buffers mapping SetIndexBuffer(0,Diff_Two_iMABuffer,INDICATOR_DATA); //--- 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[]) { //--- //--- return value of prev_calculated for next call return(rates_total); } //+------------------------------------------------------------------+
Now we start thinking: we need to add two arrays - for two iMAs. So we change the counter and add these two arrays, and we will declare two variables - they will store two handles
#property indicator_separate_window #property indicator_buffers 3 #property indicator_plots 1 //--- plot Diff_Two_iMA #property indicator_label1 "Diff_Two_iMA" #property indicator_type1 DRAW_LINE #property indicator_color1 clrYellowGreen #property indicator_style1 STYLE_SOLID #property indicator_width1 1 //--- input parameters input int Input1=9; //--- indicator buffers double Diff_Two_iMABuffer[]; double FastBuffer[]; double SlowBuffer[]; //--- int handle_iMA_Fast; // variable for storing the handle of the iMA indicator int handle_iMA_Slow; // variable for storing the handle of the iMA indicator //+------------------------------------------------------------------+ //| Custom indicator initialization function |
Add variable 'm_init_error' - this is a flag. If there is an error while creating the indicator, this flag will be set to 'true'.
double SlowBuffer[]; //--- bool m_init_error = false; // error on InInit //+------------------------------------------------------------------+ //| Custom indicator initialization function |
Adding input parameters for the 'Fast' and 'Slow' indicator
//--- input parameters input group "Fast MA" input int Inp_MA_Fast_ma_period = 9; // MA Fast: averaging period input int Inp_MA_Fast_ma_shift = 0; // MA Fast: horizontal shift input ENUM_MA_METHOD Inp_MA_Fast_ma_method = MODE_SMA; // MA Fast: smoothing type input ENUM_APPLIED_PRICE Inp_MA_Fast_applied_price = PRICE_CLOSE; // MA Fast: type of price input group "Slow MA" input int Inp_MA_Slow_ma_period = 26; // MA Slow: averaging period input int Inp_MA_Slow_ma_shift = 0; // MA Slow: horizontal shift input ENUM_MA_METHOD Inp_MA_Slow_ma_method = MODE_SMA; // MA Slow: smoothing type input ENUM_APPLIED_PRICE Inp_MA_Slow_applied_price = PRICE_CLOSE; // MA Slow: type of price //--- indicator buffers
Go to 'OnInit': link two arrays and create two handles
//+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- indicator buffers mapping SetIndexBuffer(0,Diff_Two_iMABuffer,INDICATOR_DATA); SetIndexBuffer(1,FastBuffer,INDICATOR_DATA); SetIndexBuffer(2,SlowBuffer,INDICATOR_DATA); //--- create handle of the indicator iMA handle_iMA_Fast=iMA(Symbol(),Period(),Inp_MA_Fast_ma_period,Inp_MA_Fast_ma_shift, Inp_MA_Fast_ma_method,Inp_MA_Fast_applied_price); //--- if the handle is not created if(handle_iMA_Fast==INVALID_HANDLE) { //--- tell about the failure and output the error code PrintFormat("Failed to create handle of the iMA ('Fast') indicator for the symbol %s/%s, error code %d", Symbol(), EnumToString(Period()), GetLastError()); //--- the indicator is stopped early m_init_error=true; return(INIT_SUCCEEDED); } //--- create handle of the indicator iMA handle_iMA_Slow=iMA(Symbol(),Period(),Inp_MA_Slow_ma_period,Inp_MA_Slow_ma_shift, Inp_MA_Slow_ma_method,Inp_MA_Slow_applied_price); //--- if the handle is not created if(handle_iMA_Slow==INVALID_HANDLE) { //--- tell about the failure and output the error code PrintFormat("Failed to create handle of the iMA ('Slow') indicator for the symbol %s/%s, error code %d", Symbol(), EnumToString(Period()), GetLastError()); //--- the indicator is stopped early m_init_error=true; return(INIT_SUCCEEDED); } //--- return(INIT_SUCCEEDED); }
Go to OnCalculate - Here are mainly copy-paste operations (using the iMA help)
Continued later ...
How to create an indicator - the difference between two iMAs (Moving Average).
Wow, thanks a lot, this will be very helpful.
Thanks again.
Continuation ...
Apply copy-paste and do some manual work. From the help ( iMA ) we copy almost the entire function and change it a little for ourselves (change the name of the indicator buffers, change the name of the handle and throw out 'Comment') Here just carefully compare the help ( iMA ) and my code. First of all, add the variable 'bars_calculated' to the program header:
int handle_iMA_Slow; // variable for storing the handle of the iMA indicator //--- int bars_calculated = 0; // we will keep the number of values in the Moving Average indicator bool m_init_error = false; // error on InInit //+------------------------------------------------------------------+ //| Custom indicator initialization function |
I have highlighted the main thing - this is the calculation of the difference
//+------------------------------------------------------------------+ //| 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(m_init_error) return(0); //--- number of values copied from the iMA indicator int values_to_copy; //--- determine the number of values calculated in the indicator int calculated_fast=BarsCalculated(handle_iMA_Fast); if(calculated_fast<=0) { PrintFormat("BarsCalculated(handle_iMA_Fast) returned %d, error code %d",calculated_fast,GetLastError()); return(0); } int calculated_slow=BarsCalculated(handle_iMA_Slow); if(calculated_slow<=0) { PrintFormat("BarsCalculated(handle_iMA_Slow) returned %d, error code %d",calculated_slow,GetLastError()); return(0); } if(calculated_fast!=calculated_slow) { PrintFormat("BarsCalculated(handle_iMA_Fast) returned %d, BarsCalculated(handle_iMA_Slow) returned %d",calculated_fast,calculated_slow); return(0); } int calculated=calculated_fast; //--- if it is the first start of calculation of the indicator or if the number of values in the iMA indicator changed //---or if it is necessary to calculated the indicator for two or more bars (it means something has changed in the price history) if(prev_calculated==0 || calculated!=bars_calculated || rates_total>prev_calculated+1) { //--- if the iMABuffer array is greater than the number of values in the iMA indicator for symbol/period, then we don't copy everything //--- otherwise, we copy less than the size of indicator buffers if(calculated>rates_total) values_to_copy=rates_total; else values_to_copy=calculated; } else { //--- it means that it's not the first time of the indicator calculation, and since the last call of OnCalculate() //--- for calculation not more than one bar is added values_to_copy=(rates_total-prev_calculated)+1; } //--- fill the iMABuffer array with values of the Moving Average indicator //--- if FillArrayFromBuffer returns false, it means the information is nor ready yet, quit operation if(!FillArrayFromBuffer(FastBuffer,Inp_MA_Fast_ma_shift,handle_iMA_Fast,values_to_copy)) return(0); if(!FillArrayFromBuffer(SlowBuffer,Inp_MA_Slow_ma_shift,handle_iMA_Slow,values_to_copy)) return(0); //--- memorize the number of values in the Moving Average indicator bars_calculated=calculated; //--- main loop int limit=prev_calculated-1; if(prev_calculated==0) limit=0; for(int i=limit; i<rates_total; i++) { Diff_Two_iMABuffer[i]=FastBuffer[i]-SlowBuffer[i]; } //--- return value of prev_calculated for next call return(rates_total); } //+------------------------------------------------------------------+ //| Filling indicator buffers from the MA indicator | //+------------------------------------------------------------------+ bool FillArrayFromBuffer(double &values[], // indicator buffer of Moving Average values int shift, // shift int ind_handle, // handle of the iMA indicator int amount // number of copied values ) { //--- reset error code ResetLastError(); //--- fill a part of the iMABuffer array with values from the indicator buffer that has 0 index if(CopyBuffer(ind_handle,0,-shift,amount,values)<0) { //--- if the copying fails, tell the error code PrintFormat("Failed to copy data from the iMA indicator, error code %d",GetLastError()); //--- quit with zero result - it means that the indicator is considered as not calculated return(false); } //--- everything is fine return(true); } //+------------------------------------------------------------------+ //| Indicator deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { if(handle_iMA_Fast!=INVALID_HANDLE) IndicatorRelease(handle_iMA_Fast); if(handle_iMA_Slow!=INVALID_HANDLE) IndicatorRelease(handle_iMA_Slow); } //+------------------------------------------------------------------+
Result:

- www.mql5.com
Hi guys, I have the same issue but I don't understand how it was addressed in this thread. I'm building an Expert using four indicators but when I try to bind my dynamic arrays to their respective indicator buffers using SetIndexBuffer, only the first call returns successfully. Someone kindly check my code and help me resolve this
#property indicator_buffers 4 //+------------------------------------------------------------------+ //| Global Variables | //+------------------------------------------------------------------+ enum PRICE_MODE { Close=PRICE_CLOSE, //Close price Open=PRICE_OPEN, //Open price High=PRICE_HIGH, //The maximum price for the period Low=PRICE_LOW, //The minimum price for the period Median=PRICE_MEDIAN, //Median price, (high + low)/2 Typical=PRICE_TYPICAL, //Typical price, (high + low + close)/3 Weighted=PRICE_WEIGHTED //Average price, (high + low + close + close)/4 }; input PRICE_MODE rsi_price_mode = Close ; //RSI Price Mode input int RSI_PERIOD = 14 ; //RSI Period input double PARSARSTEP = 0.02; //Parabolic SAR STEP input double PARSARMAX = 0.2; //Parabolic SAR MAX input PRICE_MODE ema_price_mode = Close ; //10EMA Price Mode input PRICE_MODE sma_price_mode = Close ; //20SMA Price Mode double RSIBuffer[10] ; double PARSARBuffer[10] ; double EMA_10_Buffer[10] ; double SMA_20_Buffer[10] ; int RSIHandle ; int PARSARHandle ; int EMA_10_Handle ; int SMA_20_Handle ; bool sar_index_bufer; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { /* ArrayResize(RSIBuffer, 11) ; ArrayResize(PARSARBuffer, 11) ; ArrayResize(EMA_10_Buffer, 11) ; ArrayResize(SMA_20_Buffer, 11) ; */ SetIndexBuffer(0, RSIBuffer) ; sar_index_bufer = SetIndexBuffer(1, PARSARBuffer) ; SetIndexBuffer(2, EMA_10_Buffer) ; SetIndexBuffer(3, SMA_20_Buffer) ; RSIHandle = iRSI(NULL,0,RSI_PERIOD,rsi_price_mode) ; PARSARHandle = iSAR(NULL,0,PARSARSTEP,PARSARMAX) ; EMA_10_Handle = iMA(NULL,0,10,0,MODE_EMA,ema_price_mode) ; SMA_20_Handle = iMA(NULL,0,20,0,MODE_SMA,sma_price_mode) ; if(RSIHandle < 0 || PARSARHandle < 0 || EMA_10_Handle < 0 || SMA_20_Handle < 0) { const string message = "One or More Indicators Failed to Initialize. Please Restart MetaTrader." ; MessageBox(message, NULL, MB_OK | 0x0040) ; return(INIT_FAILED) ; } //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- Print("SAR INDEX BUFFER: ", sar_index_bufer); if (!CopyBufferAsSeries(RSIHandle,0,0,10,true,RSIBuffer)) { Print("Failed to copy RSI buffer."); return ; } if (!CopyBufferAsSeries(PARSARHandle,1,1,10,true,PARSARBuffer)) { Print("Failed to copy SAR buffer. "); return ; } if (!CopyBufferAsSeries(EMA_10_Handle,2,1,10,true,EMA_10_Buffer)) { Print("Failed to copy EMA buffer."); return ; } if (!CopyBufferAsSeries(SMA_20_Handle,3,1,10,true,SMA_20_Buffer)) { Print("Failed to copy SMA buffer."); return ; } Print("RSI:: ", RSIBuffer[0]); Print("SAR:: ", PARSARBuffer[0]); Print("EMA10:: ", EMA_10_Buffer[0]); Print("SMA20:: ", SMA_20_Buffer[0]); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------------------+ //| The function copies the values of the indicator,the elements | //| will be indexed depending on the value of the input parameter asSeries | //+------------------------------------------------------------------------------+ bool CopyBufferAsSeries( int handle, // indicator's handle int bufer, // buffer index int start, // start index int number, // number of elements to copy bool asSeries, // if it's true, the elements will be indexed as series double &M[] // target array ) { //--- filling the array M with current values of the indicator if(CopyBuffer(handle,bufer,start,number,M)<=0) return(false); //--- the elements will be indexed as follows: //--- if asSeries=true, it will be indexed as timeseries //--- if asSeries=false, it will be indexed as default ArraySetAsSeries(M,asSeries); //--- return(true); } //+------------------------------------------------------------------+
When I print sar_index_buffer it is false. Copying to RSIBuffer works as expected while copying to PARSARBuffer fails
Hi guys, I have the same issue but I don't understand how it was addressed in this thread. I'm building an Expert using four indicators but when I try to bind my dynamic arrays to their respective indicator buffers using SetIndexBuffer, only the first call returns successfully. Someone kindly check my code and help me resolve this
When I print sar_index_buffer it is false. Copying to RSIBuffer works as expected while copying to PARSARBuffer fails
- Set target Dynamic Array as Series before calling CopyBuffer
- Changed buffer number argument to CopyBuffer to 0 for all buffers/copy operations
Hope this helps someone.
Happy coding :)

- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
Hi.
I've created a new indicator with MQL5 by using the wizard. I need three buffers for my logic, but only the first one is created.
This is my code:
When OnInit is called, only the first call to SetIndexBuffer returns true, while the other two calls returns false.
I've seen in an example that I should set the number of buffers, so I've added at the beginning the following line:
But in this case I've a compilation warning:
-- property already exists with different value and will be skipped
Since I'm a newbie I don't know where this property was already defined.
What should I do in order to create all buffers that I need?