In a standard indicator, you would build the buffer arrays with data from the parameters sent via the OnCalulate( ... ) event function. But, for multi-currency and/or multi-time-frame, you will have to use one of two solutions:
- Using the old method of the "iFunction" variations, such as iTime(), iVolume, iOpen, iClose, etc. but with a different symbol such as "EURUSD", "JPYUSD", etc. instead of the default _Symbol or Symbol().
- Using the newer method of the first variant of ArrayCopyRates() function together with array pointers of MqlRates. The "copied" arrays, will not actually take up any space and will just be pointers to the existing data of the various symbols and time-frames.
However, for this to work, one of two conditions have to exist for the multi-symbol and/or multi-time-frame to work:
- Either the respective charts for the symbols and time-frames are already open, so that no error is generated,
- or you will get an error 4066 (ERR_HISTORY_WILL_UPDATED) the first time you request the data, and you will have to code a sleep & retry loop, in order to wait for data to download and then request the data again.
My personal suggested solution, which I find as the most efficient as well as easiest way to handle the 4066 error, is the ArrayCopyRates() and MqlRates method.
There is more information about this the MQL4 documentation and help files.
PS! NB! When accessing built-in indicator functions, such as iMA(), iATR(), etc. for the various symbols and time-frames, remember to also implement the sleep and retry loops so as not to get the 4066 error either. Here is a quote from the MQL4 documentaion:
Remember, the OP is asking about an indicator. Sleep() is ignored in indicators
Sorry did not know that! I use this method quite extensively in EA's but not in Indicators, so did not know about the sleep handicap.
In that case, he will have to build a retry loop around successive calls on every tick call to the OnCalculate() function (where the use of ArrayCopyRates() is the better solution).
Alternatively, if it works in the OnInit() function, it might be the preferred method of preparing the data for the indicator, with a very long retry count (without the sleep) for this case.
...
- or you will get an error 4066 (ERR_HISTORY_WILL_UPDATED) the first time you request the data, and you will have to code a sleep & retry loop, in order to wait for data to download and then request the data again.
PS! NB! When accessing built-in indicator functions, such as iMA(), iATR(), etc. for the various symbols and time-frames, remember to also implement the sleep and retry loops so as not to get the 4066 error either. Here is a quote from the MQL4 documentaion:
Unless they changed something recently, you'll get the 4066 error every time from the first function call (and only from this first call), regardless of conditions or history update progress. It has no practical use.
FMIC: In that case, he will have to build a retry loop around successive calls on every tick call to the OnCalculate() function (where the use of ArrayCopyRates() is the better solution). Alternatively, if it works in the OnInit() function, it might be the preferred method of preparing the data for the indicator, with a very long retry count (without the sleep) for this case. |
|
if(pair1[0].time == 0) return;
This will never be true.
If there is any history loaded for the symbol and timeframe the function will retrieve the most recent value.
If there is no history loaded, you will get an Array out of range error.
Same with iTime etc
This will never be true.
If there is any history loaded for the symbol and timeframe the function will retrieve the most recent value.
If there is no history loaded, you will get an Array out of range error.
Same with iTime etc
I am inclined to agree!
Personally, I just check the return value of "ArrayCopyRates()" and after that I just keep track of the array size before accessing the array data.
With regards to "iTime()" and other such functions, I always check the "iBars()" first.
This will never be true.
if(pair1[0].time == 0) return;
If there is any history loaded for the symbol and timeframe the function will retrieve the most recent value.
If there is no history loaded, you will get an Array out of range error.
Same with iTime etc
There are many historic (pre-build 600) examples of looking at a ACR. There is no other way to do it. Subsequent calls to ACR or iTime will NOT return 4066, so how can you possibly know wether the data has been downloaded.
iTime has always returned zero on an error.
There are many historic (pre-build 600) examples of looking at a ACR. There is no other way to do it. Subsequent calls to ACR or iTime will NOT return 4066, so how can you possibly know wether the data has been downloaded.
iTime has always returned zero on an error.
What do you mean by "there is no other way to do it"?
Checking the return count from "ArrayCopyRates", and checking the array size, seems to be a more robust method of checking, than doing "pair1[0].time == 0" which can easily return an "Array index is out of range" error.
EDIT: Removed some of my statements after re-reading your post more closely.
- 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 want to choose BETWEEN 1 to 10 different currencies and 5 bars for each currency.
But i don't know how to do this.