[SOLVED] Gli indicatori non vengono istanziati correttamente quando vengono chiamati/creati da un indicatore di un diverso time-frame di lavoro. - pagina 3

 
Stanislav Korotky:
Pubblica una domanda più specifica con un codice di esempio. Potrebbe essere buggato. L'approccio funziona per me.

Ecco un esempio di codice di accesso fallito all'indicatore. Anche dopo il looping, il refresh, l'attesa (due metodi diversi di attesa).

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

Ed ecco l'ouput:

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


60 OnCalculate MAIN_LINE Dimensione del buffer = -1 | Call (1) Sleep(200)

60 OnCalculate MAIN_LINE Dimensione del buffer = -1 | Chiama (2) Sleep(300)

60 OnCalculate MAIN_LINE Dimensione del buffer = -1 | Chiama (3) Sleep(400)

60 OnCalculate MAIN_LINE Dimensione del buffer = -1 | Chiama (4) Sleep(500)

60 OnCalculate MAIN_LINE Dimensione del buffer = -1 | Chiama (5) Sleep(600)

60 OnCalculate MAIN_LINE Dimensione del buffer = -1 | Chiama (6) Sleep(700)

60 OnCalculate MAIN_LINE Dimensione del buffer = -1 | Chiama (7) Sleep(800)

60 OnCalculate MAIN_LINE Dimensione del buffer = -1 | Chiama (8) Sleep(900)

60 OnCalculate MAIN_LINE Dimensione del buffer = -1 | Chiama (9) Sleep(1000)

60 OnCalculate MAIN_LINE Dimensione del buffer = -1 | Chiama (10) Sleep(1100)

Tempo tra la creazione e il refresh() = 00:00:11

Dati richiesti non trovati

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:

Ecco un esempio di codice di accesso fallito all'indicatore. Anche dopo il looping, il refresh, l'attesa (due metodi diversi di attesa).

         Sleep(sleep);


Sleep non funzionerà su un indicatore; non potete interrompere il thread dell'interfaccia.

Provate invece con OnTimer().

 
honest_knave:

Sleep non funzionerà su un indicatore; non potete interrompere il thread dell'interfaccia.

Provate invece con OnTimer().

Ecco fatto! Questo è il workaround! Potrei baciarti, amico!

Questo permette a OnInit() di tornare alla piattaforma e a OnTimer() di saltarla e chiamare per il secondo passaggio. Ho impostato EventSetMillisecondTimer a solo 1ms e l'ho chiamato solo una volta e ora funziona.

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


Uscita:

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

OnTimer impostato su 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:

Questo è tutto! Questa è la soluzione! Potrei baciarti, amico!

Nessun problema, accetto bonifici bancari e tutte le principali carte di credito... 100 dollari, vero?
 
nicholishen:

Questo è tutto! Questa è la soluzione! Potrei baciarti, amico!

Forte!

Ti ho suggerito di usare un timer. Hai risposto che non ha funzionato per te. Ho chiesto un esempio di ciò che hai provato. Ma tu hai detto che non puoi postare più dettagli di quelli che hai già fatto.

Ora un altro uomo ti ha suggerito il timer e tu sembri contento ;-)

 
Stanislav Korotky:

Fico!

Ti ho suggerito di usare un timer. Hai risposto che non ha funzionato per te. Ho chiesto un esempio di ciò che hai provato. Ma tu hai detto che non puoi postare più dettagli di quelli che hai già fatto.

Ora un altro uomo ti ha suggerito il timer e tu sembri contento ;-)

Ehi, smettetela di cercare di fare il prepotente con i miei 150 dollari!
 
Stanislav Korotky:

Fico!

Ti ho suggerito di usare un timer. Hai risposto che non ha funzionato per te. Ho chiesto un esempio di ciò che hai provato. Ma tu hai detto che non puoi postare più dettagli di quelli che hai già fatto.

Ora un altro uomo ti ha suggerito il timer e tu sembri contento ;-)

E ora abbiamo un bug di MT5 risolto...
 
honest_knave:
Nessun problema, accetto bonifici bancari e tutte le principali carte di credito... 100 dollari non era?

100 dollari?! ...pensavo di offrire di più...

Forum sul trading, sistemi di trading automatico e test di strategie di trading

[MQL5 BUG] [SOLVED]Gli indicatori non vengono istanziati correttamente quando vengono chiamati/creati da un indicatore di un diverso time-frame di lavoro.

Stanislav Korotky, 2017.02.01 09:27

Figo!

Ti ho suggerito di usare un timer. Hai risposto che non ha funzionato per te. Ho chiesto un esempio di ciò che hai provato. Ma hai detto che non puoi postare più dettagli di quanto già fatto.

Ora un altro uomo ti ha suggerito il timer e tu sembri contento ;-)


Mi dispiace di non aver capito cosa intendevi con questo, fino ad ora. Vi considererò partner di knave, e dato che nessuno ha postato un modello funzionante, deciderò che la taglia sarà del 50% - divisa in due parti: Quindi questo è...mm...portare i due... Che ne dite se vi offro una birra? Seriamente, PM me un indirizzo BTC e mi assicurerò che siate entrambi compensati :)

Voglio ringraziarti in modo particolare per tutto il tuo aiuto... se non fosse stato per la tua condiscendenza non so dove avrei trovato la motivazione per sforzarmi! /s

 
nicholishen:

Scherzi a parte, mandami un indirizzo BTC e mi assicurerò che siate entrambi compensati :)

un'offerta generosa ma non necessaria. Sono contento che tu abbia risolto il problema.
 
Sto chiudendo questo con il service desk, ma nel caso in cui MetaQuotes stia leggendo questo, continuo a considerare questo come un grande difetto della piattaforma. Se questo è un problema di threading ci dovrebbe essere un modo migliore per gestire questo tipo di eventi piuttosto che buttare arbitrariamente (una quantità indovinata) il tempo di attesa nel codice.