[SOLVED] Indikatoren werden nicht richtig instanziiert, wenn sie von einem Indikator mit einem anderen Zeitrahmen aufgerufen/erzeugt werden.

 

UPDATE: Siehe die Umgehung unten

CopyBuffer() löst den Fehler 4806 (Indicator data not accessible) aus, wenn ein Indikator mit einem anderen Time-Frame aus dem Code eines Indikators aufgerufen wird. Der Fehler tritt auf, wenn ein gültiges Indikator-Handle mit einem anderen Time-Frame als dem aktuellen Arbeits-Time-Frame aufgerufen wird. Der Fehler tritt nur während der Initialisierung und dem ersten Aufruf von OnCalculate() VOR den ersten Tickdaten auf. Um den Fehler zu isolieren, wurden die folgenden Methoden angewandt:

Dies ist der Codeblock, der verwendet wird, um die Ausgabe von CopyBuffer() zu testen, wenn er von einem Skript, EA und Indikator aufgerufen wird.

#include <Indicators\Trend.mqh>


   CiMA ima;
   ima.Create(_Symbol,PERIOD_H1,20,0,MODE_SMA,PRICE_CLOSE);
   ima.Refresh();
  
   CIndicatorBuffer *buff = ima.At(0);
   int total = buff.Total();
   Print(__LINE__," ",__FUNCSIG__," ",buff.Name()," Buffer size = ",total);
   for(int i=0;i<total;i++){
      if(i>2) break;
      else{
         Print(__LINE__," ",__FUNCSIG__," ",ima.PeriodDescription()," iMA(",i,") value = ",DoubleToString(ima.Main(i),_Digits));  
      }
   }

Vollständiger Indikator-Code:

#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[])
  {
//---
   if(rates_total != prev_calculated || m_bufferSize < 1 ){
      ResetLastError();
      ima.Create(_Symbol,PERIOD_H1,20,0,MODE_SMA,PRICE_CLOSE);
      ima.Refresh();
      
      CIndicatorBuffer *buff = ima.At(0);
      m_bufferSize = buff.Total();
      Print(__LINE__," ",__FUNCSIG__," ",buff.Name()," Buffer size = ",m_bufferSize);
      if(m_bufferSize < 1){
         Print(ErrorDescription(GetLastError()));
      } else {
         for(int i=0;i<m_bufferSize;i++){
            if(i>2) break;
            else{
               Print(__LINE__," ",__FUNCTION__," ",ima.PeriodDescription()," iMA(",i,") value = ",DoubleToString(ima.Main(i),_Digits));  
            }
         }
      }
   }
//--- return value of prev_calculated for next call
   return(rates_total);
}
//+------------------------------------------------------------------+

Die einzige Möglichkeit, keinen Fehler zu erhalten, besteht darin, diesen Indikator auf H1-Charts (dieselbe TF) zu starten.

Links zu Forumsbeiträgen mit demselben Problem:

https://www.mql5.com/en/forum/73274

https://www.mql5.com/en/forum/13676

https://www.mql5.com/en/forum/30958

https://www.mql5.com/en/forum/16614

ABHILFE:

Die Abhilfe bestand darin, den Indikator in OnInit() zu erstellen und EventSetMillisecondTimer auf 1ms zu setzen. Dadurch konnte OnCalculate() nach seinem ersten Durchlauf zurückkehren und OnTimer für einen zweiten Durchlauf schnell aufrufen. Es war nur ein Aufruf des OnTimer-Ereignisses erforderlich, um den Indikator zu fixieren, und es war keine weitere Zeitverzögerung für die Berechnungen erforderlich.

//+------------------------------------------------------------------+
//|                                                    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);
}
//+------------------------------------------------------------------+
Error 4806 while copying buffers
Error 4806 while copying buffers
  • www.mql5.com
com/en/articles/100, but tried to change it to use the CCI indicator only.
 
Kennt jemand eine Abhilfe?
 

Ich fürchte, es handelt sich nicht um einen Fehler im MT5, sondern um einen Fehler in Ihrem Code. By the way, wie alle Themen, die Sie berichtet. Sie müssen sich mit der Plattform/Sprache auseinandersetzen, wie sie entworfen wurde, nicht wie Sie denken, dass sie ist oder wie Sie sie gerne hätten.

Warum verwenden Sie ima.Create() in OnCalculate()? Sie erhalten einen Handle, aber die Daten sind noch nicht verfügbar, Sie erhalten einen Fehler und Ihr Code wird nie wieder aufgerufen.

P.S.: Was bedeutet "Funktioniert ohne Datenzugriff." ?
 
Alain Verleyen:

Ich fürchte, es handelt sich nicht um einen Fehler im MT5, sondern um einen Fehler in Ihrem Code. By the way, wie alle Themen, die Sie berichtet. Sie müssen sich mit der Plattform/Sprache auseinandersetzen, wie sie entworfen wurde, nicht wie Sie denken, dass sie ist oder wie Sie sie gerne hätten.

Warum verwenden Sie ima.Create() in OnCalculate()? Sie erhalten ein Handle, aber die Daten sind noch nicht verfügbar, Sie erhalten einen Fehler und Ihr Code wird nie wieder aufgerufen.

P.S.: Was bedeutet "Funktioniert ohne Datenzugriff." ?
Ich fürchte, das ist tatsächlich ein Fehler in der Plattform. Ich führe genau denselben Codeblock im OnInit() im Experten aus und erhalte keine Fehler, während OnInit() im Indikator Fehler auslöst. Funktioniert ohne Datenzugriff bedeutet, dass es offline, im Tester oder außerhalb der Marktzeiten funktioniert. Ein Aufruf eines Indikators sollte ihn von überall und jederzeit instanziieren, und die Tatsache, dass die Plattform in dieser Hinsicht inkonsistent ist, bedeutet, dass dies keine Funktion, sondern ein Fehler ist. Die Verwendung von ima.Create innerhalb von oncalculate ist nur ein Beispiel dafür, dass der Indikator auch in einem anderen Zeitrahmen nicht instanziiert werden kann, und zwar von jeder Stelle aus, die Sie innerhalb des Indikators aufrufen, bevor der erste Tick (Datenaktualisierung) erfolgt. Sie können den Indikator unendlich oft aktualisieren, aber er greift erst auf die Indikatordaten zu, nachdem oncalculate genau einmal ausgeführt wurde und dann zurückkehrt. Es funktioniert beim nächsten Durchlauf, wenn ein neuer Tick eintrifft. Fehler.

Ich möchte noch einmal betonen, dass es in Experten und Skripten von überall aus korrekt funktioniert, nur in Indikatoren ist es irgendwie kaputt.

 
nicholishen:
Ich fürchte, das ist tatsächlich ein Fehler in der Plattform. Ich führe genau denselben Codeblock in OnInit() im Expert aus und bekomme keine Fehler, während OnInit() im Indikator Fehler auslöst. Funktioniert ohne Datenzugriff bedeutet, dass es offline, im Tester oder außerhalb der Marktzeiten funktioniert. Ein Aufruf eines Indikators sollte ihn von überall und jederzeit instanziieren, und die Tatsache, dass die Plattform in dieser Hinsicht inkonsistent ist, bedeutet, dass es sich nicht um eine Funktion, sondern um einen Fehler handelt. Die Verwendung von ima.Create innerhalb von oncalculate ist nur ein Beispiel dafür, dass der Indikator auch in einem anderen Zeitrahmen nicht instanziiert wird - und zwar von überall, wo Sie ihn innerhalb des Indikators aufrufen, vor dem ersten Tick (Datenaktualisierung). Ich möchte noch einmal betonen, dass es von überall in Experten und Skripten korrekt funktioniert, nur in Indikatoren ist es irgendwie kaputt.

Ok, Sie glauben mir nicht, das ist Ihr Recht, aber Sie irren sich.

Ich kann Ihnen nur empfehlen, sich an den ServiceDesk zu wenden und die Antwort hier zu veröffentlichen.

 
Alain Verleyen:

Ok, Sie glauben mir nicht, das ist Ihr Recht, aber Sie liegen falsch.

Ich kann Ihnen nur raten, sich an den ServiceDesk zu wenden und dessen Antwort hier zu veröffentlichen.

Danke, das werde ich tun. Wenn ich falsch liege, warum funktioniert es dann bei Experten und Skripten, aber nicht bei Indikatoren?
 
nicholishen:
Danke, das werde ich. Wenn ich falsch liege, warum genau funktioniert es in Experten und Skripten, aber nicht bei Indikatoren?

Denn alle Indikatoren für ein Symbol laufen auf demselben Thread. Strategy Tester, EA und Skript sind unterschiedliche Situationen.

Aber warten wir mal die Antwort von ServiceDesk ab. Vielleicht liege ich ja falsch :-)

 
Alain Verleyen:

Denn alle Indikatoren für ein Symbol laufen auf demselben Thread. Strategy Tester, EA und Skript sind unterschiedliche Situationen.

Aber warten wir die Antwort von ServiceDesk ab. Vielleicht liege ich ja falsch :-)

Nehmen wir an, dass dies der Fall ist...

  • Warum können Sie einen Indikator desselben Zeitrahmens instanziieren und sofort auf seine Daten zugreifen, aber nicht auf die Daten eines anderen Zeitrahmens?
 
nicholishen:
  • Warum können Sie einen Indikator desselben Zeitrahmens instanziieren und sofort auf dessen Daten zugreifen?

Das bedeutet eigentlich, dass Sie Glück haben, dass die Daten bereits verfügbar sind. Das ist nicht garantiert. Es kann auch fehlschlagen.
 
Stanislav Korotky:
Das bedeutet eigentlich, dass man Glück hat, dass die Daten bereits vorhanden sind. Das ist nicht garantiert. Es kann auch fehlschlagen.

Das bedeutet, dass die Daten, wenn sie einem Skript oder EA sofort zur Verfügung stehen, auch für den Indikator verfügbar sind (es handelt sich also nicht um ein Problem der Datenverfügbarkeit). Der Indikator wird einfach nicht vor dem zweiten Durchlauf von OnCalculate() (auch bekannt als der erste Tick) instanziiert.

Ich habe dies bei der Diagnose berücksichtigt. Ich habe sogar Schleifen und Wartezeiten eingebaut, nur für den Fall. Wie alle vor mir, habe ich die gleichen Probleme mit diesem speziellen Fehler.

 
nicholishen:

Das bedeutet, dass die Daten, wenn sie einem Skript oder EA sofort zur Verfügung stehen, auch für den Indikator verfügbar sind (es handelt sich also nicht um ein Problem der Datenverfügbarkeit). Der Indikator wird einfach nicht vor dem zweiten Durchlauf von OnCalculate() (auch bekannt als der erste Tick) instanziiert.

Ich habe dies bei der Diagnose berücksichtigt. Ich habe sogar Schleifen und Wartezeiten eingebaut, nur für den Fall. Wie jeder vor mir, habe ich die gleichen Probleme mit diesem speziellen Fehler.

Sie wiederholen "fehlende Instanziierung", aber das ist nicht genau. Der Indikator wird in jedem Fall instanziiert.

Das Problem ist, dass die Daten nicht synchron verfügbar sind, man muss damit umgehen. Es ist KEIN MT5-Bug, es ist ein FEATURE.

Ich schlage vor, die Diskussion zu beenden und die Antwort von SD abzuwarten.

Grund der Beschwerde: