[SOLVED] Indicators are not properly instantiated when called/created from an Indicator of different working time-frame. - page 3

 
Stanislav Korotky:
Post more specific question with a sample code. It may be buggy. The approach works for me.

Here is a code example of failed indicator access. Even after looping, refreshing, waiting (two different methods of waiting). 

//+------------------------------------------------------------------+
//|                                                    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;
}

 And here's the ouput:

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


60 OnCalculate MAIN_LINE Buffer size = -1 | Call (1) Sleep(200)

60 OnCalculate MAIN_LINE Buffer size = -1 | Call (2) Sleep(300)

60 OnCalculate MAIN_LINE Buffer size = -1 | Call (3) Sleep(400)

60 OnCalculate MAIN_LINE Buffer size = -1 | Call (4) Sleep(500)

60 OnCalculate MAIN_LINE Buffer size = -1 | Call (5) Sleep(600)

60 OnCalculate MAIN_LINE Buffer size = -1 | Call (6) Sleep(700)

60 OnCalculate MAIN_LINE Buffer size = -1 | Call (7) Sleep(800)

60 OnCalculate MAIN_LINE Buffer size = -1 | Call (8) Sleep(900)

60 OnCalculate MAIN_LINE Buffer size = -1 | Call (9) Sleep(1000)

60 OnCalculate MAIN_LINE Buffer size = -1 | Call (10) Sleep(1100)

Time Between Create and Refresh() = 00:00:11

Requested data not found

81 OnCalculateMAIN_LINE Buffer size = 1024 | H1 iMA(0) value = 113.227 | Tick-count = 2

81 OnCalculateMAIN_LINE Buffer size = 1024 | H1 iMA(1) value = 113.269 | Tick-count = 2

81 OnCalculateMAIN_LINE Buffer size = 1024 | H1 iMA(2) value = 113.313 | Tick-count = 2 

















 
nicholishen:

Here is a code example of failed indicator access. Even after looping, refreshing, waiting (two different methods of waiting). 

         Sleep(sleep);


Sleep isn't going to work on an indicator; you can't interrupt the interface thread.

Try it with OnTimer() instead. 

 
honest_knave:

Sleep isn't going to work on an indicator; you can't interrupt the interface thread.

Try it with OnTimer() instead. 

That's it! That's the workaround! I could kiss you man!

This lets the OnInit() return to the platform and OnTimer() to skip over it and call for the second pass. I set EventSetMillisecondTimer to just 1ms and only called it once and now it's working. 

 

//+------------------------------------------------------------------+
//|                                                    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);
}
//+------------------------------------------------------------------+


 Output:

 

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

OnTimer set to 1 ms

75 OnCalculateMAIN_LINE Buffer size = 1024 | H1 iMA(0) value = 113.142 | Tick-count = 2

75 OnCalculateMAIN_LINE Buffer size = 1024 | H1 iMA(1) value = 113.181 | Tick-count = 2 

 
nicholishen:

That's it! That's the workaround! I could kiss you man!

No problem, I accept bank transfers and all major credit cards... $100 wasn't it? 
 
nicholishen:

That's it! That's the workaround! I could kiss you man!

Cool!

I suggested you to use a timer. You answered that it didn't work for you. I asked for an example of what you have tried. But you said you can't post more details than already did.

Now another man suggested you the timer and you seems happy with it. ;-)

 
Stanislav Korotky:

Cool!

I suggested you to use a timer. You answered that it didn't work for you. I asked for an example of what you have tried. But you said you can't post more details than already did.

Now another man suggested you the timer and you seems happy with it. ;-)

Hey! Stop trying to muscle-in on my $150!
 
Stanislav Korotky:

Cool!

I suggested you to use a timer. You answered that it didn't work for you. I asked for an example of what you have tried. But you said you can't post more details than already did.

Now another man suggested you the timer and you seems happy with it. ;-)

And we have now an MT5 bug fixed...
 
honest_knave:
No problem, I accept bank transfers and all major credit cards... $100 wasn't it? 

$100?! ...I thought I offered more... 

Forum on trading, automated trading systems and testing trading strategies

[MQL5 BUG] [SOLVED]Indicators are not properly instantiated when called/created from an Indicator of different working time-frame.

Stanislav Korotky, 2017.02.01 09:27

Cool!

I suggested you to use a timer. You answered that it didn't work for you. I asked for an example of what you have tried. But you said you can't post more details than already did.

Now another man suggested you the timer and you seems happy with it. ;-)


 Sorry I didn't understand what you meant by that, until now. I'll consider you partners with knave, and since nobody posted a working model, I'm going to rule that the bounty will be 50% - split two ways: So that's...mm...carry the two... How bout I buy you both a beer? Seriously, PM me a BTC address and I'll make sure you're both compensated :) 

I want to especially thank you for all your help... if it weren't for your condescension I don't know where I would've found the motivation to strive on! /s

 
nicholishen:

Seriously, PM me a BTC address and I'll make sure you're both compensated :) 

a generous offer but unnecessary. Glad you got it sorted.
 
I'm closing this out with the service desk, but in case MetaQuotes is reading this I still consider this to be a major flaw in the platform. If this is an issue with threading there should be a better way to handle these type of events than by arbitrarily throwing (a guessed amount) wait time into the code.