[Les indicateurs ne sont pas correctement instanciés lorsqu'ils sont appelés/créés à partir d'un indicateur d'une période de travail différente. - page 3

 
Stanislav Korotky:
Poser une question plus spécifique avec un exemple de code. Il peut y avoir des bogues. L'approche fonctionne pour moi.

Voici un exemple de code où l'accès à l'indicateur a échoué. Même après avoir bouclé, rafraîchi, attendu (deux méthodes d'attente différentes).

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

Et voici le résultat :

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


60 OnCalculate MAIN_LINE Taille du tampon = -1 | Appel (1) Sleep(200)

60 OnCalculer MAIN_LINE Taille du tampon = -1 | Appel (2) Sleep(300)

60 OnCalculer MAIN_LINE Taille du tampon = -1 | Appel (3) Sleep(400)

60 OnCalculer MAIN_LINE Taille du tampon = -1 | Appel (4) Sleep(500)

60 OnCalculer MAIN_LINE Taille du tampon = -1 | Appel (5) Sleep(600)

60 OnCalculer MAIN_LINE Taille du tampon = -1 | Appel (6) Sleep(700)

60 OnCalculer MAIN_LINE Taille du tampon = -1 | Appel (7) Sleep(800)

60 OnCalculer MAIN_LINE Taille du tampon = -1 | Appel (8) Sleep(900)

60 OnCalculer MAIN_LINE Taille du tampon = -1 | Appel (9) Sleep(1000)

60 OnCalculer MAIN_LINE Taille du tampon = -1 | Appel (10) Sleep(1100)

Temps entre Create et Refresh() = 00:00:11

Données demandées non trouvées

81 OnCalculateMAIN_LINE Taille du tampon = 1024 | Valeur H1 iMA(0) = 113.227 | Nombre de tics = 2

81 OnCalculateMAIN_LINE Taille du tampon = 1024 | H1 Valeur iMA(1) = 113.269 | Tick-count = 2

81 OnCalculateMAIN_LINE Taille du tampon = 1024 | H1 Valeur iMA(2) = 113.313 | Tick-count = 2

















 
nicholishen:

Voici un exemple de code où l'accès à l'indicateur a échoué. Même après avoir bouclé, rafraîchi, attendu (deux méthodes d'attente différentes).

         Sleep(sleep);


Sleep ne va pas fonctionner sur un indicateur ; vous ne pouvez pas interrompre le thread de l'interface.

Essayez plutôt avec OnTimer().

 
honest_knave:

Sleep ne va pas fonctionner sur un indicateur ; vous ne pouvez pas interrompre le thread de l'interface.

Essayez plutôt avec OnTimer().

Voilà, c'est fait ! C'est la solution de contournement ! Je pourrais vous embrasser !

Cela permet à OnInit() de retourner à la plateforme et à OnTimer() de passer outre et d'appeler pour la deuxième passe. J'ai réglé EventSetMillisecondTimer à seulement 1ms et ne l'ai appelé qu'une fois et maintenant ça marche.

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


Sortie :

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

OnTimer réglé sur 1 ms

75 OnCalculateMAIN_LINE Taille du tampon = 1024 | Valeur H1 iMA(0) = 113.142 | Tick-count = 2

75 OnCalculateMAIN_LINE Taille du tampon = 1024 | H1 Valeur iMA(1) = 113.181 | Tick-count = 2

 
nicholishen:

C'est ça ! C'est la solution de rechange ! Je pourrais t'embrasser, mec !

Pas de problème, j'accepte les virements bancaires et toutes les principales cartes de crédit... 100 dollars, c'est ça ?
 
nicholishen:

C'est ça ! C'est la solution de rechange ! Je pourrais t'embrasser, mec !

Cool !

Je t'ai suggéré d'utiliser un minuteur. Tu as répondu que ça ne marchait pas pour toi. Je t'ai demandé un exemple de ce que tu as essayé. Mais tu as dit que tu ne pouvais pas poster plus de détails que ce que tu avais déjà fait.

Maintenant, un autre homme vous a suggéré le minuteur et vous semblez en être satisfait ;-)

 
Stanislav Korotky:

Cool !

Je t'ai suggéré d'utiliser un minuteur. Tu as répondu que ça ne marchait pas pour toi. J'ai demandé un exemple de ce que tu as essayé. Mais vous avez dit que vous ne pouviez pas poster plus de détails que ce que vous avez déjà fait.

Maintenant, un autre homme vous a suggéré le minuteur et vous semblez en être satisfait ;-)

Hé ! Arrêtez d'essayer d'empiéter sur mes 150 $ !
 
Stanislav Korotky:

Cool !

Je t'ai suggéré d'utiliser un minuteur. Tu as répondu que ça ne marchait pas pour toi. J'ai demandé un exemple de ce que tu as essayé. Mais vous avez dit que vous ne pouviez pas poster plus de détails que ce que vous avez déjà fait.

Maintenant, un autre homme vous a suggéré le minuteur et vous semblez en être satisfait ;-)

Et nous avons maintenant un bug MT5 corrigé...
 
honest_knave:
Pas de problème, j'accepte les virements bancaires et toutes les principales cartes de crédit... 100 dollars n'est-ce pas ?

100 $ ?! ...Je pensais offrir plus...

Forum sur le trading, les systèmes de trading automatisés et les tests de stratégies de trading

[BUG MQL5] [SOLVÉ]Les indicateurs ne sont pas correctement instanciés lorsqu'ils sont appelés/créés à partir d'un indicateur de période de travail différente.

Stanislav Korotky, 2017.02.01 09:27

Cool !

Je vous ai suggéré d'utiliser un timer. Vous avez répondu que cela ne fonctionnait pas pour vous. J'ai demandé un exemple de ce que vous avez essayé. Mais vous avez dit que vous ne pouvez pas poster plus de détails que ce que vous avez déjà fait.

Maintenant, un autre homme vous a suggéré le minuteur et vous semblez en être satisfait ;-)


Désolé, je n'avais pas compris ce que vous vouliez dire par là, jusqu'à maintenant. Je vous considère comme partenaires avec le chevalier, et puisque personne n'a posté un modèle de travail, je vais décider que la prime sera de 50% - divisée en deux : Donc c'est... mm... portez les deux... Et si je vous payais une bière à tous les deux ? Sérieusement, envoyez-moi une adresse BTC et je m'assurerai que vous soyez tous deux rémunérés :)

Je tiens à vous remercier tout particulièrement pour toute votre aide... sans votre condescendance, je ne sais pas où j'aurais trouvé la motivation de m'acharner ! /s

 
nicholishen:

Sérieusement, envoyez-moi une adresse BTC et je m'assurerai que vous soyez tous deux rémunérés :)

Une offre généreuse mais inutile. Content que vous ayez réglé le problème.
 
Je suis en train de clore cette affaire avec le service d'assistance, mais au cas où MetaQuotes lise ceci, je considère toujours que c'est un défaut majeur de la plateforme. S'il s'agit d'un problème de threading, il devrait y avoir une meilleure façon de gérer ce type d'événements qu'en introduisant arbitrairement un temps d'attente (estimé) dans le code.