Domande dai principianti MQL5 MT5 MetaTrader 5 - pagina 578

 
Artyom Trishkin:

DataCandles è una struttura. L'array dove scriviamo le candele della storia è array[]. Quindi abbiamo bisogno di renderla una serie temporale in modo che la sua indicizzazione coincida con l'indicizzazione delle candele sul grafico. Cioè la cella zero dell'array[] corrisponderà alle candele più vicine alla data corrente.

Cioè: 1. copiamo le candele nell'array array[], 2. le facciamo diventare una serie temporale, e poi leggiamo i valori da essa nella struttura.

Si può fare a meno di array[] - basta scrivere i dati direttamente dal grafico nella struttura, ma ho suggerito questo per compatibilità con Five - permette di copiare direttamente solo nell'indicatore usando high[i], low[i] e altri dati, ma nello script o Expert Advisor, dovremo prima copiare l'intervallo storico necessario nell'array, cosa che ho fatto.

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

Allarme (serie);

come questo?

Entrambi gli avvisi restituiscono ancora false

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

Allarme (serie);

come questo?

Entrambi gli avvisi restituiscono ancora false

Quindi, questo è un bug che dovrebbe essere segnalato in "Errori, bug, domande".

Ecco uno script di controllo che mostra il tempo delle candele copiate nelle celle zero e ultime dell'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:

Quindi questo è un bug che dovrebbe essere riportato in "Errori, bug, domande".

Ecco uno script di controllo che mostra il tempo delle candele copiate nelle celle zero e ultime dell'array[]:

Emette questo:

Array è serie: falso

array tempo[0]: 2016.05.12 21:00

array tempo[9]: 2016.05.12 12:00

 
Andrey Koldorkin:

Viene fuori questo:

Array è serie: falso

array tempo[0]: 2016.05.12 21:00

array tempo[9]: 2016.05.12 12:00

Ho controllato - sempre falso, ma il tempo è corretto: se all'inizio dello script seleziona Array array come serie temporale "Yes", allora:

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

Se si seleziona "No", allora:

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

i tempi delle candele scritte nell'array sono invertiti, il che significa che ArraySetAsSeriess() funziona correttamente, ma ArrayIsSeries() no, emette sempre false, cosa che ho già scritto nel thread del bug di cui sopra.

 
Andrey Koldorkin:

Oh, questa programmazione. Più avanti nel bosco....

Capite, non avete bisogno di conoscere la direzione della matrice. L'algoritmo cerca le ripetizioni. Pertanto, non si preoccupa dell'ordine in cui le barre vengono elaborate.
 
Vasiliy Sokolov:
Capite, non avete bisogno di conoscere la direzione della matrice. L'algoritmo cerca le ripetizioni. Quindi non si preoccupa dell'ordine in cui le barre vengono elaborate.
lo fa. Dopo tutto, ho bisogno di sapere quali candele hanno formato una corrispondenza e con la più vicina al prezzo corrente prendere il prezzo basso.
 
Andrey Koldorkin:
di cui hai bisogno. Perché poi ho bisogno di scoprire quali candele hanno formato una corrispondenza e prendere il prezzo Low dalla più vicina al prezzo corrente.

C'è un tempo di candela nella struttura per questo, con il quale si può trovare la candela più vicina a qualsiasi tempo necessario.

E non è necessario emettere i numeri delle candele - non coincidono con i numeri delle barre reali. Perché riempiamo l'array, e gli indici nell'array appartengono solo al numero della candela nell'array, non sul grafico.

 
Artyom Trishkin:

Ho controllato cosa produce - sempre falso, ma il tempo è corretto: se si seleziona Array array come serie temporale "Yes" quando si esegue lo script, allora:

Se si seleziona "No", allora:

I tempi delle candele scritte nell'array sono invertiti, il che significa che ArraySetAsSeriess() funziona correttamente, ma ArrayIsSeries() no, emette sempre false, cosa che ho già scritto nel thread del bug di cui sopra.

Ho modificato leggermente il codice:

ArraySetAsSeries(array,true); //qui ha appena messo true

e poi ha aggiunto numeri di candele per l'autocontrollo:

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));

Dà il seguente output:

Array è serie: falso

Candela 00 array tempo[0]: 2016.05.12 22:00

Candela 09 array tempo[9]: 2016.05.12 13:00

 
Artyom Trishkin:
Per fare questo, c'è un tempo di candela nella struttura, con il quale si può trovare la candela più vicina a qualsiasi tempo necessario.
Bene, lo stesso. si scopre che la direzione cambia con una linea di codice. non complicherà il processo. Ma mentre cerco di capire cosa sta succedendo, almeno i candelabri nella mia testa e nella macchina saranno nello stesso ordine ))
 
Andrey Koldorkin:

Ho cambiato un po' il codice:

ArraySetAsSeries(array,true); //qui ha appena messo true

e poi ha aggiunto numeri di candele per l'autocontrollo:

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));

Dà il seguente output:

Array è serie: falso

Candela 00 array tempo[0]: 2016.05.12 22:00

Candela 09 array tempo[9]: 2016.05.12 13:00

Stai usando mql4? Se è così, scoprite il numero della candela dal suo tempo, che è scritto nella struttura. iBarShift() vi aiuterà.