Pay attention to the possibility of copying synchronized time series into a set of arrays
Forum on trading, automated trading systems and testing trading strategies
MetaQuotes, 2023.03.03 11:14
MQL5: Added new CopySeries function for copying synchronized timeseries from MqlRates into separate arrays.
The CopySeries function allows obtaining only the necessary timeseries into different specified arrays during one call, while all of timeseries data will be synchronized. This means that all values in the resulting arrays at a certain index N will belong to the same bar on the specified Symbol/Timeframe pair. Therefore, there is no need for the programmer to additionally synchronize the received timeseries by the bar opening time.
Unlike CopyRates, which returns the full set of timeseries as an MqlRates array, the CopySeries function allows obtaining specific required timeseries into separate arrays. This can be done by specifying a combination of flags to select the type of timeseries. The order of the arrays passed to the function must match the order of the fields in the MqlRates structure:
struct MqlRates { datetime time; // period beginning time double open; // open price double high; // high price for the period double low; // low price for the period double close; // close price long tick_volume; // tick volume int spread; // spread long real_volume; // exchange volume }
Thus, if you need to get the values of the 'time', 'close' and 'real_volume' timeseries for the last 100 bars of the current Symbol/Timeframe, you should use the following call:
datetime time[]; double close[]; long volume[]; CopySeries(NULL,0,0,100,COPY_RATES_TIME|COPY_RATES_CLOSE|COPY_RATES_VOLUME_REAL,time,close,volume);
The order of the arrays "time, close, volume" must match the order of the fields in the MqlRates structure. The order of values in the rates_mask is ignored. The mask could be as follows:
COPY_RATES_VOLUME_REAL|COPY_RATES_TIME|COPY_RATES_CLOSE
Example
//--- input parameters input datetime InpDateFrom=D'2022.01.01 00:00:00'; input datetime InpDateTo =D'2023.01.01 00:00:00'; input uint InpCount =20; //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart(void) { //--- arrays to get timeseries from the Rates structure double open[]; double close[]; float closef[]; datetime time1[], time2[]; //---request close prices to a double array ResetLastError(); int res1=CopySeries(NULL, PERIOD_CURRENT, 0, InpCount, COPY_RATES_TIME|COPY_RATES_CLOSE, time1, close); PrintFormat("1. CopySeries returns %d values. Error code=%d", res1, GetLastError()); ArrayPrint(close); //--- now also request open prices; use float array for close prices ResetLastError(); int res2=CopySeries(NULL, PERIOD_CURRENT, 0, InpCount, COPY_RATES_TIME|COPY_RATES_CLOSE|COPY_RATES_OPEN, time2, open, closef); PrintFormat("2. CopySeries returns %d values. Error code=%d", res2, GetLastError()); ArrayPrint(closef); //--- compare the received data if((res1==res2) && (time1[0]==time2[0])) { Print(" | Time | Open | Close double | Close float |"); for(int i=0; i<10; i++) { PrintFormat("%d | %s | %.5f | %.5f | %.5f |", i, TimeToString(time1[i]), open[i], close[i], closef[i]); } } /* Result 1. CopySeries returns 0 values. Error code=0 [ 0] 1.06722 1.06733 1.06653 1.06520 1.06573 1.06649 1.06694 1.06675 1.06684 1.06604 [10] 1.06514 1.06557 1.06456 1.06481 1.06414 1.06394 1.06364 1.06386 1.06239 1.06247 2. CopySeries returns 0 values. Error code=0 [ 0] 1.06722 1.06733 1.06653 1.06520 1.06573 1.06649 1.06694 1.06675 1.06684 1.06604 [10] 1.06514 1.06557 1.06456 1.06481 1.06414 1.06394 1.06364 1.06386 1.06239 1.06247 | Time | Open | Close double | Close float | 0 | 2023.03.01 17:00 | 1.06660 | 1.06722 | 1.06722 | 1 | 2023.03.01 18:00 | 1.06722 | 1.06733 | 1.06733 | 2 | 2023.03.01 19:00 | 1.06734 | 1.06653 | 1.06653 | 3 | 2023.03.01 20:00 | 1.06654 | 1.06520 | 1.06520 | 4 | 2023.03.01 21:00 | 1.06520 | 1.06573 | 1.06573 | 5 | 2023.03.01 22:00 | 1.06572 | 1.06649 | 1.06649 | 6 | 2023.03.01 23:00 | 1.06649 | 1.06694 | 1.06694 | 7 | 2023.03.02 00:00 | 1.06683 | 1.06675 | 1.06675 | 8 | 2023.03.02 01:00 | 1.06675 | 1.06684 | 1.06684 | 9 | 2023.03.02 02:00 | 1.06687 | 1.06604 | 1.06604 | */ }
Pay attention to the possibility of copying synchronized time series into a set of arrays
Thanks @Vladislav Boyko
I was not aware of this method :). Let me try to revise my code accordingly and revert back if any problem occurred.
Regards.
Pay attention to the possibility of copying synchronized time series into a set of arrays
I have tried to change code as below
int err = 0; int barStart = MathMin(RatesTotal,iBarShift(mSymbol,PERIOD_M1,timeSessionStart)); // Returns -1 as failure int barCount = int(PeriodSeconds(mSessionTF) / 60); int barCopied = 0; do{ ResetLastError(); int barCopied = CopySeries(mSymbol,PERIOD_M1,barStart,barCount, COPY_RATES_TIME|COPY_RATES_HIGH|COPY_RATES_LOW|COPY_RATES_VOLUME_TICK, Time,High,Low,Volume); err++; } while(barCopied == -1 && err < _NoOfAttempts); if(err > _NoOfAttempts) return(false); //RatesTotal[60709] barStart[60708][2023.08.31 00:00] barStop[2023.09.01 00:00] barCount[1440] barCopied[-1] GetLastError[0] Time[0] High[0] Low[0] Volume[0]
but continued to get the same error.
Regards
To be honest, I don't have a reliable solution for copying timeseries in MQL5. I just suggested replacing 4 CopyXXX calls with one, thereby obtaining synchronized arrays.
If the array out of range error occurs here
POCTimeStart = Time[0];
Then you can try to avoid this error something like this
if(ArraySize(Time) < 1) { // Here you can print the error with debugging information return(false); } POCTimeStart = Time[0];
But this will be just a crutch that will help avoid errors when accessing the zero element of the array.
As I already said, I don't know how to reliably copy timeseries in MQL5
To be honest, I don't have a reliable solution for copying timeseries in MQL5. I just suggested replacing 4 CopyXXX calls with one, thereby obtaining synchronized arrays.
Dear @Vladislav Boyko
really appreciate your time and suggestion.
I understand you point now how it is possible to replace 4CopyXXX calls with one and obtaining synchronized arrays.
To copy data, I will look solutions to make sure required or synchronized bars have been copied.
I just wonder how it has by passed do..while loop, where the check was in place.
Regards.
void OnStart() { int _NoOfAttempts = 3; int err = 0; do{ err++; } while(err < _NoOfAttempts); PrintFormat("The cycle is complete: err = %i, _NoOfAttempts = %i", err, _NoOfAttempts); if(err > _NoOfAttempts) Print("return was executed"); else Print("return was not executed"); }
The cycle is complete: err = 3, _NoOfAttempts = 3 return was not executed
//---request close prices to a double array ResetLastError(); int res1=CopySeries(NULL, PERIOD_CURRENT, 0, InpCount, COPY_RATES_TIME|COPY_RATES_CLOSE, time1, close); PrintFormat("1. CopySeries returns %d values. Error code=%d", res1, GetLastError()); ArrayPrint(close); //--- now also request open prices; use float array for close prices ResetLastError(); int res2=CopySeries(NULL, PERIOD_CURRENT, 0, InpCount, COPY_RATES_TIME|COPY_RATES_CLOSE|COPY_RATES_OPEN, time2, open, closef); PrintFormat("2. CopySeries returns %d values. Error code=%d", res2, GetLastError()); ArrayPrint(closef);
Greetings and hope you are doing well.
I have tried all possible ways to use CopySeries() function and following are my observation after failing to succeed in any one of them.
1] If you have timeStart and timeStop parameters and not idxStart and NoOfCount values, this function creates lot of difficulties to convert time to index values. iBarShift() has its own issues for returning incorrect values for many reasons.
2] The problem aggravates, if your start time is on a different timeframe than timeframe required for copying data.
3] MQL should consider another variation of this function with timePosStart and timePosEnd
int CopySeries( string symbol_name, // symbol name ENUM_TIMEFRAMES timeframe, // period int start_pos, // start position int count, // amount to copy ulong rates_mask, // combination of flags to specify the requested series void& array1[], // array to receive the data of the first copies timeseries void& array2[] // array to receive the data of the second copied timeseries ... );
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
Dear Fellows
I am getting frequent '2024.01.21 16:20:11.328 iSessionVP v1.99 (XAUUSD,M15) array out of range in 'SessionVPHisto.mqh' (258,23) error.
Help me what I have missed to check this error in do while loop.
Thanks in advance.