Weiß jemand, wie man einen Multicurrency-Indikator entwickelt?

 
Weiß jemand, wie man einen Multicurrency-Indikator entwickelt?

Ich möchte zwischen 1 und 10 verschiedenen Währungen und 5 Balken für jede Währung wählen.

Aber ich weiß nicht, wie man das macht.

 

Bei einem Standard-Indikator würden Sie die Puffer-Arrays mit Daten aus den Parametern aufbauen, die über die Ereignisfunktion OnCalulate( ... ) gesendet werden. Für Multi-Währungen und/oder Multi-Time-Frames müssen Sie jedoch eine von zwei Lösungen verwenden:

  • Verwendung der alten Methode der "iFunction"-Variationen, wie iTime(), iVolume, iOpen, iClose usw., aber mit einem anderen Symbol wie "EURUSD", "JPYUSD" usw. anstelle des Standardwerts _Symbol oder Symbol().
  • Die Verwendung der neueren Methode der ersten Variante der Funktion ArrayCopyRates() zusammen mit Array-Zeigern von MqlRates. Die "kopierten" Arrays nehmen eigentlich keinen Platz ein und sind nur Zeiger auf die vorhandenen Daten der verschiedenen Symbole und Zeitrahmen.

Damit dies funktioniert, muss jedoch eine von zwei Bedingungen erfüllt sein, damit die Multi-Symbol- und/oder Multi-Time-Frame-Funktion funktioniert:

  • Entweder sind die jeweiligen Charts für die Symbole und Timeframes bereits geöffnet, so dass kein Fehler generiert wird,
  • oder Sie erhalten einen Fehler 4066 (ERR_HISTORY_WILL_UPDATED), wenn Sie die Daten zum ersten Mal anfordern, und Sie müssen eine sleep & retry-Schleife programmieren, um zu warten, bis die Daten heruntergeladen sind und dann die Daten erneut anfordern.

Mein persönlicher Lösungsvorschlag, den ich für den effizientesten und einfachsten Weg halte, den 4066-Fehler zu behandeln, ist die ArrayCopyRates() und MqlRates Methode.

Es gibt mehr Informationen darüber in der MQL4 Dokumentation und den Hilfedateien.

PS! ACHTUNG! Denken Sie beim Zugriff auf integrierte Indikatorfunktionen wie iMA(), iATR() usw. für die verschiedenen Symbole und Zeitrahmen daran, auch die Schleifen sleep und retry zu implementieren, um den Fehler 4066 nicht zu erhalten. Hier ist ein Zitat aus dem MQL4-Dokument:

Any indicator can be calculated on the data of not only current chart, but also on the data of any available symbol/period. If data (symbol name and/or timeframe differ from the current ones) are requested from another chart, the situation is possible that the corresponding chart was not opened in the client terminal and the necessary data must be requested from the server. In this case, error ERR_HISTORY_WILL_UPDATED (4066 - the requested history data are under updating) will be placed in the last_error variable, and one will has to re-request (see example of ArrayCopySeries())
 
Denken Sie daran, dass der OP nach einem Indikator fragt. Sleep() wird bei Indikatoren ignoriert.
 
GumRai:
Denken Sie daran, dass der OP nach einem Indikator fragt. Sleep() wird in Indikatoren ignoriert.

Tut mir leid, das wusste ich nicht! Ich verwende diese Methode recht häufig in EAs, aber nicht in Indikatoren, so wusste nicht, über den Schlaf Handicap.

In diesem Fall muss er bei jedem Tick-Aufruf der OnCalculate() -Funktion eine Wiederholungsschleife um aufeinanderfolgende Aufrufe herum aufbauen (wobei die Verwendung von ArrayCopyRates() die bessere Lösung ist).

Wenn es in der OnInit() -Funktion funktioniert, könnte es alternativ die bevorzugte Methode zur Vorbereitung der Daten für den Indikator sein, mit einer sehr langen Wiederholungszahl (ohne Sleep) für diesen Fall.

 
FMIC:

...

  • oder Sie erhalten einen Fehler 4066 (ERR_HISTORY_WILL_UPDATED), wenn Sie die Daten zum ersten Mal anfordern, und Sie müssen eine Schleife für Sleep & Retry programmieren, um zu warten, bis die Daten heruntergeladen sind, und dann die Daten erneut anfordern.

PS! ACHTUNG! Denken Sie beim Zugriff auf integrierte Indikatorfunktionen wie iMA(), iATR() usw. für die verschiedenen Symbole und Zeitrahmen daran, auch die Schleifen sleep und retry zu implementieren, um den Fehler 4066 nicht zu erhalten. Hier ist ein Zitat aus dem MQL4-Dokument:


Wenn sie nicht kürzlich etwas geändert haben, erhalten Sie den 4066-Fehler jedes Mal beim ersten Funktionsaufruf (und nur bei diesem ersten Aufruf), unabhängig von den Bedingungen oder dem Fortschritt der Aktualisierung der Historie. Es hat keinen praktischen Nutzen.
 
Ovo:
Wenn sie nicht kürzlich etwas geändert haben, erhalten Sie den Fehler 4066 jedes Mal beim ersten Funktionsaufruf (und nur bei diesem ersten Aufruf), unabhängig von den Bedingungen oder dem Fortschritt der Aktualisierung der Historie. Es hat keinen praktischen Nutzen.
Das war bei mir nicht der Fall. Wenn die Daten bereits vollständig verfügbar sind, erhalte ich den 4066-Fehler nicht. Wenn die Daten jedoch nicht direkt verfügbar sind, erhalte ich den Fehler nur beim ersten Aufruf einer Funktion für das betreffende Symbol und den time.frame. Danach gibt jede andere Funktion, die diese Daten anfordert, nicht mehr den Fehler.
 

FMIC:

In diesem Fall muss er bei jedem Tick-Aufruf der Funktion OnCalculate() eine Wiederholungsschleife um die aufeinander folgenden Aufrufe herum aufbauen (wobei die Verwendung von ArrayCopyRates() die bessere Lösung ist).

Wenn es in der Funktion OnInit() funktioniert, könnte dies die bevorzugte Methode sein, um die Daten für den Indikator vorzubereiten, mit einer sehr langen Wiederholungszahl (ohne sleep) für diesen Fall.

  1. Eine (lange oder andere) Schleife im Indikator wird nicht funktionieren. Während der Indikator läuft, kann nichts anderes im Terminal passieren. Das ist der Grund, warum Sleep in Indikatoren nicht funktionieren kann. Und warum ArrayCopyRates asynchron ist (für Indikatoren).
  2. Aktivieren Sie das Raten-Array in init. Testen Sie es in OnTick, und behandeln Sie dort die Wiederholungen. Denken Sie auch daran, dass verschiedene Charts neue Balken zu unterschiedlichen Zeiten erstellen.
    string pairs[] = {"EURUSD", "GBPUSD" ...}
    MqlRates pair0[], pair1[], ...
    bool initial;
    OnInit(){ initial=true;
       ArrayCopyRates(pair0, pairs[0], _Period);   
       ArrayCopyRates(pair1, pairs[1], _Period);
       :
    }
    OnCalculate( ... ){
       int count = IndicatorCounted();
       if(initial){
          if(pair1[0].time == 0) return;
          if(pair2[0].time == 0) return;
          :
          initial=false; count = 0; // process all bars
       }
       for(int i = Bars - 1 - MathMax(lookback, count); i >= 0; --i){
          int shift0 = iBarsShift(pairs[0], _Period, Time[i]);
          int shift1 = iBarsShift(pairs[1], _Period, Time[i]);
          buffer[i] = pair0[shift0].close - pair1[shift1].close;

  3. Wenn Sie ArrayCopyRates nicht verwenden wollen, müssen Sie das nicht tun, aber Sie müssen trotzdem die anderen Paare laden, indem Sie [in der if(initial)] das PaarN[0].time durch iTime() ersetzen.
 
   if(pair1[0].time == 0) return;

Dies wird nie der Fall sein.

Wenn für das Symbol und den Zeitrahmen eine Historie geladen ist, ruft die Funktion den aktuellsten Wert ab.

Wenn keine Historie geladen ist, erhalten Sie einen Fehler Array out of range.

Dasselbe gilt für iTime usw.

 
GumRai:

Dies wird nie der Fall sein.

Wenn für das Symbol und den Zeitrahmen eine Historie geladen ist, ruft die Funktion den aktuellsten Wert ab.

Wenn keine Historie geladen ist, erhalten Sie einen Fehler Array out of range.

Dasselbe gilt für iTime usw.

Ich bin geneigt zuzustimmen!

Ich persönlich überprüfe nur den Rückgabewert von "ArrayCopyRates()" und behalte danach nur die Array-Größe im Auge, bevor ich auf die Array-Daten zugreife.

In Bezug auf "iTime()" und andere derartige Funktionen prüfe ich immer zuerst "iBars()".

 
GumRai:

Dies wird nie der Fall sein.

  if(pair1[0].time == 0) return;

Wenn für das Symbol und den Zeitrahmen eine Historie geladen ist, ruft die Funktion den aktuellsten Wert ab.

Wenn keine Historie geladen ist, erhalten Sie einen Array out of range Fehler.

Dasselbe gilt für iTime usw.

Es gibt viele historische (vor der Erstellung von 600) Beispiele für die Betrachtung eines ACR. Es gibt keine andere Möglichkeit, dies zu tun. Nachfolgende Aufrufe von ACR oder iTime geben NICHT 4066 zurück, wie können Sie also wissen, ob die Daten heruntergeladen worden sind.

iTime hat bei einem Fehler immer Null zurückgegeben.

 
WHRoeder:

Es gibt viele historische (vor dem Build 600) Beispiele für die Betrachtung eines ACR. Es gibt keine andere Möglichkeit, dies zu tun. Nachfolgende Aufrufe von ACR oder iTime geben NICHT die Zahl 4066 zurück, wie können Sie also wissen, ob die Daten heruntergeladen wurden.

iTime hat bei einem Fehler immer Null zurückgegeben.

Was meinen Sie mit "es gibt keinen anderen Weg, es zu tun"?

Die Überprüfung der Rückgabezahl von "ArrayCopyRates" und die Überprüfung der Array-Größe scheint eine robustere Methode der Überprüfung zu sein als "pair1[0].time == 0", die leicht einen"Array index is out of range"-Fehler liefern kann.

EDIT: Ich habe einige meiner Aussagen entfernt, nachdem ich Ihren Beitrag noch einmal genauer gelesen habe.