Советник. Как рисовать раз в день?

 

Здравствуйте.

Стоит задача раз в день в 00:00 часов по времени терминала ставить стрелочку pivot, которая рассчитывается так: (high+low+close)/3, где high, low и cloce - цены прошлого дня.

На тестере все прекрасно строится.

Проблема возникает в реалтайме. Когда закидываешь эксперт в текущий день, то пивот правильно строит в начале этого дня, и рассчитывается по прошлому дню. Но! Во второй день он ставит такой же пивот, как и в первый день. В третий день рассчитывает по данным 1-го дня, в четвертый день - по данным 2-го дня, и т.д. Т.е. иными словами, идет сдвиг. Чего не должно быть.

Предположения. Я думаю, что дело в механике терминала перехода на новый день. Но где именно касяк - не могу найти.

Как решить данную проблему? Может, пытаться строить пивот не сразу, а, скажем, спустя 5 минут? Это может решить проблему?

Код:

int      oldDay;
int      dayNow;

void CalculateDay()
{

   dayNow = DayOfWeek();

   if (oldDay != dayNow)
   {
      // Рисую что хочу.
   }
}

int OnInit()
{
   oldDay = DayOfWeek() - 1;
   if (oldDay < 0) oldDay = 5;
   CalculateDay();
   return(INIT_SUCCEEDED);
}

void OnTick()
{
   CalculateDay();
   // Опять творю прекрасное.
}
 

Про iBarShift() не слыхали? Почитайте, полезно.

Вот пример расчёта пивота в этой функцией:

      int dayi = iBarShift(NULL, 1440, Time[i], false); //смещение до начала текущих суток

      double H = iHigh(NULL, 1440, dayi + 1);  //вчерашний Хай 
      double L = iLow(NULL, 1440, dayi + 1);   //вчерашний Лоу
      double C = iClose(NULL, 1440, dayi + 1); //вчерашний Клоуз
           
      double Pivot =  (H+L+C)/3; //собственно, пивот.
 
evillive:

Про iBarShift() не слыхали? Почитайте, полезно.

А почему нельзя использовать конструкцию без dayi?

double H = iHigh(NULL, PERIOD_D1, 1);  //вчерашний Хай 
double L = iLow(NULL, PERIOD_D1, 1);   //вчерашний Лоу
double C = iClose(NULL, PERIOD_D1, 1); //вчерашний Клоуз

 Третий параметр shift = 0 означает текущий формирующийся бар, а shift = 1 означает второй бар (т.е. вчера при таймфрейме D1). Я бы и не подумал в этом случае использовать iBarShift(). Что я опять упускаю?

Думаю, главная проблема в хелпе - отсутствие описания в каких случаях нужно применять. Это не только к mql4 относится.

 
solarplexus:

А почему нельзя использовать конструкцию без dayi?

 Третий параметр shift = 0 означает текущий формирующийся бар, а shift = 1 означает второй бар (т.е. вчера при таймфрейме D1). Я бы и не подумал в этом случае использовать iBarShift(). Что я опять упускаю?

Думаю, главная проблема в хелпе - отсутствие описания в каких случаях нужно применять. Это не только к mql4 относится.

А вы попробуйте без неё индикатор реализовать, будете неприятно удивлены  ;)

В виде советника не пробовал, но если расчёт проводить заново на каждом баре и рисовать линии всегда только на сегодня, то может и без  iBarShift работать будет, экспериментируйте.

 

Забыл добавить, что экспериментировать можно раз в день в 00:00 по терминальному времени. Ненаэкспериментируешься. Поэтому то я и здесь. Вдруг кто разъяснит в чем дело. А пробовать на индикаторе - не факт, что будет работать в эксперте. Я уже ни в чем не уверен. Тестер живет своей жизнью, реалтайм - своей.

Вы бы не могли все-таки объяснить на что влияет iBarShift()? А то каждое утро я неприятно удивляюсь тому, что мой пивот построен неверно.

 
solarplexus:

Забыл добавить, что экспериментировать можно раз в день в 00:00 по терминальному времени. Ненаэкспериментируешься. Поэтому то я и здесь. Вдруг кто разъяснит в чем дело. А пробовать на индикаторе - не факт, что будет работать в эксперте. Я уже ни в чем не уверен. Тестер живет своей жизнью, реалтайм - своей.

Вы бы не могли все-таки объяснить на что влияет iBarShift()? А то каждое утро я неприятно удивляюсь тому, что мой пивот построен неверно.

Чтобы нарисовать что-то не верно, нужно это "что-то" запрограммировать не верно ;)
 
artmedia70:
Чтобы нарисовать что-то не верно, нужно это "что-то" запрограммировать не верно ;)

Я думаю, вы согласитесь со мной, что из хелпа по описаниям двух функций iBarShift() и iClose() нельзя сделать вывод, что iClose будет работать неадекватно без iBarShift(). Напротив, там сказано, что "shift - Индекс получаемого значения из таймсерии (сдвиг относительно текущего бара на указанное количество баров назад).", т.е. разработчик уверен в ожидаемой работоспособности этой функции.

И само собой, очевидно, что прога работает так, как запрограммировал разработчик. Другое дело понимать более низкий уровень. Это я говорю как программист микроконтроллеров (перед тем как завести какую-либо периферию, нужно знать архитектуру микроконтроллера).

И все-таки, я хочу добиться истины. В чем же механизм работы? Почему в моем случае нужно применить iBarShift()? Какие процессы происходят с терминалом в реалтайме в 00:00 как в моем случае?

 
solarplexus:

Я думаю, вы согласитесь со мной, что из хелпа по описаниям двух функций iBarShift() и iClose() нельзя сделать вывод, что iClose будет работать неадекватно без iBarShift(). Напротив, там сказано, что "shift - Индекс получаемого значения из таймсерии (сдвиг относительно текущего бара науказанное количество баров назад).", т.е. разработчик уверен в ожидаемой работоспособности этой функции.

И само собой, очевидно, что прога работает так, как запрограммировал разработчик. Другое дело понимать более низкий уровень. Это я говорю как программист микроконтроллеров (перед тем как завести какую-либо периферию, нужно знать архитектуру микроконтроллера).

И все-таки, я хочу добиться истины. В чем же механизм работы? Почему в моем случае нужно применить iBarShift()? Какие процессы происходят с терминалом в реалтайме в 00:00 как в моем случае?

Вам нужно по времени терминала (время сервера? или локальное время?) 00:00 нарисовать pivot по (high+low+close)/3 прошлого дня. Что мешает?

(iHigh(Symbol(),PERIOD_D1,1)+iLow(Symbol(),PERIOD_D1,1)+iClose(Symbol(),PERIOD_D1,1))/3.0;

Узнаёте время какое вам нужно. Если уже оно - рисуете если ещё не нарисовано.

 
artmedia70:

Вам нужно по времени терминала (время сервера? или локальное время?) 00:00 нарисовать pivot по (high+low+close)/3 прошлого дня. Что мешает?

Узнаёте время какое вам нужно. Если уже оно - рисуете если ещё не нарисовано.

Время терминала совпадает с 00:00 UTC. Мне это и надо.

Я выполняю  именно так, как вы и написали 

(iHigh(Symbol(),PERIOD_D1,1)+iLow(Symbol(),PERIOD_D1,1)+iClose(Symbol(),PERIOD_D1,1))/3.0;

в своей функции CalculateDay()

Т.е. происходит следующее. Наступает новый день, время 00:00, рисуется мой пивот, но этот пивот строится по данным не прошлого дня, а позапрошлого. Такое ощущение, что shift=1 в функциях  iHigh, iLow и iClose и время 00:00 расходятся, если вы понимаете о чем я.

 
solarplexus:

Т.е. происходит следующее. Наступает новый день, время 00:00, рисуется мой пивот, но этот пивот строится по данным не прошлого дня, а позапрошлого. Такое ощущение, что shift=1 в функциях  iHigh, iLow и iClose и время 00:00 расходятся, если вы понимаете о чем я.

Если до этого советник (индикатор, скрипт, пользователь) не обращался к ТФ D1, то первое обращение запустит процесс закачки данных дневного ТФ с сервера ДЦ, а данные iHigh и т. д. будут неверными (проверяйте после их вызова GetLastError; ее значение ERR_HISTORY_WILL_UPDATED укажет, что началась загрузка). Чтобы получить данные сразу же, принудительно обновляйте данные другого ТФ на каждом новом тике. К примеру, можно просто вхолостую вызывать iTime(NULL, PERIOD_D1, 1), без сохранения результата.
 
Scriptong:
Если до этого советник (индикатор, скрипт, пользователь) не обращался к ТФ D1, то первое обращение запустит процесс закачки данных дневного ТФ с сервера ДЦ, а данные iHigh и т. д. будут неверными (проверяйте после их вызова GetLastError; ее значение ERR_HISTORY_WILL_UPDATED укажет, что началась загрузка). Чтобы получить данные сразу же, принудительно обновляйте данные другого ТФ на каждом новом тике. К примеру, можно просто вхолостую вызывать iTime(NULL, PERIOD_D1, 1), без сохранения результата.
Мне было бы несколько неудобно давать такой комментарий, если бы речь шла о чем-нибудь, разработанном мною.