Ваши вопросы по языку MQL4

fs256

Местный знаток
Кто знает, подскажите, нужна функция, вычисляющая смещение бара по времени текущего дня. Допустим, на М15, текущее время 12:00, нужно смещение бара, открывшегося в 10:00 относительно текущего, т.е. результат должен быть =8.
Время(часы, минуты) - задаются заранее в функции в виде integer двумя отдельными числами.
Делаю так:

MqlDateTime str1;
datetime Now=TimeCurrent();
TimeToStruct(Now,str1);
int hours=str1.hour-HourOpen1;
int minutes=MathAbs(str1.min-MinuteOpen1)/15;
Shift1=4*hours+minutes;

По функции корректно обрабатываются часы, минуты - ни в какую... ( Что не так?

Может так, по простому? Положу легкий код в виде индюка (открытие дня или ... что поставишь), так проще.
 

Вложения

  • prim.png
    prim.png
    33,7 КБ · Просмотры: 62
  • primer_12.mq4
    3,5 КБ · Просмотры: 48

AlanTrade

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

Да, я совершенно верно Вас понял. Флаг работает, инициализация - нет.
То есть она есть, но такая же кривая. Дело в том, что первый раз блок start запускается сразу после init до обновления данных. Поэтому флаг необходимо ставить на 2 срабатывания. Но это всё "оригинальные операции с гландами". Почему бы разработчикам не сделать корректную работу функции init.
 

AlanTrade

Интересующийся
Вам бы следовало предоставить свой код, вот тогда будет предметный разговор, а так это ни о чем, экстрасенсы нынче в отпуске...
А на счет "некорректности работы инициализирующего блока и не предусмотрел "выпрямления" этой ситуации" - все в руках самого прогера - что сделал, то и имеет.

Не могу согласиться, что "все в руках самого прогера", хотя и к помощи экстрасенсов и духов прибегать в этом случае нет необходимости, как и к конкретным кодам. Это проблема не кода а алгоритма исполнения программы, который заложен разработчиками в МТ4, а не "прогером".
МТ4, при включении, запускает все инструменты, init, start (1 раз) и все это на старых данных последнего вашего включения. И только после этого идет обновление данных. Таким образом, использовать специальную одноразовую функцию init для одноразовой инициализации параметров, содержащих данные по рынку, невозможно!
Почему бы не сделать корректно, обновить данные и на них запустить все инструменты? И всё. Как инженер, я понимаю, что могут существовать проблемы реализации того или иного алгоритма, но, в данном случае, это маловероятно.
Кстати, сама же MQ на это и "напарывается". Посмотрите код элементарного встроенного индикатора Volumes. Для организации инициализации индикатора на исторических барах графика в блоке start они используют хитроумную функцию IndicatorCounted() и в результате не менее хитроумных вычислений они пытаются свести цикл к одному срабатыванию.
Код:
int start()
  {
   int    i,nLimit,nCountedBars;
//---- bars count that does not changed after last indicator launch.
   nCountedBars=IndicatorCounted();
//---- last counted bar will be recounted
   if(nCountedBars>0) nCountedBars--;
   nLimit=Bars-nCountedBars;
//----
   for(i=0; i<nLimit; i++)
     {
      double dVolume=Volume[i];
      if(i==Bars-1 || dVolume>Volume[i+1])
        {
         ExtVolumesBuffer[i]=dVolume;
         ExtVolumesUpBuffer[i]=dVolume;
         ExtVolumesDownBuffer[i]=0.0;        
        }
      else
        {
         ExtVolumesBuffer[i]=dVolume;
         ExtVolumesUpBuffer[i]=0.0;
         ExtVolumesDownBuffer[i]=dVolume;        
        } 
     }        
//---- done
   return(0);
  }
"Пытаются" потому что это не удаётся. Запись в буфера происходит 2 а то и 3 раза. И это на каждом тике, которые следуют с промежутком до 50 мс, а то и меньше. Даже обычный флаг однократного срабатывания вместо всех этих вычислений, о котором говорил Vladradon, работает корректней и "ест" меньше.
Код:
int start()
  {
 int    i,nLimit,nCountedBars;  
double dVolume=Volume[i];
      if(dVolume>Volume[i+1])//i==Bars-1 || 
        {
         ExtVolumesUpBuffer[i]=dVolume;
         ExtVolumesDownBuffer[i]=0.0;        
        }
      else
        {
         ExtVolumesBuffer[i]=dVolume;
         ExtVolumesUpBuffer[i]=0.0;
         ExtVolumesDownBuffer[i]=dVolume;        
        }   
  if (bOn)
   { 
//---- bars count that does not changed after last indicator launch.
   nCountedBars=IndicatorCounted();
//---- last counted bar will be recounted
Print("nCountedBars = ",nCountedBars);
   if(nCountedBars>0) nCountedBars--;
Print("nCountedBars-- = ",nCountedBars);   
   nLimit=Bars-nCountedBars-1;

//Print("nLimit0 = ",nLimit,"  i0 = ",i);//----
 
   for(i=0; i<nLimit; i++)
     {
      dVolume=Volume[i];
      if(i==Bars-1 || dVolume>Volume[i+1])
        {
         ExtVolumesUpBuffer[i]=dVolume;
         ExtVolumesDownBuffer[i]=0.0;        
        }
      else
        {
         ExtVolumesBuffer[i]=dVolume;
         ExtVolumesUpBuffer[i]=0.0;
         ExtVolumesDownBuffer[i]=dVolume;        
        } 
     }        
    bOn=0;
    } //if (bOn) 

//---- done
   return(0);
  }
А, если бы MQ имел алгоритм работы функции init, упомянутый мной выше, не нужно было бы изощрятся.
Когда я начинал изучать MQL4 у меня стоял МТ4 билд 12. Я думал, что к настоящему моменту подобного уровня баги устранены, как и окно нового ордера на все графики с которым ничего невозможно сделать.
 

ALEKSUS

Активный участник
Подскажите, как в этом коде сделать чтоб сигнал появлялся на текущей свече, а не на следующей ?

datetime TimeArray[];
int i,limit,y=0,counted_bars=IndicatorCounted();
ArrayCopySeries(TimeArray,MODE_TIME,Symbol(),TimeFrame);

limit=Bars-counted_bars;
for(i=0,y=0;i<limit;i++)
{
if (Time<TimeArray[y]) y++;
if (G_ibuf_80 <= G_ibuf_84)
{......
 

vlad_123

Местный знаток
МТ4, при включении, запускает все инструменты, init, start (1 раз) и все это на старых данных последнего вашего включения.

Надо же... оО
Метаквоты, значит, безбожно врут вот здесь _https://book.mql4.com/ru/programm/special
И мне как-то не везет с выполнением start при запуске терминалов в выходные - не показывают комменты, обновляемые при каждом вызове.
В любом случае - прошу предоставить работающий пример кода, который подтвердит ваши слова. Запущу его с отключенным интернетом и убедюсь в коварности MQL.

Для организации инициализации индикатора на исторических барах графика в блоке start они используют хитроумную функцию IndicatorCounted() и в результате не менее хитроумных вычислений они пытаются свести цикл к одному срабатыванию.

Кстати, данная хитроумная функция - не костыль для "корявой" имплементации MQL, а оптимизация вычислений в первую очередь тяжелых по расчетам индикаторов.
 

mobidik

-----
МТ4, при включении, запускает все инструменты, init, start (1 раз) и все это на старых данных последнего вашего включения

А мне вот интересно, как в таком случае у Вас хоть что-то запустилось в самый первый раз?

Когда я начинал изучать MQL4 у меня стоял МТ4 билд 12

Вы как тогда плохо изучили предмет, так и сейчас "не в теме"...
К Вашему сведению, если не ошибаюсь, с 1 апреля 2014 года, метаквоты перестали поддерживать "старый" билд, а в новых, теперешних, нет функции IndicatorCounted().
Вообщем, учите матчасть.
 

vladradon

Программист
Насколько я знаю, start() сейчас используется только в скриптах, хотя в индюках еще работает. У меня, возможно, похожая ситуация была недавно с одним индюком, которого я в итоге вообще перенес в сова как функцию с ограничением расчетных баров - намного быстрее все стало работать, а минус в том, что я не стал визуализировать индикатор и на графике он ничего не рисует - только сигнал.
P.S. У меня очередной глюк на этом форуме (другие сайты форекссистемс работают нормально) - на одном браузере не открывается последняя страница (тупо открывает предыдущую) а на другом не работает цитирование... И это уже второй раз так - вопрос к модераторам!:please:
А вообще - у меня все функции и в индюках и совах работают и компилируются по-старому без проблем и только режим #property strict иногда заставляет корректировать код.
 
Последнее редактирование:

vlad_123

Местный знаток
P.S. У меня очередной глюк на этом форуме (другие сайты форекссистемс работают нормально) - на одном браузере не открывается последняя страница (тупо открывает предыдущую)

+1
Периодически один из топиков данного форума упорно открывается (Chrome) за несколько страниц до последней, кликание по ссылке на другой номер страницы или на УРЛ с "&goto=newpost" - ни к чему не приводит.
В это же самое время, другие топики работают нормально.
 

Elvis Burunduk

Элитный участник
на одном браузере не открывается последняя страница (тупо открывает предыдущую)

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

vladradon

Программист
Элвис, если б было все так просто... Ты куда пропал? Звякни мне на скайп - есть тема. Ато с прошлого праздника ты так на связь и не выходишь...:nda::D
 

mobidik

-----
Сэр, уж вам бы следовало бы уметь загуглить... ;)
_https://docs.mql4.com/ru/customind/indicatorcounted

И что? Причем тут гугл, когда должно быть понимание? Единственное, что Вы могли бы ответить, так это то, что данная ф-ция все еще поддерживается терминалом и только. В старых билдах ф-ция IndicatorCounted(), в индикаторах работает совместно с ф-цией start(), т.е., необходимо, как минимум, две ф-ции. Это актуально для билдов до 509. Во всех последующих вместо ф-ции start() уже используется OnCalculate(). Вот тут, Ваше умение пользоваться гуглом Вам поможет, Вы узнаете как она работает и какое возвращает значение, назначение первых двух параметров: rates_total и prev_calculated - с которыми можно провести параллель по отношению к IndicatorCounted() и Bars() и после этого Вам станет понятно, почему перестала использоваться данная ф-ция, но, повторюсь, все еще поддерживается. Так же, по Вашей ссылочке, перейдите на форум и узнаете много нареканий на работу ф-ции IndicatorCounted(), что в итоге, для её использования в индикаторах, метаквоты от неё отказались.
 

vladradon

Программист
Вот,отчасти, почему я не люблю индюки и все предрасчеты переношу в сова.:nda:
 

vlad_123

Местный знаток
а в новых, теперешних, нет функции IndicatorCounted().
Вообщем, учите матчасть.
данная ф-ция все еще поддерживается терминалом и только.
Ее нет, но она поддерживается? :facepalm:
И чисто к сведению - величина сарказма не является показателем компетентности.
 

eevviill2

Местный знаток
Элвис, если б было все так просто... Ты куда пропал? Звякни мне на скайп - есть тема. Ато с прошлого праздника ты так на связь и не выходишь...:nda::D

Я здесь. Смотрю как ты опять тупишь и как тебя глючит:D
Насколько я знаю, start() сейчас используется только в скриптах...
P.S. У меня очередной глюк...

Не start(), OnStart()
 

mobidik

-----
Я здесь. Смотрю как ты опять тупишь и как тебя глючит:D

Ох, Вася, Вася, вот ведь толковый же мужик.., прекращай грибочки покуривать, а то, что-то тебя заносит порой.

vladradon то обращался к Elvis Burunduk, ох и услышишь ты от него в свой адрес, а остальным потом читай вашу очередную "любовную" переписку.
 

vladradon

Программист
mobidik, цитирование пока не работает, поэтому общим текстом: мне совсем не интересно что-то кому-то доказывать (я имею ввиду eevviill2 во втором его пришествии) и не я первый начинаю разборки - это можно посмотреть в истории. Стукни мне в скайп - есть темы и может что-то заинтересует...
 

ALEKSUS

Активный участник
Подскажите, как в этом коде сделать чтоб сигнал появлялся на текущей свече, а не на следующей ?

datetime TimeArray[];
int i,limit,y=0,counted_bars=IndicatorCounted();
ArrayCopySeries(TimeArray,MODE_TIME,Symbol(),TimeFrame);

limit=Bars-counted_bars;
for(i=0,y=0;i<limit;i++)
{
if (Time<TimeArray[y]) y++;
if (G_ibuf_80 <= G_ibuf_84)
{......


вопрос снят, сам сделал.
 
Верх