[SOLVED] Los indicadores no se instancian correctamente cuando se llaman/crean desde un indicador de un marco de tiempo de trabajo diferente. - página 3

 
Stanislav Korotky:
Publica una pregunta más específica con un código de ejemplo. Puede ser un error. El enfoque funciona para mí.

Aquí hay un ejemplo de código de acceso fallido al indicador. Incluso después de hacer un bucle, refrescar y esperar (dos métodos diferentes de espera).

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

Y aquí está la salida:

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


60 OnCalculate MAIN_LINE Tamaño del buffer = -1 | Call (1) Sleep(200)

60 OnCalculate MAIN_LINE Tamaño del buffer = -1 | Call (2) Sleep(300)

60 OnCalculate MAIN_LINE Tamaño del buffer = -1 | Call (3) Sleep(400)

60 OnCalculate MAIN_LINE Tamaño del buffer = -1 | Call (4) Sleep(500)

60 OnCalculate MAIN_LINE Tamaño del buffer = -1 | Call (5) Sleep(600)

60 OnCalculate MAIN_LINE Tamaño del buffer = -1 | Call (6) Sleep(700)

60 OnCalculate MAIN_LINE Tamaño del buffer = -1 | Call (7) Sleep(800)

60 OnCalculate MAIN_LINE Tamaño del buffer = -1 | Call (8) Sleep(900)

60 OnCalculate MAIN_LINE Tamaño del buffer = -1 | Call (9) Sleep(1000)

60 OnCalculate MAIN_LINE Tamaño del buffer = -1 | Call (10) Sleep(1100)

Tiempo entre la creación y la actualización() = 00:00:11

Datos solicitados no encontrados

81 OnCalculateMAIN_LINE Tamaño del buffer = 1024 | Valor de H1 iMA(0) = 113.227 | Tick-count = 2

81 OnCalculateMAIN_LINE Tamaño del buffer = 1024 | H1 iMA(1) valor = 113.269 | Tick-count = 2

81 OnCalculateMAIN_LINE Tamaño del buffer = 1024 | H1 iMA(2) valor = 113.313 | Tick-count = 2

















 
nicholishen:

Aquí hay un ejemplo de código de acceso fallido al indicador. Incluso después de hacer un bucle, refrescar, esperar (dos métodos diferentes de espera).

         Sleep(sleep);


Dormir no va a funcionar en un indicador; no se puede interrumpir el hilo de la interfaz.

Inténtelo con OnTimer() en su lugar.

 
honest_knave:

Sleep no va a funcionar en un indicador; no puede interrumpir el hilo de la interfaz.

Inténtalo con OnTimer() en su lugar.

Ya está. ¡Esa es la solución! ¡Podría besarte hombre!

Esto permite que el OnInit() regrese a la plataforma y OnTimer() se salte y llame para el segundo pase. Puse EventSetMillisecondTimer a sólo 1ms y sólo lo llamé una vez y ahora está funcionando.

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


Salida:

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

OnTimer puesto a 1 ms

75 OnCalculateMAIN_LINE Tamaño del buffer = 1024 | H1 iMA(0) valor = 113.142 | Tick-count = 2

75 OnCalculateMAIN_LINE Tamaño del buffer = 1024 | H1 iMA(1) valor = 113.181 | Tick-count = 2

 
nicholishen:

¡Eso es! ¡Esa es la solución! ¡Podría besarte hombre!

No hay problema, acepto transferencias bancarias y todas las principales tarjetas de crédito... ¿100 dólares no era?
 
nicholishen:

¡Eso es! ¡Esa es la solución! ¡Podría besarte hombre!

¡Genial!

Te sugerí que usaras un temporizador. Me respondiste que no te funcionaba. Te pedí un ejemplo de lo que has probado. Pero dijiste que no podías publicar más detalles de lo que ya habías hecho.

Ahora otro hombre te sugirió el temporizador y parece que estás contento con él. ;-)

 
Stanislav Korotky:

¡Genial!

Te sugerí que usaras un temporizador. Me has contestado que no te ha funcionado. Te pedí un ejemplo de lo que has probado. Pero dijiste que no podías publicar más detalles de los que ya habías hecho.

Ahora otro hombre te sugirió el temporizador y parece que estás contento con él. ;-)

¡Oye! ¡Deja de tratar de entrometerte en mis 150 dólares!
 
Stanislav Korotky:

¡Genial!

Te sugerí que usaras un temporizador. Me has contestado que no te ha funcionado. Te pedí un ejemplo de lo que has probado. Pero dijiste que no podías publicar más detalles de los que ya habías hecho.

Ahora otro hombre te sugirió el temporizador y parece que estás contento con él. ;-)

Y ahora tenemos un bug de MT5 arreglado...
 
honest_knave:
No hay problema, acepto transferencias bancarias y todas las principales tarjetas de crédito... ¿100 dólares no era?

¡¿100 dólares?! ...pensé que ofrecía más...

Foro sobre el comercio, los sistemas de comercio automatizado y la prueba de estrategias de negociación

[MQL5 BUG] [SOLVED]Los indicadores no se instancian correctamente cuando se llaman/crean desde un indicador de diferente marco temporal de trabajo.

Stanislav Korotky, 2017.02.01 09:27

¡¡¡Genial!!!

Te sugerí que usaras un temporizador. Me respondiste que no te funcionaba. Te pedí un ejemplo de lo que has probado. Pero me dijiste que no podías postear más detalles de los que ya lo hiciste.

Ahora otro hombre te sugirió el temporizador y parece que estás contento con él. ;-)


Perdona que no haya entendido lo que querías decir, hasta ahora. Os consideraré socios de knave, y como nadie ha posteado un modelo de trabajo, voy a dictaminar que la recompensa será del 50% - dividida en dos partes: Así que eso es... mm... llevar a los dos... ¿Qué tal si os invito a los dos a una cerveza? En serio, envíame un PM con una dirección de BTC y me aseguraré de que ambos sean compensados :)

Quiero agradecerte especialmente toda tu ayuda... ¡si no fuera por tu condescendencia no sé de dónde habría sacado la motivación para esforzarme! /s

 
nicholishen:

En serio, pásame una dirección de BTC y me aseguraré de que ambos seáis compensados :)

Una oferta generosa pero innecesaria. Me alegro de que lo hayas solucionado.
 
Estoy cerrando esto con el servicio de atención al cliente, pero en caso de que MetaQuotes esté leyendo esto todavía considero que esto es un fallo importante en la plataforma. Si se trata de un problema con los hilos, debería haber una mejor manera de manejar este tipo de eventos que lanzando arbitrariamente (una cantidad adivinada) el tiempo de espera en el código.