Индикатор повреждается - страница 6

 
Rosh:
Хорошо, я подожду.

После более чем 20 часов индикатор работает правильно. Я не знаю, что сказать.


 

Рош, Увеличение/уменьшение, прокрутка влево/вправо. На какой платформе 64/32 бит вы тестируете?

 
AnkaSoftware:

Рош, Увеличение/уменьшение, прокрутка влево/вправо. На какой платформе вы тестируете 64/32 бит?

Я могу воспроизвести общую проблему на 32-битной. Единственный способ, в котором O/S кажется релевантным, это вопрос о том, почему ваша 64-битная система, кажется, периодически получает новые данные в начале или в середине истории баров, в то время как ваша 32-битная система (и 64-битная система RaptorUK) не получает. Независимо от этого, вы, похоже, собираетесь передавать свой индикатор другим людям, а изменения в истории баров - это проблемы, с которыми вы обязательно столкнетесь в реальной жизни, хотя бы потому, что ваши пользователи страдают от отключений брокера, которые приводят к тому, что пропущенные бары вставляются в середину истории при повторном подключении.

Как я уже пытался объяснить, спорным является вопрос о том, где находится эта "ошибка" - в вашем коде или в MT4. Существует ожидание того, как индикаторы будут вести себя в MT4, а ваш индикатор ведет себя не так. Например, когда вы создаете новый индикатор с помощью MetaEditor, он вставляет для вас строку "int counted_bars=IndicatorCounted();". Вы удаляете ее и игнорируете IndicatorCounted().

Я могу воспроизвести общую проблему, используя следующий индикатор, который просто рисует линию между последними 10 барными максимумами при первом запуске:

#property indicator_chart_window
#property indicator_color1 Red
#property indicator_buffers 1

double indicatorvalues[];

void init()
{
   SetIndexBuffer(0, indicatorvalues);
}

void start()
{
   static bool IsFirstCall = true;
   if (IsFirstCall) {
      IsFirstCall = false;
      for (int i = 0; i < 10; i++) {
         indicatorvalues[i] = High[i];      
      }
   }
}

Вы можете воспроизвести ту же проблему, сделав следующее:

* Откройте график для любого символа.

* Добавьте индикатор на график

* Отключите "Автопрокрутку графика" (только для того, чтобы упростить следующие шаги, а не потому, что это как-то влияет на проблему)

* Перейдите в начало графика, нажав Home.

* Нажмите Page Up для принудительной загрузки дополнительных данных. (N.B. Нет никакой проблемы, если в этот момент на график не будут добавлены дополнительные данные).

* Перейдите к концу графика, нажав End. Красная линия между максимумами теперь будет находиться не на своем месте. Она будет перемещена назад во времени.

[Все это лишь дополняет то, что уже определил RaptorUK].

 

Хорошо, Вы можете подтвердить, что IndicatorCounted() вернет -ve число, в этом случае отсутствующих баров / поврежденных индикаторов? Давайте я попробую переинициализировать массивы индикаторов и перерисовать движения с обратного бара.

 
AnkaSoftware:

OK, Можете ли вы подтвердить, что IndicatorCounted() вернет -ve число, в этом случае отсутствующих баров / поврежденных индикаторов?

Нет, что происходит - как я уже говорил на странице 5, и как вы можете легко проверить сами - это то, что MT4 сбрасывает IndicatorCounted() на ноль, когда новые бары добавляются в начало истории с помощью метода, подобного приведенному выше. Это заставит обычный индикатор перерисовать все свои исторические значения, потому что он обычно использует разницу между Bars и IndicatorCounted(), чтобы определить, какие бары "грязные" и нуждаются в обновлении. Если IndicatorCounted() равен нулю, то индикатор пересчитывает каждый исторический бар, т.е. потому что Bars - 0 = Bars.

В документации к IndicatorCounted()(https://docs.mql4.com/customind/IndicatorCounted) приведен один из примеров такой работы. Существуют и альтернативные версии, такие как https://www.mql5.com/en/forum/132447, которые нацелены на очень незначительное улучшение производительности, поскольку стандартный код https://docs.mql4.com/customind/IndicatorCounted без необходимости пересчитывает один бар, который является "чистым".
 

Добавление проверок IndicatorCounted() и повторная инициализация индикаторов, когда IndicatorCounted() возвращает значение 0, решает проблему смещения индикаторов, которая возникает при вставке исторических или дополнительных баров.

Однако существует другая проблема повреждения индикаторов, которая, по-видимому, не вызвана вставкой исторических баров. Пример кода прилагается, чтобы воспроизвести проблему, необходимо запустить его на 10+ часов, как минимум до двух переинициализаций индикаторов, т.е. IndicatorCounted() возвращает значение 0 (после запуска индикатора).

Файлы:
Причина обращения: