АвторСообщение





Сообщение: 54
Зарегистрирован: 30.05.13
Репутация: 0
ссылка на сообщение  Отправлено: 08.03.18 15:54. Заголовок: MQL4 Zig-Zag не делается мультитаймфреймным


Я позаимствовал у Игоря Зиг-зага из статьи, которая называлась как-то так... "Идеальный зиг-заг". Привёл в читабельный вид.
И хотел было сделать ещё некоторые вещи с ним, как заметил, что у меня не получается сделать этот зиг-заг МТФ.
Версия Зиг-зага, которая коректно отображает экстремумы называется ZigZagHighLow.mq4. Версия МТФ Зиг-зага называется ZZ.mq4, Коды прилагаю в сообщению. У второго индикатора имеются вводные параметры: Символ и Таймфрейм. Кроме как замены 3 функции я больше ничего не менял. По сути, должно было, как я понимаю, получить то, что мне нужно. Но не получилось.. В индикаторе ZZ.mq4 используется библиотека-прокладка GetTimeSeriesData.mq4. Она удобно для получения данных из таймсерий. В индикаторе ZZ.mq4 я заменил лишь данные таймсерий т.е. High[index] и High[index + 1], Low[index], Low[index + 1] и Bars, на соответственно методы сегодня написанной библиотеки, которую я проверил уже: getBarHighPrice(index, i_tf, i_instrument), getBarLowPrice(index, i_tf, i_instrument) и getTotalHistoryBars(i_tf, i_instrument). Так вот Зиг-заг рисуется какой-то левый. У меня такое ощущение, что он экстремумы рисует со сдвигом. Но почему вопрос. Ведь я получил количество баров с оответствующего таймфрейма, а так же цены максимальные и минимальные беру тоже с того же таймфрейма. Что не так?
Ссылка на имеющийся код

Спасибо: 0 
ПрофильЦитата Ответить
Ответов - 22 , стр: 1 2 All [только новые]







Сообщение: 55
Зарегистрирован: 30.05.13
Репутация: 0
ссылка на сообщение  Отправлено: 08.03.18 23:33. Заголовок: Я понял, что суть ка..


Я понял, что суть касяка кроется в том, что я произвожу анализ на другом ТФ, а рисовать пытают на индексах другого ТФ, а не открытого графика. Но полностью как-то не улаживается в голове всё. Вот 2 функции я уже поправил:

//+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Сравнение последнего максимума с новым максимумом |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
void checkHigh(int index) {
// найдём индекс бара с непустым значением (экстремумом)
int lastNEVIndex = getLastNoEmptyValueIndex(index);

if (lastNEVIndex == getTotalHistoryBars(i_tf)) {
// ZZBuf[index] = getBarHighPrice(index, i_tf);
datetime barOpenTime = getBarOpenTime(index, i_tf); // Время открытия бара на заданном в инпутпараметрах ТФ
int barShift = getBarShift(barOpenTime, 0); // Смещение бара на открытом ТФ
ZZBuf[barShift] = getBarHighPrice(barShift, 0);
return;
}
if (getBarHighPrice(index, i_tf) > ZZBuf[lastNEVIndex]) {
ZZBuf[lastNEVIndex] = EMPTY_VALUE;
// ZZBuf[index] = getBarHighPrice(index, i_tf);
datetime barOpenTime = getBarOpenTime(index, i_tf); // Время открытия бара на заданном в инпутпараметрах ТФ
int barShift = getBarShift(barOpenTime, 0); // Смещение бара на открытом ТФ
ZZBuf[barShift] = getBarHighPrice(barShift, 0);
}
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Сравнение последнего минимума с новым минимумом |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
void checkLow(int index) {
// найдём индекс бара с непустым значением (экстремумом)
int lastNEVIndex = getLastNoEmptyValueIndex(index);

if (lastNEVIndex == getTotalHistoryBars(i_tf)) {
// ZZBuf[index] = getBarLowPrice(index, i_tf);
datetime barOpenTime = getBarOpenTime(index, i_tf); // Время открытия бара на заданном в инпутпараметрах ТФ
int barShift = getBarShift(barOpenTime, 0); // Смещение бара на открытом ТФ
ZZBuf[barShift] = getBarLowPrice(barShift, 0);
return;
}
if (getBarLowPrice(index, i_tf) < ZZBuf[lastNEVIndex]) {
ZZBuf[lastNEVIndex] = EMPTY_VALUE;
// ZZBuf[index] = getBarLowPrice(index, i_tf);
datetime barOpenTime = getBarOpenTime(index, i_tf); // Время открытия бара на заданном в инпутпараметрах ТФ
int barShift = getBarShift(barOpenTime, 0); // Смещение бара на открытом ТФ
ZZBuf[barShift] = getBarLowPrice(barShift, 0);
}
}

Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 2585
Зарегистрирован: 03.03.13
Откуда: Украина, Каменское (Днепродзержинск)
Репутация: 3
ссылка на сообщение  Отправлено: 09.03.18 23:26. Заголовок: Написание MTF-индика..


Написание MTF-индикаторов - это довольно непростое дело. В обычной жизни можно сравнить с пространственным мышлением. Ведь мозг человека больше привык мыслить двумерно. Тех, кто умеет мыслить трехмерно, не так уж и много (стереометрия мало, кому дается). Поэтому, если программирование еще только осваиваете, то не беритесь за такую сложную задачу.

Если же готовы к трудностям, то велкам. Самая главная задача при написании MTF-индикаторов - понять, что нумерация баров на текущем ТФ и на "другом" ТФ - разная. В приведенном коде в этом направлении нет ни одного шага. Нумерации всех баров - от текущего ТФ. Для перевода индексов баров одного ТФ в другой обычно используют функцию iBarShift (тоже нет в коде). Ну и не забывайте, что индикаторные буферы относятся к текущему ТФ. А потому для отображения данных другого ТФ придется сильно попотеть.

Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 56
Зарегистрирован: 30.05.13
Репутация: 0
ссылка на сообщение  Отправлено: 10.03.18 13:17. Заголовок: Scriptong пишет: Дл..


Scriptong пишет:

 цитата:
Для перевода индексов баров одного ТФ в другой обычно используют функцию iBarShift (тоже нет в коде)


Уже не начинаю. Опыт есть. Просто я залез дальше и вот в таких сложных делах опыта не много. Чутка подвис. Думаю ещё. Индикатор Ваш, поэтому вы как никто другой понимаете как он устроен.
В прилагаемом коде должно быть. Я это уже всё учёл. Я же прикрепил ссылку на бибилотеку, там это всё учтено. Вот выложу сюда на свякий случай, чутка переписанный более оптимально:

//+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Возвращает индекс бара на открытом графика соответствующий времени открытия бара на ТФ i_tf |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
int getLocalBarShift(int index) {
datetime barOpenTime = getBarOpenTime(index, i_tf); // Время открытия бара на заданном в инпутпараметрах ТФ
return getBarShift(barOpenTime, 0); // Смещение бара на открытом ТФ
}

Функции getBarOpenTime и getBarShift берутся из библиотеки. Вот их код:
// 1.2 Возвращает индекс бара относящегося к определённому времени. =======================================================================
int getBarShift(datetime time, ENUM_TIMEFRAMES timeframe = PERIOD_CURRENT, bool exact = false) export {
return iBarShift(NULL, timeframe, time, exact);
}
// 1.7 Возвращает значение времени открытия бара, находящегося на shift баров от текущего бара в историю. =================================
datetime getBarOpenTime(int shift, ENUM_TIMEFRAMES timeframe = PERIOD_CURRENT) export {
return iTime(NULL, timeframe, shift);
}
Поиск последнего максимума получился такой:
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Сравнение последнего максимума с новым максимумом |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
void checkHigh(int index) {
// найдём индекс бара с непустым значением (экстремумом)
int lastNEVIndex = getLastNoEmptyValueIndex(index);
int barShift = getLocalBarShift(index); // Смещение бара на открытом ТФ

if (lastNEVIndex == getTotalHistoryBars(i_tf)) {
// ZZBuf[index] = getBarHighPrice(index, i_tf);
ZZBuf[barShift] = getBarHighPrice(index, i_tf);
return;
}
if (getBarHighPrice(index, i_tf) > ZZBuf[lastNEVIndex]) {
ZZBuf[lastNEVIndex] = EMPTY_VALUE;
// ZZBuf[index] = getBarHighPrice(index, i_tf);
ZZBuf[barShift] = getBarHighPrice(index, i_tf);
}
}

Вот код весь, кстати

Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 2586
Зарегистрирован: 03.03.13
Откуда: Украина, Каменское (Днепродзержинск)
Репутация: 3
ссылка на сообщение  Отправлено: 10.03.18 18:03. Заголовок: hoz пишет: Просто я..


hoz пишет:

 цитата:
Просто я залез дальше и вот в таких сложных делах опыта не много. Чутка подвис. Думаю ещё. Индикатор Ваш, поэтому вы как никто другой понимаете как он устроен.
В прилагаемом коде должно быть. Я это уже всё учёл. Я же прикрепил ссылку на бибилотеку, там это всё учтено. Вот выложу сюда на свякий случай, чутка переписанный более оптимально:


То, что использована функция iBarShift, еще ничего не дает. Ведь дело не только в ней, а в самом устройстве кода. MTF-индикатор отличается от обычного индикатора намного больше, чем самолет от кареты. Нельзя делать MTF-индикатор на основе обычного индикатора. Получится уродливая конструкция, зачастую неработающая. Для MTF-индикатора нужно строить новую архитектуру.
В приведенном коде бросаются в глаза следующие ошибки:
  • Нельзя использовать функцию GetRecalcIndex в том виде, в котором она есть. Ведь снова считаем бары текущего ТФ, а нужно - заданного.
  • В функцию ZigZag передается индекс бара текущего ТФ, а нужно - заданного.

    Я бы решил эту задачу вот так.

  • Спасибо: 1 
    ПрофильЦитата Ответить





    Сообщение: 57
    Зарегистрирован: 30.05.13
    Репутация: 0
    ссылка на сообщение  Отправлено: 21.03.18 02:51. Заголовок: Я понимаю, что вопро..


    Я понимаю, что вопрос видимо примитивный и мне за него уже где-то даже стыдно, но, тем не менее. Прямо в методе OnCalculate пишу:
    static bool b = false;
    if (!b) {
    for (int i = 0; i < 150; i++) {
    Print("g_ZZBuf[ i ] = ", g_ZZBuf[ i ]);
    b = true;
    }
    }
    Индикатор то рисует зиг-заг верно, а вот принтует у меня таким образом всегда 2147483647. Как такое вообще выходит? Ведь я вижу, что у нас там присваивается этому буферу значени цены на заданном баре, а не 2147483647, коорое означает EMPTY_VALUE

    Спасибо: 0 
    ПрофильЦитата Ответить





    Сообщение: 2591
    Зарегистрирован: 03.03.13
    Откуда: Украина, Каменское (Днепродзержинск)
    Репутация: 3
    ссылка на сообщение  Отправлено: 21.03.18 17:30. Заголовок: hoz пишет: Прямо в ..


    hoz пишет:

     цитата:
    Прямо в методе OnCalculate пишу:


    Без полного кода я вряд ли смогу угадать причину. Ведь сразу встает вопрос о том, в каком именно месте OnCalculate все это выводится?

    P. S. При написании кода на этом форума, чтобы не пропадал в коде индекс i, копируйте последовательность символов [, i, ] с пробелом внутри. Иначе форум воспринимает это за BB-код и не отображает символы.

    Спасибо: 0 
    ПрофильЦитата Ответить





    Сообщение: 58
    Зарегистрирован: 30.05.13
    Репутация: 0
    ссылка на сообщение  Отправлено: 21.03.18 23:15. Заголовок: Scriptong пишет: Бе..


    Scriptong пишет:

     цитата:
    Без полного кода я вряд ли смогу угадать причину. Ведь сразу встает вопрос о том, в каком именно месте OnCalculate все это выводится?


    Полный Вот весь исходный код. Кстати, я там под себя чутка переназвал и добавил буфер времени. Вроде как правильно. Вот его планирую прикрутить и дальше пилить индюк. Много ещё чего нужно сделать. Это ещё только начало. Как допилю обязательно Вам покажу, есс-но как увиижу, что есть подвижки в плане мат. ожидания.
    Scriptong пишет:

     цитата:

    P. S. При написании кода на этом форума, чтобы не пропадал в коде индекс i, копируйте последовательность символов [, i, ] с пробелом внутри. Иначе форум воспринимает это за BB-код и не отображает символы.


    Это я понял уже. Учту.

    Спасибо: 0 
    ПрофильЦитата Ответить





    Сообщение: 2592
    Зарегистрирован: 03.03.13
    Откуда: Украина, Каменское (Днепродзержинск)
    Репутация: 3
    ссылка на сообщение  Отправлено: 22.03.18 10:33. Заголовок: hoz пишет: Полный В..


    hoz пишет:

     цитата:
    Полный Вот весь исходный код.


    В этом коде видно, что значения индикаторного буфера распечатываются до момента расчета. Поэтому там пусто (EMPTY_VALUE). Такое значение устанавливается в индикаторных буфера МТ4 по умолчанию.


    Спасибо: 1 
    ПрофильЦитата Ответить





    Сообщение: 59
    Зарегистрирован: 30.05.13
    Репутация: 0
    ссылка на сообщение  Отправлено: 22.03.18 17:03. Заголовок: Scriptong пишет: В ..


    Scriptong пишет:

     цитата:
    В этом коде видно, что значения индикаторного буфера распечатываются до момента расчета. Поэтому там пусто (EMPTY_VALUE). Такое значение устанавливается в индикаторных буфера МТ4 по умолчанию.


    Действительно, простая задача, а я продолбался ((
    Я, кстати, добавил там буфер времени, но время не показывается. Какая-то причина в этом есть? Вот последний актуальный код.

    Ещё я заметил, что у вас не используется метод ArraySetAsSeries. Он замеляет выполнение кода? Я к тому, что удобнее, в принципе, при работе с массивами таймсерий работать как с таймсериями. Не критично, но всё-таки. Вот и возник такой вопрос..

    И ещё один момент. Метод GetExtremumOnCurrentTF странный. Он же ищет индекс экстремума от текущего до предыдущего бара. Вот мне интересно зачем это вообще нужно? Ведь в прошлой версии зиг-зага, который работал на одном ТФ был метод getLastNoEmptyValueIndex, который искал последний экстремум. Он более очевиден.

    Спасибо: 0 
    ПрофильЦитата Ответить





    Сообщение: 2593
    Зарегистрирован: 03.03.13
    Откуда: Украина, Каменское (Днепродзержинск)
    Репутация: 3
    ссылка на сообщение  Отправлено: 27.03.18 20:22. Заголовок: hoz пишет: Я, кстат..


    hoz пишет:

     цитата:
    Я, кстати, добавил там буфер времени, но время не показывается. Какая-то причина в этом есть?


    Причин сразу четыре:
  • В индикаторе разрешено отображение только одного буфера (#property indicator_buffers 1)
  • Нет настроек для отображения второго буфера
  • Сам буфер объявлен как неотображаемый (DRAW_NONE)
  • Непонятно, как возможно отображать время на шкале цены

    hoz пишет:

     цитата:
    Ещё я заметил, что у вас не используется метод ArraySetAsSeries


    В MQL4 эта функция при работе с таймсериями не требуется. Это же не MQL5, в котором таймсерии развернуты по умолчанию.

    hoz пишет:

     цитата:
    И ещё один момент. Метод GetExtremumOnCurrentTF странный. Он же ищет индекс экстремума от текущего до предыдущего бара.


    В заголовке функции описано, что она делает. Описание соответствует коду функции. Поэтому Ваше описание задачи, которую решает функция, некорректно.

  • Спасибо: 0 
    ПрофильЦитата Ответить





    Сообщение: 60
    Зарегистрирован: 30.05.13
    Репутация: 0
    ссылка на сообщение  Отправлено: 28.03.18 16:06. Заголовок: Scriptong пишет: В..


    Scriptong пишет:

     цитата:

    В индикаторе разрешено отображение только одного буфера (#property indicator_buffers 1)


    Ну так всё верно. Мне и не нужно отображать второй буфер т.е. буфер времени. Он нужен будет лишь для программирования отображения 1-го буфера.
    Я строку
    #property indicator_buffers 1 // используется 1 буфер индикатора
    оставил как есть.
    Добавил лишь в метод инициализации OnInit() поле:
    IndicatorBuffers(2);
    И всё заработало.

    Scriptong пишет:

     цитата:

    Нет настроек для отображения второго буфера


    А зачем отображать время? Что нам это даст? Ведь время это не то, что нужно выводить в кривую.

    Scriptong пишет:

     цитата:

    Сам буфер объявлен как неотображаемый (DRAW_NONE)


    Да, ведь он и не должен оображатся. Я даже не представляю, прямо сейчас, к чему это могло бы быть нужно.

    Scriptong пишет:

     цитата:

    Непонятно, как возможно отображать время на шкале цены


    Мне тоже. Но я же и не задавал.

    Спасибо: 0 
    ПрофильЦитата Ответить





    Сообщение: 2594
    Зарегистрирован: 03.03.13
    Откуда: Украина, Каменское (Днепродзержинск)
    Репутация: 3
    ссылка на сообщение  Отправлено: 02.04.18 21:04. Заголовок: hoz пишет: Ну так в..


    hoz пишет:

     цитата:
    Ну так всё верно. Мне и не нужно отображать второй буфер т.е. буфер времени.


    Вы задали вопрос:

     цитата:
    Я, кстати, добавил там буфер времени, но время не показывается.



    Я резонно ответил, что не понимаю, зачем отображать время на шкале цены. Теперь Вы говорите то же самое. Так в чем же тогда заключался вопрос?

    Спасибо: 0 
    ПрофильЦитата Ответить





    Сообщение: 63
    Зарегистрирован: 30.05.13
    Репутация: 0
    ссылка на сообщение  Отправлено: 04.04.18 11:42. Заголовок: Scriptong пишет: Я ..


    Scriptong пишет:

     цитата:
    Я резонно ответил, что не понимаю, зачем отображать время на шкале цены. Теперь Вы говорите то же самое. Так в чем же тогда заключался вопрос?


    Я не верно выразился. Время не принтовалось. Но вопрос уже решил сам, поэтому последнее сообщение удалил)) А вот то, что индикатор торомзит, это уже вопрос..

    Спасибо: 0 
    ПрофильЦитата Ответить





    Сообщение: 2595
    Зарегистрирован: 03.03.13
    Откуда: Украина, Каменское (Днепродзержинск)
    Репутация: 3
    ссылка на сообщение  Отправлено: 04.04.18 15:06. Заголовок: hoz пишет: А вот то..


    hoz пишет:

     цитата:
    А вот то, что индикатор торомзит, это уже вопрос..


    У меня не просто тормозит, а намертво виснет.
    Причина в том, что Вами была изменена логика функции ProcessBar: вынесено определение текущего тренда из блока, отрабатывающего общее отсутствие тренда, в общий блок. В итоге индикатор пропускал все свечи, на которых невозможно было определить новый тренд. Непонятно, зачем это делать, если тренд уже известен. Другое дело, когда тренд неизвестен.
    Было:

     цитата:
    ENUM_TREND_DIR eNewTrend = getTrend(barIndex);
    if (eNewTrend == TREND_DIR_NONE) continue;
    // Тренд еще не был определен
    if (stZZProperty.trend == TREND_DIR_NONE) {
    stZZProperty.setData(eNewTrend, barIndex, (eNewTrend == TREND_DIR_UPWARD)? iHigh(NULL, i_TF, barIndex) : iLow(NULL, i_TF, barIndex), iTime(NULL, i_TF, barIndex));
    showOrDeleteExtremum(stZZProperty, stZZProperty.price);
    continue;
    }



    Нужно:

     цитата:
    // Тренд еще не был определен
    if (stZZProperty.trend == TREND_DIR_NONE) {
    ENUM_TREND_DIR eNewTrend = getTrend(barIndex);
    if (eNewTrend == TREND_DIR_NONE) continue;

    stZZProperty.setData(eNewTrend, barIndex, (eNewTrend == TREND_DIR_UPWARD)? iHigh(NULL, i_TF, barIndex) : iLow(NULL, i_TF, barIndex), iTime(NULL, i_TF, barIndex));
    showOrDeleteExtremum(stZZProperty, stZZProperty.price);
    continue;
    }



    Спасибо: 0 
    ПрофильЦитата Ответить





    Сообщение: 62
    Зарегистрирован: 30.05.13
    Репутация: 0
    ссылка на сообщение  Отправлено: 04.04.18 11:40. Заголовок: Я перенёс цикл из фу..


    Я перенёс цикл из функции ZigZag в функцию processBar т.к. иначе не придумал как реализовать присвоение значений таймсерии буфера времени образования экстремумов. Из-за этой причины видимо у меня сейчас подтормаживает индикатор при первоначальной загрузке графика, смене таймфрейма и тд. Потом всё работает нормально. Как можно понять в чём причина торможения?
    Вот исходник

    Спасибо: 0 
    ПрофильЦитата Ответить





    Сообщение: 2596
    Зарегистрирован: 03.03.13
    Откуда: Украина, Каменское (Днепродзержинск)
    Репутация: 3
    ссылка на сообщение  Отправлено: 04.04.18 15:11. Заголовок: hoz пишет: Я перенё..


    hoz пишет:

     цитата:
    Я перенёс цикл из функции ZigZag в функцию processBar


    Не понимаю, что от этого изменилось? Разве что можно поговорить о разной производительности. Возможно, Ваш способ чуток быстрее. Но он хуже читается.

    Наличие буфера g_ZZTimeBuf для меня как было, так и остается загадкой. В индикаторе он не используется. Даже если допустить, что он нужен для чтения данных индикатора из советника или другого индикатора, то все равно получаем масло масленое: запрашиваем значение, записанное в ячейке под индексом barIndex, в которой записано время открытия этого бара. Спрашивается: зачем для этого индикатор, если можно было напрямую взять время открытия бара, если его индекс нам известен?

    Спасибо: 0 
    ПрофильЦитата Ответить





    Сообщение: 64
    Зарегистрирован: 30.05.13
    Репутация: 0
    ссылка на сообщение  Отправлено: 04.04.18 16:05. Заголовок: Scriptong пишет: На..


    Scriptong пишет:

     цитата:
    Наличие буфера g_ZZTimeBuf для меня как было, так и остается загадкой. В индикаторе он не используется. Даже если допустить, что он нужен для чтения данных индикатора из советника или другого индикатора, то все равно получаем масло масленое: запрашиваем значение, записанное в ячейке под индексом barIndex, в которой записано время открытия этого бара. Спрашивается: зачем для этого индикатор, если можно было напрямую взять время открытия бара, если его индекс нам известен?


    Да, изначально думал передавать его в совок. Но теперь думаю, что это лишнее видимо. Получается по циклу пробегаем по барам, которые нам интересные. В цикле, соответственно, вызываем в iCustom наш зиг-заг и там же мы передаёт индексы бара, на котором ищем экстремум, соответственно, если iCustom вернёт не пустое значение, значим экстремум есть, а значит и время можно получить у этого бара (экстремума) и др. нужные данные. Я прав? Получается, я буфер лишним добавил.
    Scriptong пишет:

     цитата:
    Не понимаю, что от этого изменилось? Разве что можно поговорить о разной производительности. Возможно, Ваш способ чуток быстрее. Но он хуже читается.


    Изменилось, то, что, если бы пришлось оставить буфер времени, иначе не получилось у меня переделать индикатор так, что бы время всё-таки сохранялось. Это видно в методе processBar. Там есть блок:
    if (stZZProperty.trend == TREND_DIR_NONE) {
    ENUM_TREND_DIR eNewTrend = getTrend(barIndex);
    if (eNewTrend == TREND_DIR_NONE)
    return;

    stZZProperty.setData(eNewTrend, barIndex, (eNewTrend == TREND_DIR_UPWARD)? iHigh(NULL, i_TF, barIndex) : iLow(NULL, i_TF, barIndex), iTime(NULL, i_TF, barIndex));
    showOrDeleteExtremum(stZZProperty, stZZProperty.price);
    return;
    У меня такое ощущение, что мой вариант медленнее. Нужно будет замерить скорость. Если это так, то верну как и было.

    Спасибо: 0 
    ПрофильЦитата Ответить





    Сообщение: 2597
    Зарегистрирован: 03.03.13
    Откуда: Украина, Каменское (Днепродзержинск)
    Репутация: 3
    ссылка на сообщение  Отправлено: 05.04.18 09:45. Заголовок: hoz пишет: Да, изна..


    hoz пишет:

     цитата:
    Да, изначально думал передавать его в совок. Но теперь думаю, что это лишнее видимо. Получается по циклу пробегаем по барам, которые нам интересные. В цикле, соответственно, вызываем в iCustom наш зиг-заг и там же мы передаёт индексы бара, на котором ищем экстремум, соответственно, если iCustom вернёт не пустое значение, значим экстремум есть, а значит и время можно получить у этого бара (экстремума) и др. нужные данные. Я прав? Получается, я буфер лишним добавил.


    Да. Я именно об этом. Если известен индекс бара экстремума, то автоматически известно и время его открытия.

    hoz пишет:

     цитата:
    У меня такое ощущение, что мой вариант медленнее. Нужно будет замерить скорость. Если это так, то верну как и было.


    Там разница будет едва заметна. Достаточно сложно определить. А потому результаты получатся как с преобладанием одной, так и другой стороны. Я бы не заморачивался.

    Спасибо: 0 
    ПрофильЦитата Ответить





    Сообщение: 65
    Зарегистрирован: 30.05.13
    Репутация: 0
    ссылка на сообщение  Отправлено: 05.04.18 10:44. Заголовок: Scriptong пишет: Та..


    Scriptong пишет:

     цитата:
    Там разница будет едва заметна. Достаточно сложно определить. А потому результаты получатся как с преобладанием одной, так и другой стороны. Я бы не заморачивался.


    Что-то с терминалом было. Другой устаонвил, теперь всё быстро.

    Вот график построения зиг-зага. График открыт М30, а в инпут-параметры индикатора передаю Н1, соответственно:


    Так вот я на скрине описал текущий трабл индюка.
    Метод getTrend() я переписал как вижу сейчас. Особо ничего не поменялось, но так нужно. Хотя, видимо нужно будет ещё что-то дописать. В getTrend() же дописал условие, что бы если от текущего бара прошло менее n-баров, тренд сохранялся прежним т.е. триггера на изменение тренда ещё нет.

    Вот я думаю, что нужно это как-то исправить. Думаю, но ещё не решил..
    На данный момент, вот что имеется
    Кстати, я сравнил то, что отображает ваш вариант индикатора и мой. Так вот в данном случает, находясь на М30 и рисуя по Н1 разницы нет. Получается, какяк изначально имеется.

    Спасибо: 0 
    ПрофильЦитата Ответить





    Сообщение: 2598
    Зарегистрирован: 03.03.13
    Откуда: Украина, Каменское (Днепродзержинск)
    Репутация: 3
    ссылка на сообщение  Отправлено: 06.04.18 14:54. Заголовок: hoz пишет: Получает..


    hoz пишет:

     цитата:
    Получается, какяк изначально имеется.


    Это не баг, а недостаток информации. Дело в том, что располагая только свечной информацией, невозможно достоверно установить последовательность возникновения экстремумов. Поэтому на свечах, поглощающих предыдущие свечи (максимум выше предыдущего максимума и минимум ниже предыдущего минимума) всегда будут появляться подобные проблемы. Чтобы их устранить 100% (не выдвигая предположений типа: на медвежьей свече минимум всегда позже максимума, а на бычьей - всегда раньше), нужно анализировать меньший ТФ, а в случае графика М1 - тиковую историю. Вот тогда ZigZag будет на 100% достоверным.
    Только вот вопрос: а нужно ли это для индикатора, являющегося тестерным Граалем?

    P. S. Плюс есть еще одна проблема. Даже располагая всей необходимой информацией, сталкиваемся с невозможностью отображения двух экстремумов ZZ на одном баре (по крайней мере при использовании индикаторных буферов). Чтобы отобразить на одном баре два экстремума, понадобится либо задействование еще одного индикаторного буфера, либо переход к отображению данных при помощи трендовых линий.

    Спасибо: 0 
    ПрофильЦитата Ответить





    Сообщение: 67
    Зарегистрирован: 30.05.13
    Репутация: 0
    ссылка на сообщение  Отправлено: 07.04.18 11:46. Заголовок: Scriptong пишет: Эт..


    Scriptong пишет:

     цитата:
    Это не баг, а недостаток информации. Дело в том, что располагая только свечной информацией, невозможно достоверно установить последовательность возникновения экстремумов. Поэтому на свечах, поглощающих предыдущие свечи (максимум выше предыдущего максимума и минимум ниже предыдущего минимума) всегда будут появляться подобные проблемы. Чтобы их устранить 100% (не выдвигая предположений типа: на медвежьей свече минимум всегда позже максимума, а на бычьей - всегда раньше), нужно анализировать меньший ТФ, а в случае графика М1 - тиковую историю. Вот тогда ZigZag будет на 100% достоверным.
    Только вот вопрос: а нужно ли это для индикатора, являющегося тестерным Граалем?


    По сути да, я здесь не прав.

    Scriptong пишет:

     цитата:
    P. S. Плюс есть еще одна проблема. Даже располагая всей необходимой информацией, сталкиваемся с невозможностью отображения двух экстремумов ZZ на одном баре (по крайней мере при использовании индикаторных буферов). Чтобы отобразить на одном баре два экстремума, понадобится либо задействование еще одного индикаторного буфера, либо переход к отображению данных при помощи трендовых линий.


    Если будет не 1 буфер, то отобразиться же всё. У меня есть такой зиг-заг. Тока он написал кривовато, и руки до него не добрались пока что. Хотя он рмсует несколько зиг-загов на одном графике и у него соответственно столько же буферов.

    Кстати, возник ещё один интересный момент. Я добавил сюда метод:

    int getLastNoEmptyValueIndex(int index) {
    while (index < iBars(NULL, i_TF)) {
    if (g_ZZPriceBuf[index] != EMPTY_VALUE)
    return index;
    Print("index = ", index);
    index++;
    }
    return index;
    }

    Этот метод я использую в методе getTrend() для того, что бы узнать индекс последнего сформированного экстремума.

    ENUM_TREND_DIR getTrend(ZZProperty& stZZProperty, int barIndex) {
    int lastZZBarIndex = getLastNoEmptyValueIndex(barIndex);
    if ((lastZZBarIndex - barIndex) < 3)
    return stZZProperty.trend;

    // Новая свеча выше предыдущей
    if (iHigh(NULL, i_TF, barIndex) > iHigh(NULL, i_TF, barIndex + 1)) {
    return TREND_DIR_UPWARD;
    }

    // Новая свеча ниже предыдущей
    if (iLow(NULL, i_TF, barIndex) < iLow(NULL, i_TF, barIndex + 1)) {
    return TREND_DIR_DOWNWARD;
    }
    return TREND_DIR_NONE;
    }

    Это нужно, что бы зиг-заг не искал экстремум на баре, если последний сформированный экстремум находится на растоянии N-баров. Фильтр нужен, что бы на каждом баре не рисовались экстремумы, как это иногда бывает..
    Так вот возникает ошибка в строке 92 у меня:


     цитата:
    2018.04.07 12:28:17.132 2018.02.19 18:00:00 ZZ_mtf AUDUSDm,M30: array out of range in 'ZZ_mtf.mq4' (92,21)



    Ошибка в строке кода:

    if (g_ZZPriceBuf[index] != EMPTY_VALUE)

    Я так понял, здесь придётся для этой задачи сделать массив буфера динамическим? (если, конечно, это возможно. Вижу, что, вроде как, размер массива g_ZZPriceBuf меньше, чем g_ZZPriceBuf[index] на индексе в цикле.
    Вот код

    Спасибо: 0 
    ПрофильЦитата Ответить





    Сообщение: 68
    Зарегистрирован: 30.05.13
    Репутация: 0
    ссылка на сообщение  Отправлено: 07.04.18 11:49. Заголовок: Scriptong пишет: Эт..


    Scriptong пишет:

     цитата:
    Это не баг, а недостаток информации. Дело в том, что располагая только свечной информацией, невозможно достоверно установить последовательность возникновения экстремумов. Поэтому на свечах, поглощающих предыдущие свечи (максимум выше предыдущего максимума и минимум ниже предыдущего минимума) всегда будут появляться подобные проблемы. Чтобы их устранить 100% (не выдвигая предположений типа: на медвежьей свече минимум всегда позже максимума, а на бычьей - всегда раньше), нужно анализировать меньший ТФ, а в случае графика М1 - тиковую историю. Вот тогда ZigZag будет на 100% достоверным.
    Только вот вопрос: а нужно ли это для индикатора, являющегося тестерным Граалем?


    По сути да, я здесь не прав.

    Scriptong пишет:

     цитата:
    P. S. Плюс есть еще одна проблема. Даже располагая всей необходимой информацией, сталкиваемся с невозможностью отображения двух экстремумов ZZ на одном баре (по крайней мере при использовании индикаторных буферов). Чтобы отобразить на одном баре два экстремума, понадобится либо задействование еще одного индикаторного буфера, либо переход к отображению данных при помощи трендовых линий.


    Если будет не 1 буфер, то отобразиться же всё. У меня есть такой зиг-заг. Тока он написал кривовато, и руки до него не добрались пока что. Хотя он рмсует несколько зиг-загов на одном графике и у него соответственно столько же буферов.

    Кстати, возник ещё один интересный момент. Я добавил сюда метод:

    int getLastNoEmptyValueIndex(int index) {
    while (index < iBars(NULL, i_TF)) {
    if (g_ZZPriceBuf[index] != EMPTY_VALUE)
    return index;
    Print("index = ", index);
    index++;
    }
    return index;
    }

    Этот метод я использую в методе getTrend() для того, что бы узнать индекс последнего сформированного экстремума.

    ENUM_TREND_DIR getTrend(ZZProperty& stZZProperty, int barIndex) {
    int lastZZBarIndex = getLastNoEmptyValueIndex(barIndex);
    if ((lastZZBarIndex - barIndex) < 3)
    return stZZProperty.trend;

    // Новая свеча выше предыдущей
    if (iHigh(NULL, i_TF, barIndex) > iHigh(NULL, i_TF, barIndex + 1)) {
    return TREND_DIR_UPWARD;
    }

    // Новая свеча ниже предыдущей
    if (iLow(NULL, i_TF, barIndex) < iLow(NULL, i_TF, barIndex + 1)) {
    return TREND_DIR_DOWNWARD;
    }
    return TREND_DIR_NONE;
    }

    Это нужно, что бы зиг-заг не искал экстремум на баре, если последний сформированный экстремум находится на растоянии N-баров. Фильтр нужен, что бы на каждом баре не рисовались экстремумы, как это иногда бывает..
    Так вот возникает ошибка в строке 92 у меня:


     цитата:
    2018.04.07 12:28:17.132 2018.02.19 18:00:00 ZZ_mtf AUDUSDm,M30: array out of range in 'ZZ_mtf.mq4' (92,21)



    Ошибка в строке кода:

    if (g_ZZPriceBuf[index] != EMPTY_VALUE)

    Я так понял, здесь придётся для этой задачи сделать массив буфера динамическим? (если, конечно, это возможно. Вижу, что, вроде как, размер массива g_ZZPriceBuf меньше, чем g_ZZPriceBuf[index] на индексе в цикле.
    Вот код

    Спасибо: 0 
    ПрофильЦитата Ответить
    Ответов - 22 , стр: 1 2 All [только новые]
    Ответ:
    1 2 3 4 5 6 7 8 9
    большой шрифт малый шрифт надстрочный подстрочный заголовок большой заголовок видео с youtube.com картинка из интернета картинка с компьютера ссылка файл с компьютера русская клавиатура транслитератор  цитата  кавычки моноширинный шрифт моноширинный шрифт горизонтальная линия отступ точка LI бегущая строка оффтопик свернутый текст

    показывать это сообщение только модераторам
    не делать ссылки активными
    Имя, пароль:      зарегистрироваться    
    Тему читают:
    - участник сейчас на форуме
    - участник вне форума
    Все даты в формате GMT  2 час. Хитов сегодня: 8
    Права: смайлы да, картинки да, шрифты да, голосования нет
    аватары да, автозамена ссылок вкл, премодерация откл, правка нет