Questions from Beginners MQL5 MT5 MetaTrader 5 - page 578

 
Artyom Trishkin:

DataCandles is a structure. The array where we write the candlesticks from the history is array[]. So we need to make it as a timeseries to make its indexing coincide with indexing of candlesticks on the chart. I.e. the zero cell of array[] will correspond to the closest candlesticks to the current date.

I.e. 1. we copy candlesticks into array array[], 2. we make it a time series, and then read values from it into the structure.

You can do without array[] - just write data directly from the chart into the structure, but I suggested this for compatibility with Five - it allows to copy directly only in the indicator using high[i], low[i] and other data, but in the script or Expert Advisor, we will have to first copy the necessary history interval into the array, which I did.

bool series=ArrayIsSeries(array);
Alert (series);
ArraySetAsSeries (array, true);
bool series=ArrayIsSeries(array);

Alert (series);

like this?

Both alerts still return false

 
Andrey Koldorkin:
bool series=ArrayIsSeries(array);
Alert (series);
ArraySetAsSeries(array, true);
bool series=ArrayIsSeries(array);

Alert (series);

like this?

Both alerts still return false

So, this is a bug which should be reported to "Errors, Bugs, Questions".

Here is a check script, it shows time of copied candlesticks in zero and last cells of array[]:

//+------------------------------------------------------------------+
//|                                                     TestCopy.mq4 |
//|              Copyright 2016, Artem A. Trishkin, Skype artmedia70 |
//|                       https://login.mql5.com/ru/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, Artem A. Trishkin, Skype artmedia70"
#property link      "https://login.mql5.com/ru/users/artmedia70"
#property version   "1.00"
#property strict
#property script_show_inputs

enum enumYN
  {
   enYes=1, // Да
   enNo=0,  // Нет
  };

//--- input parameters
input int Search_Period=10;   // Количество копируемых свечей
int searchPeriod=(Search_Period<1)?1:Search_Period;
input int Delta=2;            // Количество пунктов допуска
int delta=(Delta<0)?0:Delta;
input enumYN AsSeries=enYes;  // Массив array как таймсерия
MqlRates array[];             // Массив структур для копирования Open, High, Low, Close, Time
  
struct DataCandle             // Структура для хранения всех совпадений
  {
   int number_matched;           // Количество совпадений
   MqlRates reference_candle;    // Данные эталонной свечи
   MqlRates matched_candles[];   // Массив свечей, совпадающих с эталонной по нужному критерию 
  };
  DataCandle dataCandle[];    // Массив структур данных свечей и их совпадений
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//---
   int copy_bars=(int)fmin(Search_Period,Bars(Symbol(),Period()));   // количество копируемых свечей
   int copied=CopyRates(Symbol(),PERIOD_CURRENT,1,copy_bars,array);  // копируем данные
   if(copied>0) {                                                    // если скопировали
      ArraySetAsSeries(array,AsSeries);                              // задаём массив как таймсерию или нет
      ArrayResize(dataCandle,copied);                                // задаём размер структуры равным числу скопированных данных
      ZeroMemory(dataCandle);                                        // Обнуляем данные в структуре
      //--- основной цикл по "эталонным" свечам в массиве array. Их параметры будем искать в доп. цикле
      for(int i=0; i<copy_bars-1; i++) {                             // цикл по скопированным данным от начала до "на один меньше размера массива"
         dataCandle[i].reference_candle.high=array[i].high;          // ищем этот high
         dataCandle[i].reference_candle.low=array[i].low;            // запомнили low для сравнения
         dataCandle[i].reference_candle.time=array[i].time;          // запомнили time для вывода в журнал
         //--- поиск совпадений с эталонной свечой, индексируемой индексом основного цикла i
         int size=0;                                                 // размер массива совпадающих свечей
         ArrayResize(dataCandle[i].matched_candles,size);            // Размер массива совпадений в ноль
         dataCandle[i].number_matched=size;                          // Инициализируем количество совпадений нулём
         //--- теперь ищем совпадения по high свечей в цикле j с high эталонной свечи с индексом i
         for(int j=0; j<copy_bars; j++) {                            // в цикле от i+1 до copy_bars
            if(j==i) continue;                                       // пропустим свечу "саму себя"
            //--- если совпадают high эталонной свечи (i) и свечи с индексом j (с допуском на величину Point)
            if(NormalizeDouble(delta*Point()-fabs(array[i].high-array[j].high),Digits())>=0) {
               size++;                                               
               ArrayResize(dataCandle[i].matched_candles,size);            // увеличим размер массива совпадающих свечей
               dataCandle[i].number_matched=size;                          // запишем количество совпадений
               dataCandle[i].matched_candles[size-1].high=array[j].high;   // запишем в массив high совпадающей свечи
               dataCandle[i].matched_candles[size-1].low=array[j].low;     // запишем в массив low совпадающей свечи
               dataCandle[i].matched_candles[size-1].time=array[j].time;   // запишем в массив время совпадающей свечи
               //Print("Время свечи ",i," :",TimeToString(dataCandle[i].reference_candle.time=array[i].time),", high=",DoubleToString(dataCandle[i].reference_candle.high=array[i].high,Digits()),". Совпадение со свечой ",TimeToString(dataCandle[i].matched_candles[size-1].time=array[j].time),", её high ",DoubleToString(dataCandle[i].matched_candles[size-1].high=array[j].high,Digits()),". Совпадений: ",(string)dataCandle[i].number_matched);
               }
            }
         }
      }

   //--- Посмотрим чего понаписали в массивы
   Alert("Array is series: ",ArrayIsSeries(array),
         "\ntime array[0]: ",TimeToString(array[0].time,TIME_DATE|TIME_MINUTES),
         "\ntime array[",string(searchPeriod-1),"]: ",TimeToString(array[ArraySize(array)-1].time,TIME_DATE|TIME_MINUTES));
   for(int i=0; i<ArraySize(dataCandle)-1; i++) {
      string refs_txt="";
      string matched_txt="";
      refs_txt="Свеча "+IntegerToString(i,2,'0')+": время "+TimeToString(dataCandle[i].reference_candle.time)+", high: "+DoubleToString(dataCandle[i].reference_candle.high,Digits())+" имеет совпадений: "+(string)dataCandle[i].number_matched+" шт. ";
      if(dataCandle[i].number_matched>0) {
         for(int j=0; j<ArraySize(dataCandle[i].matched_candles); j++) {
            matched_txt="Совпадение "+IntegerToString(j+1)+": "+TimeToString(dataCandle[i].matched_candles[j].time)+", high: "+DoubleToString(dataCandle[i].matched_candles[j].high,Digits());
            }
         }
      Print(refs_txt,matched_txt);
      }
  }
//+------------------------------------------------------------------+
 
Artyom Trishkin:

So this is a bug which should be reported to "Errors, bugs, questions".

Here is a check script, it shows time of copied candlesticks in zero and last cells of array[]:

Outputs this:

Array is series: false

time array[0]: 2016.05.12 21:00

time array[9]: 2016.05.12 12:00

 
Andrey Koldorkin:

It comes up with this:

Array is series: false

time array[0]: 2016.05.12 21:00

time array[9]: 2016.05.12 12:00

I checked it - always false, but time is correct: if at start of script select Array array as time series "Yes", then:

Array is series: false
time array[0]: 2016.05.12 21:00
time array[9]: 2016.05.12 12:00

If you select "No", then:

Array is series: false
time array[0]: 2016.05.12 12:00
time array[9]: 2016.05.12 21:00

the times of the candlesticks written to the array are reversed, which means ArraySetAsSeriess() works correctly, but ArrayIsSeries() does not, it always outputs false, which I have already written to the above bug thread.

 
Andrey Koldorkin:

Oh this programming. The further into the woods....

Understand, you don't need to know the direction of the array. The algorithm is looking for repeats. Therefore, it doesn't care what order the bars are processed in.
 
Vasiliy Sokolov:
Understand, you don't need to know the direction of the array. The algorithm is looking for repeats. So it doesn't care what order the bars are processed in.
it does. After all, I then need to know which candlesticks formed a match and with the closest to the current price take the price Low.
 
Andrey Koldorkin:
you need. Because then I need to find out which candlesticks formed a match and take the price Low from the closest to the current price.

There is a candle time in the structure for this, by which you can find the closest candle to any time you need.

And you don't need to output the candlestick numbers - they don't coincide with real bar numbers. Because we fill the array, and the indexes in the array belong only to the candlestick's number in the array, not on the chart.

 
Artyom Trishkin:

I checked what it gives out - always false, but the time is correct: if you select Array array as time series "Yes" when running the script, then:

If you select "No", then:

The times of the candlesticks written to the array are reversed, which means ArraySetAsSeriess() works correctly, but ArrayIsSeries() does not, it always outputs false, which I have already written to the above bug thread.

I slightly modified the code:

ArraySetAsSeries(array,true); //there just put true

and then added numbers of candlesticks for self-check:

Alert("Array is series: ",ArrayIsSeries(array),

"\nCandle "+IntegerToString(0,2,'0')+" time array[0]: ",TimeToString(array[0].time,TIME_DATE|TIME_MINUTES),

"\nSwitch "+IntegerToString(searchperiod-1,2,'0')+" time array[",string(searchperiod-1),"]:",TimeToString(array[ArraySize(array)-1].time,TIME_DATE|TIME_MINUTES));

It gives the following output:

Array is series: false

Candle 00 time array[0]: 2016.05.12 22:00

Candle 09 time array[9]: 2016.05.12 13:00

 
Artyom Trishkin:
To do this, there is a candle time in the structure, by which you can find the closest candle to any time you need.
Well, all the same. it turns out that the direction changes with one line of code. it will not complicate the process. But while I'm just trying to figure out what's going on, at least the candlesticks in my head and machine will be in the same order ))
 
Andrey Koldorkin:

I've changed the code a bit:

ArraySetAsSeries(array,true); //there just put true

and then added numbers of candlesticks for self-check:

Alert("Array is series: ",ArrayIsSeries(array),

"\nCandle "+IntegerToString(0,2,'0')+" time array[0]: ",TimeToString(array[0].time,TIME_DATE|TIME_MINUTES),

"\nSwitch "+IntegerToString(searchperiod-1,2,'0')+" time array[",string(searchperiod-1),"]:",TimeToString(array[ArraySize(array)-1].time,TIME_DATE|TIME_MINUTES));

It gives the following output:

Array is series: false

Candle 00 time array[0]: 2016.05.12 22:00

Candle 09 time array[9]: 2016.05.12 13:00

Are you using mql4? If so, find out the candlestick number from its time, which is written in the structure. iBarShift() will help you.