Preguntas de los principiantes MQL5 MT5 MetaTrader 5 - página 578

 
Artyom Trishkin:

DataCandles es una estructura. El array donde escribimos las velas del historial es array[]. Así que tenemos que hacerlo como una serie de tiempo para que su indexación coincida con la indexación de las velas en el gráfico. Es decir, la celda cero del array[] corresponderá a las velas más cercanas a la fecha actual.

Es decir, 1. copiamos los candelabros en el array array[], 2. lo convertimos en una serie temporal, y luego leemos los valores de la misma en la estructura.

Se puede prescindir de array[] - simplemente escribir los datos directamente desde el gráfico en la estructura, pero sugerí esto por compatibilidad con Five - permite copiar directamente sólo en el indicador usando high[i], low[i] y otros datos, pero en el script o Expert Advisor, tendremos que copiar primero el intervalo de historia necesario en el array, lo cual hice.

bool series=ArrayIsSeries(array);
Alerta (serie);
ArraySetAsSeries (array, true);
bool series=ArrayIsSeries(array);

Alerta (serie);

¿así?

Ambas alertas siguen devolviendo falso

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

Alerta (serie);

¿así?

Ambas alertas siguen devolviendo falso

Por lo tanto, se trata de un error que debe ser reportado a "Errores, Bugs, Preguntas".

Aquí hay un script de comprobación, muestra el tiempo de las velas copiadas en las celdas cero y última del 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:

Por lo tanto, se trata de un error que debe ser reportado a "Errores, bugs, preguntas".

Aquí hay un script de comprobación, muestra el tiempo de las velas copiadas en las celdas cero y última del array[]:

Sale esto:

El array es una serie: falso

tiempo array[0]: 2016.05.12 21:00

matriz de tiempo[9]: 2016.05.12 12:00

 
Andrey Koldorkin:

Sale esto:

El array es una serie: falso

tiempo array[0]: 2016.05.12 21:00

matriz de tiempo[9]: 2016.05.12 12:00

Lo he comprobado - siempre es falso, pero el tiempo es correcto: si al inicio del script se selecciona Array array como serie temporal "Sí", entonces:

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

Si selecciona "No", entonces:

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

los tiempos de las velas escritas en el array están invertidos, lo que significa que ArraySetAsSeriess() funciona correctamente, pero ArrayIsSeries() no, siempre da como resultado false, lo que ya he escrito en el hilo de errores anterior.

 
Andrey Koldorkin:

Oh, esta programación. Cuanto más se adentre en el bosque....

Entiende que no necesitas saber la dirección de la matriz. El algoritmo busca repeticiones. Por lo tanto, no le importa el orden en que se procesan las barras.
 
Vasiliy Sokolov:
Entiende que no necesitas saber la dirección de la matriz. El algoritmo busca repeticiones. Así que no le importa el orden en que se procesan las barras.
lo hace. Después de todo, necesito saber qué velas formaron una coincidencia y con la más cercana al precio actual tomar el precio Bajo.
 
Andrey Koldorkin:
que necesitas. Porque entonces necesito averiguar qué velas formaron una coincidencia y tomar el precio Bajo de la más cercana al precio actual.

Para ello existe una vela de tiempo en la estructura, mediante la cual puedes encontrar la vela más cercana a cualquier hora que necesites.

Y no es necesario emitir los números de las velas, ya que no coinciden con los números reales de las barras. Porque llenamos el array, y los índices en el array pertenecen sólo al número de la vela en el array, no en el gráfico.

 
Artyom Trishkin:

He comprobado lo que produce - siempre falso, pero el tiempo es correcto: si seleccionas Array array como serie temporal "Sí" al ejecutar el script, entonces:

Si selecciona "No", entonces:

Los tiempos de las velas escritas en el array están invertidos, lo que significa que ArraySetAsSeriess() funciona correctamente, pero ArrayIsSeries() no, siempre da como resultado false, lo que ya he escrito en el hilo de errores anterior.

He modificado ligeramente el código:

ArraySetAsSeries(array,true); //aquí sólo hay que poner true

y luego agregó números de velas para la autocomprobación:

Alert("El array es una serie: ",ArrayIsSeries(array),

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

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

Da la siguiente salida:

El array es una serie: falso

Vela 00 tiempo array[0]: 2016.05.12 22:00

Vela 09 matriz de tiempo[9]: 2016.05.12 13:00

 
Artyom Trishkin:
Para ello, hay una vela de tiempo en la estructura, por lo que puede encontrar la vela más cercana a cualquier hora que usted necesita.
Resulta que la dirección cambia con una línea de código. no complicará el proceso. Pero mientras intento averiguar qué pasa, al menos los candelabros de mi cabeza y de la máquina estarán en el mismo orden ))
 
Andrey Koldorkin:

He cambiado un poco el código:

ArraySetAsSeries(array,true); //aquí sólo hay que poner true

y luego agregó números de velas para la autocomprobación:

Alert("El array es una serie: ",ArrayIsSeries(array),

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

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

Da la siguiente salida:

El array es una serie: falso

Vela 00 tiempo array[0]: 2016.05.12 22:00

Vela 09 matriz de tiempo[9]: 2016.05.12 13:00

¿Estás usando mql4? Si es así, averigüe el número de la vela a partir de su hora, que está escrita en la estructura. iBarShift() le ayudará.