Novichokkk Anzahl der Balken, die dem Indikator für die Berechnung zur Verfügung stehen, und entspricht der Anzahl der im Diagramm verfügbaren Balken.
Zum Beispiel MA5, Durchschnitt von 5 Balken, eingestellt auf die Anzeige von 100 Balken. Dann rechnet der Indikator vom 104. bis zum 100. Balken und beginnt mit dem Zeichnen der Linie beim 100sten Balken. Dann ist rates_total=5, oder 100, oder 104?
int limit = rates_total-100;if(prev_calculated <= 0)
{
// Вот тут нужно инициализировать все буферы пустыми значениямиArrayInitialize(Buffer0, EMPTY_VALUE);
ArrayInitialize(Buffer1, 0);
ArrayInitialize(Buffer2, clrNONE);
// ... и т.д.
}
else
limit = prev_calculated - 1;
//--- Экономный просчёт индикатораfor(int i = limit; i < rates_total; i++)
{
Buffer0[i] = (/*что-то там*/);
}
Die Berechnung erfolgt also anhand der letzten 100 Balken.
Im Wesentlichen sind rates_total und Bars() dass elbe , nur dassBars() eine Funktion ist, so dass ihr Aufruf mehr Ausführungszeit kostet als das Lesen des Wertes der Variablen rates_total.
Ich danke Ihnen. Das ist eine sehr ausführliche Antwort!
Du verwirrst die Neulinge wieder)
In MQL5-Indikatoren ist der Null-Balken die Vergangenheit , bis Sie die Indizierung umkehren.
Ich denke, ich habe eine erschöpfende Antwort gegeben. Ich habe zwei Indikatoren beigefügt, die sich leicht unterscheiden. Ein Neuling, der die Bedeutung gesehen hat, wird zu einem normalen Oldtimer heranwachsen, und dann wird er selbst Hinweise geben. Und wer verwirrt sein wird - nun, es bedeutet "was ist notwendig?".
Ich habe alle Puffer, ihre Indizierung, im Einsatz. Und der Null-Balken ist auf dem Chart. Im Indikator, in seinem gezeichneten Puffer (und auch in dem berechneten) kann es nur einen Null-Array-Index geben. Ich ziehe es vor, dass der Null-Balken auf dem Chart mit dem Null-Index des Indikator-Puffer-Arrays übereinstimmt - damit Anfänger nicht verwirrt werden.
Ich habe versucht, den Code zu beschreiben, ich hoffe, er ist korrekt. Vielleicht hilft es auch jemand anderem, wenn es richtig ist.
//+------------------------------------------------------------------+//| TestCalculate.mq5 |//| Copyright 2023, MetaQuotes Ltd. |//| https://www.mql5.com |//+------------------------------------------------------------------+#property copyright"Copyright 2023, MetaQuotes Ltd."#property link"https://www.mql5.com"#property version"1.00"#property indicator_chart_window//#property indicator_buffers1// Тут понятно. Задаём 1 буфер и одно отображение.#property indicator_plots1// На самом графике.//--- plot BufferClose#property indicator_label1"BufferClose"// #property indicator_type1DRAW_LINE//#property indicator_color1clrRed// Тут тоже понятно. Свойства для описания отображаемой линии.#property indicator_style1STYLE_SOLID// Название, линия, цвет, стиль, толщина. #property indicator_width11// Если бы было 2 таких #property indicator_plots 2,// то было бы 2 таких блока, на каждую линию отдельно. И бувера 2 минимум,// если не нужно промежуточных вычислений без вывода.//--- indicator buffersdouble BufferClose[]; // Объявляем динамический массив типа double ,// в который в будущем будем скидывать значения типа double,// которые и будут являться значениями, по которым будет строиться индикатор,// в данном случае линия.//+------------------------------------------------------------------+//| Custom indicator initialization function |//+------------------------------------------------------------------+intOnInit() // функция инициализации программы
{
//--- indicator buffers mappingSetIndexBuffer(0,BufferClose,INDICATOR_DATA);// соединяем индикаторный буфер с нашим объявленным массивом, // так как индикаторный буфер у нас всего 1, это буде первый,// а индексация у него будет начинаться с 0 как в массиве, далее передаём в функцию// название самого массива, из которого будем брать значения-BufferClose,// далее устанавливаем INDICATOR_DATA что говори о том что // данный буфер не для промежуточных вычислений, который не нужно выводить// на экран. А именно то, что это отображаемый буфер.ArraySetAsSeries(BufferClose,true); // Поскольку направление индексации у всех массивов и индикаторах буферов// не совпадает с направлением индексации тайм серий (а работать мы будем с ними),// то функцией ArraySetAsSeries меняем направление индексации,// передаём название нашего массива, и вторым значением // устанавливаем true, что означает что нумерация в массиве теперь будет производиться // в обратном порядке, вернее так же как и в массивах тайм серий.//---return(INIT_SUCCEEDED); // оператор return возвращает нам что инициализация прошла успешно
}
//+------------------------------------------------------------------+//| Custom indicator iteration function |//+------------------------------------------------------------------+intOnCalculate(constint rates_total, // инициализируем (вызываем) функцию обработки событий есть 2-х видов, на основе обработки массивов,constint prev_calculated, // и на основе обработки тайм серий (наш вариант). Потому в функцию передаём переченьconstdatetime &time[], // массивов тайм серий, к которым можно будет обращаться внутри функции. constdouble &open[], // Не забываем массивы в функцию передаются по ссылкам (&).constdouble &high[], // Так же передаём в функцию 2 параметра. constdouble &low[], // rates_total Размер массива price[] или входных тайм серий, доступных индикатору для расчетаconstdouble &close[], // Наш вариант для входных тайм серий, поэтому Во втором варианте функции значение параметраconstlong &tick_volume[], // соответствует количеству баров на графике, на котором он запущен.constlong &volume[], // Второй prev_calculated Содержит значение, которое вернула функция OnCalculate() на предыдущем вызове. constint &spread[]) // Предназначено для пропуска в расчетах тех баров, которые не изменились с предыдущего запуска этой функции.
{
//---ArraySetAsSeries(close,true); //ArraySetAsSeries(time,true);// // Переданные в функцию массивы отражают ценовые данные, т.е. эти массивы имеют признак тайм серии // и функция ArrayIsSeries() вернет true при проверке этих массивов. Но тем не менее,// направление индексации необходимо в любом случае проверять только функцией ArrayGetAsSeries().// Чтобы не зависеть от умолчаний, необходимо безусловно вызывать функцию// ArraySetAsSeries() для тех массивов, с которыми предполагается работать, // и установить требуемое направление индексации.// В нашем случае вызовем её для массивов close и time.string txt=""; // Объявим строковую переменную txt и присвоим ей пустое значение .int limit=rates_total-prev_calculated; // Так как пример учебный, она нам понадобится для наглядного выведения далее информации.// Так же объявим целочисленную переменную limit и присвоим ей значение rates_total-prev_calculated.// Она нам будет нужна в дальнейшем для работы в цикле, в котором мы будем проходиться циклом и // записывать полученные значения цен в созданный массив, от которого потом и будет // строиться линия индикатора.//--- Первый запуск или изменение исторических данныхif(limit>1)
{
limit=rates_total-1;
txt=StringFormat
("Первый запуск или изменение исторических данных. \nrates_total=%ld, prev_calculated=%ld, rates_total-prev_calculated=%ld, limit=%ld\nИнициализируем буфер",
rates_total,prev_calculated,rates_total-prev_calculated,limit
);
Print(txt);
ArrayInitialize(BufferClose,EMPTY_VALUE);
}
// При первом запуске, или смене исторических данных, prev_calculated=0,// так как предыдущего вызова ещё не было, это первый. // Поэтому вводим проверку if(limit>1), и если это правда, то это значит,// что обсчета ещё не было, и цикл начнём с переменной limit.// При этом последний элемент индикаторного буфера будет заполняться с индексом rates_total-1// Далее (потом в конце, когда пойдём по циклу) // в основном цикле заполнится массив именно этим размером rates_total.
//
// А пока инициализируем наш массив пустым.//--- Новый барif(limit==1)
{
txt="Новый бар, рассчитываем 2 бара - первый и нулевой";
PrintFormat("%s. %s, limit=%ld",(string)time[0],txt,limit);
}
// Это условие для того, чтобы показать изменение// переменной limit на каждом шаге.// В данном случае пришёл новый бар, то есть // rates_total увеличился на один бар, а prev_calculated стал равен прошлому rates_total,// то есть limit=rates_total-prev_calculated=1// то есть цикл будет с 1 до 0, то есть в массив пишем не все прошлые значения, // а 2 последних на 0-м и 1-м баре (поскольку массивы мы развернули это несформированный // первый бар на графике, и второй за ним) обсчет идет 2-х последних баров.//--- Текущий барif(limit==0)
{
txt=StringFormat
("Рассчитываем текущий бар. rates_total=%ld, prev_calculated=%ld, rates_total-prev_calculated=%ld, limit=%ld",
rates_total,prev_calculated,rates_total-prev_calculated,limit
);
}
Comment(txt);
// То же самое, промежуточный показ данных на следующем шаге.// Поскольку на текущем баре цена меняется, он ещё не сформирован.// То получается что он не входит в новый rates_total,// Но при этом обрабатывается, так как цена меняется.// В этом случае несформированный бар внутри бара будет иметь// limit=rates_total-prev_calculated=0, то есть rates_total=prev_calculated// то есть обсчитывается только нулевой бар.//--- Основной циклfor(int i=limit;i>=0;i--) // Это цикл, который после каждой новой обработки событий// работает с массивом, но при первом запуске заполняет его весь// Размеров в данном случае rates_total.// А при последующих обработках обсчитывает и добавляет в него только // 2 последних бара.
{
BufferClose[i]=close[i];
}
//--- return value of prev_calculated for next callreturn(rates_total); // В конце программы обработчику событий нужно вернуть
// значение rates_total, чтобы при следующей обработке
// обсчёт вёлся с учётом этой информации. Атак как при первой обработке
// значение prev_calculated равно 0, то при следующем обращении
// prev_calculated будет равно этому возвращённому значению.
}
//+------------------------------------------------------------------+// Примечание. rates_total Размер массива price[] или входных тайм серий, // доступных индикатору для расчета. При том если прокрутить историю графика глубоко назад, // то история подгружается, но при этом это не первый запуск индикатора.// Получается что rates_total увеличивается при этом prev_calculated сбрасывается на 0,// как при первом запуске.
Ich mag den Rollover der Pufferindizierung wirklich nicht. Deshalb habe ich beschlossen, eine alternative Variante des Indikators zu zeigen
//+------------------------------------------------------------------+//| TestCalculate.mq5 |//| Copyright 2023, MetaQuotes Ltd. |//| https://www.mql5.com |//+------------------------------------------------------------------+#property copyright"Copyright 2023, MetaQuotes Ltd."#property link"https://www.mql5.com"#property version"1.00"#property indicator_chart_window#property indicator_buffers1#property indicator_plots1//--- plot BufferClose#property indicator_label1"BufferClose"#property indicator_type1DRAW_LINE#property indicator_color1clrDarkOrchid#property indicator_style1STYLE_SOLID#property indicator_width12//--- indicator buffersdouble BufferClose[];
//+------------------------------------------------------------------+//| Custom indicator initialization function |//+------------------------------------------------------------------+intOnInit()
{
//--- indicator buffers mappingSetIndexBuffer(0,BufferClose); //,INDICATOR_DATA); INDICATOR_DATA — по умолчанию. Поэтому это можно не писать.//---return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+//| Custom indicator iteration function |//+------------------------------------------------------------------+intOnCalculate(constint rates_total,
constint prev_calculated,
constdatetime &time[],
constdouble &open[],
constdouble &high[],
constdouble &low[],
constdouble &close[],
constlong &tick_volume[],
constlong &volume[],
constint &spread[])
{
//---string txt="";
int limit=rates_total-prev_calculated;
//--- Первый запуск или изменение исторических данныхif(limit>1)
{
limit=rates_total-1;
txt=StringFormat
("Первый запуск или изменение исторических данных. \nrates_total=%ld, prev_calculated=%ld, rates_total-prev_calculated=%ld, limit=%ld\nИнициализируем буфер",
rates_total,prev_calculated,rates_total-prev_calculated,limit
);
Print(txt);
//--- Заполнять индикаторный буфер пустыми значениями желательно, но не обязательно если индикатор не DRAW_ARROW или DRAW_COLOR_ARROW.ArrayInitialize(BufferClose,EMPTY_VALUE);
//--- Обнулять исключительно когда prev_calculated == 0 или как в этом случае rates_total-prev_calculated > 1
}
//--- Новый барif(limit==1)
{
txt="Новый бар, рассчитываем 2 бара - первый и нулевой";
PrintFormat("%s. %s, limit=%ld",(string)time[0],txt,limit);
}
//--- Текущий барif(limit==0)
{
txt=StringFormat
("Рассчитываем текущий бар. rates_total=%ld, prev_calculated=%ld, rates_total-prev_calculated=%ld, limit=%ld",
rates_total,prev_calculated,rates_total-prev_calculated,limit
);
}
Comment(txt);
//--- ВСЁ ОТ СТРОКИ №44 И ВКЛЮЧАЯ ЭТУ СТРОКУ НОСИТ ИСКЛЮЧИТЕЛЬНО ИНФОРМАЦИОННЫЙ ХАРАКТЕР И В РАБОЧЕМ ИНДИКАТОРЕ СОВЕРШЕННО НЕОБЯЗАТЕЛЬНО.//---if(prev_calculated > 0 && rates_total-prev_calculated > 1)
return0; // Если во время работы индикатора подгрузились новые бары, запустим пересчёт индикатора с нуля…//--- Основной цикл//--- Пересчитаем индикатор или от начала истории (от нулевого бара) или только последний барint i=fmax(0, prev_calculated-1);
while(i < rates_total && !IsStopped())
{
BufferClose[i]=close[i];
i++;
}
//--- return value of prev_calculated for next callreturn(rates_total);
}
//+------------------------------------------------------------------+
Artyom, manchmal wird jeder müde und macht Fehler. Betrachten Sie es nicht als Kritik, aber rates_total - Bars() wird immer Null sein...
Im Allgemeinen ist es sehr schwierig, dieses Zeichen zu erklären. Ein Opfer der USE...
rates_total istBars() in dem Satz. Das heißt,rates_total ist Bars().
In dem folgenden Code
Er hat Recht.
Ich habe die USE nicht genommen. Sie existierte damals nicht.Zum Beispiel MA5, Durchschnitt von 5 Balken, eingestellt auf die Anzeige von 100 Balken. Dann rechnet der Indikator vom 104. bis zum 100. Balken und beginnt mit dem Zeichnen der Linie beim 100sten Balken. Dann ist rates_total=5, oder 100, oder 104?
Die Berechnung erfolgt also anhand der letzten 100 Balken.
Im Wesentlichen sind rates_total und Bars() dass elbe , nur dassBars() eine Funktion ist, so dass ihr Aufruf mehr Ausführungszeit kostet als das Lesen des Wertes der Variablen rates_total.
Vielen Dank, das ist sehr klar.
Was habe ich Ihrer Meinung nach falsch geschrieben? Begründen Sie es bitte.
Was ist die Grenze und woher kommt die Schleife in meinem und Ihrem Beispiel.
Nun, dann sollte Buffer0 wie in der Zeitreihe ArraySetAsSeries(Buffer0,true) indiziert werden ; ansonsten ist das Beispiel nicht klar.
Im Allgemeinen ist es so. Ich denke, dass es nicht sehr korrekt ist, Indikatoren von der Nulllinie bis zur Vergangenheit zu berechnen.
Ich berechne sie immer von der Vergangenheit bis zur Gegenwart. Ziehen wir hier eine Linie auf Close:
Angabe der Anzahl der zu zählenden Takte:
Angabe der Anzahl der zu zählenden Takte:
Ich danke Ihnen. Das ist eine sehr ausführliche Antwort!
Es geht so. Ich denke, dass es nicht sehr korrekt ist, Indikatoren vom Null-Balken aus in der Zeit zurück zu berechnen.
Sie verwirren Anfänger wieder)
In MQL5-Indikatoren ist der Null-Balken die Vergangenheit , bis Sie die Indexierung umkehren.
P.S. Artem hat wieder Recht. Ich habe den falschen Begriff verwendet, statt "Nullbar" hätte ich "Nullindex" schreiben müssen.
Ich danke Ihnen. Das ist eine sehr ausführliche Antwort!
Du verwirrst die Neulinge wieder)
In MQL5-Indikatoren ist der Null-Balken die Vergangenheit , bis Sie die Indizierung umkehren.
Ich denke, ich habe eine erschöpfende Antwort gegeben. Ich habe zwei Indikatoren beigefügt, die sich leicht unterscheiden. Ein Neuling, der die Bedeutung gesehen hat, wird zu einem normalen Oldtimer heranwachsen, und dann wird er selbst Hinweise geben. Und wer verwirrt sein wird - nun, es bedeutet "was ist notwendig?".
Ich habe alle Puffer, ihre Indizierung, im Einsatz. Und der Null-Balken ist auf dem Chart. Im Indikator, in seinem gezeichneten Puffer (und auch in dem berechneten) kann es nur einen Null-Array-Index geben. Ich ziehe es vor, dass der Null-Balken auf dem Chart mit dem Null-Index des Indikator-Puffer-Arrays übereinstimmt - damit Anfänger nicht verwirrt werden.
Ich habe versucht, den Code zu beschreiben, ich hoffe, er ist korrekt. Vielleicht hilft es auch jemand anderem, wenn es richtig ist.
Ich mag den Rollover der Pufferindizierung wirklich nicht. Deshalb habe ich beschlossen, eine alternative Variante des Indikators zu zeigen