//+------------------------------------------------------------------+//| 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_inputsenum enumYN
{
enYes=1, // Да
enNo=0, // Нет
};
//--- input parametersinputint Search_Period=10; // Количество копируемых свечейint searchPeriod=(Search_Period<1)?1:Search_Period;
inputint Delta=2; // Количество пунктов допускаint delta=(Delta<0)?0:Delta;
input enumYN AsSeries=enYes; // Массив array как таймсерияMqlRates array[]; // Массив структур для копирования Open, High, Low, Close, Timestruct DataCandle // Структура для хранения всех совпадений
{
int number_matched; // Количество совпаденийMqlRates reference_candle; // Данные эталонной свечиMqlRates matched_candles[]; // Массив свечей, совпадающих с эталонной по нужному критерию
};
DataCandle dataCandle[]; // Массив структур данных свечей и их совпадений//+------------------------------------------------------------------+//| Script program start function |//+------------------------------------------------------------------+voidOnStart()
{
//---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 для вывода в журнал//--- поиск совпадений с эталонной свечой, индексируемой индексом основного цикла iint size=0; // размер массива совпадающих свечейArrayResize(dataCandle[i].matched_candles,size); // Размер массива совпадений в ноль
dataCandle[i].number_matched=size; // Инициализируем количество совпадений нулём//--- теперь ищем совпадения по high свечей в цикле j с high эталонной свечи с индексом ifor(int j=0; j<copy_bars; j++) { // в цикле от i+1 до copy_barsif(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);
}
}
//+------------------------------------------------------------------+
"/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) 。
"/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) 。
DataCandles是一个结构。我们写入历史上的烛台的数组是array[]。因此,我们需要将其作为一个时间序列,使其索引与图表上的烛台索引相吻合。也就是说,数组[]的零格将对应于离当前日期最近的蜡烛图。
即:1.我们把蜡烛图复制到数组array[]中,2.我们把它变成一个时间序列,然后把它的值读到结构中。
你可以不使用array[]--直接从图表中写入数据到结构中,但我建议这样做是为了与Five兼容--它只允许在指标中使用high[i]、low[i]和其他数据直接复制,但在脚本或专家顾问中,我们将不得不首先把必要的历史区间复制到数组中,我就是这样做的。
警报(系列)。
像这样?
这两个警报仍然返回错误
警报(系列)。
像这样?
这两个警报仍然返回错误
因此,这是一个错误,应该报告给 "错误、漏洞、问题"。
下面是一个检查脚本,它显示了数组[]的零格和最后一格中复制的蜡烛图的时间。
所以这是一个错误,应该报告给 "错误,错误,问题"。
下面是一个检查脚本,它显示了数组[]的零格和最后一格中复制的蜡烛图的时间。
输出这个。
阵列是系列: false
时间数组[0]: 2016.05.12 21:00
时间阵列[9]: 2016.05.12 12:00
它得出的结果是这样的。
阵列是系列: false
时间数组[0]: 2016.05.12 21:00
时间阵列[9]: 2016.05.12 12:00
我检查了一下--总是假的,但时间是正确的:如果在脚本开始时选择Array数组作为时间序列 "是",那么。
如果你选择 "不",那么。
写入数组的烛台时间是相反的,这意味着ArraySetAsSeriess() 工作正常,但ArrayIsSeries()没有,它总是输出错误,这一点我已经写在上面的bug线程中。
哦,这个编程。越是进入树林....
理解,你不需要知道阵列的方向。该算法正在寻找重复的内容。因此,它并不关心条形图是按什么顺序处理的。
你需要。因为接下来我需要找出哪些蜡烛图形成了匹配,并从最接近当前价格 的蜡烛图中提取低价。
在这个结构中,有一个蜡烛时间,通过它,你可以找到最接近你需要的任何时间的蜡烛。
而且你不需要输出蜡烛图的数字--它们与真实的条形图数字不一致。因为我们填充了数组,而数组中的索引只属于数组中的烛台编号,而不是图表上的。
我检查了它给出的结果--总是假的,但时间是正确的:如果你在运行脚本时选择阵列数组作为时间序列 "是",那么。
如果你选择 "不",那么。
写入数组的蜡烛图的时间是相反的,这意味着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
要做到这一点,在结构上有一个蜡烛时间,通过它你可以找到离你需要的任何时间最近的蜡烛。
我对代码进行了一些修改。
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