Logo

Вход

Войти с помощью соц. сетей
X
 
  • Фильтр
  • Время
  • Показать
Очистить всё
новые сообщения
  • #1 Свернуть

    Индикатор и скрипт возвращают разное количество баров!

    Сегодня я явно удивился. Пишу не первый день, но такой дичи ещё не встречал. Искал причину не корректной отрисовки индикатора и.. оказалось, что индикатор возвращает не реальное количество баров, находящеется на конкретном торговом инструменте конкретного таймфрейма.
    Скрипт и индикатор используют библиотечные функции. В приведённых примерах, которые я выложил их лишь 2 (barsTotal() и barOpenTime()). Я упростил до самого простого варианта, что бы можно было увидеть что я имею ввиду. Т.к. весь индикатор достаточно сложный, .. ес-но, что желающих его понять, навряд ли, будет много )) Библиотечные функции я вытянул с библиотек и поместил прямо в демонстрационные файлы.
    Вот скрипт:
    Код:
    //+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    //|                                                                                                                                                                 experience.mq5 |
    //|                                                                                                                                                                            hoz |
    //|                                                                                                                                                                                |
    //+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    
    //==================================================================================================================================================================================
    // 1.1 Возвращает количество баров в окне торгового инструмента активного окна на заданном таймфрейме. =============================================================================
    int barsTotal(ENUM_TIMEFRAMES tf = PERIOD_CURRENT) {    // ТФ, количество баров которого требуется получить
    //---
      return Bars(_Symbol, tf);
    }
    //==================================================================================================================================================================================
    // 7.1 Возвращает значение времени открытия бара торгового инструмента активного окна, находящегося на shift баров от 0-го бара в историю. =========================================
    datetime barOpenTime(int shift,                                // Индекс бара, время открытия которого требуется определить
                         ENUM_TIMEFRAMES tf = PERIOD_CURRENT) {    // ТФ, на котором будет происходить поиск открытия баров функцией CopyTime()
    //---
      datetime barOpenTime[1];    // Массив, в котором находятся цены открытия баров активного окна
    //---
      return ((CopyTime(_Symbol, tf, shift, 1, barOpenTime) != -1) ? barOpenTime[0] : WRONG_VALUE);
    }
    //+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    //|                                                                                Script program start function                                                                   |
    //+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    void OnStart() {
    //---
      int firstBarIndexThisTF = barsTotal(PERIOD_CURRENT) - 1;
      Print(__FUNCTION__, " :: firstBarIndexThisTF = ", firstBarIndexThisTF);
      datetime firstBarTimeThisTF = barOpenTime(firstBarIndexThisTF);
      Print(__FUNCTION__, " :: firstBarTimeThisTF = ", TimeToString(firstBarTimeThisTF, TIME_DATE|TIME_MINUTES));
    }
    Вот индикатор:
    Код:
    //+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    //|                                                                                                                                                             invalidExample.mq5 |
    //|                                                                                                                                                                            hoz |
    //|                                                                                                                                                                                |
    //+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    #property copyright "hoz"
    #property link      ""
    #property version   "1.00"
    #property indicator_chart_window            // Индикатор отображается в окне графика
    #property indicator_buffers 1               // Используется 3 буфера индикатора
    #property indicator_plots   1               // Количество графических серий индикатора
    //---- plot properties
    #property indicator_type1  DRAW_SECTION     // Вид графического построения
    #property indicator_color1 clrDodgerBlue    // Цвет отображения данных 1-го буфера
    #property indicator_style1 STYLE_SOLID      // Стиль графической серии
    #property indicator_width1 2                // Толщина линий 1-го буфера
    
    double extremum_price_buffer[];            // Буфер, хранящий цены кривой Zig-Zag'а (непустые значения - экстремумы)
    //==================================================================================================================================================================================
    // Custom indicator initialization function. =======================================================================================================================================
    int OnInit() {
    //--- indicator buffers mapping
      SetIndexBuffer(0, extremum_price_buffer, INDICATOR_DATA);               // Первый буфер - экстремумы
      PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, EMPTY_VALUE);                   // Установка пустого значения буфера extremum_price_buffer, по которому нет отрисовки
      ArraySetAsSeries(extremum_price_buffer, true);
    //---
      return INIT_SUCCEEDED;
    }
    //==================================================================================================================================================================================
    // 1.1 Возвращает количество баров в окне торгового инструмента активного окна на заданном таймфрейме. =============================================================================
    int barsTotal(ENUM_TIMEFRAMES tf = PERIOD_CURRENT) {    // ТФ, количество баров которого требуется получить
    //---
      return Bars(_Symbol, tf);
    }
    //==================================================================================================================================================================================
    // 7.1 Возвращает значение времени открытия бара торгового инструмента активного окна, находящегося на shift баров от 0-го бара в историю. =========================================
    datetime barOpenTime(int shift,                                // Индекс бара, время открытия которого требуется определить
                         ENUM_TIMEFRAMES tf = PERIOD_CURRENT) {    // ТФ, на котором будет происходить поиск открытия баров функцией CopyTime()
    //---
      datetime barOpenTime[1];    // Массив, в котором находятся цены открытия баров активного окна
    //---
      return ((CopyTime(_Symbol, tf, shift, 1, barOpenTime) != -1) ? barOpenTime[0] : WRONG_VALUE);
    }
    //==================================================================================================================================================================================
    // Определение индекса бара, с которого необходимо производить перерасчет. =========================================================================================================
    int recalcIndex(int countedBars) {    // Количество уже обработанных баров таймфрейма открытого графика
    //---
      if (countedBars == 0) {
        ArrayInitialize(extremum_price_buffer, EMPTY_VALUE);
        int firstBarIndexThisTF = barsTotal() - 1;
        Print(__FUNCTION__, " :: firstBarIndexThisTF = ", firstBarIndexThisTF);
        Print(__FUNCTION__, " :: firstBarTimeThisTF = ", TimeToString(barOpenTime(firstBarIndexThisTF), TIME_DATE|TIME_MINUTES));
        return barsTotal() - 2;
      }
    //---
      return 1;
    }
    //==================================================================================================================================================================================
    // Custom indicator iteration function. ============================================================================================================================================
    int OnCalculate(const int rates_total,
                    const int prev_calculated,
                    const datetime &time[],
                    const double &open[],
                    const double &high[],
                    const double &low[],
                    const double &close[],
                    const long &tick_volume[],
                    const long &volume[],
                    const int &spread[]) {
    //---
      int limit = recalcIndex(prev_calculated);    // Определим первый расчетный бар
    //--- return value of prev_calculated for next call
      return rates_total;
    }
    То же самое я прикрепляю к сообщению.
    Так вот как в индикаторе так и в скрипте я принтую индекс первого в истории бара и время его появления. На выходе вижу разные значения.
    Индикатор в журнал принтует:
    2018.10.11 23:32:23.534 invalidExample (AUDJPY,M15) recalcIndex :: firstBarIndexThisTF = 10020
    2018.10.11 23:32:23.534 invalidExample (AUDJPY,M15) recalcIndex :: firstBarTimeThisTF = 2018.05.18 14:30
    Накидываю скрипт на тот же график, где запущен индикатор и вижу:
    Код:
    2018.10.11 23:32:23.534	invalidExample (AUDJPY,M15)	recalcIndex :: firstBarIndexThisTF = 10020
    2018.10.11 23:32:23.534	invalidExample (AUDJPY,M15)	recalcIndex :: firstBarTimeThisTF = 2018.05.18 14:30
    С чего бы это вдруг? На протяжении некоторого времени, я натыкался вообще на другие варианты. Дата былав другой. Хотя, сейчас во время написания этого сообщения только количество баров не одинаковое возвращается. Где верное... вопрос..
  • <a href="https://www.instaforex.org/ru/?x=ruforum">InstaForex</a>
  • #2 Свернуть

    Сообщение от скальпер Посмотреть сообщение
    Накидываю скрипт на тот же график, где запущен индикатор и вижу:
    А я вот вижу, что в ваших цитатах они показывают одно и то же.

    И для чего вы в recalcIndex() передаете prev_calculated если кол-во доступных баров у вас заходит в rates_total?
     

    Комментарий

    • #3 Свернуть

      Сообщение от ir0407 Посмотреть сообщение
      А я вот вижу, что в ваших цитатах они показывают одно и то же.

      И для чего вы в recalcIndex() передаете prev_calculated если кол-во доступных баров у вас заходит в rates_total?
      Извеняюсь. я вчера уже к вечеру замучанный был. Написал некорректный принт скрипта.
      Вот, что возвращает индикатор:
      2018.10.12 07:59:11.433 invalidExample (AUDJPY,M15) recalcIndex :: firstBarIndexThisTF = 10032
      2018.10.12 07:59:11.433 invalidExample (AUDJPY,M15) recalcIndex :: firstBarTimeThisTF = 2018.05.18 19:45
      Вот, что возвращает скрипт:
      2018.10.12 07:59:16.520 experience (AUDJPY,M15) OnStart :: firstBarIndexThisTF = 9999
      2018.10.12 07:59:16.520 experience (AUDJPY,M15) OnStart :: firstBarTimeThisTF = 2018.05.21 04:00
      Как видно, график и таймфрейм тот же, а дата и время, а так же количество баров разные. Терминал гонит что-ли?
      Кстати, в настройках у меня выставлено "Макс. баров в окне 10000".
      Кстати, скрипт возвращает корренктное количество данных и дату с точностью до секунды буквально. Всё правильно. А индикатор возвращает какую-то левоту (дата на 3 дня раньше) чем дата первого бара. А если учесть, что я запросил предпоследний бар, то пробел чутка больше.
       
      Последний раз редактировалось скальпер; 12.10.2018, 08:13.

      Комментарий

      • #4 Свернуть

        Сообщение от ir0407 Посмотреть сообщение
        А я вот вижу, что в ваших цитатах они показывают одно и то же.

        И для чего вы в recalcIndex() передаете prev_calculated если кол-во доступных баров у вас заходит в rates_total?
        Я же писал, что это лишь мнимый каркас. Реально индикатор не так спроектирован. Если интереует как на самом деле я эту функцию написал в оригинале, то вот:
        Код:
        //==================================================================================================================================================================================
        // Определение индекса бара, с которого необходимо производить перерасчет. =========================================================================================================
        int recalcIndex(int countedBars) {    // Количество уже обработанных баров таймфрейма открытого графика
        //---
          int barsTotalOtherTF = barsTotal(i_tf);
        
          if ((countedBars == 0) || (barsTotalOtherTF - g_prevCalculated > 1)) {
            ArrayInitialize(extremum_price_buffer, EMPTY_VALUE);
            ArrayInitialize(tendention_buffer, TREND_NONE);
            int firstBarIndexCurTF = barsTotal(PERIOD_CURRENT) - 1;
            return barShift(barOpenTime(firstBarIndexCurTF), i_tf) - 2;
          }
        //---
          return 1;
        }
           

        Комментарий

        • #5 Свернуть

          Сообщение от скальпер Посмотреть сообщение
          Я же писал, что это лишь мнимый каркас. Реально индикатор не так спроектирован. Если интереует как на самом деле я эту функцию написал в оригинале, то вот:
          И нафига так изголяться? У вас же реальное кол-во баров для текущего ТФ заходит в индюк через rates_total, а вы зачем-то пытаетесь их еще дополнительно вычислять через задний проход, через prev_calculated. Просто проверьте сколько баров заходит через rates_total и сколько вам показывает скрипт.
             

          Комментарий

          • #6 Свернуть

            Сообщение от ir0407 Посмотреть сообщение
            И нафига так изголяться? У вас же реальное кол-во баров для текущего ТФ заходит в индюк через rates_total, а вы зачем-то пытаетесь их еще дополнительно вычислять через задний проход, через prev_calculated. Просто проверьте сколько баров заходит через rates_total и сколько вам показывает скрипт.
            Ну так всё элементарно. Скрипт показывает дату первого бара в истории. Причём это видно на графике, если промотать на первый бар на нужном графике или нажать "Home". А изгаляться необходимо, т.к. если индикатор является мультитаймфреймынм, то тот rates_total, который можно передать нам не интересен т.к. это лишь количество баров на открытом графике, а не на том, который мы хотим обработать. Понимаете?
               

            Комментарий

            • #7 Свернуть

              Сообщение от скальпер Посмотреть сообщение
              А изгаляться необходимо, т.к. если индикатор является мультитаймфреймынм, то тот rates_total, который можно передать нам не интересен т.к. это лишь количество баров на открытом графике, а не на том, который мы хотим обработать. Понимаете?
              Понимаю... Но судя по вашим кодам у вас разница в кол-ве баров между скриптом и индикатором именно на текущем ТФ.

              А что касается МТФ, то там все намного сложнее. Терминал не следит наличием истории на не текущих ТФ и вполне логично, что в кэше терминала на не текущих ТФ история может либо отставать либо отсутствовать вообще, при этом наличие истории для младших ТФ аж никак не является гарантией наличия истории за тот же период для старших ТФ(и наоборот). Внимательно прочтите в справке раздел "Справочник MQL5 / Доступ к таймсериям и индикаторам / Организация доступа к данным " и вам должно стать более менее понятно почему на не текущих ТФ может не хватать истории.
                 

              Комментарий

              • #8 Свернуть

                Сообщение от ir0407 Посмотреть сообщение
                Понимаю... Но судя по вашим кодам у вас разница в кол-ве баров между скриптом и индикатором именно на текущем ТФ.
                Именно так. Терминал даже на текущем ТФ не может получить количество баров. Это финиш.. Я понимаю, что можно передать его параметром из OnCalculate(), но всё-равно это не противоречит тому, что терминал гонит. Получить данные должно быть возможным из любого места. Я имею ввиду, хотя бы текущего графика. Придётся понять, что это костыль и передавать параметр.

                Сообщение от ir0407 Посмотреть сообщение
                А что касается МТФ, то там все намного сложнее. Терминал не следит наличием истории на не текущих ТФ и вполне логично, что в кэше терминала на не текущих ТФ история может либо отставать либо отсутствовать вообще, при этом наличие истории для младших ТФ аж никак не является гарантией наличия истории за тот же период для старших ТФ(и наоборот). Внимательно прочтите в справке раздел "Справочник MQL5 / Доступ к таймсериям и индикаторам / Организация доступа к данным " и вам должно стать более менее понятно почему на не текущих ТФ может не хватать истории.
                И это странно. Данные то у терминала должны присутствовать, иначе нафига такой терминал нужен то?
                   
                Последний раз редактировалось скальпер; 12.10.2018, 13:03.

                Комментарий

                • #9 Свернуть

                  Сообщение от скальпер Посмотреть сообщение
                  И это странно. Данные то у терминала должны присутствовать, иначе нафига такой терминал нужен то?
                  А вы представляете сколько будет нужно терминалу ресурсов компа если он постоянно будет качать все котировки для всех ТФ в одно и то же время да еще и по нескольким инструментам сразу? Оптимизация однако... Поэтому терминал качает только то, что его заставляют качать и не более того.

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

                  А "подкачивать" котировки нужно все же самостоятельно, путем запроса нужных данных в несколько приемов и через обработку ошибок
                  функций, которые занимаются этой подкачкой. Это стандартная рутина, но для МТФ ее обязательно нужно делать ввиду того, что терминал этим занимается от случая к случаю.
                     
                  Последний раз редактировалось ir0407; 12.10.2018, 13:23.

                  Комментарий

                  • #10 Свернуть

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

                    Комментарий

                    • #11 Свернуть

                      Сообщение от ir0407 Посмотреть сообщение
                      А вы представляете сколько будет нужно терминалу ресурсов компа если он постоянно будет качать все котировки для всех ТФ в одно и то же время? Оптимизация однако...
                      Щяс с ходу не скажу, где я это читал, но в справке написано, что в отличие от мт4 в мт5 котировки не разделяются на таймфреймы. Щяс они выкачиваются просто в файлы и всё. Вид общий. А когда эти котировки нужно использовать, тогда они подгружаются уже с этих файлов. Это если грубо описать процесс. Получается, что все данные как-бы имеются всегда.

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

                      Сообщение от ir0407 Посмотреть сообщение
                      А "подкачивать" котировки нужно все же самостоятельно, путем запроса нужных данных в несколько приемов и через обработку ошибок
                      функций, которые занимаются этой подкачкой. Это стандартная рутина, но для МТФ ее обязательно нужно делать ввиду того, что терминал этим занимается от случая к случаю.
                      Это я прекрасно понимаю.
                         

                      Комментарий

                      • #12 Свернуть

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

                        Комментарий

                        • #13 Свернуть

                          Сообщение от скальпер Посмотреть сообщение
                          Щяс с ходу не скажу, где я это читал, но в справке написано, что в отличие от мт4 в мт5 котировки не разделяются на таймфреймы. Щяс они выкачиваются просто в файлы и всё. Вид общий. А когда эти котировки нужно использовать, тогда они подгружаются уже с этих файлов. Это если грубо описать процесс. Получается, что все данные как-бы имеются всегда.
                          Вот когда вы начнете обрабатывать ошибки тех функций, которые подкачивают историю, вы поймете, что ваше "все данные как-бы имеются всегда" - это из того анекдота, в котором "на заборе написано, а за забором никогда нету".
                           

                          Комментарий

                          • #14 Свернуть

                            Сообщение от скальпер Посмотреть сообщение
                            Щяс с ходу не скажу, где я это читал, но в справке написано, что в отличие от мт4 в мт5 котировки не разделяются на таймфреймы. Щяс они выкачиваются просто в файлы и всё. Вид общий. А когда эти котировки нужно использовать, тогда они подгружаются уже с этих файлов. Это если грубо описать процесс. Получается, что все данные как-бы имеются всегда.
                            так то оно так, но там тож "засада"... МТ5 должен подготовить запрашиваемый ТФ и лишь тогда будут доступны данные этого ТФ для запроса или отображения, это можно даже визуально увидеть - откройте в терминале символ который никогда не использовали, какую-нибудь мексиканскую пису и сразу переключите на месяц, увидите как подгружаются данные - график будет онлайн закачиваться и увеличиваться количество баров, дождитесь загрузки месячного графика и потом попробуйте переключать на другие ТФ, Вы должны увидеть на некоторых ТФ черный квадрат, который через несколько секунд станет графиком ТФ - вот это и есть подготовка ТФ, при вызове из советника или индикатора может происходить такая же ситуация - данные есть, а ТФ не подготовлен

                            https://www.mql5.com/ru/docs/series/timeseries_access

                            Комментарий

                            • <a href="https://www.instaforex.org/ru/?x=ruforum">InstaForex</a>
                            • #15 Свернуть

                              Сообщение от IgorM Посмотреть сообщение
                              так то оно так, но там тож "засада"... МТ5 должен подготовить запрашиваемый ТФ и лишь тогда будут доступны данные этого ТФ для запроса или отображения, это можно даже визуально увидеть - откройте в терминале символ который никогда не использовали, какую-нибудь мексиканскую пису и сразу переключите на месяц, увидите как подгружаются данные - график будет онлайн закачиваться и увеличиваться количество баров, дождитесь загрузки месячного графика и потом попробуйте переключать на другие ТФ, Вы должны увидеть на некоторых ТФ черный квадрат, который через несколько секунд станет графиком ТФ - вот это и есть подготовка ТФ, при вызове из советника или индикатора может происходить такая же ситуация - данные есть, а ТФ не подготовлен

                              https://www.mql5.com/ru/docs/series/timeseries_access
                              Метаквтоы сами себе противоречат в данном случае. Это понятно. Но есть 1 момент. Сразу видно, что 5-ку проектировали на коленке. Паттерны проектирования точно не использовали.. Ведь, если указано в настройках, что используем лишь 10 тыс баров и на рабочем ТФ и на другом, т.е., например, ТФ выше.. должно возвращаться не более 10 тыс. баров.
                              Например, находясь на ТФ М15, если возвращается 10014 баров, что не 10тыс заявленных, но примерно то, что требуется с погрешностью, то запрос количества баров с ТФ Н1 не должене быть, скажем так, 24 тыс или 48 тыс.
                               

                              Комментарий

                              Сейчас онлайн

                              working...
                              X