I found that the problem is an error due to the fact that MQL5 does not wait for the data to download in the new TF, so one get ERROR 4806. The next time an indicator is loaded the data is ready, and that explains the behaviour of why the new TF indicator appears after another indicator is loaded.
2023.11.04 07:47:36.060 MA_MultiTF (EURUSD,M1) Not All data of ExtHandle1 is calculated (-1bars ). Error4806
A suggested solution in this POST is to calculate the next bar in the next tick. The problem is that at that time one is already on the OnCalculate part of the indicator, so the handle is never created (This is why the indicator never appears), the question is then how can one trigger the OnInit again, if an error occurs in the OnCalculate?
Here is an example of classic MTF mean, that yields this error:
//+------------------------------------------------------------------+ //| MA_MultiTF.mq5 | //| Copyright 2017, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2017, MetaQuotes Software Corp." #property link "https://www.mql5.com" //---- indicator settings #property indicator_chart_window #property indicator_buffers 1 #property indicator_plots 1 #property indicator_type1 DRAW_LINE #property indicator_color1 Blue #property indicator_width1 1 //---- input parameters input ENUM_TIMEFRAMES tf = 5; // Time Frame input int maPeriod = 13; // MA period input int Shift = 0; // Shift input ENUM_MA_METHOD InpMAMethod = MODE_SMA; // Moving average method input ENUM_APPLIED_PRICE InpAppliedPrice = PRICE_CLOSE; // Applied price input bool Interpolate = true; input int Bars_Calculated = 500; //---- indicator buffers double ExtMA[]; //---- handles for moving averages int MA_Handle; //--- bars minimum for calculation int ExtBarsMinimum; ENUM_TIMEFRAMES _tf; int pf; int draw_begin; //--- we will keep the number of values in the Moving Average indicator int bars_calculated=0; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { _tf=tf; ENUM_TIMEFRAMES timeframe; int draw_shift=Shift;// initial PLOT_SHIFT value draw_begin=maPeriod;// initial value PLOT_DRAW_BEGIN //--- timeframe=_Period; if(_tf<=timeframe)_tf=timeframe;// if the TF is less than or is equal to the current one, set it to PERIOD_CURRENT pf=(int)MathFloor(_tf/timeframe);// calculate coefficient for PLOT_DRAW_BEGIN, PLOT_SHIFT and the number of calculation bars. draw_begin=maPeriod*pf;// calculate PLOT_DRAW_BEGIN draw_shift=Shift*pf;// calculate PLOT_SHIFT //---- indicator buffers mapping SetIndexBuffer(0,ExtMA,INDICATOR_DATA); //--- PlotIndexSetInteger(0,PLOT_SHIFT,draw_shift); //line shifts when drawing PlotIndexSetString(0,PLOT_LABEL,"MA("+string(tf)+" "+string(maPeriod)+")");//name for DataWindow //---- Disabling drawing of empty indicator values PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0.0); //--- get MA's handles MA_Handle=iMA(NULL,_tf,maPeriod,0,InpMAMethod,InpAppliedPrice); // if(MA_Handle==INVALID_HANDLE) { Print("getting MA Handle is failed! Error",GetLastError()); return(INIT_FAILED); } //--- set accuracy IndicatorSetInteger(INDICATOR_DIGITS,_Digits); //--- bars minimum for calculation ExtBarsMinimum=draw_begin+draw_shift;// calculate the minimum required number of bars for the calculation //--- initialization done 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 for rates total if(rates_total<ExtBarsMinimum+pf) return(0); // not enough bars for calculation int limit,limit1; if(Bars_Calculated!=0)draw_begin=Bars(NULL,0)-Bars_Calculated; //--- PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,draw_begin+pf); //sets first bar from what index will be drawn //--- apply timeseries indexing to array elements ArraySetAsSeries(time,true); ArraySetAsSeries(ExtMA,true); //--- not all data may be calculated int calculated=BarsCalculated(MA_Handle); //--- if(calculated<=0) { Print("Not All data of ExtHandle1 is calculated (",calculated,"bars ). Error",GetLastError()); return(0); } //--- detect start position //--- calculations of the necessary amount of data to be copied //--- and the 'limit' starting index for the bars recalculation loop if(prev_calculated>rates_total || prev_calculated<=0|| calculated!=bars_calculated)// checking for the first start of the indicator calculation { limit=rates_total-ExtBarsMinimum-1; // starting index for calculation of all bars } else { limit=(rates_total-prev_calculated)+pf+1; // starting index for calculation of new bars } if(Bars_Calculated!=0) limit=MathMin(Bars_Calculated,limit); //--- main cycle for(int i=limit;i>=0 && !IsStopped();i--) { int n; datetime t=time[i]; ExtMA[i]=_CopyBuffer(MA_Handle,t); if(!Interpolate) continue; //--- limit1=limit; if(limit==Bars_Calculated)limit1=limit-1; datetime times= _iTime(t); for(n = 1; i+n<limit1+1 && time[i+n]>= times; n++) continue; double factor=1.0/n; for(int k=1; k<n; k++) ExtMA[i+k]=k*factor*ExtMA[i+n]+(1.0-k*factor)*ExtMA[i]; } //--- bars_calculated=calculated; //--- return value of prev_calculated for next call return(rates_total); } //+------------------------------------------------------------------+ datetime _iTime(datetime start_time) { if(start_time < 0) return(-1); datetime Arr[]; if(CopyTime(NULL,_tf, start_time, 1, Arr)>0) return(Arr[0]); else return(-1); } //+--------- CopyBuffer MA Handle ----------------------------------+ double _CopyBuffer(int handle,datetime start_time) { double buf[]; if(CopyBuffer(handle,0,start_time,1,buf)>0) return(buf[0]); return(EMPTY_VALUE); } //+-------------------- END -----------------------------------------+After working on this issue, I also found this POST , which claims to use a timer, but the error still persists
- 2019.09.16
- www.mql5.com
Hi Gerard,
A suggested solution in this Post is to add a delay a then refresh the handle. I am trying this but have not fixed the problem.
- 2017.01.30
- www.mql5.com
I found this POST, which appears to provide a good solution.
if (BarsCalculated(handlerMtf) < 0) { PrintFormat("Data not found (Timeframe :: %s-%d) >>", GetLastError()); ChartSetSymbolPeriod(0, NULL, 0); return 0; }
- 2018.06.17
- www.mql5.com
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
I am currently using an indicator I found in the codebase.
When it loads in the chart it displays fine (Left figure), but when I change the TimeFrame, the indicator disappear (middle figure); when I add any other indicator ,the original indicator appears with the updated change (left figure).
Like if it fails to initiate after changing the TF.... is there a reason for this behavior?