Merkmale der Sprache mql5, Feinheiten und Techniken - Seite 31

 
Artyom Trishkin:

Haben Sie sich den Code, den ich Ihnen gezeigt habe, überhaupt angesehen? Haben Sie es getestet?

Ich habe nicht gefragt, wie man den Indikatorpuffer füllt, sondern warum leere Werte zurückgegeben werden, wenn ich Werte aus AO und nicht aus dem aktuellen Balken nehme.
Ich habe es - es gibt keinen Verlauf, er wird geladen, und während er AO aus einem nicht nativen Zeitrahmen lädt, kommt die Fehlermeldung "keine Daten".

Ich möchte prüfen, ob die Historie vollständig geladen ist, um nicht in den Indikatorzyklus zu gelangen.

Wenn Sie CopyBuffer in einem Indikator verwenden, um Daten von einem anderen Indikator zu erhalten, müssen Sie:

  1. Drehen Sie Ihren Indikatorpuffer so, dass der ganz rechte Balken auf dem Diagramm dem Index "0" im Indikatorpuffer entspricht.
  2. So wird der "aktuelle Balken" im Indikator "iMTF_AO.mq5" der RECHTESTE Balken im Diagramm sein und dem Index "0" im Indikatorpuffer "Buffer[]" entsprechen.
  3. Und um den "aktuellen Balken" aus dem Indikator (CopyBuffer(handle,0,shift,1,array)) zu erhalten, muss der Parameter "shift" gleich "0" sein.

Wenn Sie den Indikatorpuffer nicht umdrehen wollen, tun Sie dies (vorübergehend): AO(0) - um zu verstehen, wie man Werte eines anderen Indikators von einem INDICATOR erhält. Es kann sein, dass ein oder zwei Mal ein Fehler auftritt, aber nur so lange, bis die Zeitreihe erstellt ist, und dann sind die Werte stabil.

 
Artyom Trishkin:
Haben Sie meine Antwort gesehen? Haben Sie es ausprobiert?
 
Wladimir Karputow:

Wenn Sie CopyBuffer in einem Indikator verwenden, um Daten von einem anderen Indikator abzurufen, sollten Sie dies tun:

  1. Drehen Sie Ihren Indikatorpuffer um, so dass der ganz rechte Balken im Diagramm dem Index "0" im Indikatorpuffer entspricht.
  2. Der "aktuelle Balken" im Indikator "iMTF_AO.mq5" ist also der RECHTESTE Balken im Diagramm und entspricht dem Index "0" im Indikatorpuffer "Buffer[]".
  3. Und um den "aktuellen Balken" aus dem Indikator (CopyBuffer(handle,0,shift,1,array)) zu erhalten, muss der Parameter "shift" gleich "0" sein.

Wenn Sie den Indikatorpuffer nicht umdrehen wollen, tun Sie dies (vorübergehend): AO(0) - um zu verstehen, wie man Werte eines anderen Indikators von einem INDICATOR erhält. Es kann sein, dass ein oder zwei Mal ein Fehler auftritt - aber nur solange, bis eine Zeitreihe erstellt wird, dann sind die Werte stabil.

1. Mein Code hat es, und es war sofort da:

   ArraySetAsSeries(Buffer,true);
   int bars=Bars(NULL,PeriodForWork);
   datetime time_limit=GetTime(Symbol(),PeriodForWork,bars-1);
   int limit_p=GetBarShift(Symbol(),Period(),time_limit);
   if(rates_total<1) return(0);

2. das tut es.

3. Die Verschiebung entspricht dem Zyklusindex i. Und die Schleife geht vom Anfang der historischen Daten (rates_total-1) bis zum Ende (zu den aktuellen Daten)

Eine weitere Frage ist, ob wir diese Daten in Bezug auf eine nicht-native TF berechnen sollten, um keine Daten aus fehlenden Balken zu erhalten. Und wir müssen vor dem Zyklus feststellen, dass die Geschichte der gewünschten TF vollständig synchronisiert ist.

 
Artyom Trishkin:

1. Mein Code hat es, und ich hatte es sofort:

2. es ist so, wie es ist.

3. Die Verschiebung entspricht dem Zyklusindex i. Und die Schleife geht vom Anfang der historischen Daten (rates_total-1) bis zum Ende (zu den aktuellen Daten)

Ein weiteres Problem ist, dass wir diese Daten in Bezug auf einen nicht nativen Zeitrahmen berechnen müssen, damit wir keine Daten aus fehlenden Balken erhalten. Und wir sollten vor der Schleife feststellen, dass die Geschichte des benötigten Zeitrahmens vollständig synchronisiert ist.


Überarbeitung der Schleife für den Aufruf von AO: put von "0" auf irgendeinen Wert (jetzt von irgendeinem Wert auf Null). Beim Auftreten von Fehlern - vergleichen Sie auf einmal: die Anzahl der berechneten Balken ("limit_p") und rates_total des aktuellen Indikators.


Hinzugefügt: und hier machen diese Zeilen alle Bemühungen um eine berechnete "Grenze" zunichte (wenn wir uns auf einen nicht-nativen Zeitrahmen beziehen):

   if(limit>1) 
     {
      limit=rates_total-1;
     }

Grob gesagt, war "Limit" zunächst (beim Zugriff auf einen nicht nativen Zeitrahmen) gleich 156, aber unter BACK! wurde "Limit" zu "154566666666".



 
Alexey Kozitsyn:
Haben Sie die Synchronisierung ausprobiert? Außerdem raten die Entwickler, die Daten des gewünschten TF/Symbols durch den Timer aktuell zu halten.

Nein, ich habe es noch nicht ausprobiert. Ich habe über die Unterstützung der Datenrelevanz gesehen, ich erinnere mich - ich weiß.

Zunächst ist es jedoch notwendig, OnCalculate() zu beenden, wenn die Daten zum angegebenen Datum und zum aktuellen Datum noch nicht synchronisiert sind.

Ich verstehe das mit dem aktuellen:

if(rates_total<1) return(0);

Über gegeben - es ist notwendig, seine Bars() - ihre Zahl anstelle von rates_total zu überprüfen.

Aber ich weiß nicht, über die Grenze - es kann auf den aktuellen Zeitrahmen (als ein Beispiel aus einem anderen Indikator) überprüft werden:

   int limit=rates_total-prev_calculated;
   if(limit>1) {
      limit=rates_total-4;
      ArrayInitialize(BufferAoDN,EMPTY_VALUE);
      ArrayInitialize(BufferAoUP,EMPTY_VALUE);
      ArrayInitialize(BufferMacdDN,EMPTY_VALUE);
      ArrayInitialize(BufferMacdUP,EMPTY_VALUE);
      ArrayInitialize(BufferRsiDN,EMPTY_VALUE);
      ArrayInitialize(BufferRsiUP,EMPTY_VALUE);
      ArrayInitialize(BufferStochDN,EMPTY_VALUE);
      ArrayInitialize(BufferStochUP,EMPTY_VALUE);
      }

Aber in diesem Testindikator erhalten wir Daten sowohl aus dem aktuellen Zeitrahmen (er zeigt die Berechnungen in OnCalculate()) als auch aus dem angegebenen Zeitrahmen - um AO-Daten aus dem angegebenen Zeitrahmen zu erhalten.

Ich kann mich immer noch nicht daran erinnern, wie man alle notwendigen Daten für die Anzahl der Balken berechnet - denn die Schleife sollte mit dem Balken beginnen, der dem Zeitpunkt des historischen Balkens mit den ersten vorhandenen Daten des aktuellen oder des angegebenen Balkens entspricht - wenn es weniger ist - von diesem Balken aus starten wir die Schleife. Der Grenzwert sollte auch korrekt berechnet werden, um das Auftreten eines neuen Balkens zu erkennen, was zu einer vollständigen Neuberechnung oder nur zu einer Neuberechnung des aktuellen Balkens führen sollte (je nachdem, was passiert ist - die Eröffnung eines neuen Balkens oder das Laden der Historie).

Vielleicht versuche ich, an alles gleichzeitig zu denken, und denke dabei eine Menge unnötiger Dinge...

 
Wladimir Karputow:


Überarbeitung des Schleifenaufrufs zu AO: put von "0" und zu irgendeinem Wert (jetzt von irgendeinem Wert zu Null). Beim Auftreten von Fehlern - vergleichen Sie auf einmal: die Anzahl der berechneten Balken ("limit_p") und rates_total des aktuellen Indikators.


Hinzugefügt: und diese Zeilen löschen alle Bemühungen des berechneten "Limits" (wenn sie sich auf einen nicht-nativen Zeitrahmen beziehen):

grob gesagt, wurde "limit" zunächst (bei der Adressierung eines nicht nativen Zeitrahmens) zu 156, und unter BATCH! und "limit" bereits zu "154566666666"

Ja, ich habe gleich darüber geschrieben, dass ich hier in der Eile Mist gebaut habe.

Aber ich werde die Schleife nicht ändern - es ist ein ziemlich komplizierter Indikator, in dem alles auf der Berechnung der Geschichte vom Anfang bis zum Ende aufgebaut ist - es ist einfacher, die Grenzen neu zu berechnen und die Daten zu erhalten, als den gesamten Indikator neu zu schreiben - alle seine Logik.

 
Artyom Trishkin:

Nein, ich habe es noch nicht ausprobiert. Ich habe über die Unterstützung der Datenrelevanz gesehen, ich erinnere mich - ich weiß.

Zunächst ist es jedoch notwendig, OnCalculate() zu beenden, wenn die Daten zum angegebenen Datum und zum aktuellen Datum noch nicht synchronisiert sind.

Die aktuelle ist eindeutig:

Das ist nicht ganz so. Wenn Sie das Terminal zum ersten Mal mit dem Indikator laden, erhalten Sie möglicherweise nicht das, was Sie erwarten. Im Laufe des Tages und bei Unterbrechungen der Verbindung kann es auch zu Fehlern kommen.

Zum Ausstieg aus OnCalculate(): Die erste Anforderung Bars() sollte in der Initialisierungsphase erfolgen, dann in OnCalculate() die Synchronisierung der aktuellen und der erforderlichen TFs überprüfen. Wenn es keine Synchronisierung gibt, verlassen Sie die Seite.

 
Artyom Trishkin:

Ja, das habe ich auch gleich gesagt, dass ich in der Eile etwas falsch gemacht habe.

Ich möchte die Schleife nicht ändern, es gibt einen ziemlich komplizierten Indikator, der auf der Berechnung der Geschichte vom Anfang bis zum Ende basiert - es ist einfacher, die Grenzen neu zu berechnen und die Daten richtig zu empfangen, als den ganzen Indikator neu zu schreiben - seine ganze Logik.

Artem, was meinen Sie mit "vom Anfang bis zum Ende"?

Halten Sie es für die beste Lösung, alle Felder umzudrehen?

Warum

ArraySetAsSeries(Buffer,true);

wenn man nur einen Wert kopiert?

Beim Kopieren einer anderen als der aktuellen TF ist es besser, die Zeit des benötigten Taktes an die Funktion CopyBuffer() zu übergeben. Andernfalls wird der gewünschte Takt nicht kopiert.

 
Alexey Viktorov:

1. artyom, was meinen Sie mit "vom Anfang bis zum Ende"?

2. denken Sie, dass das Umdrehen aller Felder der beste Ausweg ist?

3. Warum

4. wenn Sie nur 1 Wert kopieren?

Beim Kopieren der Zeit des gewünschten Balkens in die Funktion CopyBuffer(), die nicht der aktuelle Zeitrahmen ist, ist es besser, diesen zu übergeben. Andernfalls wird der gewünschte Takt nicht kopiert.

1. Der Beginn der historischen Daten ist der allererste Balken in der Historie mit der kürzesten Öffnungszeit, das Ende der historischen Daten ist der aktuelle Balken.

2. Ich kopiere von einer 4 auf eine 5.

Nun, weil in Buffer[] die Daten in einer Schleife von rates_total-1 bis 0 geschrieben werden. Wenn wir es nicht als Zeitreihe machen, werden sie vorwärts und rückwärts im Diagramm angezeigt.

4. Ich möchte einen Wert zu einem bestimmten Zeitpunkt kopieren, der den Daten von Balken i eines bestimmten Zeitrahmens entspricht.

Schauen Sie, wie lakonisch und einfach es ist, die Daten nicht des aktuellen Zeitrahmens in mql4 zu erhalten. Ich frage mich, wie es möglich ist, Indikator-Daten in mql5 zu erhalten und es wird nicht funktionieren - es gibt immer den Fehler 4806, wenn ich den Zeitrahmen, die nicht mit dem Zeitrahmen des Charts der Indikator arbeitet in der Funktion des Empfangs AO Daten entsprechen übergeben.

//+------------------------------------------------------------------+
double GetDataAO(string sy, int timeframe, int shift) {
   double array[1];
   ZeroMemory(array);
#ifdef __MQL4__
   array[0]=iAO(sy,timeframe,shift);
#else 
   ResetLastError();
   if(CopyBuffer(handle_ao,0,shift,1,array)==WRONG_VALUE) {
      Print(__FUNCTION__," > Error: ",GetLastError());
      return(0);
      }
#endif 
   return(array[0]);
}
//+------------------------------------------------------------------+

Gleichzeitig wird in OnInit() das Indikator-Handle erstellt, das dem aktuellen Preis entspricht, von dem wir Daten erhalten wollen:

handle_ao=iAO(symbol,periodForWork);

D.h., egal wie wir denf schalten, der Griff wird immer mit dem notwendigen (in den Einstellungen gewählten)f erstellt. Die AO-Daten können jedoch nur ermittelt werden, wenn die in den Einstellungen ausgewählte Funktion und die aktuelle Funktion übereinstimmen. Wenn sie nicht übereinstimmen, wird von der Funktion immer Null zurückgegeben.

Die Frage ist: WARUM?

 
Artyom Trishkin:

1. Der Beginn der historischen Daten ist der allererste Balken in der Geschichte mit der kürzesten Eröffnungszeit, das Ende der historischen Daten ist der aktuelle Balken.

2. Ich schreibe von vier auf fünf um.

Nun, weil in Buffer[] die Daten in einer Schleife von rates_total-1 bis 0 geschrieben werden. Wenn wir es nicht als Zeitreihe machen, werden sie vorwärts und rückwärts im Diagramm angezeigt.

4. Ich kopiere jeweils einen Wert, der den Daten des Balkens i des angegebenen Zeitrahmens entspricht.

Sehen Sie sich an, wie lakonisch und einfach es ist, in mql4 Daten zu erhalten, die nicht dem aktuellen Zeitrahmen entsprechen. Ich frage mich, wie es möglich ist, Indikator-Daten in mql5 zu erhalten und es wird nicht funktionieren - es gibt immer Fehler 4806, wenn ich den Zeitrahmen, die nicht mit dem Zeitrahmen des Charts der Indikator arbeitet in der Funktion des Empfangs AO Daten entsprechen übergeben.

Gleichzeitig wird in OnInit() das Indikator-Handle erstellt, das dem aktuellen Preis entspricht, von dem wir Daten erhalten wollen:

D.h., egal wie wir denf schalten, der Griff wird immer mit dem notwendigen (in den Einstellungen gewählten)f erstellt. Die AO-Daten können jedoch nur ermittelt werden, wenn die in den Einstellungen ausgewählte Funktion und die aktuelle Funktion übereinstimmen. Wenn sie nicht übereinstimmen, wird von der Funktion immer Null zurückgegeben.

Die Frage: WARUM?

1. Nur eine Klarstellung. Jetzt verstehe ich, dass wir über dieselbe Sache sprechen.

Ich verstehe es, aber ich bin nicht der Meinung, dass es notwendig ist, Arrays umzukehren. Ist ein Indikator für zwei Terminals erforderlich? Fast wie 2in1 eine Sense und eine Axt zu machen.

3. soweit ich weiß, wird Buffer[] vom Empfänger in der Funktion CopyBuffer() verwendet, um nur einen Indikatorwert zu erhalten.

4. Sie haben das Wichtigste nicht beachtet. Der Beginn des Kopierens des Indikatorwertes sollte nicht durch den Taktindex, sondern durch den Zeitpunkt des i-ten Taktes bestimmt werden.

int  CopyBuffer( 
   int       indicator_handle,     // handle индикатора 
   int       buffer_num,           // номер буфера индикатора 
   datetime  start_time,           // с какой даты 
   int       count,                // сколько копируем 
   double    buffer[]              // массив, куда будут скопированы данные 
   );
Grund der Beschwerde: