Любые вопросы новичков по MQL4 и MQL5, помощь и обсуждение по алгоритмам и кодам - страница 2497

 
Artyom Trishkin #:

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

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

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

Как всё красиво описано и много букв - информативно! Но да, это и происходит в реальности, о чём знают не все.

Artyom Trishkin #:

Для чего вот это?

У меня примерно также, но Я отказался от iBars()

// ENUM_TIMEFRAMES timeFrames[] = {PERIOD_M15,PERIOD_M30,PERIOD_H1,PERIOD_H4};
CountTF = 4;
for(int i=0; i<CountTF; i++) {
      long b=SeriesInfoInteger(Symbol(),timeFrames[i],SERIES_BARS_COUNT);
      //Print("Histiry ",timeFrameToString(timeFrames[i]),", bar=",b);
      if(b<10) {
        Print("Download histiry ",timeFrameToString(timeFrames[i]),", bar=",b);
        ChartSetSymbolPeriod(0,NULL,0); // ???
        return(0);
      }
    }
 // далее код выполнения

Принты остались с момента, когда Я его запустил, далее их нет

--

Как видно, иногда мало одно раза, чтобы получить другой период, так что цикл вряд-ли поможет

 
Vitaly Muzichenko #:
Как видно, иногда мало одно раза, чтобы получить другой период, так что цикл вряд-ли поможет
Да. Такую ситуацию я обрабатывал в статье тоже. 
 
Artyom Trishkin #:
Да. Такую ситуацию я обрабатывал в статье тоже. 

У вас появилось красивое решение?

 
Vitaly Muzichenko #:

У вас появилось красивое решение?

Нет. Обычные наляпанные "костыли", обрабатывающие возможные возникающие ситуации. Просто в лоб.

Но нужно понимание, что

  1. таймсерии в терминале строятся от младшей к старшей,
  2. исходя из п.1, мы не сможем на одном тике получить вместе с данными текущего периода графика данные старшего графика без использования OnChartEvent(),
  3. нужно все используемые таймсерии для расчёта держать в "горячем" виде, обращаясь к ним не реже, чем каждые две минуты, используя для этого OnTimer(),
  4. чтобы индикатор, использующий для построения данные с неродного таймфрейма, мог быть отображён на графике в выходные дни или при очень редких тиках, необходимо его время от времени "подпинывать" принудительной эмуляцией тика,
  5. в выходные дни для отрисовки индикатора контролировать prev_calculated, который обнуляется при возникновении редких странных тиков, после которых индикатор обнуляется, и для его перерисовки необходимо эмулировать ещё один тик.
  6. если данные с одной эмуляции получить не удалось, необходимо их дождаться в контролируемом цикле; обычно достаточно до пяти раз послать тик.

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

Всё это описывалось в статье. Повторяться точнее и подробнее уже лень.

 
Artyom Trishkin #:

Нет. Обычные наляпанные "костыли", обрабатывающие возможные возникающие ситуации. Просто в лоб.

Но нужно понимание, что

  1. таймсерии в терминале строятся от младшей к старшей,
  2. исходя из п.1, мы не сможем на одном тике получить вместе с данными текущего периода графика данные старшего графика без использования OnChartEvent(),
  3. нужно все используемые таймсерии для расчёта держать в "горячем" виде, обращаясь к ним не реже, чем каждые две минуты, используя для этого OnTimer(),
  4. чтобы индикатор, использующий для построения данные с неродного таймфрейма, мог быть отображён на графике в выходные дни или при очень редких тиках, необходимо его время от времени "подпинывать" принудительной эмуляцией тика,
  5. в выходные дни для отрисовки индикатора контролировать prev_calculated, который обнуляется при возникновении редких странных тиков, после которых индикатор обнуляется, и для его перерисовки необходимо эмулировать ещё один тик.
  6. если данные с одной эмуляции получить не удалось, необходимо их дождаться в контролируемом цикле; обычно достаточно до пяти раз послать тик.

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

Всё это описывалось в статье. Повторяться точнее и подробнее уже лень.

Спасибо за развёрнутый ответ!!!

 

Парни, всем привет))) год не открывал редактор, попросили изменить угол привязки индикатора, но как оказалось режим торговли в один клик его перекрывает... можно ли привязку сделать так чтоб при открытии окошка Торговля в один клик индикатор тоже смещался вниз под него??? Если можно - подскажите как и что прописать. Спасибо)))


 
to_ha #:

Парни, всем привет))) год не открывал редактор, попросили изменить угол привязки индикатора, но как оказалось режим торговли в один клик его перекрывает... можно ли привязку сделать так чтоб при открытии окошка Торговля в один клик индикатор тоже смещался вниз под него??? Если можно - подскажите как и что прописать. Спасибо)))

if(ChartGetInteger(0, CHART_SHOW_ONE_CLICK))

Определяешь развёрнута панелька или свёрнута, ну и исходя из этого, смещаешь текст.

Я это применял в замене коммента, посмотри может в коде понятнее будет.

Comment
Comment
  • www.mql5.com
A simple replacement for a comment. Works in the tester 50 times faster than the standard function.
 
Aleksandr Slavskii #:

Определяешь развёрнута панелька или свёрнута, ну и исходя из этого, смещаешь текст.

Я это применял в замене коммента, посмотри может в коде понятнее будет.

Приогромная благодарочка))) обязательно щяс гляну!

 

Всем привет! 

Подскажите, пожалуйста, что не так...

Хочу снять цены на трендовых линиях , которые сам нарисовал....Цены линий нужно снять на каждом баре по времени , даже если линия не проходит через него  (то есть не только в точках фиксирования). С первой линии цену снял, а со второй линии не получается...(

input int QuantBars=7;  // Количество баров выборки
input int c=15       ;  // Количество секунд на таймере


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
  {
   EventSetTimer(c);
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   EventKillTimer();

  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
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[])
  {
//---

//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+


void OnTimer()

  {
   Print("Работает таймер  ",c);

   int i;
   int j;

   string NameLine[];
   double PriceLine[];

   for(j=0; j<=QuantBars; j++)
     {
      for(i=0; i<ObjectsTotal(); i++)
        {

         int Size_NameLine=ArraySize(NameLine);
         int NewSize_NameLine=ArrayResize(NameLine,Size_NameLine+1,100);
         NameLine[Size_NameLine]=ObjectName(i);
         NameLine[i]=ObjectName(i);


         int Size_PriceLine=ArraySize(PriceLine);
         int NewSize_PriceLine=ArrayResize(PriceLine,Size_PriceLine+1,100);
         
         PriceLine[j]= ObjectGetValueByTime(0,NameLine[i],Time[j],i);


         Print("Линия N -  ",i,"  ",NameLine[i],"    Бар N - ", j, "   Цена на линии - ", DoubleToStr(PriceLine[j],Digits));

        }
     }
   return;
  }

//+------------------------------------------------------------------+
 
AlexProf #:
         PriceLine[j]= ObjectGetValueByTime(0,NameLine[i],Time[j],i);

Это лишнее

         PriceLine[j]= ObjectGetValueByTime(0,NameLine[i],Time[j],i);

Здесь должен быть или 0 или ничего, так как 0 прописан по умолчанию