From time to time, my indicator simply disappears. And it's not simple to put it back.
Can someone help me understand why it is happening?
Most probably you have an "array out of range" or eventually a "divide by 0" critical error. Check your log (Experts tab).
CopyRates() is a function, you need to check the returned value and act accordingly (see documentation).
Most probably you have an "array out of range" or eventually a "divide by 0" critical error. Check your log (Experts tab).
CopyRates() is a function, you need to check the returned value and act accordingly (see documentation).
You are right!
The error is an "array out of range".
I read the documentation in the link and the function documentation, but I still did not get it!
Why sometimes I got this error and sometimes not? Since is the same number of bars, and nothing that I am aware changed...
I am researching it, but is there any known way to prevent this error?
Thank you, very much for you kindness replying this post
From time to time, my indicator simply disappears. And it's not simple to put it back.
Can someone help me understand why it is happening?
You are right!
The error is an "array out of range".
I read the documentation in the link and the function documentation, but I still did not get it!
Why sometimes I got this error and sometimes not? Since is the same number of bars, and nothing that I am aware changed...
I am researching it, but is there any known way to prevent this error?
Thank you, very much for you kindness replying this post
Not only one of the symbol can have less bars than the other as pointed by @Petr Nosek but it could also happen that a symbol has a bar for a given time and the other not. You NEED to check the returned value of CopyRates() as I already advised you. You asked 1 value so it should return 1 value, otherwise you have to deal with it.
That being said your way to request 1 value at a time for both symbols is very inefficient, but that's an other matter.
Obviously you have failed to get data by CopyRates(). Probably your "iptSymbol" has less Bars than "_Symbol". You have to deal with it.
Thank you! You helped me a lot with the "array out of range" error. I will show how dealt with it.
Not only one of the symbol can have less bars than the other as pointed by @Petr Nosek but it could also happen that a symbol has a bar for a given time and the other not. You NEED to check the returned value of CopyRates() as I already advised you. You asked 1 value so it should return 1 value, otherwise you have to deal with it.
That being said your way to request 1 value at a time for both symbols is very inefficient, but that's an other matter.
Thanks again. Although I am studying the documentation, I still can not understand what you mean by "You NEED to check the returned value".
I used an "If" operator... but I don't think that's what you meant.
Also, I'd be glad if you tell your thoughts about a more efficient way to achieve the same results.
This is the new code:
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[]) { //--- ArraySetAsSeries(time,true); ArraySetAsSeries(close,true); ArraySetAsSeries(SDBuffer,true); MqlRates rates1[]; ArraySetAsSeries(rates1,true); MqlRates rates2[]; ArraySetAsSeries(rates2,true); double razao; int TotalBarsIptSymbol; TotalBarsIptSymbol=iBars(iptSymbol,_Period); if(prev_calculated<rates_total) { for(int i=0;i<MathMin(rates_total,TotalBarsIptSymbol)-1;i++) { if (CopyRates(_Symbol,_Period,time[i],1,rates1)) {} else return(rates_total); if (CopyRates(iptSymbol,_Period,time[i],1,rates2)) {} else return(rates_total); razao=rates2[0].close/rates1[0].close; SDBuffer[i]=razao; } } //--- return value of prev_calculated for next call return(rates_total); }
Thank you! You helped me a lot with the "array out of range" error. I will show how dealt with it.
Thanks again. Although I am studying the documentation, I still can not understand what you mean by "You NEED to check the returned value".
I used an "If" operator... but I don't think that's what you meant.
Also, I'd be glad if you tell your thoughts about a more efficient way to achieve the same results.
This is the new code:
Read the documentation of CopyRates(). If it's a matter of language, the documentation also exists in Portuguese.
Return Value
Returns the number of copied elements or -1 in case of an error.
That doesn't seem hard to understand. Is it ?
Read the documentation of CopyRates(). If it's a matter of language, the documentation also exists in Portuguese.
That doesn't seem hard to understand. Is it ?
I've already read it. But i was unable to deal with it. At least, now, I think i got it. Thanks!
if(prev_calculated<rates_total) { for(int i=0;i<MathMin(rates_total,TotalBarsIptSymbol)-2;i++) { if(CopyRates(_Symbol,_Period,time[i],1,rates1)<0) { Print("Erro: ",GetLastError()); } if(CopyRates(iptSymbol,_Period,time[i],1,rates2)<0) { Print("Erro: ",GetLastError()); } razao=rates2[0].close/rates1[0].close; SDBuffer[i]=razao; } }
Could you tell me something to be more efficient?
I've already read it. But i was unable to deal with it. At least, now, I think i got it. Thanks!
Could you tell me something to be more efficient?
//+------------------------------------------------------------------+ //| 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[]) { //--- int limit,toCopy; //--- if(prev_calculated==0) { ArrayInitialize(SDBuffer,EMPTY_VALUE); int iptBars = iBars(iptSymbol,_Period); toCopy = (iptBars>rates_total || iptBars==0 ? rates_total : iptBars); limit = rates_total-toCopy; } else { //--- update only on new bar if(prev_calculated==rates_total) return(rates_total); limit = prev_calculated-1; toCopy = rates_total-limit; } int copied=CopyRates(iptSymbol,_Period,0,toCopy,rates); if(copied==-1) { /* error ... */ return(0); }; for(int i=limit,iptIndex=0;i<rates_total;i++) { while(iptIndex<copied-1 && rates[iptIndex].time<time[i]) { ++iptIndex; } //--- if(rates[iptIndex].time==time[i]) SDBuffer[i]=rates[iptIndex].close/close[i]; else SDBuffer[i]=EMPTY_VALUE; } //--- return value of prev_calculated for next call return(rates_total); }
Wow! That's very impressive! And I am very grateful!
I will take my time to understand it completely and improve my skills based on your example.
And I still can use your way of thinking to adapt it for another indicators.
Thanks A LOT!!!
![MQL5 - Language of trade strategies built-in the MetaTrader 5 client terminal](https://c.mql5.com/i/registerlandings/logo-2.png)
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
From time to time, my indicator simply disappears. And it's not simple to put it back.
Can someone help me understand why it is happening?