初学者的问题 MQL5 MT5 MetaTrader 5 - 页 578

 
Artyom Trishkin:

DataCandles是一个结构。我们写入历史上的烛台的数组是array[]。因此,我们需要将其作为一个时间序列,使其索引与图表上的烛台索引相吻合。也就是说,数组[]的零格将对应于离当前日期最近的蜡烛图。

即:1.我们把蜡烛图复制到数组array[]中,2.我们把它变成一个时间序列,然后把它的值读到结构中。

你可以不使用array[]--直接从图表中写入数据到结构中,但我建议这样做是为了与Five兼容--它只允许在指标中使用high[i]、low[i]和其他数据直接复制,但在脚本或专家顾问中,我们将不得不首先把必要的历史区间复制到数组中,我就是这样做的。

bool series=ArrayIsSeries(array)。
警报(系列)。
ArraySetAsSeries(数组,真)。
bool series=ArrayIsSeries(array)。

警报(系列)。

像这样?

这两个警报仍然返回错误

 
Andrey Koldorkin:
bool series=ArrayIsSeries(array)。
警报(系列)。
ArraySetAsSeries(array, true)。
bool series=ArrayIsSeries(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:

所以这是一个错误,应该报告给 "错误,错误,问题"。

下面是一个检查脚本,它显示了数组[]的零格和最后一格中复制的蜡烛图的时间。

输出这个。

阵列是系列: false

时间数组[0]: 2016.05.12 21:00

时间阵列[9]: 2016.05.12 12:00

 
Andrey Koldorkin:

它得出的结果是这样的。

阵列是系列: false

时间数组[0]: 2016.05.12 21:00

时间阵列[9]: 2016.05.12 12:00

我检查了一下--总是假的,但时间是正确的:如果在脚本开始时选择Array数组作为时间序列 "是",那么。

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

如果你选择 "不",那么。

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

写入数组的烛台时间是相反的,这意味着ArraySetAsSeriess() 工作正常,但ArrayIsSeries()没有,它总是输出错误,这一点我已经写在上面的bug线程中。

 
Andrey Koldorkin:

哦,这个编程。越是进入树林....

理解,你不需要知道阵列的方向。该算法正在寻找重复的内容。因此,它并不关心条形图是以什么顺序处理的。
 
Vasiliy Sokolov:
理解,你不需要知道阵列的方向。该算法正在寻找重复的内容。因此,它并不关心条形图是按什么顺序处理的。
它是这样的。毕竟,我需要知道哪些蜡烛图形成了匹配,并且与当前价格 最接近的蜡烛图采取Low价格。
 
Andrey Koldorkin:
你需要。因为接下来我需要找出哪些蜡烛图形成了匹配,并从最接近当前价格 的蜡烛图中提取低价。

在这个结构中,有一个蜡烛时间,通过它,你可以找到最接近你需要的任何时间的蜡烛。

而且你不需要输出蜡烛图的数字--它们与真实的条形图数字不一致。因为我们填充了数组,而数组中的索引只属于数组中的烛台编号,而不是图表上的。

 
Artyom Trishkin:

我检查了它给出的结果--总是假的,但时间是正确的:如果你在运行脚本时选择阵列数组作为时间序列 "是",那么。

如果你选择 "不",那么。

写入数组的蜡烛图的时间是相反的,这意味着ArraySetAsSeriess()工作正常,但ArrayIsSeries()没有,它总是输出错误,这一点我已经写到上述错误线程中。

我稍微修改了一下代码。

ArraySetAsSeries(array,true); //在这里只需输入true即可。

然后增加了烛台的数量进行自我检查。

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(arraySize(array)-1].time,TIME_DATE|TIME_MINUTES) 。

它给出了以下输出。

阵列是系列: false

蜡烛00时间阵列[0]:2016.05.12 22:00

蜡烛09时间阵列[9]:2016.05.12 13:00

 
Artyom Trishkin:
要做到这一点,在结构上有一个蜡烛时间,通过它你可以找到离你需要的任何时间最近的蜡烛。
好吧,都一样。事实证明,只要有一行代码就能改变方向。它不会使过程复杂化。但当我只是想弄清楚发生了什么时,至少我脑子里的烛台和机器里的烛台会有相同的顺序 ))
 
Andrey Koldorkin:

我对代码进行了一些修改。

ArraySetAsSeries(array,true); //在这里只需输入true即可。

然后增加了烛台的数量进行自我检查。

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(arraySize(array)-1].time,TIME_DATE|TIME_MINUTES) 。

它给出了以下输出。

阵列是系列: false

蜡烛00时间阵列[0]:2016.05.12 22:00

蜡烛09时间阵列[9]:2016.05.12 13:00

你在使用mql4吗?如果是这样,从它的时间中找出蜡烛图的编号,这写在结构中。iBarShift() 将帮助你。