[SOLVED] Индикаторы неправильно инстанцируются при вызове/создании из индикатора другого рабочего таймфрейма. - страница 3

 
Stanislav Korotky:
Задайте более конкретный вопрос с примером кода. Это может быть багги. Этот подход работает для меня.

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

//+------------------------------------------------------------------+
//|                                                    THROWAWAY.mq5 |
//|                                                      nicholishen |
//|                                   www.reddit.com/u/nicholishenFX |
//+------------------------------------------------------------------+
#property copyright "nicholishen"
#property link      "www.reddit.com/u/nicholishenFX"
#property version   "1.00"
#property indicator_chart_window

#include <Indicators\Trend.mqh>
#include <errordescription.mqh>

CiMA ima;
int m_bufferSize = -1;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   static int iCnt = 0;
//--- indicator buffers mapping
      Print("-----------------------",TimeCurrent(),"--------------------------");
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| 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[])
  {
   static int tickCnt = 0;
   tickCnt++;
//---
   if(rates_total != prev_calculated || m_bufferSize < 1 ){
      ResetLastError();
      datetime createTime = TimeCurrent();
      ima.Create(_Symbol,PERIOD_H1,20,0,MODE_SMA,PRICE_CLOSE);
      ima.Refresh(); //no wait time!
          
      CIndicatorBuffer *buff = ima.At(0);
      m_bufferSize = buff.Total();
      int call = 0;
      int sleep = 200;
      // try with Sleep function ...
      while(buff.Total() <= 0 && call < 10){
         Sleep(sleep);
         ima.Refresh(); // Refreshed 10x since create
         m_bufferSize = buff.Total();
         call++;
         Print(__LINE__," ",__FUNCTION__," ",buff.Name(),
               " Buffer size = ",m_bufferSize," | Call (",
               call,")"," Sleep(",sleep,")"
               );
         sleep+=100;
        
      }
      // try wait with looping  
      if(buff.Total() <=0){
         datetime waitTime = timeLoop(createTime);
         Print("Time Between Create and Refresh() = ",TimeToString(waitTime,TIME_SECONDS));
         ima.Refresh();
         m_bufferSize = buff.Total();
      }
      if(m_bufferSize < 1){
         Print(ErrorDescription(GetLastError()));
         return(rates_total);
      } else {
         for(int i=0;i<m_bufferSize;i++){
            if(i>2return(rates_total);
            else{
               Print(__LINE__," ",__FUNCTION__,buff.Name(),
                     " Buffer size = ",m_bufferSize,
                     " | ",ima.PeriodDescription()," iMA(",i,") value = ",
                     DoubleToString(ima.Main(i),_Digits),
                     " | Tick-count = ",tickCnt
                     );  
            }
         }
      }
   }
//--- return value of prev_calculated for next call
   return(rates_total);
}
//+------------------------------------------------------------------+
void OnDeinit(const int reason){

}

datetime timeLoop(datetime timeIn){
   int cnt = 0;
   while(TimeCurrent() - timeIn < 10 && !IsStopped()){
      Comment("Time looping i = ",cnt);
      cnt++;
   }
   return TimeCurrent() - timeIn;
}

И вот результат:

-----------------------2017.01.31 23:48:03--------------------------


60 OnCalculate MAIN_LINE Размер буфера = -1 | Call (1) Sleep(200)

60 OnCalculate MAIN_LINE Размер буфера = -1 | Вызов (2) Sleep(300)

60 OnCalculate MAIN_LINE Размер буфера = -1 | Вызов (3) Sleep(400)

60 OnCalculate MAIN_LINE Размер буфера = -1 | Вызов (4) Sleep(500)

60 OnCalculate MAIN_LINE Размер буфера = -1 | Вызов (5) Sleep(600)

60 OnCalculate MAIN_LINE Размер буфера = -1 | Вызов (6) Sleep(700)

60 OnCalculate MAIN_LINE Размер буфера = -1 | Вызов (7) Sleep(800)

60 OnCalculate MAIN_LINE Размер буфера = -1 | Вызов (8) Sleep(900)

60 OnCalculate MAIN_LINE Размер буфера = -1 | Вызов (9) Sleep(1000)

60 OnCalculate MAIN_LINE Размер буфера = -1 | Вызов (10) Sleep(1100)

Время между созданием и обновлением() = 00:00:11

Запрашиваемые данные не найдены

81 OnCalculateMAIN_LINE Размер буфера = 1024 | Значение H1 iMA(0) = 113.227 | Tick-count = 2

81 OnCalculateMAIN_LINE Размер буфера = 1024 | H1 iMA(1) значение = 113.269 | Tick-count = 2

81 OnCalculateMAIN_LINE Размер буфера = 1024 | H1 iMA(2) значение = 113.313 | Tick-count = 2

















 
nicholishen:

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

         Sleep(sleep);


Sleep не сработает на индикаторе; вы не можете прервать поток интерфейса.

Попробуйте вместо этого использовать OnTimer().

 
honest_knave:

Sleep не будет работать на индикаторе; вы не можете прервать поток интерфейса.

Попробуйте вместо этого использовать OnTimer().

Вот и все! Это обходной путь! Я могу тебя расцеловать!

Это позволяет OnInit() вернуться к платформе, а OnTimer() пропустить ее и вызвать для второго прохода. Я установил EventSetMillisecondTimer на 1 мс и вызвал его только один раз, и теперь он работает.

//+------------------------------------------------------------------+
//|                                                    THROWAWAY.mq5 |
//|                                                      nicholishen |
//|                                   www.reddit.com/u/nicholishenFX |
//+------------------------------------------------------------------+
#property copyright "nicholishen"
#property link      "www.reddit.com/u/nicholishenFX"
#property version   "1.00"
#property indicator_chart_window

#include <Indicators\Trend.mqh>
#include <errordescription.mqh>

CiMA ima;
int m_bufferSize = -1;
bool timedEvent = false;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
      int waitMS = 1;
      Print("-----------------------",TimeCurrent(),"--------------------------");
  
      ima.Create(_Symbol,PERIOD_H1,20,0,MODE_SMA,PRICE_CLOSE);
      EventSetMillisecondTimer(waitMS);
      Print("OnTimer set to ",waitMS," ms");
      
//---
   return(INIT_SUCCEEDED);
  }

void OnTimer()
  {
//---
   ima.Refresh();
   EventKillTimer();
   timedEvent = true;
  
  }
//+------------------------------------------------------------------+
//| 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[])
  {

   static int tickCnt = 0;
   tickCnt++;
  
   if(!timedEvent)return rates_total;
//---
   if(rates_total != prev_calculated || m_bufferSize < 1 ){
      ResetLastError();
      CIndicatorBuffer *buff = ima.At(0);
      m_bufferSize = buff.Total();
      if(m_bufferSize <=0) ima.Refresh();
      // try wait with looping  
      
      if(m_bufferSize < 1){
         Print(ErrorDescription(GetLastError()));
        
      } else {
         for(int i=0;i<m_bufferSize;i++){
            if(i>2) break;
            else{
               Print(__LINE__," ",__FUNCTION__,buff.Name(),
                     " Buffer size = ",m_bufferSize,
                     " | ",ima.PeriodDescription()," iMA(",i,") value = ",
                     DoubleToString(ima.Main(i),_Digits),
                     " | Tick-count = ",tickCnt
                     );  
            }
         }
      }
   }
//--- return value of prev_calculated for next call
   return(rates_total);
}
//+------------------------------------------------------------------+


Выходные данные:

-----------------------2017.02.01 01:31:01--------------------------

OnTimer установлен на 1 мс

75 OnCalculateMAIN_LINE Размер буфера = 1024 | H1 iMA(0) value = 113.142 | Tick-count = 2

75 OnCalculateMAIN_LINE Размер буфера = 1024 | H1 iMA(1) значение = 113.181 | Tick-count = 2

 
nicholishen:

Вот оно! Это обходной путь! Я могу поцеловать тебя!

Без проблем, я принимаю банковские переводы и все основные кредитные карты... 100 долларов, не так ли?
 
nicholishen:

Вот оно! Это обходной путь! Я могу поцеловать тебя!

Круто!

Я предложил тебе использовать таймер. Вы ответили, что это вам не подходит. Я попросил привести пример того, что вы пробовали. Но вы сказали, что не можете опубликовать больше деталей, чем уже сделали.

Теперь другой человек предложил вам таймер, и вы, кажется, довольны им. ;-)

 
Stanislav Korotky:

Круто!

Я предложил вам использовать таймер. Вы ответили, что это вам не подходит. Я попросил привести пример того, что вы пробовали. Но вы сказали, что не можете опубликовать больше деталей, чем уже сделали.

Теперь другой человек предложил вам таймер, и вы, кажется, довольны им. ;-)

Эй! Прекратите пытаться влезть в мои $150!
 
Stanislav Korotky:

Круто!

Я предложил вам использовать таймер. Вы ответили, что это вам не подходит. Я попросил привести пример того, что вы пробовали. Но вы сказали, что не можете опубликовать больше деталей, чем уже сделали.

Теперь другой человек предложил вам таймер, и вы, кажется, довольны им. ;-)

И теперь у нас есть исправленная ошибка MT5...
 
honest_knave:
Нет проблем, я принимаю банковские переводы и все основные кредитные карты... $100, не так ли?

100 долларов?! ...я думал, что предлагаю больше...

Форум о трейдинге, автоматических торговых системах и тестировании торговых стратегий

[MQL5 BUG][SOLVED]Индикаторы неправильно инстанцируются при вызове/создании из индикатора другого рабочего таймфрейма.

Станислав Короткий, 2017.02.01 09:27

Круто!

Я предлагал вам использовать таймер. Вы ответили, что он у вас не работает. Я попросил привести пример того, что вы пробовали. Но вы сказали, что не можете опубликовать больше деталей, чем уже сделали.

Теперь другой человек предложил вам таймер, и вы, кажется, довольны им. ;-)


Извините, я не понимал, что вы имели в виду, до сих пор. Я буду считать вас партнерами с knave, и поскольку никто не выложил рабочую модель, я буду считать, что баунти будет 50% - делится на двоих: Так что... мм... несите вдвоем... Как насчет того, чтобы угостить вас обоих пивом? Серьезно, пришлите мне адрес BTC и я позабочусь о том, чтобы вы оба получили компенсацию :)

Хочу особо поблагодарить Вас за помощь... если бы не Ваша снисходительность, не знаю, где бы я нашла мотивацию стремиться дальше! /s

 
nicholishen:

Серьезно, сообщите мне адрес BTC, и я позабочусь о том, чтобы вы оба получили компенсацию :)

щедрое предложение, но ненужное. Рад, что вы разобрались с этим.
 
Я закрываю этот вопрос в службе поддержки, но если MetaQuotes читает это, я все еще считаю это серьезным недостатком платформы. Если это проблема с потоками, то должен быть лучший способ обработки такого рода событий, чем произвольный выброс (угаданного количества) времени ожидания в код.